Merge "Initial commit for VideoView2Impl"
diff --git a/Android.bp b/Android.bp
index 2685ac3..19c0580 100644
--- a/Android.bp
+++ b/Android.bp
@@ -117,7 +117,7 @@
         "core/java/android/content/ISyncServiceAdapter.aidl",
         "core/java/android/content/ISyncStatusObserver.aidl",
         "core/java/android/content/om/IOverlayManager.aidl",
-        "core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl",
+        "core/java/android/content/pm/ICrossProfileApps.aidl",
         "core/java/android/content/pm/IDexModuleRegisterCallback.aidl",
         "core/java/android/content/pm/ILauncherApps.aidl",
         "core/java/android/content/pm/IOnAppsChangedListener.aidl",
@@ -242,6 +242,7 @@
         "core/java/android/security/IKeystoreService.aidl",
         "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
         "core/java/android/service/autofill/IAutoFillService.aidl",
+        "core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
         "core/java/android/service/autofill/IFillCallback.aidl",
         "core/java/android/service/autofill/ISaveCallback.aidl",
         "core/java/android/service/carrier/ICarrierService.aidl",
@@ -324,6 +325,8 @@
         "core/java/android/view/IOnKeyguardExitResult.aidl",
         "core/java/android/view/IPinnedStackController.aidl",
         "core/java/android/view/IPinnedStackListener.aidl",
+        "core/java/android/view/IRemoteAnimationRunner.aidl",
+        "core/java/android/view/IRemoteAnimationFinishedCallback.aidl",
         "core/java/android/view/IRotationWatcher.aidl",
         "core/java/android/view/IWallpaperVisibilityListener.aidl",
         "core/java/android/view/IWindow.aidl",
@@ -464,6 +467,8 @@
         "telecomm/java/com/android/internal/telecom/IInCallService.aidl",
         "telecomm/java/com/android/internal/telecom/ITelecomService.aidl",
         "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
+	"telephony/java/android/telephony/data/IDataService.aidl",
+	"telephony/java/android/telephony/data/IDataServiceCallback.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl",
@@ -496,6 +501,7 @@
         "telephony/java/com/android/ims/internal/IImsService.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceController.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl",
+	"telephony/java/com/android/ims/internal/IImsSmsListener.aidl",
         "telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl",
         "telephony/java/com/android/ims/internal/IImsUt.aidl",
         "telephony/java/com/android/ims/internal/IImsUtListener.aidl",
@@ -519,9 +525,31 @@
         "telephony/java/com/android/internal/telephony/ITelephony.aidl",
         "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
         "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IDeleteProfileCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl",
         "telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl",
         "telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
+        "wifi/java/android/net/wifi/ISoftApCallback.aidl",
         "wifi/java/android/net/wifi/IWifiManager.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
diff --git a/Android.mk b/Android.mk
index 3c6dd37..73c1ccd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -829,4 +829,5 @@
 include $(call first-makefiles-under,$(LOCAL_PATH))
 endif
 
-endif # ANDROID_BUILD_EMBEDDED
\ No newline at end of file
+endif # ANDROID_BUILD_EMBEDDED
+
diff --git a/apct-tests/perftests/core/src/android/os/PssPerfTest.java b/apct-tests/perftests/core/src/android/os/PssPerfTest.java
new file mode 100644
index 0000000..400115d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/PssPerfTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PssPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testPss() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Debug.getPss();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index 93a0fc3..6975609 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -29,6 +29,7 @@
 import android.text.Layout;
 import android.text.style.TextAppearanceSpan;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,7 +53,7 @@
     private static final boolean NO_STYLE_TEXT = false;
     private static final boolean STYLE_TEXT = true;
 
-    private final Random mRandom = new Random(31415926535L);
+    private Random mRandom;
 
     private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     private static final int ALPHABET_LENGTH = ALPHABET.length();
@@ -98,6 +99,11 @@
         return ssb;
     }
 
+    @Before
+    public void setUp() {
+        mRandom = new Random(0);
+    }
+
     @Test
     public void testCreate_FixedText_NoStyle_Greedy_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
@@ -190,8 +196,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -206,8 +215,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -222,8 +234,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -238,8 +253,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -254,8 +272,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
diff --git a/api/current.txt b/api/current.txt
index ad78307..5515b01 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -211,6 +211,7 @@
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
     field public static final int accessibilityFlags = 16843652; // 0x1010384
+    field public static final int accessibilityHeading = 16844160; // 0x1010580
     field public static final int accessibilityLiveRegion = 16843758; // 0x10103ee
     field public static final int accessibilityPaneTitle = 16844156; // 0x101057c
     field public static final int accessibilityTraversalAfter = 16843986; // 0x10104d2
@@ -602,6 +603,7 @@
     field public static final int fingerprintAuthDrawable = 16844008; // 0x10104e8
     field public static final int finishOnCloseSystemDialogs = 16843431; // 0x10102a7
     field public static final int finishOnTaskLaunch = 16842772; // 0x1010014
+    field public static final int firstBaselineToTopHeight = 16844157; // 0x101057d
     field public static final int firstDayOfWeek = 16843581; // 0x101033d
     field public static final int fitsSystemWindows = 16842973; // 0x10100dd
     field public static final int flipInterval = 16843129; // 0x1010179
@@ -798,6 +800,7 @@
     field public static final int largeHeap = 16843610; // 0x101035a
     field public static final int largeScreens = 16843398; // 0x1010286
     field public static final int largestWidthLimitDp = 16843622; // 0x1010366
+    field public static final int lastBaselineToBottomHeight = 16844158; // 0x101057e
     field public static final int launchMode = 16842781; // 0x101001d
     field public static final int launchTaskBehindSourceAnimation = 16843922; // 0x1010492
     field public static final int launchTaskBehindTargetAnimation = 16843921; // 0x1010491
@@ -855,6 +858,7 @@
     field public static final int left = 16843181; // 0x10101ad
     field public static final int letterSpacing = 16843958; // 0x10104b6
     field public static final int level = 16844032; // 0x1010500
+    field public static final int lineHeight = 16844159; // 0x101057f
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -5856,11 +5860,15 @@
     method public java.lang.CharSequence getLabel();
     method public java.lang.String getResultKey();
     method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
+    method public static int getResultsSource(android.content.Intent);
     method public boolean isDataOnly();
+    method public static void setResultsSource(android.content.Intent, int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.RemoteInput> CREATOR;
     field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
     field public static final java.lang.String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+    field public static final int SOURCE_CHOICE = 1; // 0x1
+    field public static final int SOURCE_FREE_FORM_INPUT = 0; // 0x0
   }
 
   public static final class RemoteInput.Builder {
@@ -6354,6 +6362,7 @@
     field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
     field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
     field public static final java.lang.String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE = "android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
+    field public static final java.lang.String SUPPORT_TRANSFER_OWNERSHIP_META_DATA = "android.app.support_transfer_ownership";
   }
 
   public class DeviceAdminService extends android.app.Service {
@@ -6367,7 +6376,7 @@
     method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
     method public void addUserRestriction(android.content.ComponentName, java.lang.String);
     method public boolean bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
-    method public boolean clearApplicationUserData(android.content.ComponentName, java.lang.String, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener, java.util.concurrent.Executor);
+    method public boolean clearApplicationUserData(android.content.ComponentName, java.lang.String, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener);
     method public void clearCrossProfileIntentFilters(android.content.ComponentName);
     method public deprecated void clearDeviceOwnerApp(java.lang.String);
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
@@ -6397,6 +6406,7 @@
     method public java.util.List<java.lang.String> getDelegatePackages(android.content.ComponentName, java.lang.String);
     method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String);
     method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
+    method public java.lang.CharSequence getEndUserSessionMessage(android.content.ComponentName);
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -6432,6 +6442,7 @@
     method public boolean getScreenCaptureDisabled(android.content.ComponentName);
     method public java.util.List<android.os.UserHandle> getSecondaryUsers(android.content.ComponentName);
     method public java.lang.CharSequence getShortSupportMessage(android.content.ComponentName);
+    method public java.lang.CharSequence getStartUserSessionMessage(android.content.ComponentName);
     method public boolean getStorageEncryption(android.content.ComponentName);
     method public int getStorageEncryptionStatus();
     method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
@@ -6494,6 +6505,7 @@
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
     method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
     method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
+    method public void setEndUserSessionMessage(android.content.ComponentName, java.lang.CharSequence);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setKeyPairCertificate(android.content.ComponentName, java.lang.String, java.util.List<java.security.cert.Certificate>, boolean);
@@ -6537,6 +6549,7 @@
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.CharSequence);
+    method public void setStartUserSessionMessage(android.content.ComponentName, java.lang.CharSequence);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void setSystemSetting(android.content.ComponentName, java.lang.String, java.lang.String);
@@ -7068,8 +7081,8 @@
 
   public final class Slice implements android.os.Parcelable {
     ctor protected Slice(android.os.Parcel);
-    method public static android.app.slice.Slice bindSlice(android.content.ContentResolver, android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
-    method public static android.app.slice.Slice bindSlice(android.content.Context, android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
+    method public static deprecated android.app.slice.Slice bindSlice(android.content.ContentResolver, android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
+    method public static deprecated android.app.slice.Slice bindSlice(android.content.Context, android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
     method public int describeContents();
     method public java.util.List<java.lang.String> getHints();
     method public java.util.List<android.app.slice.SliceItem> getItems();
@@ -7086,6 +7099,7 @@
     field public static final java.lang.String HINT_MAX = "max";
     field public static final java.lang.String HINT_NO_TINT = "no_tint";
     field public static final java.lang.String HINT_PARTIAL = "partial";
+    field public static final java.lang.String HINT_SEE_MORE = "see_more";
     field public static final java.lang.String HINT_SELECTED = "selected";
     field public static final java.lang.String HINT_SHORTCUT = "shortcut";
     field public static final java.lang.String HINT_SUMMARY = "summary";
@@ -7155,7 +7169,10 @@
   }
 
   public class SliceManager {
+    method public android.app.slice.Slice bindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
+    method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
     method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
+    method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri);
     method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
     method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>);
     method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, android.os.Handler);
@@ -7174,7 +7191,7 @@
     method public final java.lang.String getType(android.net.Uri);
     method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
     method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
-    method public deprecated android.app.slice.Slice onBindSlice(android.net.Uri);
+    method public java.util.Collection<android.net.Uri> onGetSliceDescendants(android.net.Uri);
     method public android.net.Uri onMapIntentToUri(android.content.Intent);
     method public void onSlicePinned(android.net.Uri);
     method public void onSliceUnpinned(android.net.Uri);
@@ -10671,6 +10688,13 @@
     field public int reqTouchScreen;
   }
 
+  public class CrossProfileApps {
+    method public android.graphics.drawable.Drawable getProfileSwitchingIconDrawable(android.os.UserHandle);
+    method public java.lang.CharSequence getProfileSwitchingLabel(android.os.UserHandle);
+    method public java.util.List<android.os.UserHandle> getTargetUserProfiles();
+    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle);
+  }
+
   public final class FeatureGroupInfo implements android.os.Parcelable {
     ctor public FeatureGroupInfo();
     ctor public FeatureGroupInfo(android.content.pm.FeatureGroupInfo);
@@ -11156,7 +11180,7 @@
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
-    field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
+    field public static final deprecated java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
     field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
@@ -11465,17 +11489,6 @@
 
 }
 
-package android.content.pm.crossprofile {
-
-  public class CrossProfileApps {
-    method public android.graphics.drawable.Drawable getProfileSwitchingIcon(android.os.UserHandle);
-    method public java.lang.CharSequence getProfileSwitchingLabel(android.os.UserHandle);
-    method public java.util.List<android.os.UserHandle> getTargetUserProfiles();
-    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle);
-  }
-
-}
-
 package android.content.res {
 
   public class AssetFileDescriptor implements java.io.Closeable android.os.Parcelable {
@@ -15713,6 +15726,7 @@
     field public static final int CONTROL_AE_MODE_ON_ALWAYS_FLASH = 3; // 0x3
     field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH = 2; // 0x2
     field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4; // 0x4
+    field public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5; // 0x5
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2; // 0x2
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0; // 0x0
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1; // 0x1
@@ -26226,9 +26240,9 @@
     method public void applyTransportModeTransform(java.io.FileDescriptor, int, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransforms(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void removeTransportModeTransforms(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void removeTransportModeTransforms(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
+    method public void removeTransportModeTransforms(java.net.Socket) throws java.io.IOException;
+    method public void removeTransportModeTransforms(java.net.DatagramSocket) throws java.io.IOException;
+    method public void removeTransportModeTransforms(java.io.FileDescriptor) throws java.io.IOException;
     field public static final int DIRECTION_IN = 0; // 0x0
     field public static final int DIRECTION_OUT = 1; // 0x1
   }
@@ -26281,7 +26295,9 @@
     method public android.net.ProxyInfo getHttpProxy();
     method public java.lang.String getInterfaceName();
     method public java.util.List<android.net.LinkAddress> getLinkAddresses();
+    method public java.lang.String getPrivateDnsServerName();
     method public java.util.List<android.net.RouteInfo> getRoutes();
+    method public boolean isPrivateDnsActive();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR;
   }
@@ -32209,6 +32225,7 @@
     field public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1; // 0xffffffff
     field public static final int THREAD_PRIORITY_URGENT_AUDIO = -19; // 0xffffffed
     field public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8; // 0xfffffff8
+    field public static final int THREAD_PRIORITY_VIDEO = -10; // 0xfffffff6
   }
 
   public abstract class ProxyFileDescriptorCallback {
@@ -42301,10 +42318,10 @@
   }
 
   public class MeasuredText implements android.text.Spanned {
-    method public static android.text.MeasuredText build(java.lang.CharSequence, android.text.TextPaint, android.text.TextDirectionHeuristic);
-    method public static android.text.MeasuredText build(java.lang.CharSequence, android.text.TextPaint, android.text.TextDirectionHeuristic, int, int);
     method public char charAt(int);
+    method public int getBreakStrategy();
     method public int getEnd();
+    method public int getHyphenationFrequency();
     method public android.text.TextPaint getPaint();
     method public int getParagraphCount();
     method public int getParagraphEnd(int);
@@ -42321,6 +42338,15 @@
     method public java.lang.CharSequence subSequence(int, int);
   }
 
+  public static final class MeasuredText.Builder {
+    ctor public MeasuredText.Builder(java.lang.CharSequence, android.text.TextPaint);
+    method public android.text.MeasuredText build();
+    method public android.text.MeasuredText.Builder setBreakStrategy(int);
+    method public android.text.MeasuredText.Builder setHyphenationFrequency(int);
+    method public android.text.MeasuredText.Builder setRange(int, int);
+    method public android.text.MeasuredText.Builder setTextDirection(android.text.TextDirectionHeuristic);
+  }
+
   public abstract interface NoCopySpan {
   }
 
@@ -44057,6 +44083,18 @@
     field public static final deprecated boolean RELEASE = true;
   }
 
+  public class DataUnit extends java.lang.Enum {
+    method public long toBytes(long);
+    method public static android.util.DataUnit valueOf(java.lang.String);
+    method public static final android.util.DataUnit[] values();
+    enum_constant public static final android.util.DataUnit GIBIBYTES;
+    enum_constant public static final android.util.DataUnit GIGABYTES;
+    enum_constant public static final android.util.DataUnit KIBIBYTES;
+    enum_constant public static final android.util.DataUnit KILOBYTES;
+    enum_constant public static final android.util.DataUnit MEBIBYTES;
+    enum_constant public static final android.util.DataUnit MEGABYTES;
+  }
+
   public class DebugUtils {
     method public static boolean isObjectSelected(java.lang.Object);
   }
@@ -47990,7 +48028,6 @@
     field public float buttonBrightness;
     field public float dimAmount;
     field public int flags;
-    field public long flags2;
     field public int format;
     field public int gravity;
     field public float horizontalMargin;
@@ -48178,6 +48215,7 @@
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
+    method public boolean isHeading();
     method public boolean isImportantForAccessibility();
     method public boolean isLongClickable();
     method public boolean isMultiLine();
@@ -48221,6 +48259,7 @@
     method public void setError(java.lang.CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setHeading(boolean);
     method public void setHintText(java.lang.CharSequence);
     method public void setImportantForAccessibility(boolean);
     method public void setInputType(int);
@@ -48354,7 +48393,7 @@
     method public int getColumnSpan();
     method public int getRowIndex();
     method public int getRowSpan();
-    method public boolean isHeading();
+    method public deprecated boolean isHeading();
     method public boolean isSelected();
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean);
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean);
@@ -52513,6 +52552,7 @@
     method public int getExtendedPaddingBottom();
     method public int getExtendedPaddingTop();
     method public android.text.InputFilter[] getFilters();
+    method public int getFirstBaselineToTopHeight();
     method public java.lang.String getFontFeatureSettings();
     method public java.lang.String getFontVariationSettings();
     method public boolean getFreezesText();
@@ -52530,6 +52570,7 @@
     method public int getInputType();
     method public int getJustificationMode();
     method public final android.text.method.KeyListener getKeyListener();
+    method public int getLastBaselineToBottomHeight();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
     method public int getLineBounds(int, android.graphics.Rect);
@@ -52577,6 +52618,7 @@
     method public android.graphics.Typeface getTypeface();
     method public android.text.style.URLSpan[] getUrls();
     method public boolean hasSelection();
+    method public boolean isAccessibilityHeading();
     method public boolean isAllCaps();
     method public boolean isCursorVisible();
     method public boolean isElegantTextHeight();
@@ -52599,6 +52641,7 @@
     method protected void onTextChanged(java.lang.CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
+    method public void setAccessibilityHeading(boolean);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int);
@@ -52626,6 +52669,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFallbackLineSpacing(boolean);
     method public void setFilters(android.text.InputFilter[]);
+    method public void setFirstBaselineToTopHeight(int);
     method public void setFontFeatureSettings(java.lang.String);
     method public boolean setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
@@ -52647,7 +52691,9 @@
     method public void setInputType(int);
     method public void setJustificationMode(int);
     method public void setKeyListener(android.text.method.KeyListener);
+    method public void setLastBaselineToBottomHeight(int);
     method public void setLetterSpacing(float);
+    method public void setLineHeight(int);
     method public void setLineSpacing(float, float);
     method public void setLines(int);
     method public final void setLinkTextColor(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 762b6e8..87cc6b5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -430,6 +430,7 @@
     method public java.lang.String getCurrentTransport();
     method public boolean isAppEligibleForBackup(java.lang.String);
     method public boolean isBackupEnabled();
+    method public boolean isBackupServiceActive(android.os.UserHandle);
     method public java.lang.String[] listAllTransports();
     method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver);
     method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int);
@@ -789,7 +790,9 @@
     field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
     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 java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
+    field public static final java.lang.String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.intent.action.SIM_APPLICATION_STATE_CHANGED";
+    field public static final java.lang.String ACTION_SIM_CARD_STATE_CHANGED = "android.intent.action.SIM_CARD_STATE_CHANGED";
+    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_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";
@@ -1117,9 +1120,9 @@
   }
 
   public static class BrightnessConfiguration.Builder {
-    ctor public BrightnessConfiguration.Builder();
+    ctor public BrightnessConfiguration.Builder(float[], float[]);
     method public android.hardware.display.BrightnessConfiguration build();
-    method public android.hardware.display.BrightnessConfiguration.Builder setCurve(float[], float[]);
+    method public android.hardware.display.BrightnessConfiguration.Builder setDescription(java.lang.String);
   }
 
   public final class DisplayManager {
@@ -3556,6 +3559,7 @@
     method public boolean isRestrictedProfile();
     field public static final java.lang.String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
     field public static final deprecated java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
+    field public static final java.lang.String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
     field public static final int RESTRICTION_NOT_SET = 0; // 0x0
     field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
     field public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 4; // 0x4
@@ -3854,6 +3858,28 @@
 
 }
 
+package android.service.autofill {
+
+  public abstract class AutofillFieldClassificationService extends android.app.Service {
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public java.util.List<java.lang.String> onGetAvailableAlgorithms();
+    method public java.lang.String onGetDefaultAlgorithm();
+    method public android.service.autofill.AutofillFieldClassificationService.Scores onGetScores(java.lang.String, android.os.Bundle, java.util.List<android.view.autofill.AutofillValue>, java.util.List<java.lang.String>);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
+  }
+
+  public static final class AutofillFieldClassificationService.Scores implements android.os.Parcelable {
+    ctor public AutofillFieldClassificationService.Scores(java.lang.String, int, int);
+    ctor public AutofillFieldClassificationService.Scores(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.String getAlgorithm();
+    method public float[][] getScores();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.AutofillFieldClassificationService.Scores> CREATOR;
+  }
+
+}
+
 package android.service.notification {
 
   public final class Adjustment implements android.os.Parcelable {
@@ -4436,6 +4462,8 @@
     method public deprecated boolean getDataEnabled();
     method public deprecated boolean getDataEnabled(int);
     method public boolean getEmergencyCallbackMode();
+    method public int getSimApplicationState();
+    method public int getSimCardState();
     method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method public android.os.Bundle getVisualVoicemailSettings();
     method public int getVoiceActivationState();
@@ -4469,6 +4497,7 @@
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
     field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
+    field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
     field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
@@ -4476,6 +4505,8 @@
     field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
     field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4
     field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0
+    field public static final int SIM_STATE_LOADED = 10; // 0xa
+    field public static final int SIM_STATE_PRESENT = 11; // 0xb
   }
 
   public abstract class VisualVoicemailService extends android.app.Service {
@@ -4535,6 +4566,38 @@
     field public static final int TYPE_COMMON = 0; // 0x0
   }
 
+  public abstract class DataService extends android.app.Service {
+    method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
+    field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
+    field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
+  }
+
+  public class DataService.DataServiceProvider {
+    ctor public DataService.DataServiceProvider(int);
+    method public void deactivateDataCall(int, boolean, boolean, android.telephony.data.DataServiceCallback);
+    method public void getDataCallList(android.telephony.data.DataServiceCallback);
+    method public final int getSlotId();
+    method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
+    method protected void onDestroy();
+    method public void setDataProfile(java.util.List<android.telephony.data.DataProfile>, boolean, android.telephony.data.DataServiceCallback);
+    method public void setInitialAttachApn(android.telephony.data.DataProfile, boolean, android.telephony.data.DataServiceCallback);
+    method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, boolean, android.net.LinkProperties, android.telephony.data.DataServiceCallback);
+  }
+
+  public class DataServiceCallback {
+    method public void onDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
+    method public void onDeactivateDataCallComplete(int);
+    method public void onGetDataCallListComplete(int, java.util.List<android.telephony.data.DataCallResponse>);
+    method public void onSetDataProfileComplete(int);
+    method public void onSetInitialAttachApnComplete(int);
+    method public void onSetupDataCallComplete(int, android.telephony.data.DataCallResponse);
+    field public static final int RESULT_ERROR_BUSY = 3; // 0x3
+    field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
+    field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2
+    field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1
+    field public static final int RESULT_SUCCESS = 0; // 0x0
+  }
+
 }
 
 package android.telephony.ims {
diff --git a/api/test-current.txt b/api/test-current.txt
index 6941731..acc819e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -320,9 +320,9 @@
   }
 
   public static class BrightnessConfiguration.Builder {
-    ctor public BrightnessConfiguration.Builder();
+    ctor public BrightnessConfiguration.Builder(float[], float[]);
     method public android.hardware.display.BrightnessConfiguration build();
-    method public android.hardware.display.BrightnessConfiguration.Builder setCurve(float[], float[]);
+    method public android.hardware.display.BrightnessConfiguration.Builder setDescription(java.lang.String);
   }
 
   public final class DisplayManager {
@@ -563,11 +563,6 @@
     method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
   }
 
-  public final class EditDistanceScorer {
-    method public static android.service.autofill.EditDistanceScorer getInstance();
-    method public float getScore(android.view.autofill.AutofillValue, java.lang.String);
-  }
-
   public final class FillResponse implements android.os.Parcelable {
     method public int getFlags();
   }
@@ -966,6 +961,9 @@
 
   public final class Choreographer {
     method public static long getFrameDelay();
+    method public void postCallback(int, java.lang.Runnable, java.lang.Object);
+    method public void postCallbackDelayed(int, java.lang.Runnable, java.lang.Object, long);
+    method public void removeCallbacks(int, java.lang.Runnable, java.lang.Object);
     method public static void setFrameDelay(long);
     field public static final int CALLBACK_ANIMATION = 1; // 0x1
   }
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 2c35d41..5eff548 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -36,7 +36,7 @@
     src/config/ConfigManager.cpp \
     src/external/StatsPuller.cpp \
     src/external/StatsCompanionServicePuller.cpp \
-    src/external/ResourcePowerManagerPuller.cpp \
+    src/external/SubsystemSleepStatePuller.cpp \
     src/external/CpuTimePerUidPuller.cpp \
     src/external/CpuTimePerUidFreqPuller.cpp \
     src/external/StatsPullerManagerImpl.cpp \
@@ -134,7 +134,7 @@
 
 LOCAL_MODULE_CLASS := EXECUTABLES
 
-LOCAL_INIT_RC := statsd.rc
+#LOCAL_INIT_RC := statsd.rc
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 0ed1c1f..ca097d0 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -185,6 +185,7 @@
  */
 void StatsService::dump_impl(FILE* out) {
     mConfigManager->Dump(out);
+    StatsdStats::getInstance().dumpStats(out);
 }
 
 /**
@@ -296,9 +297,8 @@
     fprintf(out, "  NAME          The name of the configuration\n");
     fprintf(out, "\n");
     fprintf(out, "\n");
-    fprintf(out, "usage: adb shell cmd stats print-stats [reset]\n");
+    fprintf(out, "usage: adb shell cmd stats print-stats\n");
     fprintf(out, "  Prints some basic stats.\n");
-    fprintf(out, "  reset: 1 to reset the statsd stats. default=0.\n");
 }
 
 status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
@@ -487,14 +487,8 @@
         fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
                 mProcessor->GetMetricsSize(key));
     }
-    fprintf(out, "Detailed statsd stats in logcat...\n");
     StatsdStats& statsdStats = StatsdStats::getInstance();
-    bool reset = false;
-    if (args.size() > 1) {
-        reset = strtol(args[1].string(), NULL, 10);
-    }
-    vector<uint8_t> output;
-    statsdStats.dumpStats(&output, reset);
+    statsdStats.dumpStats(out);
     return NO_ERROR;
 }
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4a7f0c4..7d513cd 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -94,9 +94,8 @@
         MobileBytesTransfer mobile_bytes_transfer = 10002;
         MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 10003;
         KernelWakelock kernel_wakelock = 10004;
-        PlatformSleepState platform_sleep_state = 10005;
-        SleepStateVoter sleep_state_voter = 10006;
-        SubsystemSleepState subsystem_sleep_state = 10007;
+        SubsystemSleepState subsystem_sleep_state = 10005;
+        // 10006 and 10007 are free to use.
         CpuTimePerFreq cpu_time_per_freq = 10008;
         CpuTimePerUid cpu_time_per_uid = 10009;
         CpuTimePerUidFreq cpu_time_per_uid_freq = 10010;
@@ -1027,44 +1026,21 @@
 }
 
 /**
- * Pulls PowerStatePlatformSleepState.
- *
- * Definition here:
+ * Pulls low power state information. This includes platform and subsystem sleep state information,
+ * PowerStatePlatformSleepState, PowerStateVoter or PowerStateSubsystemSleepState as defined in
  *   hardware/interfaces/power/1.0/types.hal
- */
-message PlatformSleepState {
-    optional string name = 1;
-    optional uint64 residency_in_msec_since_boot = 2;
-    optional uint64 total_transitions = 3;
-    optional bool supported_only_in_suspend = 4;
-}
-
-/**
- * Pulls PowerStateVoter.
- *
- * Definition here:
- *   hardware/interfaces/power/1.0/types.hal
- */
-message SleepStateVoter {
-    optional string platform_sleep_state_name = 1;
-    optional string voter_name = 2;
-    optional uint64 total_time_in_msec_voted_for_since_boot = 3;
-    optional uint64 total_number_of_times_voted_since_boot = 4;
-}
-
-/**
- * Pulls PowerStateSubsystemSleepState.
- *
- * Definition here:
  *   hardware/interfaces/power/1.1/types.hal
  */
 message SubsystemSleepState {
-    optional string subsystem_name = 1;
-    optional string subsystem_sleep_state_name = 2;
-    optional uint64 residency_in_msec_since_boot = 3;
-    optional uint64 total_transitions = 4;
-    optional uint64 last_entry_timestamp_ms = 5;
-    optional bool supported_only_in_suspend = 6;
+    // 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;
+    // The number of times it entered, or voted for entering the sleep state
+    optional uint64 count = 2;
+    // The length of time spent in, or spent voting for, the sleep state
+    optional uint64 timeMs = 3;
 }
 
 /**
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 2525721..7a1bb0c 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -19,6 +19,7 @@
 
 #include "SimpleConditionTracker.h"
 #include "guardrail/StatsdStats.h"
+#include "dimension.h"
 
 #include <log/logprint.h>
 
@@ -171,12 +172,12 @@
         // We get a new output key.
         newCondition = matchStart ? ConditionState::kTrue : ConditionState::kFalse;
         if (matchStart && mInitialValue != ConditionState::kTrue) {
-            mSlicedConditionState[outputKey] = 1;
+            mSlicedConditionState.insert(std::make_pair(outputKey, 1));
             changed = true;
         } else if (mInitialValue != ConditionState::kFalse) {
             // it's a stop and we don't have history about it.
             // If the default condition is not false, it means this stop is valuable to us.
-            mSlicedConditionState[outputKey] = 0;
+            mSlicedConditionState.insert(std::make_pair(outputKey, 0));
             changed = true;
         }
     } else {
@@ -341,7 +342,23 @@
             conditionState = conditionState |
                     (startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse);
         } else {
-            conditionState = conditionState | mInitialValue;
+            // For unseen key, check whether the require dimensions are subset of sliced condition
+            // output.
+            bool seenDimension = false;
+            for (const auto& slice : mSlicedConditionState) {
+                if (IsSubDimension(slice.first.getDimensionsValue(),
+                                   key.getDimensionsValue())) {
+                    seenDimension = true;
+                    conditionState = conditionState |
+                        (slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse);
+                }
+                if (conditionState == ConditionState::kTrue) {
+                    break;
+                }
+            }
+            if (!seenDimension) {
+                conditionState = conditionState | mInitialValue;
+            }
         }
     }
     conditionCache[mIndex] = conditionState;
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index 554ff8a8..1481921 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -255,7 +255,7 @@
     metric->set_id(2);  // "METRIC_2"
     metric->set_what(104);
     metric->set_bucket(ONE_MINUTE);
-    FieldMatcher* dimensions = metric->mutable_dimensions();
+    FieldMatcher* dimensions = metric->mutable_dimensions_in_what();
     dimensions->set_field(UID_PROCESS_STATE_TAG_ID);
     dimensions->add_child()->set_field(UID_PROCESS_STATE_UID_KEY);
 
@@ -278,7 +278,7 @@
     metric->set_what(104);
     metric->set_bucket(ONE_MINUTE);
 
-    dimensions = metric->mutable_dimensions();
+    dimensions = metric->mutable_dimensions_in_what();
     dimensions->set_field(UID_PROCESS_STATE_TAG_ID);
     dimensions->add_child()->set_field(UID_PROCESS_STATE_UID_KEY);
     metric->set_condition(202);
@@ -288,7 +288,7 @@
     metric->set_id(4);
     metric->set_what(107);
     metric->set_bucket(ONE_MINUTE);
-    dimensions = metric->mutable_dimensions();
+    dimensions = metric->mutable_dimensions_in_what();
     dimensions->set_field(WAKE_LOCK_TAG_ID);
     dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
 
@@ -306,7 +306,7 @@
     durationMetric->set_id(5);
     durationMetric->set_bucket(ONE_MINUTE);
     durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-    dimensions = durationMetric->mutable_dimensions();
+    dimensions = durationMetric->mutable_dimensions_in_what();
     dimensions->set_field(WAKE_LOCK_TAG_ID);
     dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
     durationMetric->set_what(205);
@@ -323,7 +323,7 @@
     durationMetric->set_id(6);
     durationMetric->set_bucket(ONE_MINUTE);
     durationMetric->set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
-    dimensions = durationMetric->mutable_dimensions();
+    dimensions = durationMetric->mutable_dimensions_in_what();
     dimensions->set_field(WAKE_LOCK_TAG_ID);
     dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
     durationMetric->set_what(205);
@@ -376,7 +376,7 @@
     valueMetric->mutable_value_field()->set_field(KERNEL_WAKELOCK_TAG_ID);
     valueMetric->mutable_value_field()->add_child()->set_field(KERNEL_WAKELOCK_COUNT_KEY);
     valueMetric->set_condition(201);
-    dimensions = valueMetric->mutable_dimensions();
+    dimensions = valueMetric->mutable_dimensions_in_what();
     dimensions->set_field(KERNEL_WAKELOCK_TAG_ID);
     dimensions->add_child()->set_field(KERNEL_WAKELOCK_NAME_KEY);
     // This is for testing easier. We should never set bucket size this small.
diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp
index 09499b6..bb7a044 100644
--- a/cmds/statsd/src/dimension.cpp
+++ b/cmds/statsd/src/dimension.cpp
@@ -331,13 +331,15 @@
         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()) {
+            if (dimension.value_tuple().dimensions_value_size() <
+                sub.value_tuple().dimensions_value_size()) {
                 return false;
             }
             bool allSub = true;
-            for (int i = 0; i < sub.value_tuple().dimensions_value_size(); ++i) {
+            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) {
+                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));
                 }
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index 58c7b12..bb2e8c0 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -23,7 +23,7 @@
 #include <climits>
 #include "CpuTimePerUidFreqPuller.h"
 #include "CpuTimePerUidPuller.h"
-#include "ResourcePowerManagerPuller.h"
+#include "SubsystemSleepStatePuller.h"
 #include "StatsCompanionServicePuller.h"
 #include "StatsPullerManagerImpl.h"
 #include "StatsService.h"
@@ -58,13 +58,9 @@
     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::PLATFORM_SLEEP_STATE,
-                     make_shared<ResourcePowerManagerPuller>(android::util::PLATFORM_SLEEP_STATE)});
-    mPullers.insert({android::util::SLEEP_STATE_VOTER,
-                     make_shared<ResourcePowerManagerPuller>(android::util::SLEEP_STATE_VOTER)});
     mPullers.insert(
             {android::util::SUBSYSTEM_SLEEP_STATE,
-             make_shared<ResourcePowerManagerPuller>(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>()});
diff --git a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp
similarity index 85%
rename from cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
rename to cmds/statsd/src/external/SubsystemSleepStatePuller.cpp
index 2e29fb0..6d12e25 100644
--- a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
+++ b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp
@@ -30,10 +30,10 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include "external/ResourcePowerManagerPuller.h"
+#include "external/SubsystemSleepStatePuller.h"
 #include "external/StatsPuller.h"
 
-#include "ResourcePowerManagerPuller.h"
+#include "SubsystemSleepStatePuller.h"
 #include "logd/LogEvent.h"
 #include "statslog.h"
 
@@ -73,10 +73,10 @@
     return gPowerHalV1_0 != nullptr;
 }
 
-ResourcePowerManagerPuller::ResourcePowerManagerPuller(int tagId) : StatsPuller(tagId) {
+SubsystemSleepStatePuller::SubsystemSleepStatePuller() : StatsPuller(android::util::SUBSYSTEM_SLEEP_STATE) {
 }
 
-bool ResourcePowerManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+bool SubsystemSleepStatePuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
     std::lock_guard<std::mutex> lock(gPowerHalMutex);
 
     if (!getPowerHal()) {
@@ -89,8 +89,6 @@
     data->clear();
 
     Return<void> ret;
-    if (mTagId == android::util::PLATFORM_SLEEP_STATE ||
-        mTagId == android::util::SLEEP_STATE_VOTER) {
         ret = gPowerHalV1_0->getPlatformLowPowerStats(
                 [&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
                     if (status != Status::SUCCESS) return;
@@ -98,12 +96,11 @@
                     for (size_t i = 0; i < states.size(); i++) {
                         const PowerStatePlatformSleepState& state = states[i];
 
-                        auto statePtr = make_shared<LogEvent>(android::util::PLATFORM_SLEEP_STATE,
+                        auto statePtr = make_shared<LogEvent>(android::util::SUBSYSTEM_SLEEP_STATE,
                                                               timestamp);
                         statePtr->write(state.name);
-                        statePtr->write(state.residencyInMsecSinceBoot);
                         statePtr->write(state.totalTransitions);
-                        statePtr->write(state.supportedOnlyInSuspend);
+                        statePtr->write(state.residencyInMsecSinceBoot);
                         statePtr->init();
                         data->push_back(statePtr);
                         VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
@@ -111,12 +108,11 @@
                              (long long)state.totalTransitions,
                              state.supportedOnlyInSuspend ? 1 : 0);
                         for (auto voter : state.voters) {
-                            auto voterPtr = make_shared<LogEvent>(android::util::SLEEP_STATE_VOTER,
+                            auto voterPtr = make_shared<LogEvent>(android::util::SUBSYSTEM_SLEEP_STATE,
                                                                   timestamp);
-                            voterPtr->write(state.name);
-                            voterPtr->write(voter.name);
-                            voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
+                            voterPtr->write((std::string)state.name + "." + (std::string)voter.name);
                             voterPtr->write(voter.totalNumberOfTimesVotedSinceBoot);
+                            voterPtr->write(voter.totalTimeInMsecVotedForSinceBoot);
                             voterPtr->init();
                             data->push_back(voterPtr);
                             VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
@@ -131,9 +127,7 @@
             gPowerHalV1_0 = nullptr;
             return false;
         }
-    }
 
-    if (mTagId == android::util::SUBSYSTEM_SLEEP_STATE) {
         // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
         sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
                 android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
@@ -149,13 +143,10 @@
                                     const PowerStateSubsystemSleepState& state =
                                             subsystem.states[j];
                                     auto subsystemStatePtr = make_shared<LogEvent>(
-                                            android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
-                                    subsystemStatePtr->write(subsystem.name);
-                                    subsystemStatePtr->write(state.name);
-                                    subsystemStatePtr->write(state.residencyInMsecSinceBoot);
+                                        android::util::SUBSYSTEM_SLEEP_STATE, timestamp);
+                                    subsystemStatePtr->write((std::string)subsystem.name + "." + (std::string)state.name);
                                     subsystemStatePtr->write(state.totalTransitions);
-                                    subsystemStatePtr->write(state.lastEntryTimestampMs);
-                                    subsystemStatePtr->write(state.supportedOnlyInSuspend);
+                                    subsystemStatePtr->write(state.residencyInMsecSinceBoot);
                                     subsystemStatePtr->init();
                                     data->push_back(subsystemStatePtr);
                                     VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
@@ -168,7 +159,6 @@
                         }
                     });
         }
-    }
     return true;
 }
 
diff --git a/cmds/statsd/src/external/ResourcePowerManagerPuller.h b/cmds/statsd/src/external/SubsystemSleepStatePuller.h
similarity index 90%
rename from cmds/statsd/src/external/ResourcePowerManagerPuller.h
rename to cmds/statsd/src/external/SubsystemSleepStatePuller.h
index 3399408..17ce5b4cb 100644
--- a/cmds/statsd/src/external/ResourcePowerManagerPuller.h
+++ b/cmds/statsd/src/external/SubsystemSleepStatePuller.h
@@ -26,9 +26,9 @@
 /**
  * Reads hal for sleep states
  */
-class ResourcePowerManagerPuller : public StatsPuller {
+class SubsystemSleepStatePuller : public StatsPuller {
 public:
-    ResourcePowerManagerPuller(int tagId);
+    SubsystemSleepStatePuller();
     bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
 };
 
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 36dd616..63bde7d 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -66,8 +66,6 @@
         {android::util::MOBILE_BYTES_TRANSFER, 1},
         {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, 1},
         {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, 1},
-        {android::util::PLATFORM_SLEEP_STATE, 1},
-        {android::util::SLEEP_STATE_VOTER, 1},
         {android::util::SUBSYSTEM_SLEEP_STATE, 1},
         {android::util::CPU_TIME_PER_FREQ, 1},
         {android::util::CPU_TIME_PER_UID, 1},
@@ -357,73 +355,135 @@
     }
 }
 
+void StatsdStats::dumpStats(FILE* out) const {
+    lock_guard<std::mutex> lock(mLock);
+    time_t t = mStartTimeSec;
+    struct tm* tm = localtime(&t);
+    char timeBuffer[80];
+    strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
+    fprintf(out, "Stats collection start second: %s\n", timeBuffer);
+    fprintf(out, "%lu Config in icebox: \n", (unsigned long)mIceBox.size());
+    for (const auto& configStats : mIceBox) {
+        fprintf(out,
+                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
+                "#matcher=%d, #alert=%d,  valid=%d\n",
+                configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
+                configStats.deletion_time_sec(), configStats.metric_count(),
+                configStats.condition_count(), configStats.matcher_count(),
+                configStats.alert_count(), configStats.is_valid());
+
+        for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
+            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
+        }
+
+        for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
+            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
+        }
+    }
+    fprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size());
+    for (auto& pair : mConfigStats) {
+        auto& key = pair.first;
+        auto& configStats = pair.second;
+
+        fprintf(out,
+                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
+                "#matcher=%d, #alert=%d,  valid=%d\n",
+                configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
+                configStats.deletion_time_sec(), configStats.metric_count(),
+                configStats.condition_count(), configStats.matcher_count(),
+                configStats.alert_count(), configStats.is_valid());
+        for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
+            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
+        }
+
+        for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
+            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
+        }
+
+        for (const auto& dumpTime : configStats.dump_report_time_sec()) {
+            fprintf(out, "\tdump report time: %d\n", dumpTime);
+        }
+
+        // Add matcher stats
+        auto matcherIt = mMatcherStats.find(key);
+        if (matcherIt != mMatcherStats.end()) {
+            const auto& matcherStats = matcherIt->second;
+            for (const auto& stats : matcherStats) {
+                fprintf(out, "matcher %lld matched %d times\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+        // Add condition stats
+        auto conditionIt = mConditionStats.find(key);
+        if (conditionIt != mConditionStats.end()) {
+            const auto& conditionStats = conditionIt->second;
+            for (const auto& stats : conditionStats) {
+                fprintf(out, "condition %lld max output tuple size %d\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+        // Add metrics stats
+        auto metricIt = mMetricsStats.find(key);
+        if (metricIt != mMetricsStats.end()) {
+            const auto& conditionStats = metricIt->second;
+            for (const auto& stats : conditionStats) {
+                fprintf(out, "metrics %lld max output tuple size %d\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+        // Add anomaly detection alert stats
+        auto alertIt = mAlertStats.find(key);
+        if (alertIt != mAlertStats.end()) {
+            const auto& alertStats = alertIt->second;
+            for (const auto& stats : alertStats) {
+                fprintf(out, "alert %lld declared %d times\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+    }
+    fprintf(out, "********Pushed Atom stats***********\n");
+    const size_t atomCounts = mPushedAtomStats.size();
+    for (size_t i = 2; i < atomCounts; i++) {
+        if (mPushedAtomStats[i] > 0) {
+            fprintf(out, "Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
+        }
+    }
+
+    fprintf(out, "********Pulled Atom stats***********\n");
+    for (const auto& pair : mPulledAtomStats) {
+        fprintf(out, "Atom %d->%ld, %ld, %ld\n", (int)pair.first, (long)pair.second.totalPull,
+             (long)pair.second.totalPullFromCache, (long)pair.second.minPullIntervalSec);
+    }
+
+    if (mAnomalyAlarmRegisteredStats > 0) {
+        fprintf(out, "********AnomalyAlarmStats stats***********\n");
+        fprintf(out, "Anomaly alarm registrations: %d\n", mAnomalyAlarmRegisteredStats);
+    }
+
+    fprintf(out,
+            "UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
+            "lost=%d\n",
+            mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
+            mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
+}
+
 void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
     lock_guard<std::mutex> lock(mLock);
 
-    if (DEBUG) {
-        time_t t = mStartTimeSec;
-        struct tm* tm = localtime(&t);
-        char timeBuffer[80];
-        strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p", tm);
-        VLOG("=================StatsdStats dump begins====================");
-        VLOG("Stats collection start second: %s", timeBuffer);
-    }
     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));
 
-    VLOG("%lu Config in icebox: ", (unsigned long)mIceBox.size());
     for (const auto& configStats : mIceBox) {
         const int numBytes = configStats.ByteSize();
         vector<char> buffer(numBytes);
         configStats.SerializeToArray(&buffer[0], numBytes);
         proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CONFIG_STATS, &buffer[0],
                     buffer.size());
-
-        // surround the whole block with DEBUG, so that compiler can strip out the code
-        // in production.
-        if (DEBUG) {
-            VLOG("*****ICEBOX*****");
-            VLOG("Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
-                 "#matcher=%d, #alert=%d,  #valid=%d",
-                 configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
-                 configStats.deletion_time_sec(), configStats.metric_count(),
-                 configStats.condition_count(), configStats.matcher_count(),
-                 configStats.alert_count(), configStats.is_valid());
-
-            for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
-                VLOG("\tbroadcast time: %d", broadcastTime);
-            }
-
-            for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
-                VLOG("\tdata drop time: %d", dataDropTime);
-            }
-        }
     }
 
     for (auto& pair : mConfigStats) {
         auto& configStats = pair.second;
-        if (DEBUG) {
-            VLOG("********Active Configs***********");
-            VLOG("Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
-                 "#matcher=%d, #alert=%d,  #valid=%d",
-                 configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
-                 configStats.deletion_time_sec(), configStats.metric_count(),
-                 configStats.condition_count(), configStats.matcher_count(),
-                 configStats.alert_count(), configStats.is_valid());
-            for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
-                VLOG("\tbroadcast time: %d", broadcastTime);
-            }
-
-            for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
-                VLOG("\tdata drop time: %d", dataDropTime);
-            }
-
-            for (const auto& dumpTime : configStats.dump_report_time_sec()) {
-                VLOG("\tdump report time: %d", dumpTime);
-            }
-        }
-
         addSubStatsToConfigLocked(pair.first, configStats);
 
         const int numBytes = configStats.ByteSize();
@@ -439,7 +499,6 @@
         configStats.clear_alert_stats();
     }
 
-    VLOG("********Pushed Atom stats***********");
     const size_t atomCounts = mPushedAtomStats.size();
     for (size_t i = 2; i < atomCounts; i++) {
         if (mPushedAtomStats[i] > 0) {
@@ -448,34 +507,24 @@
             proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, (int32_t)i);
             proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, mPushedAtomStats[i]);
             proto.end(token);
-
-            VLOG("Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
         }
     }
 
-    VLOG("********Pulled Atom stats***********");
     for (const auto& pair : mPulledAtomStats) {
         android::os::statsd::writePullerStatsToStream(pair, &proto);
-        VLOG("Atom %d->%ld, %ld, %ld\n", (int) pair.first, (long) pair.second.totalPull, (long) pair.second.totalPullFromCache, (long) pair.second.minPullIntervalSec);
     }
 
     if (mAnomalyAlarmRegisteredStats > 0) {
-        VLOG("********AnomalyAlarmStats stats***********");
         long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
         proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
                     mAnomalyAlarmRegisteredStats);
         proto.end(token);
-        VLOG("Anomaly alarm registrations: %d", mAnomalyAlarmRegisteredStats);
     }
 
     const int numBytes = mUidMapStats.ByteSize();
     vector<char> buffer(numBytes);
     mUidMapStats.SerializeToArray(&buffer[0], numBytes);
     proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS, &buffer[0], buffer.size());
-    VLOG("UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
-         "lost=%d",
-         mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
-         mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
 
     output->clear();
     size_t bufferSize = proto.size();
@@ -495,7 +544,6 @@
     }
 
     VLOG("reset=%d, returned proto size %lu", reset, (unsigned long)bufferSize);
-    VLOG("=================StatsdStats dump ends====================");
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 52ab253..9178daa4 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -189,6 +189,11 @@
      */
     void dumpStats(std::vector<uint8_t>* buffer, bool reset);
 
+    /**
+     * Output statsd stats in human readable format to [out] file.
+     */
+    void dumpStats(FILE* out) const;
+
     typedef struct {
         long totalPull;
         long totalPullFromCache;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 3e98098..ef27210 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -50,8 +50,9 @@
 // for CountMetricDataWrapper
 const int FIELD_ID_DATA = 1;
 // for CountMetricData
-const int FIELD_ID_DIMENSION = 1;
-const int FIELD_ID_BUCKET_INFO = 2;
+const int FIELD_ID_DIMENSION_IN_WHAT = 1;
+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;
@@ -70,7 +71,7 @@
     }
 
     // TODO: use UidMap if uid->pkg_name is required
-    mDimensions = metric.dimensions();
+    mDimensions = metric.dimensions_in_what();
 
     if (metric.links().size() > 0) {
         mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
@@ -98,7 +99,7 @@
     auto count_metrics = report->mutable_count_metrics();
     for (const auto& counter : mPastBuckets) {
         CountMetricData* metricData = count_metrics->add_data();
-        *metricData->mutable_dimension() = counter.first.getDimensionsValue();
+        *metricData->mutable_dimensions_in_what() = counter.first.getDimensionsValue();
         for (const auto& bucket : counter.second) {
             CountBucketInfo* bucketInfo = metricData->add_bucket_info();
             bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
@@ -127,7 +128,7 @@
 
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
-                FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
+                FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
         writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput);
         protoOutput->end(dimensionToken);
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index b546297..58dd464 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -49,8 +49,9 @@
 // for DurationMetricDataWrapper
 const int FIELD_ID_DATA = 1;
 // for DurationMetricData
-const int FIELD_ID_DIMENSION = 1;
-const int FIELD_ID_BUCKET_INFO = 2;
+const int FIELD_ID_DIMENSION_IN_WHAT = 1;
+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;
@@ -80,7 +81,7 @@
     }
 
     // TODO: use UidMap if uid->pkg_name is required
-    mDimensions = metric.dimensions();
+    mDimensions = metric.dimensions_in_what();
 
     if (metric.links().size() > 0) {
         mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
@@ -154,7 +155,7 @@
     auto duration_metrics = report->mutable_duration_metrics();
     for (const auto& pair : mPastBuckets) {
         DurationMetricData* metricData = duration_metrics->add_data();
-        *metricData->mutable_dimension() = pair.first.getDimensionsValue();
+        *metricData->mutable_dimensions_in_what() = pair.first.getDimensionsValue();
         for (const auto& bucket : pair.second) {
             auto bucketInfo = metricData->add_bucket_info();
             bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
@@ -183,7 +184,7 @@
 
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
-                FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
+                FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
         writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput);
         protoOutput->end(dimensionToken);
 
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index ae47bd8..17305e3 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -51,8 +51,9 @@
 // for GaugeMetricDataWrapper
 const int FIELD_ID_DATA = 1;
 // for GaugeMetricData
-const int FIELD_ID_DIMENSION = 1;
-const int FIELD_ID_BUCKET_INFO = 2;
+const int FIELD_ID_DIMENSION_IN_WHAT = 1;
+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;
@@ -79,7 +80,7 @@
     mFieldFilter = metric.gauge_fields_filter();
 
     // TODO: use UidMap if uid->pkg_name is required
-    mDimensions = metric.dimensions();
+    mDimensions = metric.dimensions_in_what();
 
     if (metric.links().size() > 0) {
         mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
@@ -138,7 +139,7 @@
 
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
-                FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
+                FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
         writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput);
         protoOutput->end(dimensionToken);
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 74bd6f9..c7550f7 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -54,8 +54,9 @@
 // for ValueMetricDataWrapper
 const int FIELD_ID_DATA = 1;
 // for ValueMetricData
-const int FIELD_ID_DIMENSION = 1;
-const int FIELD_ID_BUCKET_INFO = 2;
+const int FIELD_ID_DIMENSION_IN_WHAT = 1;
+const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
+const int FIELD_ID_BUCKET_INFO = 3;
 // for ValueBucketInfo
 const int FIELD_ID_START_BUCKET_NANOS = 1;
 const int FIELD_ID_END_BUCKET_NANOS = 2;
@@ -80,7 +81,7 @@
     }
 
     mBucketSizeNs = bucketSizeMills * 1000000;
-    mDimensions = metric.dimensions();
+    mDimensions = metric.dimensions_in_what();
 
     if (metric.links().size() > 0) {
         mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
@@ -123,7 +124,7 @@
     auto value_metrics = report->mutable_value_metrics();
     for (const auto& pair : mPastBuckets) {
         ValueMetricData* metricData = value_metrics->add_data();
-        *metricData->mutable_dimension() = pair.first.getDimensionsValue();
+        *metricData->mutable_dimensions_in_what() = pair.first.getDimensionsValue();
         for (const auto& bucket : pair.second) {
             ValueBucketInfo* bucketInfo = metricData->add_bucket_info();
             bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
@@ -149,7 +150,7 @@
 
         // First fill dimension.
         long long dimensionToken = protoOutput->start(
-                FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
+            FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
         writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput);
         protoOutput->end(dimensionToken);
 
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index bc887ac..a0173ee 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -227,7 +227,8 @@
         int metricIndex = allMetricProducers.size();
         metricMap.insert({metric.id(), metricIndex});
         int trackerIndex;
-        if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.has_dimensions(),
+        if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
+                                         metric.has_dimensions_in_what(),
                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
                                          trackerIndex)) {
             return false;
@@ -279,7 +280,7 @@
         int trackerIndices[3] = {-1, -1, -1};
         if (!simplePredicate.has_start() ||
             !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex,
-                                         metric.has_dimensions(), allAtomMatchers,
+                                         metric.has_dimensions_in_what(), allAtomMatchers,
                                          logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
             ALOGE("Duration metrics must specify a valid the start event matcher");
             return false;
@@ -287,14 +288,14 @@
 
         if (simplePredicate.has_stop() &&
             !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex,
-                                         metric.has_dimensions(), allAtomMatchers,
+                                         metric.has_dimensions_in_what(), allAtomMatchers,
                                          logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
             return false;
         }
 
         if (simplePredicate.has_stop_all() &&
             !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex,
-                                         metric.has_dimensions(), allAtomMatchers,
+                                         metric.has_dimensions_in_what(), allAtomMatchers,
                                          logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
             return false;
         }
@@ -371,7 +372,8 @@
         int metricIndex = allMetricProducers.size();
         metricMap.insert({metric.id(), metricIndex});
         int trackerIndex;
-        if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.has_dimensions(),
+        if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
+                                         metric.has_dimensions_in_what(),
                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
                                          trackerIndex)) {
             return false;
@@ -429,7 +431,8 @@
         int metricIndex = allMetricProducers.size();
         metricMap.insert({metric.id(), metricIndex});
         int trackerIndex;
-        if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.has_dimensions(),
+        if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
+                                         metric.has_dimensions_in_what(),
                                          allAtomMatchers, logTrackerMap, trackerToMetricMap,
                                          trackerIndex)) {
             return false;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index b0c3197..eefb7dc 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -106,9 +106,9 @@
             t->set_uid(uid[j]);
         }
         mBytesUsed += snapshot->ByteSize();
+        ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
         StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
-        ensureBytesUsedBelowLimit();
         getListenerListCopyLocked(&broadcastList);
     }
     // To avoid invoking callback while holding the internal lock. we get a copy of the listener
@@ -142,9 +142,9 @@
         log->set_uid(uid);
         log->set_version(versionCode);
         mBytesUsed += log->ByteSize();
+        ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
         StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
-        ensureBytesUsedBelowLimit();
 
         auto range = mMap.equal_range(int(uid));
         bool found = false;
@@ -222,9 +222,9 @@
         log->set_app(app);
         log->set_uid(uid);
         mBytesUsed += log->ByteSize();
+        ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
         StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
-        ensureBytesUsedBelowLimit();
 
         auto range = mMap.equal_range(int(uid));
         for (auto it = range.first; it != range.second; ++it) {
@@ -471,10 +471,13 @@
                                                              {"AID_AUTOMOTIVE_EVS", 1062},
                                                              {"AID_LOWPAN", 1063},
                                                              {"AID_HSM", 1064},
+                                                             {"AID_RESERVED_DISK", 1065},
+                                                             {"AID_STATSD", 1066},
+                                                             {"AID_INCIDENTD", 1067},
                                                              {"AID_SHELL", 2000},
                                                              {"AID_CACHE", 2001},
                                                              {"AID_DIAG", 2002}};
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 4e37977..3304f6c 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -152,9 +152,9 @@
     // until the memory consumed by mOutput is below the specified limit.
     void ensureBytesUsedBelowLimit();
 
-    // Override used for testing the max memory allowed by uid map. -1 means we use the value
+    // Override used for testing the max memory allowed by uid map. 0 means we use the value
     // specified in StatsdStats.h with the rest of the guardrails.
-    size_t maxBytesOverride = -1;
+    size_t maxBytesOverride = 0;
 
     // Cache the size of mOutput;
     size_t mBytesUsed;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 2596a5f..bb2193f 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -56,9 +56,11 @@
 }
 
 message CountMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
 
-  repeated CountBucketInfo bucket_info = 2;
+  optional DimensionsValue dimensions_in_condition = 2;
+
+  repeated CountBucketInfo bucket_info = 3;
 }
 
 message DurationBucketInfo {
@@ -70,9 +72,11 @@
 }
 
 message DurationMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
 
-  repeated DurationBucketInfo bucket_info = 2;
+  optional DimensionsValue dimensions_in_condition = 2;
+
+  repeated DurationBucketInfo bucket_info = 3;
 }
 
 message ValueBucketInfo {
@@ -84,9 +88,11 @@
 }
 
 message ValueMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
 
-  repeated ValueBucketInfo bucket_info = 2;
+  optional DimensionsValue dimensions_in_condition = 2;
+
+  repeated ValueBucketInfo bucket_info = 3;
 }
 
 message GaugeBucketInfo {
@@ -98,9 +104,11 @@
 }
 
 message GaugeMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
 
-  repeated GaugeBucketInfo bucket_info = 2;
+  optional DimensionsValue dimensions_in_condition = 2;
+
+  repeated GaugeBucketInfo bucket_info = 3;
 }
 
 message UidMapping {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index d45a6b0..afb0bc4 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -178,7 +178,9 @@
 
     optional int64 condition = 3;
 
-    optional FieldMatcher dimensions = 4;
+    optional FieldMatcher dimensions_in_what = 4;
+
+    optional FieldMatcher dimensions_in_condition = 7;
 
     optional TimeUnit bucket = 5;
 
@@ -201,7 +203,9 @@
     }
     optional AggregationType aggregation_type = 5 [default = SUM];
 
-    optional FieldMatcher dimensions = 6;
+    optional FieldMatcher dimensions_in_what = 6;
+
+    optional FieldMatcher dimensions_in_condition = 8;
 
     optional TimeUnit bucket = 7;
 }
@@ -215,7 +219,9 @@
 
     optional int64 condition = 4;
 
-    optional FieldMatcher dimensions = 5;
+    optional FieldMatcher dimensions_in_what = 5;
+
+    optional FieldMatcher dimensions_in_condition = 8;
 
     optional TimeUnit bucket = 6;
 
@@ -231,7 +237,9 @@
 
     optional int64 condition = 4;
 
-    optional FieldMatcher dimensions = 5;
+    optional FieldMatcher dimensions_in_what = 5;
+
+    optional FieldMatcher dimensions_in_condition = 9;
 
     optional TimeUnit bucket = 6;
 
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index c542db2..1d75e20 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -111,20 +111,21 @@
 
         int index = 0;
         int uid = 0;
-        string configName;
+        int64_t configID = 0;
         char* substr = strtok(name, "-");
         // Timestamp lives at index 2 but we skip parsing it as it's not needed.
         while (substr != nullptr && index < 2) {
-            if (index) {
+            if (index == 0) {
                 uid = atoi(substr);
-            } else {
-                configName = substr;
+            } else if (index == 1) {
+                configID = StrToInt64(substr);
             }
             index++;
+            substr = strtok(nullptr, "-");
         }
         if (index < 2) continue;
 
-        sendBroadcast(ConfigKey(uid, StrToInt64(configName)));
+        sendBroadcast(ConfigKey(uid, configID));
     }
 }
 
@@ -143,19 +144,23 @@
 
         int index = 0;
         int uid = 0;
-        string configName;
+        int64_t configID = 0;
+        int64_t timestamp = 0;
         char* substr = strtok(name, "-");
-        // Timestamp lives at index 2 but we skip parsing it as it's not needed.
-        while (substr != nullptr && index < 2) {
-            if (index) {
+        while (substr != nullptr && index < 3) {
+            if (index == 0) {
                 uid = atoi(substr);
-            } else {
-                configName = substr;
+            } else if (index == 1) {
+                configID = StrToInt64(substr);
+            } else if (index == 2) {
+                timestamp = atoi(substr);
             }
             index++;
+            substr = strtok(nullptr, "-");
         }
-        if (index < 2) continue;
-        string file_name = StringPrintf("%s/%s", path, name);
+        if (index < 3) continue;
+        string file_name = StringPrintf("%s/%d-%lld-%lld", STATS_SERVICE_DIR, uid,
+                                        (long long)configID, (long long)timestamp);
         int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
         if (fd != -1) {
             string content;
@@ -186,29 +191,32 @@
 
         int index = 0;
         int uid = 0;
-        string configName;
+        int64_t configID = 0;
+        int64_t timestamp = 0;
         char* substr = strtok(name, "-");
-        // Timestamp lives at index 2 but we skip parsing it as it's not needed.
-        while (substr != nullptr && index < 2) {
-            if (index) {
+        while (substr != nullptr && index < 3) {
+            if (index == 0) {
                 uid = atoi(substr);
-            } else {
-                configName = substr;
+            } else if (index == 1) {
+                configID = StrToInt64(substr);
+            } else if (index == 2) {
+                timestamp = atoi(substr);
             }
             index++;
+            substr = strtok(nullptr, "-");
         }
-        if (index < 2) continue;
+        if (index < 3) continue;
 
-        string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name);
-        VLOG("full file %s", file_name.c_str());
+        string file_name = StringPrintf("%s/%d-%lld-%lld", STATS_SERVICE_DIR, uid,
+                                        (long long)configID, (long long)timestamp);
         int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
         if (fd != -1) {
             string content;
             if (android::base::ReadFdToString(fd, &content)) {
                 StatsdConfig config;
                 if (config.ParseFromString(content)) {
-                    configsMap[ConfigKey(uid, StrToInt64(configName))] = config;
-                    VLOG("map key uid=%d|name=%s", uid, name);
+                    configsMap[ConfigKey(uid, configID)] = config;
+                    VLOG("map key uid=%d|configID=%lld", uid, (long long)configID);
                 }
             }
             close(fd);
diff --git a/cmds/statsd/statsd.rc b/cmds/statsd/statsd.rc
index c260ae1..920273b 100644
--- a/cmds/statsd/statsd.rc
+++ b/cmds/statsd/statsd.rc
@@ -16,6 +16,7 @@
     class main
     user statsd
     group statsd log
+    writepid /dev/cpuset/system-background/tasks
 
 on post-fs-data
     # Create directory for statsd
diff --git a/cmds/statsd/tests/ConfigManager_test.cpp b/cmds/statsd/tests/ConfigManager_test.cpp
index cc02f34..62bdba4 100644
--- a/cmds/statsd/tests/ConfigManager_test.cpp
+++ b/cmds/statsd/tests/ConfigManager_test.cpp
@@ -91,7 +91,7 @@
     {
         InSequence s;
 
-        manager->Startup();
+        manager->StartupForTest();
 
         // Add another one
         EXPECT_CALL(*(listener.get()), OnConfigUpdated(ConfigKeyEq(1, StringToId("zzz")),
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index fe0f59d..f90ca40 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -81,8 +81,8 @@
     metric->set_id(3);
     metric->set_what(StringToId("SCREEN_IS_ON"));
     metric->set_bucket(ONE_MINUTE);
-    metric->mutable_dimensions()->set_field(2 /*SCREEN_STATE_CHANGE*/);
-    metric->mutable_dimensions()->add_child()->set_field(1);
+    metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+    metric->mutable_dimensions_in_what()->add_child()->set_field(1);
 
     config.add_no_report_metric(3);
 
@@ -132,8 +132,8 @@
     metric->set_id(3);
     metric->set_what(StringToId("SCREEN_IS_ON"));
     metric->set_bucket(ONE_MINUTE);
-    metric->mutable_dimensions()->set_field(2 /*SCREEN_STATE_CHANGE*/);
-    metric->mutable_dimensions()->add_child()->set_field(1);
+    metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+    metric->mutable_dimensions_in_what()->add_child()->set_field(1);
 
     auto alert = config.add_alert();
     alert->set_id(3);
@@ -217,7 +217,7 @@
     metric->set_what(StringToId("BATTERY_LOW"));
     metric->set_bucket(ONE_MINUTE);
     // This case is interesting. We want to dimension across two atoms.
-    metric->mutable_dimensions()->add_child()->set_field(1);
+    metric->mutable_dimensions_in_what()->add_child()->set_field(1);
 
     auto alert = config.add_alert();
     alert->set_id(103);
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 39c9549..a56db28 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -44,7 +44,7 @@
     auto countMetric = config.add_count_metric();
     countMetric->set_id(123456);
     countMetric->set_what(wakelockAcquireMatcher.id());
-    *countMetric->mutable_dimensions() =
+    *countMetric->mutable_dimensions_in_what() =
         CreateAttributionUidAndTagDimensions(
             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
     countMetric->set_bucket(ONE_MINUTE);
@@ -155,7 +155,8 @@
 
     auto data = countMetrics.data(0);
     ValidateAttributionUidAndTagDimension(
-        data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
+            "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);
@@ -166,7 +167,8 @@
 
     data = countMetrics.data(1);
     ValidateAttributionUidAndTagDimension(
-        data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
+            "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);
@@ -177,7 +179,8 @@
 
     data = countMetrics.data(2);
     ValidateAttributionUidAndTagDimension(
-        data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule3");
+        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
+            "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);
@@ -185,7 +188,8 @@
 
     data = countMetrics.data(3);
     ValidateAttributionUidAndTagDimension(
-        data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
+            "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);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
index 10a6c36..8250297 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
@@ -51,7 +51,7 @@
     fieldMatcher->add_child()->set_field(3);  // type (enum)
     fieldMatcher->add_child()->set_field(4);  // activity_name(str)
     fieldMatcher->add_child()->set_field(7);  // activity_start_msec(int64)
-    *gaugeMetric->mutable_dimensions() =
+    *gaugeMetric->mutable_dimensions_in_what() =
         CreateDimensions(android::util::APP_START_CHANGED, {1 /* uid field */ });
     gaugeMetric->set_bucket(ONE_MINUTE);
 
@@ -148,10 +148,10 @@
     EXPECT_EQ(gaugeMetrics.data_size(), 2);
 
     auto data = gaugeMetrics.data(0);
-    EXPECT_EQ(data.dimension().field(), android::util::APP_START_CHANGED);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).value_int(), appUid1);
+    EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid1);
     EXPECT_EQ(data.bucket_info_size(), 3);
     EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
     EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
@@ -172,10 +172,11 @@
     EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_start_msec(), 105L);
 
     data = gaugeMetrics.data(1);
-    EXPECT_EQ(data.dimension().field(), android::util::APP_START_CHANGED);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).value_int(), appUid2);
+
+    EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid2);
     EXPECT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
     EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index cdc4467..7512abc 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -46,7 +46,7 @@
     auto isSyncingPredicate = CreateIsSyncingPredicate();
     *isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions() =
         CreateDimensions(
-            android::util::SYNC_STATE_CHANGED, {1 /* uid field */});
+            android::util::SYNC_STATE_CHANGED, {1 /* uid field */, 2 /* name field*/});
 
     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
@@ -68,7 +68,7 @@
     countMetric->set_what(appCrashMatcher.id());
     countMetric->set_condition(combinationPredicate->id());
     // The metric is dimensioning by uid only.
-    *countMetric->mutable_dimensions() =
+    *countMetric->mutable_dimensions_in_what() =
         CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
     countMetric->set_bucket(ONE_MINUTE);
 
@@ -199,12 +199,11 @@
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
     auto data = reports.reports(0).metrics(0).count_metrics().data(0);
     // Validate dimension value.
-    EXPECT_EQ(data.dimension().field(),
-              android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value_size(), 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);
     // Uid field.
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).value_int(), appUid);
+    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);
@@ -216,12 +215,12 @@
     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);
     // Validate dimension value.
-    EXPECT_EQ(data.dimension().field(),
+    EXPECT_EQ(data.dimensions_in_what().field(),
               android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value_size(), 1);
+    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
     // Uid field.
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(data.dimension().value_tuple().dimensions_value(0).value_int(), appUid);
+    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);
 }
 
 #else
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index fcdaafc..e656b98 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -51,7 +51,7 @@
     durationMetric->set_condition(screenIsOffPredicate.id());
     durationMetric->set_aggregation_type(aggregationType);
     // The metric is dimensioning by first attribution node and only by uid.
-    *durationMetric->mutable_dimensions() =
+    *durationMetric->mutable_dimensions_in_what() =
         CreateAttributionUidDimensions(
             android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
     durationMetric->set_bucket(ONE_MINUTE);
@@ -125,7 +125,8 @@
         auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
         // Validate dimension value.
         ValidateAttributionUidDimension(
-            data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 111);
+            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);
@@ -143,7 +144,7 @@
         data = reports.reports(0).metrics(0).duration_metrics().data(0);
         // Validate dimension value.
         ValidateAttributionUidDimension(
-            data.dimension(), android::util::WAKELOCK_STATE_CHANGED, 111);
+            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.
@@ -172,7 +173,7 @@
         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.dimension(), android::util::WAKELOCK_STATE_CHANGED, 111);
+            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);
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 7eb93b9..1fc33de 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -138,7 +138,7 @@
 void sortMetricDataByDimensionsValue(const T& metricData, T* sortedMetricData) {
     std::map<HashableDimensionKey, int> dimensionIndexMap;
     for (int i = 0; i < metricData.data_size(); ++i) {
-        dimensionIndexMap.insert(std::make_pair(metricData.data(i).dimension(), i));
+        dimensionIndexMap.insert(std::make_pair(metricData.data(i).dimensions_in_what(), i));
     }
     for (const auto& itr : dimensionIndexMap) {
         *sortedMetricData->add_data() = metricData.data(itr.second);
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 93dba71..33c8abf 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
@@ -97,9 +97,14 @@
                 = log.getDurationMetrics();
         sb.append("Dimension size: ").append(durationMetricDataWrapper.getDataCount()).append("\n");
         for (StatsLog.DurationMetricData duration : durationMetricDataWrapper.getDataList()) {
-            sb.append("dimension: ");
-            displayDimension(sb, duration.getDimension());
+            sb.append("dimension_in_what: ");
+            displayDimension(sb, duration.getDimensionsInWhat());
             sb.append("\n");
+            if (duration.hasDimensionsInCondition()) {
+                sb.append("dimension_in_condition: ");
+                displayDimension(sb, duration.getDimensionsInCondition());
+                sb.append("\n");
+            }
 
             for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList())  {
                 sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
@@ -124,9 +129,14 @@
                 = log.getCountMetrics();
         sb.append("Dimension size: ").append(countMetricDataWrapper.getDataCount()).append("\n");
         for (StatsLog.CountMetricData count : countMetricDataWrapper.getDataList()) {
-            sb.append("dimension: ");
-            displayDimension(sb, count.getDimension());
+            sb.append("dimension_in_what: ");
+            displayDimension(sb, count.getDimensionsInWhat());
             sb.append("\n");
+            if (count.hasDimensionsInCondition()) {
+                sb.append("dimension_in_condition: ");
+                displayDimension(sb, count.getDimensionsInCondition());
+                sb.append("\n");
+            }
 
             for (StatsLog.CountBucketInfo info : count.getBucketInfoList())  {
                 sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
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 862ebe14..75489ad 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
@@ -108,9 +108,14 @@
                 = log.getDurationMetrics();
         sb.append("Dimension size: ").append(durationMetricDataWrapper.getDataCount()).append("\n");
         for (StatsLog.DurationMetricData duration : durationMetricDataWrapper.getDataList()) {
-            sb.append("dimension: ");
-            displayDimension(sb, duration.getDimension());
+            sb.append("dimension_in_what: ");
+            displayDimension(sb, duration.getDimensionsInWhat());
             sb.append("\n");
+            if (duration.hasDimensionsInCondition()) {
+                sb.append("dimension_in_condition: ");
+                displayDimension(sb, duration.getDimensionsInCondition());
+                sb.append("\n");
+            }
 
             for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList())  {
                 sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
@@ -135,9 +140,14 @@
                 = log.getCountMetrics();
         sb.append("Dimension size: ").append(countMetricDataWrapper.getDataCount()).append("\n");
         for (StatsLog.CountMetricData count : countMetricDataWrapper.getDataList()) {
-            sb.append("dimension: ");
-            displayDimension(sb, count.getDimension());
+            sb.append("dimension_in_what: ");
+            displayDimension(sb, count.getDimensionsInWhat());
             sb.append("\n");
+            if (count.hasDimensionsInCondition()) {
+                sb.append("dimension_in_condition: ");
+                displayDimension(sb, count.getDimensionsInCondition());
+                sb.append("\n");
+            }
 
             for (StatsLog.CountBucketInfo info : count.getBucketInfoList())  {
                 sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aa099eb..0a5b848 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,6 +16,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;
@@ -98,6 +99,7 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.RemoteAnimationDefinition;
 import android.view.SearchEvent;
 import android.view.View;
 import android.view.View.OnCreateContextMenuListener;
@@ -857,6 +859,7 @@
     private boolean mHasCurrentPermissionsRequest;
 
     private boolean mAutoFillResetNeeded;
+    private boolean mAutoFillIgnoreFirstResumePause;
 
     /** The last autofill id that was returned from {@link #getNextAutofillId()} */
     private int mLastAutofillId = View.LAST_APP_AUTOFILL_ID;
@@ -1253,10 +1256,7 @@
         getApplication().dispatchActivityStarted(this);
 
         if (mAutoFillResetNeeded) {
-            AutofillManager afm = getAutofillManager();
-            if (afm != null) {
-                afm.onVisibleForAutofill();
-            }
+            getAutofillManager().onVisibleForAutofill();
         }
     }
 
@@ -1320,6 +1320,20 @@
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
         getApplication().dispatchActivityResumed(this);
         mActivityTransitionState.onResume(this, isTopOfTask());
+        if (mAutoFillResetNeeded) {
+            if (!mAutoFillIgnoreFirstResumePause) {
+                View focus = getCurrentFocus();
+                if (focus != null && focus.canNotifyAutofillEnterExitEvent()) {
+                    // TODO: in Activity killed/recreated case, i.e. SessionLifecycleTest#
+                    // testDatasetVisibleWhileAutofilledAppIsLifecycled: the View's initial
+                    // window visibility after recreation is INVISIBLE in onResume() and next frame
+                    // ViewRootImpl.performTraversals() changes window visibility to VISIBLE.
+                    // So we cannot call View.notifyEnterOrExited() which will do nothing
+                    // when View.isVisibleToUser() is false.
+                    getAutofillManager().notifyViewEntered(focus);
+                }
+            }
+        }
         mCalled = true;
     }
 
@@ -1681,6 +1695,19 @@
     protected void onPause() {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
         getApplication().dispatchActivityPaused(this);
+        if (mAutoFillResetNeeded) {
+            if (!mAutoFillIgnoreFirstResumePause) {
+                if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill notifyViewExited " + this);
+                View focus = getCurrentFocus();
+                if (focus != null && focus.canNotifyAutofillEnterExitEvent()) {
+                    getAutofillManager().notifyViewExited(focus);
+                }
+            } else {
+                // reset after first pause()
+                if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill got first pause " + this);
+                mAutoFillIgnoreFirstResumePause = false;
+            }
+        }
         mCalled = true;
     }
 
@@ -1871,6 +1898,10 @@
         mTranslucentCallback = null;
         mCalled = true;
 
+        if (mAutoFillResetNeeded) {
+            getAutofillManager().onInvisibleForAutofill();
+        }
+
         if (isFinishing()) {
             if (mAutoFillResetNeeded) {
                 getAutofillManager().onActivityFinished();
@@ -6266,7 +6297,7 @@
 
         mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
 
-        final AutofillManager afm = getAutofillManager();
+        final AutofillManager afm = mAutofillManager;
         if (afm != null) {
             afm.dump(prefix, writer);
         } else {
@@ -6616,7 +6647,6 @@
      *    to run as a {@link android.service.vr.VrListenerService} is not installed, or has
      *    not been enabled in user settings.
      *
-     * @see android.content.pm.PackageManager#FEATURE_VR_MODE
      * @see android.content.pm.PackageManager#FEATURE_VR_MODE_HIGH_PERFORMANCE
      * @see android.service.vr.VrListenerService
      * @see android.provider.Settings#ACTION_VR_LISTENER_SETTINGS
@@ -7120,13 +7150,23 @@
         }
     }
 
-    final void performResume() {
+    final void performResume(boolean followedByPause) {
         performRestart(true /* start */);
 
         mFragments.execPendingActions();
 
         mLastNonConfigurationInstances = null;
 
+        if (mAutoFillResetNeeded) {
+            // When Activity is destroyed in paused state, and relaunch activity, there will be
+            // extra onResume and onPause event,  ignore the first onResume and onPause.
+            // see ActivityThread.handleRelaunchActivity()
+            mAutoFillIgnoreFirstResumePause = followedByPause;
+            if (mAutoFillIgnoreFirstResumePause && DEBUG_LIFECYCLE) {
+                Slog.v(TAG, "autofill will ignore first pause when relaunching " + this);
+            }
+        }
+
         mCalled = false;
         // mResumed is set by the instrumentation
         mInstrumentation.callActivityOnResume(this);
@@ -7311,7 +7351,7 @@
             }
         } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
             Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
-            getAutofillManager().onAuthenticationResult(requestCode, resultData);
+            getAutofillManager().onAuthenticationResult(requestCode, resultData, getCurrentFocus());
         } else {
             Fragment frag = mFragments.findFragmentByWho(who);
             if (frag != null) {
@@ -7585,6 +7625,12 @@
         return !mStopped;
     }
 
+    /** @hide */
+    @Override
+    public boolean isDisablingEnterExitEventForAutofill() {
+        return mAutoFillIgnoreFirstResumePause || !mResumed;
+    }
+
     /**
      * If set to true, this indicates to the system that it should never take a
      * screenshot of the activity to be used as a representation while it is not in a started state.
@@ -7659,6 +7705,22 @@
         }
     }
 
+    /**
+     * Registers remote animations per transition type for this activity.
+     *
+     * @param definition The remote animation definition that defines which transition whould run
+     *                   which remote animation.
+     * @hide
+     */
+    @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+    public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
+        try {
+            ActivityManager.getService().registerRemoteAnimations(mToken, definition);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to call registerRemoteAnimations", e);
+        }
+    }
+
     class HostCallbacks extends FragmentHostCallback<Activity> {
         public HostCallbacks() {
             super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 972ffcb..ccb54f9 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -324,4 +324,19 @@
      * Returns if more users can be started without stopping currently running users.
      */
     public abstract boolean canStartMoreUsers();
+
+    /**
+     * Sets the user switcher message for switching from {@link android.os.UserHandle#SYSTEM}.
+     */
+    public abstract void setSwitchingFromSystemUserMessage(String switchingFromSystemUserMessage);
+
+    /**
+     * Sets the user switcher message for switching to {@link android.os.UserHandle#SYSTEM}.
+     */
+    public abstract void setSwitchingToSystemUserMessage(String switchingToSystemUserMessage);
+
+    /**
+     * Returns maximum number of users that can run simultaneously.
+     */
+    public abstract int getMaxRunningUsers();
 }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index e61c5b7..4bcd677 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,12 +16,14 @@
 
 package android.app;
 
+import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.content.Context;
@@ -44,6 +46,7 @@
 import android.util.Slog;
 import android.view.AppTransitionAnimationSpec;
 import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.RemoteAnimationAdapter;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
@@ -241,6 +244,8 @@
     private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE
             = "android:instantapps.installerbundle";
     private static final String KEY_SPECS_FUTURE = "android:activity.specsFuture";
+    private static final String KEY_REMOTE_ANIMATION_ADAPTER
+            = "android:activity.remoteAnimationAdapter";
 
     /** @hide */
     public static final int ANIM_NONE = 0;
@@ -268,6 +273,8 @@
     public static final int ANIM_CLIP_REVEAL = 11;
     /** @hide */
     public static final int ANIM_OPEN_CROSS_PROFILE_APPS = 12;
+    /** @hide */
+    public static final int ANIM_REMOTE_ANIMATION = 13;
 
     private String mPackageName;
     private Rect mLaunchBounds;
@@ -304,6 +311,7 @@
     private int mRotationAnimationHint = -1;
     private Bundle mAppVerificationBundle;
     private IAppTransitionAnimationSpecsFuture mSpecsFuture;
+    private RemoteAnimationAdapter mRemoteAnimationAdapter;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -826,6 +834,20 @@
         return opts;
     }
 
+    /**
+     * Create an {@link ActivityOptions} instance that lets the application control the entire
+     * animation using a {@link RemoteAnimationAdapter}.
+     * @hide
+     */
+    @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+    public static ActivityOptions makeRemoteAnimation(
+            RemoteAnimationAdapter remoteAnimationAdapter) {
+        final ActivityOptions opts = new ActivityOptions();
+        opts.mRemoteAnimationAdapter = remoteAnimationAdapter;
+        opts.mAnimationType = ANIM_REMOTE_ANIMATION;
+        return opts;
+    }
+
     /** @hide */
     public boolean getLaunchTaskBehind() {
         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -922,6 +944,7 @@
             mSpecsFuture = IAppTransitionAnimationSpecsFuture.Stub.asInterface(opts.getBinder(
                     KEY_SPECS_FUTURE));
         }
+        mRemoteAnimationAdapter = opts.getParcelable(KEY_REMOTE_ANIMATION_ADAPTER);
     }
 
     /**
@@ -1070,6 +1093,11 @@
     }
 
     /** @hide */
+    public RemoteAnimationAdapter getRemoteAnimationAdapter() {
+        return mRemoteAnimationAdapter;
+    }
+
+    /** @hide */
     public static ActivityOptions fromBundle(Bundle bOptions) {
         return bOptions != null ? new ActivityOptions(bOptions) : null;
     }
@@ -1309,6 +1337,7 @@
         mAnimSpecs = otherOptions.mAnimSpecs;
         mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
         mSpecsFuture = otherOptions.mSpecsFuture;
+        mRemoteAnimationAdapter = otherOptions.mRemoteAnimationAdapter;
     }
 
     /**
@@ -1403,7 +1432,9 @@
         if (mAppVerificationBundle != null) {
             b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);
         }
-
+        if (mRemoteAnimationAdapter != null) {
+            b.putParcelable(KEY_REMOTE_ANIMATION_ADAPTER, mRemoteAnimationAdapter);
+        }
         return b;
     }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 70c383b..934b0f3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -166,6 +166,7 @@
 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.List;
@@ -220,6 +221,9 @@
     // Whether to invoke an activity callback after delivering new configuration.
     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;
+
     /**
      * Denotes an invalid sequence number corresponding to a process state change.
      */
@@ -252,6 +256,8 @@
     final H mH = new H();
     final Executor mExecutor = new HandlerExecutor(mH);
     final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
+    final ArrayDeque<Integer> mRecentTokens = new ArrayDeque<>();
+
     // List of new activities (via ActivityRecord.nextIdle) that should
     // be reported when next we idle.
     ActivityClientRecord mNewActivities = null;
@@ -2168,6 +2174,18 @@
         pw.println(String.format(format, objs));
     }
 
+    @Override
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "mActivities:");
+
+        for (ArrayMap.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
+            pw.println(prefix + "  [token:" + entry.getKey().hashCode() + " record:"
+                    + entry.getValue().toString() + "]");
+        }
+
+        pw.println(prefix + "mRecentTokens:" + mRecentTokens);
+    }
+
     public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
             boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
             int pid, String processName,
@@ -2852,6 +2870,11 @@
             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;
@@ -3073,7 +3096,7 @@
         checkAndBlockForNetworkAccess();
         deliverNewIntents(r, intents);
         if (resumed) {
-            r.activity.performResume();
+            r.activity.performResume(false);
             r.activity.mTemporaryPause = false;
         }
 
@@ -3695,7 +3718,7 @@
                     deliverResults(r, r.pendingResults);
                     r.pendingResults = null;
                 }
-                r.activity.performResume();
+                r.activity.performResume(r.startsNotResumed);
 
                 synchronized (mResourcesManager) {
                     // If there is a pending local relaunch that was requested when the activity was
@@ -4414,7 +4437,7 @@
             checkAndBlockForNetworkAccess();
             deliverResults(r, results);
             if (resumed) {
-                r.activity.performResume();
+                r.activity.performResume(false);
                 r.activity.mTemporaryPause = false;
             }
         }
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 9f1e983..ac6cba1 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -34,6 +34,7 @@
 import android.view.SurfaceView;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 import dalvik.system.CloseGuard;
 
@@ -58,6 +59,8 @@
     private StateCallback mActivityViewCallback;
 
     private IInputForwarder mInputForwarder;
+    // Temp container to store view coordinates on screen.
+    private final int[] mLocationOnScreen = new int[2];
 
     private final CloseGuard mGuard = CloseGuard.get();
     private boolean mOpened; // Protected by mGuard.
@@ -198,11 +201,30 @@
         performRelease();
     }
 
+    /**
+     * Triggers an update of {@link ActivityView}'s location on screen to properly set touch exclude
+     * regions and avoid focus switches by touches on this view.
+     */
+    public void onLocationChanged() {
+        updateLocation();
+    }
+
     @Override
     public void onLayout(boolean changed, int l, int t, int r, int b) {
         mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
     }
 
+    /** Send current location and size to the WM to set tap exclude region for this view. */
+    private void updateLocation() {
+        try {
+            getLocationOnScreen(mLocationOnScreen);
+            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
+                    mLocationOnScreen[0], mLocationOnScreen[1], getWidth(), getHeight());
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         return injectInputEvent(event) || super.onTouchEvent(event);
@@ -241,6 +263,7 @@
             } else {
                 mVirtualDisplay.setSurface(surfaceHolder.getSurface());
             }
+            updateLocation();
         }
 
         @Override
@@ -248,6 +271,7 @@
             if (mVirtualDisplay != null) {
                 mVirtualDisplay.resize(width, height, getBaseDisplayDensity());
             }
+            updateLocation();
         }
 
         @Override
@@ -257,6 +281,7 @@
             if (mVirtualDisplay != null) {
                 mVirtualDisplay.setSurface(null);
             }
+            cleanTapExcludeRegion();
         }
     }
 
@@ -290,6 +315,7 @@
         if (mInputForwarder != null) {
             mInputForwarder = null;
         }
+        cleanTapExcludeRegion();
 
         final boolean displayReleased;
         if (mVirtualDisplay != null) {
@@ -313,6 +339,17 @@
         mOpened = false;
     }
 
+    /** Report to server that tap exclude region on hosting display should be cleared. */
+    private void cleanTapExcludeRegion() {
+        // Update tap exclude region with an empty rect to clean the state on server.
+        try {
+            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
+                    0 /* left */, 0 /* top */, 0 /* width */, 0 /* height */);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
     /** Get density of the hosting display. */
     private int getBaseDisplayDensity() {
         final WindowManager wm = mContext.getSystemService(WindowManager.class);
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 45c0e0c..0f66652 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -24,6 +24,7 @@
 
 import com.android.internal.content.ReferrerIntent;
 
+import java.io.PrintWriter;
 import java.util.List;
 
 /**
@@ -121,4 +122,11 @@
      * provided token.
      */
     public abstract ActivityThread.ActivityClientRecord getActivityClient(IBinder token);
+
+    /**
+     * Debugging output.
+     * @param pw {@link PrintWriter} to write logs to.
+     * @param prefix Prefix to prepend to output.
+     */
+    public abstract void dump(PrintWriter pw, String prefix);
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1653430..4914ffa 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -872,13 +872,19 @@
 
         // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
         // generally not allowed, except if the caller specifies the task id the activity should
-        // be launched in.
-        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
-                && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
+        // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
+        // maintain this for backwards compatibility.
+        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;
+
+        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
+                && (targetSdkVersion < Build.VERSION_CODES.N
+                        || targetSdkVersion >= Build.VERSION_CODES.P)
+                && (options == null
+                        || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
             throw new AndroidRuntimeException(
                     "Calling startActivity() from outside of an Activity "
-                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
-                    + " Is this really what you want?");
+                            + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+                            + " Is this really what you want?");
         }
         mMainThread.getInstrumentation().execStartActivity(
                 getOuterContext(), mMainThread.getApplicationThread(), null,
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 696899f..04ee77d 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -65,6 +65,7 @@
 import android.os.StrictMode;
 import android.os.WorkSource;
 import android.service.voice.IVoiceInteractionSession;
+import android.view.RemoteAnimationDefinition;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
@@ -672,4 +673,9 @@
       *  user unlock progress.
       */
      boolean startUserInBackgroundWithListener(int userid, IProgressListener unlockProgressListener);
+
+     /**
+      * Registers remote animations for a specific activity.
+      */
+     void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition);
 }
diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java
index 02a0124..b7100e6 100644
--- a/core/java/android/app/RemoteInput.java
+++ b/core/java/android/app/RemoteInput.java
@@ -24,6 +24,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -73,6 +74,15 @@
     private static final String EXTRA_DATA_TYPE_RESULTS_DATA =
             "android.remoteinput.dataTypeResultsData";
 
+    /** Extra added to a clip data intent object identifying the source of the results. */
+    private static final String EXTRA_RESULTS_SOURCE = "android.remoteinput.resultsSource";
+
+    /** The user manually entered the data. */
+    public static final int SOURCE_FREE_FORM_INPUT = 0;
+
+    /** The user selected one of the choices from {@link #getChoices}. */
+    public static final int SOURCE_CHOICE = 1;
+
     // Flags bitwise-ored to mFlags
     private static final int FLAG_ALLOW_FREE_FORM_INPUT = 0x1;
 
@@ -416,6 +426,48 @@
         intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
     }
 
+    /**
+     * Set the source of the RemoteInput results. This method should only be called by remote
+     * input collection services (e.g.
+     * {@link android.service.notification.NotificationListenerService})
+     * when sending results to a pending intent.
+     *
+     * @see #SOURCE_FREE_FORM_INPUT
+     * @see #SOURCE_CHOICE
+     *
+     * @param intent The intent to add remote input source to. The {@link ClipData}
+     *               field of the intent will be modified to contain the source.
+     *               field of the intent will be modified to contain the source.
+     * @param source The source of the results.
+     */
+    public static void setResultsSource(Intent intent, int source) {
+        Intent clipDataIntent = getClipDataIntentFromIntent(intent);
+        if (clipDataIntent == null) {
+            clipDataIntent = new Intent();  // First time we've added a result.
+        }
+        clipDataIntent.putExtra(EXTRA_RESULTS_SOURCE, source);
+        intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
+    }
+
+    /**
+     * Get the source of the RemoteInput results.
+     *
+     * @see #SOURCE_FREE_FORM_INPUT
+     * @see #SOURCE_CHOICE
+     *
+     * @param intent The intent object that fired in response to an action or content intent
+     *               which also had one or more remote input requested.
+     * @return The source of the results. If no source was set, {@link #SOURCE_FREE_FORM_INPUT} will
+     * be returned.
+     */
+    public static int getResultsSource(Intent intent) {
+        Intent clipDataIntent = getClipDataIntentFromIntent(intent);
+        if (clipDataIntent == null) {
+            return SOURCE_FREE_FORM_INPUT;
+        }
+        return clipDataIntent.getExtras().getInt(EXTRA_RESULTS_SOURCE, SOURCE_FREE_FORM_INPUT);
+    }
+
     private static String getExtraResultsKeyForData(String mimeType) {
         return EXTRA_DATA_TYPE_RESULTS_DATA + mimeType;
     }
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6eafcc4..33277ea 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -38,12 +38,12 @@
 import android.content.Context;
 import android.content.IRestrictionsManager;
 import android.content.RestrictionsManager;
+import android.content.pm.CrossProfileApps;
+import android.content.pm.ICrossProfileApps;
 import android.content.pm.IShortcutService;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutManager;
-import android.content.pm.crossprofile.CrossProfileApps;
-import android.content.pm.crossprofile.ICrossProfileApps;
 import android.content.res.Resources;
 import android.hardware.ConsumerIrManager;
 import android.hardware.ISerialManager;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index aa05b76..302d52f 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -467,6 +467,31 @@
     public static final String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE =
             "android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
 
+    /**
+     * Name under which a device administration component indicates whether it supports transfer of
+     * ownership. This meta-data is of type <code>boolean</code>. A value of <code>true</code>
+     * allows this administrator to be used as a target administrator for a transfer. If the value
+     * is <code>false</code>, ownership cannot be transferred to this administrator. The default
+     * value is <code>false</code>.
+     * <p>This metadata is used to avoid ownership transfer migration to an administrator with a
+     * version which does not yet support it.
+     * <p>Usage:
+     * <pre>
+     * &lt;receiver name="..." android:permission="android.permission.BIND_DEVICE_ADMIN"&gt;
+     *     &lt;meta-data
+     *         android:name="android.app.device_admin"
+     *         android:resource="@xml/..." /&gt;
+     *     &lt;meta-data
+     *         android:name="android.app.support_transfer_ownership"
+     *         android:value="true" /&gt;
+     * &lt;/receiver&gt;
+     * </pre>
+     *
+     * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
+     */
+    public static final String SUPPORT_TRANSFER_OWNERSHIP_META_DATA =
+            "android.app.support_transfer_ownership";
+
     private DevicePolicyManager mManager;
     private ComponentName mWho;
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 67b59f6..9329d56 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -18,7 +18,6 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.ColorInt;
-import android.annotation.Condemned;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -50,8 +49,6 @@
 import android.net.ProxyInfo;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -8983,15 +8980,6 @@
         }
     }
 
-    /** {@hide} */
-    @Condemned
-    @Deprecated
-    public boolean clearApplicationUserData(@NonNull ComponentName admin,
-            @NonNull String packageName, @NonNull OnClearApplicationUserDataListener listener,
-            @NonNull Handler handler) {
-        return clearApplicationUserData(admin, packageName, listener, new HandlerExecutor(handler));
-    }
-
     /**
      * Called by the device owner or profile owner to clear application user data of a given
      * package. The behaviour of this is equivalent to the target application calling
@@ -9002,14 +8990,14 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The name of the package which will have its user data wiped.
-     * @param listener A callback object that will inform the caller when the clearing is done.
      * @param executor The executor through which the listener should be invoked.
+     * @param listener A callback object that will inform the caller when the clearing is done.
      * @throws SecurityException if the caller is not the device owner/profile owner.
      * @return whether the clearing succeeded.
      */
     public boolean clearApplicationUserData(@NonNull ComponentName admin,
-            @NonNull String packageName, @NonNull OnClearApplicationUserDataListener listener,
-            @NonNull @CallbackExecutor Executor executor) {
+            @NonNull String packageName, @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnClearApplicationUserDataListener listener) {
         throwIfParentInstance("clearAppData");
         Preconditions.checkNotNull(executor);
         try {
@@ -9108,6 +9096,11 @@
      * will be received in the
      * {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)} callback.
      *
+     * <p>The incoming target administrator must have the
+     * {@link DeviceAdminReceiver#SUPPORT_TRANSFER_OWNERSHIP_META_DATA} <code>meta-data</code> tag
+     * included in its corresponding <code>receiver</code> component with a value of {@code true}.
+     * Otherwise an {@link IllegalArgumentException} will be thrown.
+     *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with
      * @param target which {@link DeviceAdminReceiver} we want the new administrator to be
      * @param bundle data to be sent to the new administrator
@@ -9124,4 +9117,84 @@
             throw re.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Called by a device owner to specify the user session start message. This may be displayed
+     * during a user switch.
+     * <p>
+     * The message should be limited to a short statement or it may be truncated.
+     * <p>
+     * If the message needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this message accordingly.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @param startUserSessionMessage message for starting user session, or {@code null} to use
+     * system default message.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public void setStartUserSessionMessage(
+            @NonNull ComponentName admin, @Nullable CharSequence startUserSessionMessage) {
+        throwIfParentInstance("setStartUserSessionMessage");
+        try {
+            mService.setStartUserSessionMessage(admin, startUserSessionMessage);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Called by a device owner to specify the user session end message. This may be displayed
+     * during a user switch.
+     * <p>
+     * The message should be limited to a short statement or it may be truncated.
+     * <p>
+     * If the message needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this message accordingly.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @param endUserSessionMessage message for ending user session, or {@code null} to use system
+     * default message.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public void setEndUserSessionMessage(
+            @NonNull ComponentName admin, @Nullable CharSequence endUserSessionMessage) {
+        throwIfParentInstance("setEndUserSessionMessage");
+        try {
+            mService.setEndUserSessionMessage(admin, endUserSessionMessage);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the user session start message.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public CharSequence getStartUserSessionMessage(@NonNull ComponentName admin) {
+        throwIfParentInstance("getStartUserSessionMessage");
+        try {
+            return mService.getStartUserSessionMessage(admin);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the user session end message.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public CharSequence getEndUserSessionMessage(@NonNull ComponentName admin) {
+        throwIfParentInstance("getEndUserSessionMessage");
+        try {
+            return mService.getEndUserSessionMessage(admin);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index b692ffd9..531bef0 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -123,4 +123,13 @@
      * @param userId User ID of the profile.
      */
     public abstract void reportSeparateProfileChallengeChanged(@UserIdInt int userId);
+
+    /**
+     * Check whether the user could have their password reset in an untrusted manor due to there
+     * being an admin which can call {@link #resetPassword} to reset the password without knowledge
+     * of the previous password.
+     *
+     * @param userId The user in question
+     */
+    public abstract boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId);
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9cdd1f8..eac7f7e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -391,4 +391,9 @@
 
     List<String> getDisallowedSystemApps(in ComponentName admin, int userId, String provisioningAction);
     void transferOwnership(in ComponentName admin, in ComponentName target, in PersistableBundle bundle);
+
+    void setStartUserSessionMessage(in ComponentName admin, in CharSequence startUserSessionMessage);
+    void setEndUserSessionMessage(in ComponentName admin, in CharSequence endUserSessionMessage);
+    CharSequence getStartUserSessionMessage(in ComponentName admin);
+    CharSequence getEndUserSessionMessage(in ComponentName admin);
 }
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 3a6a5b2..12f4483 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -27,6 +27,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 import android.util.Pair;
 
@@ -387,6 +388,29 @@
     }
 
     /**
+     * Report whether the backup mechanism is currently active.
+     * When it is inactive, the device will not perform any backup operations, nor will it
+     * deliver data for restore, although clients can still safely call BackupManager methods.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
+    public boolean isBackupServiceActive(UserHandle user) {
+        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+                "isBackupServiceActive");
+        checkServiceBinder();
+        if (sService != null) {
+            try {
+                return sService.isBackupServiceActive(user.getIdentifier());
+            } catch (RemoteException e) {
+                Log.e(TAG, "isBackupEnabled() couldn't connect");
+            }
+        }
+        return false;
+    }
+
+    /**
      * Enable/disable data restore at application install time.  When enabled, app
      * installation will include an attempt to fetch the app's historical data from
      * the archival restore dataset (if any).  When disabled, no such attempt will
diff --git a/core/java/android/app/servertransaction/ActivityLifecycleItem.java b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
index 0fdc7c5..9a50a00 100644
--- a/core/java/android/app/servertransaction/ActivityLifecycleItem.java
+++ b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
@@ -17,7 +17,9 @@
 package android.app.servertransaction;
 
 import android.annotation.IntDef;
+import android.os.Parcel;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -26,6 +28,7 @@
  * @hide
  */
 public abstract class ActivityLifecycleItem extends ClientTransactionItem {
+    private String mDescription;
 
     @IntDef(prefix = { "UNDEFINED", "PRE_", "ON_" }, value = {
             UNDEFINED,
@@ -53,4 +56,39 @@
     /** A final lifecycle state that an activity should reach. */
     @LifecycleState
     public abstract int getTargetState();
+
+
+    protected ActivityLifecycleItem() {
+    }
+
+    protected ActivityLifecycleItem(Parcel in) {
+        mDescription = in.readString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mDescription);
+    }
+
+    /**
+     * Sets a description that can be retrieved later for debugging purposes.
+     * @param description Description to set.
+     * @return The {@link ActivityLifecycleItem}.
+     */
+    public ActivityLifecycleItem setDescription(String description) {
+        mDescription = description;
+        return this;
+    }
+
+    /**
+     * Retrieves description if set through {@link #setDescription(String)}.
+     */
+    public String getDescription() {
+        return mDescription;
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "target state:" + getTargetState());
+        pw.println(prefix + "description: " + mDescription);
+    }
 }
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 08ad2f0..fc07879 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -26,6 +26,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -237,4 +238,12 @@
         result = 31 * result + Objects.hashCode(mLifecycleStateRequest);
         return result;
     }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "mActivityToken:" + mActivityToken.hashCode());
+        pw.println(prefix + "mLifecycleStateRequest:");
+        if (mLifecycleStateRequest != null) {
+            mLifecycleStateRequest.dump(pw, prefix + "  ");
+        }
+    }
 }
diff --git a/core/java/android/app/servertransaction/DestroyActivityItem.java b/core/java/android/app/servertransaction/DestroyActivityItem.java
index 83da5f3..cbcf6c7 100644
--- a/core/java/android/app/servertransaction/DestroyActivityItem.java
+++ b/core/java/android/app/servertransaction/DestroyActivityItem.java
@@ -76,12 +76,14 @@
     /** Write to Parcel. */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
         dest.writeBoolean(mFinished);
         dest.writeInt(mConfigChanges);
     }
 
     /** Read from Parcel. */
     private DestroyActivityItem(Parcel in) {
+        super(in);
         mFinished = in.readBoolean();
         mConfigChanges = in.readInt();
     }
diff --git a/core/java/android/app/servertransaction/PauseActivityItem.java b/core/java/android/app/servertransaction/PauseActivityItem.java
index 880fef7..70a4755 100644
--- a/core/java/android/app/servertransaction/PauseActivityItem.java
+++ b/core/java/android/app/servertransaction/PauseActivityItem.java
@@ -114,6 +114,7 @@
     /** Write to Parcel. */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
         dest.writeBoolean(mFinished);
         dest.writeBoolean(mUserLeaving);
         dest.writeInt(mConfigChanges);
@@ -122,6 +123,7 @@
 
     /** Read from Parcel. */
     private PauseActivityItem(Parcel in) {
+        super(in);
         mFinished = in.readBoolean();
         mUserLeaving = in.readBoolean();
         mConfigChanges = in.readInt();
diff --git a/core/java/android/app/servertransaction/ResumeActivityItem.java b/core/java/android/app/servertransaction/ResumeActivityItem.java
index 9249c6e..ed90f2c 100644
--- a/core/java/android/app/servertransaction/ResumeActivityItem.java
+++ b/core/java/android/app/servertransaction/ResumeActivityItem.java
@@ -113,6 +113,7 @@
     /** Write to Parcel. */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
         dest.writeInt(mProcState);
         dest.writeBoolean(mUpdateProcState);
         dest.writeBoolean(mIsForward);
@@ -120,6 +121,7 @@
 
     /** Read from Parcel. */
     private ResumeActivityItem(Parcel in) {
+        super(in);
         mProcState = in.readInt();
         mUpdateProcState = in.readBoolean();
         mIsForward = in.readBoolean();
diff --git a/core/java/android/app/servertransaction/StopActivityItem.java b/core/java/android/app/servertransaction/StopActivityItem.java
index 5c5c304..b814d1a 100644
--- a/core/java/android/app/servertransaction/StopActivityItem.java
+++ b/core/java/android/app/servertransaction/StopActivityItem.java
@@ -83,12 +83,14 @@
     /** Write to Parcel. */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
         dest.writeBoolean(mShowWindow);
         dest.writeInt(mConfigChanges);
     }
 
     /** Read from Parcel. */
     private StopActivityItem(Parcel in) {
+        super(in);
         mShowWindow = in.readBoolean();
         mConfigChanges = in.readInt();
     }
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 5b0ea6b..78b393a 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -33,6 +33,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 
 /**
@@ -122,6 +124,21 @@
         final IBinder token = transaction.getActivityToken();
         final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
 
+        // TODO(b/71506345): Remove once root cause is found.
+        if (r == null) {
+            final StringWriter stringWriter = new StringWriter();
+            final PrintWriter pw = new PrintWriter(stringWriter);
+            final String prefix = "  ";
+
+            pw.println("Lifecycle transaction does not have valid ActivityClientRecord.");
+            pw.println("Transaction:");
+            transaction.dump(pw, prefix);
+            pw.println("Executor:");
+            dump(pw, prefix);
+
+            Slog.wtf(TAG, stringWriter.toString());
+        }
+
         // Cycle to the state right before the final requested state.
         cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
 
@@ -245,4 +262,9 @@
     private static void log(String message) {
         if (DEBUG_RESOLVER) Slog.d(TAG, message);
     }
+
+    private void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "mTransactionHandler:");
+        mTransactionHandler.dump(pw, prefix + "  ");
+    }
 }
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index b8fb2e3..6093a4a 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -21,12 +21,10 @@
 import android.annotation.StringDef;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
-import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IContentProvider;
 import android.content.Intent;
-import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
@@ -67,6 +65,7 @@
             HINT_TOGGLE,
             HINT_HORIZONTAL,
             HINT_PARTIAL,
+            HINT_SEE_MORE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SliceHint {}
@@ -151,7 +150,11 @@
      * Used to indicate the maximum integer value for a {@link #SUBTYPE_SLIDER}.
      */
     public static final String HINT_MAX = "max";
-
+    /**
+     * A hint representing that this item should be used to indicate that there's more
+     * content associated with this slice.
+     */
+    public static final String HINT_SEE_MORE = "see_more";
     /**
      * Key to retrieve an extra added to an intent when a control is changed.
      */
@@ -553,16 +556,11 @@
     }
 
     /**
-     * Turns a slice Uri into slice content.
-     *
-     * @param resolver ContentResolver to be used.
-     * @param uri The URI to a slice provider
-     * @param supportedSpecs List of supported specs.
-     * @return The Slice provided by the app or null if none is given.
-     * @see Slice
+     * @deprecated TO BE REMOVED.
      */
-    public static @Nullable Slice bindSlice(ContentResolver resolver, @NonNull Uri uri,
-            List<SliceSpec> supportedSpecs) {
+    @Deprecated
+    public static @Nullable Slice bindSlice(ContentResolver resolver,
+            @NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) {
         Preconditions.checkNotNull(uri, "uri");
         IContentProvider provider = resolver.acquireProvider(uri);
         if (provider == null) {
@@ -590,60 +588,11 @@
     }
 
     /**
-     * Turns a slice intent into slice content. Expects an explicit intent. If there is no
-     * {@link ContentProvider} associated with the given intent this will throw
-     * {@link IllegalArgumentException}.
-     *
-     * @param context The context to use.
-     * @param intent The intent associated with a slice.
-     * @param supportedSpecs List of supported specs.
-     * @return The Slice provided by the app or null if none is given.
-     * @see Slice
-     * @see SliceProvider#onMapIntentToUri(Intent)
-     * @see Intent
+     * @deprecated TO BE REMOVED.
      */
+    @Deprecated
     public static @Nullable Slice bindSlice(Context context, @NonNull Intent intent,
-            List<SliceSpec> supportedSpecs) {
-        Preconditions.checkNotNull(intent, "intent");
-        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
-                "Slice intent must be explicit " + intent);
-        ContentResolver resolver = context.getContentResolver();
-
-        // Check if the intent has data for the slice uri on it and use that
-        final Uri intentData = intent.getData();
-        if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) {
-            return bindSlice(resolver, intentData, supportedSpecs);
-        }
-        // Otherwise ask the app
-        List<ResolveInfo> providers =
-                context.getPackageManager().queryIntentContentProviders(intent, 0);
-        if (providers == null) {
-            throw new IllegalArgumentException("Unable to resolve intent " + intent);
-        }
-        String authority = providers.get(0).providerInfo.authority;
-        Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(authority).build();
-        IContentProvider provider = resolver.acquireProvider(uri);
-        if (provider == null) {
-            throw new IllegalArgumentException("Unknown URI " + uri);
-        }
-        try {
-            Bundle extras = new Bundle();
-            extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
-            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
-                    new ArrayList<>(supportedSpecs));
-            final Bundle res = provider.call(resolver.getPackageName(),
-                    SliceProvider.METHOD_MAP_INTENT, null, extras);
-            if (res == null) {
-                return null;
-            }
-            return res.getParcelable(SliceProvider.EXTRA_SLICE);
-        } catch (RemoteException e) {
-            // Arbitrary and not worth documenting, as Activity
-            // Manager will kill this process shortly anyway.
-            return null;
-        } finally {
-            resolver.releaseProvider(provider);
-        }
+            @NonNull List<SliceSpec> supportedSpecs) {
+        return context.getSystemService(SliceManager.class).bindSlice(intent, supportedSpecs);
     }
 }
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 0c5f225d..74864cb 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -17,17 +17,29 @@
 package android.app.slice;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.IContentProvider;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Pair;
 
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -39,6 +51,8 @@
 @SystemService(Context.SLICE_SERVICE)
 public class SliceManager {
 
+    private static final String TAG = "SliceManager";
+
     private final ISliceManager mService;
     private final Context mContext;
     private final ArrayMap<Pair<Uri, SliceCallback>, ISliceListener> mListenerLookup =
@@ -224,6 +238,126 @@
     }
 
     /**
+     * Obtains a list of slices that are descendants of the specified Uri.
+     * <p>
+     * Not all slice providers will implement this functionality, in which case,
+     * an empty collection will be returned.
+     *
+     * @param uri The uri to look for descendants under.
+     * @return All slices within the space.
+     * @see SliceProvider#onGetSliceDescendants(Uri)
+     */
+    public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) {
+        ContentResolver resolver = mContext.getContentResolver();
+        IContentProvider provider = resolver.acquireProvider(uri);
+        try {
+            Bundle extras = new Bundle();
+            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
+            final Bundle res = provider.call(resolver.getPackageName(),
+                    SliceProvider.METHOD_GET_DESCENDANTS, null, extras);
+            return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to get slice descendants", e);
+        } finally {
+            resolver.releaseProvider(provider);
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Turns a slice Uri into slice content.
+     *
+     * @param uri The URI to a slice provider
+     * @param supportedSpecs List of supported specs.
+     * @return The Slice provided by the app or null if none is given.
+     * @see Slice
+     */
+    public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) {
+        Preconditions.checkNotNull(uri, "uri");
+        ContentResolver resolver = mContext.getContentResolver();
+        IContentProvider provider = resolver.acquireProvider(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            Bundle extras = new Bundle();
+            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
+            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
+                    new ArrayList<>(supportedSpecs));
+            final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_SLICE,
+                    null, extras);
+            Bundle.setDefusable(res, true);
+            if (res == null) {
+                return null;
+            }
+            return res.getParcelable(SliceProvider.EXTRA_SLICE);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            resolver.releaseProvider(provider);
+        }
+    }
+
+    /**
+     * Turns a slice intent into slice content. Expects an explicit intent. If there is no
+     * {@link android.content.ContentProvider} associated with the given intent this will throw
+     * {@link IllegalArgumentException}.
+     *
+     * @param intent The intent associated with a slice.
+     * @param supportedSpecs List of supported specs.
+     * @return The Slice provided by the app or null if none is given.
+     * @see Slice
+     * @see SliceProvider#onMapIntentToUri(Intent)
+     * @see Intent
+     */
+    public @Nullable Slice bindSlice(@NonNull Intent intent,
+            @NonNull List<SliceSpec> supportedSpecs) {
+        Preconditions.checkNotNull(intent, "intent");
+        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
+                "Slice intent must be explicit " + intent);
+        ContentResolver resolver = mContext.getContentResolver();
+
+        // Check if the intent has data for the slice uri on it and use that
+        final Uri intentData = intent.getData();
+        if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) {
+            return bindSlice(intentData, supportedSpecs);
+        }
+        // Otherwise ask the app
+        List<ResolveInfo> providers =
+                mContext.getPackageManager().queryIntentContentProviders(intent, 0);
+        if (providers == null) {
+            throw new IllegalArgumentException("Unable to resolve intent " + intent);
+        }
+        String authority = providers.get(0).providerInfo.authority;
+        Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(authority).build();
+        IContentProvider provider = resolver.acquireProvider(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            Bundle extras = new Bundle();
+            extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
+            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
+                    new ArrayList<>(supportedSpecs));
+            final Bundle res = provider.call(resolver.getPackageName(),
+                    SliceProvider.METHOD_MAP_INTENT, null, extras);
+            if (res == null) {
+                return null;
+            }
+            return res.getParcelable(SliceProvider.EXTRA_SLICE);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            resolver.releaseProvider(provider);
+        }
+    }
+
+    /**
      * Class that listens to changes in {@link Slice}s.
      */
     public interface SliceCallback {
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 8483931..aa41f14 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -36,6 +36,9 @@
 import android.os.UserHandle;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
@@ -113,11 +116,19 @@
     /**
      * @hide
      */
+    public static final String METHOD_GET_DESCENDANTS = "get_descendants";
+    /**
+     * @hide
+     */
     public static final String EXTRA_INTENT = "slice_intent";
     /**
      * @hide
      */
     public static final String EXTRA_SLICE = "slice";
+    /**
+     * @hide
+     */
+    public static final String EXTRA_SLICE_DESCENDANTS = "slice_descendants";
 
     private static final boolean DEBUG = false;
 
@@ -139,14 +150,6 @@
      * @see {@link Slice#HINT_PARTIAL}
      */
     public Slice onBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs) {
-        return onBindSlice(sliceUri);
-    }
-
-    /**
-     * @deprecated migrating to {@link #onBindSlice(Uri, List)}
-     */
-    @Deprecated
-    public Slice onBindSlice(Uri sliceUri) {
         return null;
     }
 
@@ -183,6 +186,20 @@
     }
 
     /**
+     * Obtains a list of slices that are descendants of the specified Uri.
+     * <p>
+     * Implementing this is optional for a SliceProvider, but does provide a good
+     * discovery mechanism for finding slice Uris.
+     *
+     * @param uri The uri to look for descendants under.
+     * @return All slices within the space.
+     * @see SliceManager#getSliceDescendants(Uri)
+     */
+    public @NonNull Collection<Uri> onGetSliceDescendants(@NonNull Uri uri) {
+        return Collections.emptyList();
+    }
+
+    /**
      * This method must be overridden if an {@link IntentFilter} is specified on the SliceProvider.
      * In that case, this method can be called and is expected to return a non-null Uri representing
      * a slice. Otherwise this will throw {@link UnsupportedOperationException}.
@@ -290,10 +307,35 @@
                         "Slice binding requires the permission BIND_SLICE");
             }
             handleUnpinSlice(uri);
+        } else if (method.equals(METHOD_GET_DESCENDANTS)) {
+            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+            Bundle b = new Bundle();
+            b.putParcelableArrayList(EXTRA_SLICE_DESCENDANTS,
+                    new ArrayList<>(handleGetDescendants(uri)));
+            return b;
         }
         return super.call(method, arg, extras);
     }
 
+    private Collection<Uri> handleGetDescendants(Uri uri) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            return onGetSliceDescendants(uri);
+        } else {
+            CountDownLatch latch = new CountDownLatch(1);
+            Collection<Uri>[] output = new Collection[1];
+            Handler.getMain().post(() -> {
+                output[0] = onGetSliceDescendants(uri);
+                latch.countDown();
+            });
+            try {
+                latch.await();
+                return output[0];
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
     private void handlePinSlice(Uri sliceUri) {
         if (Looper.myLooper() == Looper.getMainLooper()) {
             onSlicePinned(sliceUri);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 3290d57..9f11d6e 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -79,8 +79,9 @@
  * {@link BluetoothDevice} objects representing all paired devices with
  * {@link #getBondedDevices()}; start device discovery with
  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
- * listen for incoming connection requests with
- * {@link #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
+ * listen for incoming RFComm connection requests with {@link
+ * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
+ * Channels (CoC) connection requests with listenUsingL2capCoc(int)}; or start a scan for
  * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
  * </p>
  * <p>This class is thread safe.</p>
@@ -210,6 +211,14 @@
     public static final int STATE_BLE_TURNING_OFF = 16;
 
     /**
+     * UUID of the GATT Read Characteristics for LE_PSM value.
+     *
+     * @hide
+     */
+    public static final UUID LE_PSM_CHARACTERISTIC_UUID =
+            UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
+
+    /**
      * Human-readable string helper for AdapterState
      *
      * @hide
@@ -1675,6 +1684,27 @@
     }
 
     /**
+     * Get the maximum number of connected audio devices.
+     *
+     * @return the maximum number of connected audio devices
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getMaxConnectedAudioDevices() {
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) {
+                return mService.getMaxConnectedAudioDevices();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return 1;
+    }
+
+    /**
      * Return true if hardware has entries available for matching beacons
      *
      * @return true if there are hw entries available for matching beacons
@@ -2139,7 +2169,9 @@
                         min16DigitPin);
         int errno = socket.mSocket.bindListen();
         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            socket.setChannel(socket.mSocket.getPort());
+            int assignedChannel = socket.mSocket.getPort();
+            if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
+            socket.setChannel(assignedChannel);
         }
         if (errno != 0) {
             //TODO(BT): Throw the same exception error code
@@ -2180,12 +2212,18 @@
      * @hide
      */
     public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
+        Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
         BluetoothServerSocket socket =
                 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
-                        false);
+                                          false);
         int errno = socket.mSocket.bindListen();
         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            socket.setChannel(socket.mSocket.getPort());
+            int assignedChannel = socket.mSocket.getPort();
+            if (DBG) {
+                Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
+                        + assignedChannel);
+            }
+            socket.setChannel(assignedChannel);
         }
         if (errno != 0) {
             //TODO(BT): Throw the same exception error code
@@ -2744,4 +2782,103 @@
             scanner.stopScan(scanCallback);
         }
     }
+
+    /**
+     * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
+     * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
+     * for incoming connections.
+     * <p>A remote device connecting to this socket will be authenticated and communication on this
+     * socket will be encrypted.
+     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
+     * {@link BluetoothServerSocket}.
+     * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {#link
+     * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
+     * closed, Bluetooth is turned off, or the application exits unexpectedly.
+     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
+     * defined and performed by the application.
+     * <p>Use {@link BluetoothDevice#createL2capCocSocket(int, int)} to connect to this server
+     * socket from another Android device that is given the PSM value.
+     *
+     * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
+     * @return an L2CAP CoC BluetoothServerSocket
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions, or unable to start this CoC
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothServerSocket listenUsingL2capCoc(int transport)
+            throws IOException {
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        BluetoothServerSocket socket =
+                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
+                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
+        int errno = socket.mSocket.bindListen();
+        if (errno != 0) {
+            throw new IOException("Error: " + errno);
+        }
+
+        int assignedPsm = socket.mSocket.getPort();
+        if (assignedPsm == 0) {
+            throw new IOException("Error: Unable to assign PSM value");
+        }
+        if (DBG) {
+            Log.d(TAG, "listenUsingL2capCoc: set assigned PSM to "
+                    + assignedPsm);
+        }
+        socket.setChannel(assignedPsm);
+
+        return socket;
+    }
+
+    /**
+     * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
+     * assign a dynamic PSM value. This socket can be used to listen for incoming connections.
+     * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
+     * to man-in-the-middle attacks. Use {@link #listenUsingL2capCoc}, if an encrypted and
+     * authenticated communication channel is desired.
+     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
+     * {@link BluetoothServerSocket}.
+     * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
+     * can be read from the {#link BluetoothServerSocket#getPsm()} and this value will be released
+     * when this server socket is closed, Bluetooth is turned off, or the application exits
+     * unexpectedly.
+     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
+     * defined and performed by the application.
+     * <p>Use {@link BluetoothDevice#createInsecureL2capCocSocket(int, int)} to connect to this
+     * server socket from another Android device that is given the PSM value.
+     *
+     * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
+     * @return an L2CAP CoC BluetoothServerSocket
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions, or unable to start this CoC
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
+            throws IOException {
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        BluetoothServerSocket socket =
+                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
+                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
+        int errno = socket.mSocket.bindListen();
+        if (errno != 0) {
+            throw new IOException("Error: " + errno);
+        }
+
+        int assignedPsm = socket.mSocket.getPort();
+        if (assignedPsm == 0) {
+            throw new IOException("Error: Unable to assign PSM value");
+        }
+        if (DBG) {
+            Log.d(TAG, "listenUsingInsecureL2capOn: set assigned PSM to "
+                    + assignedPsm);
+        }
+        socket.setChannel(assignedPsm);
+
+        return socket;
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 9b736b7..ac21395 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1921,4 +1921,75 @@
         }
         return null;
     }
+
+    /**
+     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
+     * be used to start a secure outgoing connection to the remote device with the same dynamic
+     * protocol/service multiplexer (PSM) value.
+     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capCoc(int)} for
+     * peer-peer Bluetooth applications.
+     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
+     * <p>Application using this API is responsible for obtaining PSM value from remote device.
+     * <p>The remote device will be authenticated and communication on this socket will be
+     * encrypted.
+     * <p> Use this socket if an authenticated socket link is possible. Authentication refers
+     * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a
+     * secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int,
+     * int)}.
+     *
+     * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
+     * @param psm dynamic PSM value from remote device
+     * @return a CoC #BluetoothSocket ready for an outgoing connection
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
+        if (!isBluetoothEnabled()) {
+            Log.e(TAG, "createL2capCocSocket: Bluetooth is not enabled");
+            throw new IOException();
+        }
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        if (DBG) Log.d(TAG, "createL2capCocSocket: transport=" + transport + ", psm=" + psm);
+        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
+                null);
+    }
+
+    /**
+     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
+     * be used to start a secure outgoing connection to the remote device with the same dynamic
+     * protocol/service multiplexer (PSM) value.
+     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingInsecureL2capCoc(int)}
+     * for peer-peer Bluetooth applications.
+     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
+     * <p>Application using this API is responsible for obtaining PSM value from remote device.
+     * <p> The communication channel may not have an authenticated link key, i.e. it may be subject
+     * to man-in-the-middle attacks. Use {@link #createL2capCocSocket(int, int)} if an encrypted and
+     * authenticated communication channel is possible.
+     *
+     * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
+     * @param psm dynamic PSM value from remote device
+     * @return a CoC #BluetoothSocket ready for an outgoing connection
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
+        if (!isBluetoothEnabled()) {
+            Log.e(TAG, "createInsecureL2capCocSocket: Bluetooth is not enabled");
+            throw new IOException();
+        }
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        if (DBG) {
+            Log.d(TAG, "createInsecureL2capCocSocket: transport=" + transport + ", psm=" + psm);
+        }
+        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
+                null);
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
index dc00d63..d46b2e3 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -73,17 +73,18 @@
     private final boolean mOutgoing;
     private final UUID mUUID;
     private final long mCreationElapsedMilli;
+    private final boolean mInBandRing;
 
     /**
      * Creates BluetoothHeadsetClientCall instance.
      */
     public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number,
-            boolean multiParty, boolean outgoing) {
-        this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing);
+            boolean multiParty, boolean outgoing, boolean inBandRing) {
+        this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing, inBandRing);
     }
 
     public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state,
-            String number, boolean multiParty, boolean outgoing) {
+            String number, boolean multiParty, boolean outgoing, boolean inBandRing) {
         mDevice = device;
         mId = id;
         mUUID = uuid;
@@ -91,6 +92,7 @@
         mNumber = number != null ? number : "";
         mMultiParty = multiParty;
         mOutgoing = outgoing;
+        mInBandRing = inBandRing;
         mCreationElapsedMilli = SystemClock.elapsedRealtime();
     }
 
@@ -200,6 +202,16 @@
         return mOutgoing;
     }
 
+    /**
+     * Checks if the ringtone will be generated by the connected phone
+     *
+     * @return <code>true</code> if in band ring is enabled, <code>false</code> otherwise.
+     */
+    public boolean isInBandRing() {
+        return mInBandRing;
+    }
+
+
     @Override
     public String toString() {
         return toString(false);
@@ -253,6 +265,8 @@
         builder.append(mMultiParty);
         builder.append(", mOutgoing: ");
         builder.append(mOutgoing);
+        builder.append(", mInBandRing: ");
+        builder.append(mInBandRing);
         builder.append("}");
         return builder.toString();
     }
@@ -266,7 +280,8 @@
                 public BluetoothHeadsetClientCall createFromParcel(Parcel in) {
                     return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null),
                             in.readInt(), UUID.fromString(in.readString()), in.readInt(),
-                            in.readString(), in.readInt() == 1, in.readInt() == 1);
+                            in.readString(), in.readInt() == 1, in.readInt() == 1,
+                            in.readInt() == 1);
                 }
 
                 @Override
@@ -284,6 +299,7 @@
         out.writeString(mNumber);
         out.writeInt(mMultiParty ? 1 : 0);
         out.writeInt(mOutgoing ? 1 : 0);
+        out.writeInt(mInBandRing ? 1 : 0);
     }
 
     @Override
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 58d090d..ebb7f18 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -68,6 +68,7 @@
 public final class BluetoothServerSocket implements Closeable {
 
     private static final String TAG = "BluetoothServerSocket";
+    private static final boolean DBG = false;
     /*package*/ final BluetoothSocket mSocket;
     private Handler mHandler;
     private int mMessage;
@@ -169,6 +170,7 @@
      * close any {@link BluetoothSocket} received from {@link #accept()}.
      */
     public void close() throws IOException {
+        if (DBG) Log.d(TAG, "BluetoothServerSocket:close() called. mChannel=" + mChannel);
         synchronized (this) {
             if (mHandler != null) {
                 mHandler.obtainMessage(mMessage).sendToTarget();
@@ -197,6 +199,20 @@
     }
 
     /**
+     * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
+     * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
+     * {#link BluetoothAdapter.listenUsingL2capCoc(int)} or {#link
+     * BluetoothAdapter.listenUsingInsecureL2capCoc(int)}. The returned value is undefined if this
+     * method is called on non-L2CAP server sockets.
+     *
+     * @return the assigned PSM or LE_PSM value depending on transport
+     * @hide
+     */
+    public int getPsm() {
+        return mChannel;
+    }
+
+    /**
      * Sets the channel on which future sockets are bound.
      * Currently used only when a channel is auto generated.
      */
@@ -227,6 +243,10 @@
                 sb.append("TYPE_L2CAP");
                 break;
             }
+            case BluetoothSocket.TYPE_L2CAP_LE: {
+                sb.append("TYPE_L2CAP_LE");
+                break;
+            }
             case BluetoothSocket.TYPE_SCO: {
                 sb.append("TYPE_SCO");
                 break;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 0569913..09f9684 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -99,6 +99,16 @@
     /** L2CAP socket */
     public static final int TYPE_L2CAP = 3;
 
+    /** L2CAP socket on BR/EDR transport
+     * @hide
+     */
+    public static final int TYPE_L2CAP_BREDR = TYPE_L2CAP;
+
+    /** L2CAP socket on LE transport
+     * @hide
+     */
+    public static final int TYPE_L2CAP_LE = 4;
+
     /*package*/ static final int EBADFD = 77;
     /*package*/ static final int EADDRINUSE = 98;
 
@@ -417,6 +427,7 @@
             return -1;
         }
         try {
+            if (DBG) Log.d(TAG, "bindListen(): mPort=" + mPort + ", mType=" + mType);
             mPfd = bluetoothProxy.getSocketManager().createSocketChannel(mType, mServiceName,
                     mUuid, mPort, getSecurityFlags());
         } catch (RemoteException e) {
@@ -451,7 +462,7 @@
                     mSocketState = SocketState.LISTENING;
                 }
             }
-            if (DBG) Log.d(TAG, "channel: " + channel);
+            if (DBG) Log.d(TAG, "bindListen(): channel=" + channel + ", mPort=" + mPort);
             if (mPort <= -1) {
                 mPort = channel;
             } // else ASSERT(mPort == channel)
@@ -515,7 +526,7 @@
     /*package*/ int read(byte[] b, int offset, int length) throws IOException {
         int ret = 0;
         if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
-        if (mType == TYPE_L2CAP) {
+        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
             int bytesToRead = length;
             if (VDBG) {
                 Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length
@@ -558,7 +569,7 @@
         //      Rfcomm uses dynamic allocation, and should not have any bindings
         //      to the actual message length.
         if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
-        if (mType == TYPE_L2CAP) {
+        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
             if (length <= mMaxTxPacketSize) {
                 mSocketOS.write(b, offset, length);
             } else {
@@ -702,7 +713,7 @@
     }
 
     private void createL2capRxBuffer() {
-        if (mType == TYPE_L2CAP) {
+        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
             // Allocate the buffer to use for reads.
             if (VDBG) Log.v(TAG, "  Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize);
             mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f69e764..265f7c7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4146,7 +4146,7 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
-     * {@link android.content.pm.crossprofile.CrossProfileApps} for cross profile operations.
+     * {@link android.content.pm.CrossProfileApps} for cross profile operations.
      *
      * @see #getSystemService(String)
      */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6e99709..f05a4d1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3516,12 +3516,83 @@
      * For more details see TelephonyIntents.ACTION_SIM_STATE_CHANGED. This is here
      * because TelephonyIntents is an internal class.
      * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
+     * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
+    @Deprecated
     @SystemApi
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
 
     /**
+     * Broadcast Action: The sim card state has changed.
+     * The intent will have the following extra values:</p>
+     * <dl>
+     *   <dt>{@link android.telephony.TelephonyManager.EXTRA_SIM_STATE}</dt>
+     *   <dd>The sim card state. One of:
+     *     <dl>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_ABSENT}</dt>
+     *       <dd>SIM card not found</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_CARD_IO_ERROR}</dt>
+     *       <dd>SIM card IO error</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_CARD_RESTRICTED}</dt>
+     *       <dd>SIM card is restricted</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PRESENT}</dt>
+     *       <dd>SIM card is present</dd>
+     *     </dl>
+     *   </dd>
+     * </dl>
+     *
+     * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * <p class="note">The current state can also be queried using
+     * {@link android.telephony.TelephonyManager.getSimCardState()}
+     *
+     * <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_SIM_CARD_STATE_CHANGED =
+            "android.intent.action.SIM_CARD_STATE_CHANGED";
+
+    /**
+     * Broadcast Action: The sim application state has changed.
+     * The intent will have the following extra values:</p>
+     * <dl>
+     *   <dt>{@link android.telephony.TelephonyManager.EXTRA_SIM_STATE}</dt>
+     *   <dd>The sim application state. One of:
+     *     <dl>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_NOT_READY}</dt>
+     *       <dd>SIM card applications not ready</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED}</dt>
+     *       <dd>SIM card PIN locked</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PUK_REQUIRED}</dt>
+     *       <dd>SIM card PUK locked</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_NETWORK_LOCKED}</dt>
+     *       <dd>SIM card network locked</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PERM_DISABLED}</dt>
+     *       <dd>SIM card permanently disabled due to PUK failures</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_LOADED}</dt>
+     *       <dd>SIM card data loaded</dd>
+     *     </dl>
+     *   </dd>
+     * </dl>
+     *
+     * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * <p class="note">The current state can also be queried using
+     * {@link android.telephony.TelephonyManager.getSimApplicationState()}
+     *
+     * <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_SIM_APPLICATION_STATE_CHANGED =
+            "android.intent.action.SIM_APPLICATION_STATE_CHANGED";
+
+    /**
      * Broadcast Action: indicate that the phone service state has changed.
      * The intent will have the following extra values:</p>
      * <p>
diff --git a/core/java/android/content/pm/crossprofile/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
similarity index 92%
rename from core/java/android/content/pm/crossprofile/CrossProfileApps.java
rename to core/java/android/content/pm/CrossProfileApps.java
index 414c138..7d5d609 100644
--- a/core/java/android/content/pm/crossprofile/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.crossprofile;
+package android.content.pm;
 
 import android.annotation.NonNull;
 import android.content.ComponentName;
@@ -57,13 +57,14 @@
      *        action {@link android.content.Intent#ACTION_MAIN}, category
      *        {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
      *        be thrown.
-     * @param user The UserHandle of the profile, must be one of the users returned by
+     * @param targetUser The UserHandle of the profile, must be one of the users returned by
      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
      *        be thrown.
      */
-    public void startMainActivity(@NonNull ComponentName component, @NonNull UserHandle user) {
+    public void startMainActivity(@NonNull ComponentName component,
+            @NonNull UserHandle targetUser) {
         try {
-            mService.startActivityAsUser(mContext.getPackageName(), component, user);
+            mService.startActivityAsUser(mContext.getPackageName(), component, targetUser);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
@@ -114,7 +115,7 @@
     }
 
     /**
-     * Return an icon that calling app can show to user for the semantic of profile switching --
+     * Return a drawable that calling app can show to user for the semantic of profile switching --
      * launching its own activity in specified user profile. For example, it may return a briefcase
      * icon if the given user handle is the managed profile one.
      *
@@ -124,9 +125,9 @@
      * @return an icon that calling app can show user for the semantic of launching its own
      *         activity in specified user profile.
      *
-     * @see #startMainActivity(ComponentName, UserHandle, Rect, Bundle)
+     * @see #startMainActivity(ComponentName, UserHandle)
      */
-    public @NonNull Drawable getProfileSwitchingIcon(@NonNull UserHandle userHandle) {
+    public @NonNull Drawable getProfileSwitchingIconDrawable(@NonNull UserHandle userHandle) {
         verifyCanAccessUser(userHandle);
 
         final boolean isManagedProfile =
diff --git a/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl
similarity index 95%
rename from core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl
rename to core/java/android/content/pm/ICrossProfileApps.aidl
index 227f91f5..e79deb9 100644
--- a/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl
+++ b/core/java/android/content/pm/ICrossProfileApps.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm.crossprofile;
+package android.content.pm;
 
 import android.content.ComponentName;
 import android.content.Intent;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index deb8dfb..bcf80ee 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1297,6 +1297,15 @@
      */
     public static final int INSTALL_FAILED_INSTANT_APP_INVALID = -116;
 
+    /**
+     * Installation parse return code: this is passed in the
+     * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the dex metadata file is invalid or
+     * if there was no matching apk file for a dex metadata file.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_BAD_DEX_METADATA = -117;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DELETE_" }, value = {
             DELETE_KEEP_DATA,
@@ -2535,31 +2544,22 @@
      * Devices declaring this feature must include an application implementing a
      * {@link android.service.vr.VrListenerService} that can be targeted by VR applications via
      * {@link android.app.Activity#setVrModeEnabled}.
+     * @deprecated use {@link #FEATURE_VR_MODE_HIGH_PERFORMANCE} instead.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_VR_MODE = "android.software.vr.mode";
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
-     * The device implements {@link #FEATURE_VR_MODE} but additionally meets extra CDD requirements
-     * to provide a high-quality VR experience.  In general, devices declaring this feature will
-     * additionally:
-     * <ul>
-     *   <li>Deliver consistent performance at a high framerate over an extended period of time
-     *   for typical VR application CPU/GPU workloads with a minimal number of frame drops for VR
-     *   applications that have called
-     *   {@link android.view.Window#setSustainedPerformanceMode}.</li>
-     *   <li>Implement {@link #FEATURE_HIFI_SENSORS} and have a low sensor latency.</li>
-     *   <li>Include optimizations to lower display persistence while running VR applications.</li>
-     *   <li>Implement an optimized render path to minimize latency to draw to the device's main
-     *   display.</li>
-     *   <li>Include the following EGL extensions: EGL_ANDROID_create_native_client_buffer,
-     *   EGL_ANDROID_front_buffer_auto_refresh, EGL_EXT_protected_content,
-     *   EGL_KHR_mutable_render_buffer, EGL_KHR_reusable_sync, and EGL_KHR_wait_sync.</li>
-     *   <li>Provide at least one CPU core that is reserved for use solely by the top, foreground
-     *   VR application process for critical render threads while such an application is
-     *   running.</li>
-     * </ul>
+     * The device implements an optimized mode for virtual reality (VR) applications that handles
+     * stereoscopic rendering of notifications, disables most monocular system UI components
+     * while a VR application has user focus and meets extra CDD requirements to provide a
+     * high-quality VR experience.
+     * Devices declaring this feature must include an application implementing a
+     * {@link android.service.vr.VrListenerService} that can be targeted by VR applications via
+     * {@link android.app.Activity#setVrModeEnabled}.
+     * and must meet CDD requirements to provide a high-quality VR experience.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_VR_MODE_HIGH_PERFORMANCE
@@ -5627,6 +5627,8 @@
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return "INSTALL_FAILED_DUPLICATE_PERMISSION";
             case INSTALL_FAILED_NO_MATCHING_ABIS: return "INSTALL_FAILED_NO_MATCHING_ABIS";
             case INSTALL_FAILED_ABORTED: return "INSTALL_FAILED_ABORTED";
+            case INSTALL_FAILED_BAD_DEX_METADATA:
+                return "INSTALL_FAILED_BAD_DEX_METADATA";
             default: return Integer.toString(status);
         }
     }
@@ -5671,6 +5673,7 @@
             case INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_MANIFEST_EMPTY: return PackageInstaller.STATUS_FAILURE_INVALID;
+            case INSTALL_FAILED_BAD_DEX_METADATA: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_FAILED_INTERNAL_ERROR: return PackageInstaller.STATUS_FAILURE;
             case INSTALL_FAILED_USER_RESTRICTED: return PackageInstaller.STATUS_FAILURE_INCOMPATIBLE;
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return PackageInstaller.STATUS_FAILURE_CONFLICT;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6d6c02a..4a71467 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -240,6 +240,9 @@
     }
 
     /** @hide */
+    public static final String APK_FILE_EXTENSION = ".apk";
+
+    /** @hide */
     public static class NewPermissionInfo {
         public final String name;
         public final int sdkVersion;
@@ -613,7 +616,7 @@
     }
 
     public static boolean isApkPath(String path) {
-        return path.endsWith(".apk");
+        return path.endsWith(APK_FILE_EXTENSION);
     }
 
     /**
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
new file mode 100644
index 0000000..c5f1c85
--- /dev/null
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -0,0 +1,230 @@
+/**
+ * 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.content.pm.dex;
+
+import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
+import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
+
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.PackageParser.PackageParserException;
+import android.util.ArrayMap;
+import android.util.jar.StrictJarFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class used to compute and validate the location of dex metadata files.
+ *
+ * @hide
+ */
+public class DexMetadataHelper {
+    private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
+
+    private DexMetadataHelper() {}
+
+    /** Return true if the given file is a dex metadata file. */
+    public static boolean isDexMetadataFile(File file) {
+        return isDexMetadataPath(file.getName());
+    }
+
+    /** Return true if the given path is a dex metadata path. */
+    private static boolean isDexMetadataPath(String path) {
+        return path.endsWith(DEX_METADATA_FILE_EXTENSION);
+    }
+
+    /**
+     * Return the size (in bytes) of all dex metadata files associated with the given package.
+     */
+    public static long getPackageDexMetadataSize(PackageLite pkg) {
+        long sizeBytes = 0;
+        Collection<String> dexMetadataList = DexMetadataHelper.getPackageDexMetadata(pkg).values();
+        for (String dexMetadata : dexMetadataList) {
+            sizeBytes += new File(dexMetadata).length();
+        }
+        return sizeBytes;
+    }
+
+    /**
+     * Search for the dex metadata file associated with the given target file.
+     * If it exists, the method returns the dex metadata file; otherwise it returns null.
+     *
+     * Note that this performs a loose matching suitable to be used in the InstallerSession logic.
+     * i.e. the method will attempt to match the {@code dmFile} regardless of {@code targetFile}
+     * extension (e.g. 'foo.dm' will match 'foo' or 'foo.apk').
+     */
+    public static File findDexMetadataForFile(File targetFile) {
+        String dexMetadataPath = buildDexMetadataPathForFile(targetFile);
+        File dexMetadataFile = new File(dexMetadataPath);
+        return dexMetadataFile.exists() ? dexMetadataFile : null;
+    }
+
+    /**
+     * Return the dex metadata files for the given package as a map
+     * [code path -> dex metadata path].
+     *
+     * NOTE: involves I/O checks.
+     */
+    public static Map<String, String> getPackageDexMetadata(PackageParser.Package pkg) {
+        return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths());
+    }
+
+    /**
+     * Return the dex metadata files for the given package as a map
+     * [code path -> dex metadata path].
+     *
+     * NOTE: involves I/O checks.
+     */
+    private static Map<String, String> getPackageDexMetadata(PackageLite pkg) {
+        return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths());
+    }
+
+    /**
+     * Look up the dex metadata files for the given code paths building the map
+     * [code path -> dex metadata].
+     *
+     * For each code path (.apk) the method checks if a matching dex metadata file (.dm) exists.
+     * If it does it adds the pair to the returned map.
+     *
+     * Note that this method will do a strict
+     * matching based on the extension ('foo.dm' will only match 'foo.apk').
+     *
+     * This should only be used for code paths extracted from a package structure after the naming
+     * was enforced in the installer.
+     */
+    private static Map<String, String> buildPackageApkToDexMetadataMap(
+            List<String> codePaths) {
+        ArrayMap<String, String> result = new ArrayMap<>();
+        for (int i = codePaths.size() - 1; i >= 0; i--) {
+            String codePath = codePaths.get(i);
+            String dexMetadataPath = buildDexMetadataPathForApk(codePath);
+
+            if (Files.exists(Paths.get(dexMetadataPath))) {
+                result.put(codePath, dexMetadataPath);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Return the dex metadata path associated with the given code path.
+     * (replaces '.apk' extension with '.dm')
+     *
+     * @throws IllegalArgumentException if the code path is not an .apk.
+     */
+    public static String buildDexMetadataPathForApk(String codePath) {
+        if (!PackageParser.isApkPath(codePath)) {
+            throw new IllegalStateException(
+                    "Corrupted package. Code path is not an apk " + codePath);
+        }
+        return codePath.substring(0, codePath.length() - APK_FILE_EXTENSION.length())
+                + DEX_METADATA_FILE_EXTENSION;
+    }
+
+    /**
+     * Return the dex metadata path corresponding to the given {@code targetFile} using a loose
+     * matching.
+     * i.e. the method will attempt to match the {@code dmFile} regardless of {@code targetFile}
+     * extension (e.g. 'foo.dm' will match 'foo' or 'foo.apk').
+     */
+    private static String buildDexMetadataPathForFile(File targetFile) {
+        return PackageParser.isApkFile(targetFile)
+                ? buildDexMetadataPathForApk(targetFile.getPath())
+                : targetFile.getPath() + DEX_METADATA_FILE_EXTENSION;
+    }
+
+    /**
+     * Validate the dex metadata files installed for the given package.
+     *
+     * @throws PackageParserException in case of errors.
+     */
+    public static void validatePackageDexMetadata(PackageParser.Package pkg)
+            throws PackageParserException {
+        Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
+        for (String dexMetadata : apkToDexMetadataList) {
+            validateDexMetadataFile(dexMetadata);
+        }
+    }
+
+    /**
+     * Validate that the given file is a dex metadata archive.
+     * This is just a sanity validation that the file is a zip archive.
+     *
+     * @throws PackageParserException if the file is not a .dm file.
+     */
+    private static void validateDexMetadataFile(String dmaPath) throws PackageParserException {
+        StrictJarFile jarFile = null;
+        try {
+            jarFile = new StrictJarFile(dmaPath, false, false);
+        } catch (IOException e) {
+            throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
+                    "Error opening " + dmaPath, e);
+        } finally {
+            if (jarFile != null) {
+                try {
+                    jarFile.close();
+                } catch (IOException ignored) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Validates that all dex metadata paths in the given list have a matching apk.
+     * (for any foo.dm there should be either a 'foo' of a 'foo.apk' file).
+     * If that's not the case it throws {@code IllegalStateException}.
+     *
+     * This is used to perform a basic sanity check during adb install commands.
+     * (The installer does not support stand alone .dm files)
+     */
+    public static void validateDexPaths(String[] paths) {
+        ArrayList<String> apks = new ArrayList<>();
+        for (int i = 0; i < paths.length; i++) {
+            if (PackageParser.isApkPath(paths[i])) {
+                apks.add(paths[i]);
+            }
+        }
+        ArrayList<String> unmatchedDmFiles = new ArrayList<>();
+        for (int i = 0; i < paths.length; i++) {
+            String dmPath = paths[i];
+            if (isDexMetadataPath(dmPath)) {
+                boolean valid = false;
+                for (int j = apks.size() - 1; j >= 0; j--) {
+                    if (dmPath.equals(buildDexMetadataPathForFile(new File(apks.get(j))))) {
+                        valid = true;
+                        break;
+                    }
+                }
+                if (!valid) {
+                    unmatchedDmFiles.add(dmPath);
+                }
+            }
+        }
+        if (!unmatchedDmFiles.isEmpty()) {
+            throw new IllegalStateException("Unmatched .dm files: " + unmatchedDmFiles);
+        }
+    }
+
+}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 49f357e..a2991e6 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -66,7 +66,7 @@
      * created or opened until one of {@link #getWritableDatabase} or
      * {@link #getReadableDatabase} is called.
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name of the database file, or null for an in-memory database
      * @param factory to use for creating cursor objects, or null for the default
      * @param version number of the database (starting at 1); if the database is older,
@@ -86,7 +86,7 @@
      * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
      * used to handle corruption when sqlite reports database corruption.</p>
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name of the database file, or null for an in-memory database
      * @param factory to use for creating cursor objects, or null for the default
      * @param version number of the database (starting at 1); if the database is older,
@@ -107,7 +107,7 @@
      * created or opened until one of {@link #getWritableDatabase} or
      * {@link #getReadableDatabase} is called.
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name of the database file, or null for an in-memory database
      * @param version number of the database (starting at 1); if the database is older,
      *     {@link #onUpgrade} will be used to upgrade the database; if the database is
@@ -128,7 +128,7 @@
      * minimumSupportedVersion is found, it is simply deleted and a new database is created with the
      * given name and version
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name the name of the database file, null for a temporary in-memory database
      * @param factory to use for creating cursor objects, null for default
      * @param version the required version of the database
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ce1fba7..639795a 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -183,7 +183,9 @@
           TEMPLATE_RECORD,
           TEMPLATE_VIDEO_SNAPSHOT,
           TEMPLATE_ZERO_SHUTTER_LAG,
-          TEMPLATE_MANUAL })
+          TEMPLATE_MANUAL,
+          TEMPLATE_MOTION_TRACKING_PREVIEW,
+          TEMPLATE_MOTION_TRACKING_BEST})
      public @interface RequestTemplate {};
 
     /**
@@ -424,14 +426,17 @@
      * {@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.  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.
+     * 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 PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code FULL FOV 640}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Live preview with a tracking YUV output and a maximum-resolution YUV for still captures.</td> </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>
      *
@@ -899,12 +904,6 @@
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
-     *
-     * @see #TEMPLATE_PREVIEW
-     * @see #TEMPLATE_RECORD
-     * @see #TEMPLATE_STILL_CAPTURE
-     * @see #TEMPLATE_VIDEO_SNAPSHOT
-     * @see #TEMPLATE_MANUAL
      */
     @NonNull
     public abstract 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 1c7f289..2294ec5 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1359,6 +1359,20 @@
      */
     public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4;
 
+    /**
+     * <p>An external flash has been turned on.</p>
+     * <p>It informs the camera device that an external flash has been turned on, and that
+     * metering (and continuous focus if active) should be quickly recaculated to account
+     * for the external flash. Otherwise, this mode acts like ON.</p>
+     * <p>When the external flash is turned off, AE mode should be changed to one of the
+     * other available AE modes.</p>
+     * <p>If the camera device supports AE external flash mode, aeState must be
+     * FLASH_REQUIRED after the camera device finishes AE scan and it's too dark without
+     * flash.</p>
+     * @see CaptureRequest#CONTROL_AE_MODE
+     */
+    public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index cf27c70..ce75fa52 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1076,6 +1076,7 @@
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH ON_AUTO_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li>
+     *   <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p>
@@ -1093,6 +1094,7 @@
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH
      * @see #CONTROL_AE_MODE_ON_ALWAYS_FLASH
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
+     * @see #CONTROL_AE_MODE_ON_EXTERNAL_FLASH
      */
     @PublicKey
     public static final Key<Integer> CONTROL_AE_MODE =
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index b6b0c90..237a92d 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -691,6 +691,7 @@
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH ON_AUTO_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li>
+     *   <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p>
@@ -708,6 +709,7 @@
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH
      * @see #CONTROL_AE_MODE_ON_ALWAYS_FLASH
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
+     * @see #CONTROL_AE_MODE_ON_EXTERNAL_FLASH
      */
     @PublicKey
     public static final Key<Integer> CONTROL_AE_MODE =
@@ -877,7 +879,7 @@
      * </tr>
      * </tbody>
      * </table>
-     * <p>When {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is AE_MODE_ON_*:</p>
+     * <p>When {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is AE_MODE_ON*:</p>
      * <table>
      * <thead>
      * <tr>
@@ -998,10 +1000,13 @@
      * </tr>
      * </tbody>
      * </table>
+     * <p>If the camera device supports AE external flash mode (ON_EXTERNAL_FLASH is included in
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}), aeState must be FLASH_REQUIRED after the camera device
+     * finishes AE scan and it's too dark without flash.</p>
      * <p>For the above table, the camera device may skip reporting any state changes that happen
      * without application intervention (i.e. mode switch, trigger, locking). Any state that
      * can be skipped in that manner is called a transient state.</p>
-     * <p>For example, for above AE modes (AE_MODE_ON_*), in addition to the state transitions
+     * <p>For example, for above AE modes (AE_MODE_ON*), in addition to the state transitions
      * listed in above table, it is also legal for the camera device to skip one or more
      * transient states between two results. See below table for examples:</p>
      * <table>
@@ -1072,6 +1077,7 @@
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
+     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 2156491..67e97bf 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.hardware.display;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.Parcel;
@@ -25,6 +26,7 @@
 import com.android.internal.util.Preconditions;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 /** @hide */
 @SystemApi
@@ -32,10 +34,12 @@
 public final class BrightnessConfiguration implements Parcelable {
     private final float[] mLux;
     private final float[] mNits;
+    private final String mDescription;
 
-    private BrightnessConfiguration(float[] lux, float[] nits) {
+    private BrightnessConfiguration(float[] lux, float[] nits, String description) {
         mLux = lux;
         mNits = nits;
+        mDescription = description;
     }
 
     /**
@@ -51,10 +55,19 @@
         return Pair.create(Arrays.copyOf(mLux, mLux.length), Arrays.copyOf(mNits, mNits.length));
     }
 
+    /**
+     * Returns description string.
+     * @hide
+     */
+    public String getDescription() {
+        return mDescription;
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeFloatArray(mLux);
         dest.writeFloatArray(mNits);
+        dest.writeString(mDescription);
     }
 
     @Override
@@ -72,7 +85,9 @@
             }
             sb.append("(").append(mLux[i]).append(", ").append(mNits[i]).append(")");
         }
-        sb.append("]}");
+        sb.append("], '");
+        sb.append(mDescription);
+        sb.append("'}");
         return sb.toString();
     }
 
@@ -81,6 +96,7 @@
         int result = 1;
         result = result * 31 + Arrays.hashCode(mLux);
         result = result * 31 + Arrays.hashCode(mNits);
+        result = result * 31 + mDescription.hashCode();
         return result;
     }
 
@@ -93,16 +109,17 @@
             return false;
         }
         final BrightnessConfiguration other = (BrightnessConfiguration) o;
-        return Arrays.equals(mLux, other.mLux) && Arrays.equals(mNits, other.mNits);
+        return Arrays.equals(mLux, other.mLux) && Arrays.equals(mNits, other.mNits)
+                && Objects.equals(mDescription, other.mDescription);
     }
 
     public static final Creator<BrightnessConfiguration> CREATOR =
             new Creator<BrightnessConfiguration>() {
         public BrightnessConfiguration createFromParcel(Parcel in) {
-            Builder builder = new Builder();
             float[] lux = in.createFloatArray();
             float[] nits = in.createFloatArray();
-            builder.setCurve(lux, nits);
+            Builder builder = new Builder(lux, nits);
+            builder.setDescription(in.readString());
             return builder.build();
         }
 
@@ -117,6 +134,29 @@
     public static class Builder {
         private float[] mCurveLux;
         private float[] mCurveNits;
+        private String mDescription;
+
+        /**
+         * STOPSHIP remove when app has stopped using this.
+         * @hide
+         */
+        public Builder() {
+        }
+
+        /**
+         * Constructs the builder with the control points for the brightness curve.
+         *
+         * Brightness curves must have strictly increasing ambient brightness values in lux and
+         * monotonically increasing display brightness values in nits. In addition, the initial
+         * control point must be 0 lux.
+         *
+         * @throws IllegalArgumentException if the initial control point is not at 0 lux.
+         * @throws IllegalArgumentException if the lux levels are not strictly increasing.
+         * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
+         */
+        public Builder(float[] lux, float[] nits) {
+            setCurve(lux, nits);
+        }
 
         /**
          * Sets the control points for the brightness curve.
@@ -128,6 +168,9 @@
          * @throws IllegalArgumentException if the initial control point is not at 0 lux.
          * @throws IllegalArgumentException if the lux levels are not strictly increasing.
          * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
+         *
+         * STOPSHIP remove when app has stopped using this.
+         * @hide
          */
         public Builder setCurve(float[] lux, float[] nits) {
             Preconditions.checkNotNull(lux);
@@ -151,6 +194,17 @@
         }
 
         /**
+         * Set description of the brightness curve.
+         *
+         * @param description brief text describing the curve pushed. It maybe truncated
+         *                    and will not be displayed in the UI
+         */
+        public Builder setDescription(@Nullable String description) {
+            mDescription = description;
+            return this;
+        }
+
+        /**
          * Builds the {@link BrightnessConfiguration}.
          *
          * A brightness curve <b>must</b> be set before calling this.
@@ -159,7 +213,7 @@
             if (mCurveLux == null || mCurveNits == null) {
                 throw new IllegalStateException("A curve must be set!");
             }
-            return new BrightnessConfiguration(mCurveLux, mCurveNits);
+            return new BrightnessConfiguration(mCurveLux, mCurveNits, mDescription);
         }
 
         private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) {
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 76ab35d..36673cd 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -639,7 +639,7 @@
     @TestApi
     @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
     public void setBrightnessConfiguration(BrightnessConfiguration c) {
-        setBrightnessConfigurationForUser(c, UserHandle.myUserId());
+        setBrightnessConfigurationForUser(c, UserHandle.myUserId(), mContext.getPackageName());
     }
 
     /**
@@ -650,8 +650,9 @@
      *
      * @hide
      */
-    public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId) {
-        mGlobal.setBrightnessConfigurationForUser(c, userId);
+    public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId,
+            String packageName) {
+        mGlobal.setBrightnessConfigurationForUser(c, userId, packageName);
     }
 
     /**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index cbb5a7d..9c851f1 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -480,9 +480,10 @@
      *
      * @hide
      */
-    public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId) {
+    public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId,
+            String packageName) {
         try {
-            mDm.setBrightnessConfigurationForUser(c, userId);
+            mDm.setBrightnessConfigurationForUser(c, userId, packageName);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 3f6dd2e..078958a 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -179,6 +179,11 @@
     public abstract void persistBrightnessSliderEvents();
 
     /**
+     * Notifies the display manager that resource overlays have changed.
+     */
+    public abstract void onOverlayChanged();
+
+    /**
      * Describes the requested power state of the display.
      *
      * This object is intended to describe the general characteristics of the
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 61c42e1..5b7b32f 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -90,5 +90,6 @@
     // Sets the global brightness configuration for a given user. Requires
     // CONFIGURE_DISPLAY_BRIGHTNESS, and INTERACT_ACROSS_USER if the user being configured is not
     // the same as the calling user.
-    void setBrightnessConfigurationForUser(in BrightnessConfiguration c, int userId);
+    void setBrightnessConfigurationForUser(in BrightnessConfiguration c, int userId,
+            String packageName);
 }
diff --git a/core/java/android/hardware/location/ContextHubMessage.java b/core/java/android/hardware/location/ContextHubMessage.java
index 2a4ad00..f85ce3e 100644
--- a/core/java/android/hardware/location/ContextHubMessage.java
+++ b/core/java/android/hardware/location/ContextHubMessage.java
@@ -34,12 +34,11 @@
 @SystemApi
 @Deprecated
 public class ContextHubMessage {
+    private static final int DEBUG_LOG_NUM_BYTES = 16;
     private int mType;
     private int mVersion;
     private byte[]mData;
 
-    private static final String TAG = "ContextHubMessage";
-
     /**
      * Get the message type
      *
@@ -136,4 +135,28 @@
             return new ContextHubMessage[size];
         }
     };
+
+    @Override
+    public String toString() {
+        int length = mData.length;
+
+        String ret =
+                "ContextHubMessage[type = " + mType + ", length = " + mData.length + " bytes](";
+        if (length > 0) {
+            ret += "data = 0x";
+        }
+        for (int i = 0; i < Math.min(length, DEBUG_LOG_NUM_BYTES); i++) {
+            ret += Byte.toHexString(mData[i], true /* upperCase */);
+
+            if ((i + 1) % 4 == 0) {
+                ret += " ";
+            }
+        }
+        if (length > DEBUG_LOG_NUM_BYTES) {
+            ret += "...";
+        }
+        ret += ")";
+
+        return ret;
+    }
 }
diff --git a/core/java/android/hardware/location/NanoAppMessage.java b/core/java/android/hardware/location/NanoAppMessage.java
index 716a194..6635258 100644
--- a/core/java/android/hardware/location/NanoAppMessage.java
+++ b/core/java/android/hardware/location/NanoAppMessage.java
@@ -28,6 +28,7 @@
  */
 @SystemApi
 public final class NanoAppMessage implements Parcelable {
+    private static final int DEBUG_LOG_NUM_BYTES = 16;
     private long mNanoAppId;
     private int mMessageType;
     private byte[] mMessageBody;
@@ -142,4 +143,29 @@
                     return new NanoAppMessage[size];
                 }
             };
+
+    @Override
+    public String toString() {
+        int length = mMessageBody.length;
+
+        String ret = "NanoAppMessage[type = " + mMessageType + ", length = " + mMessageBody.length
+                + " bytes, " + (mIsBroadcasted ? "broadcast" : "unicast") + ", nanoapp = 0x"
+                + Long.toHexString(mNanoAppId) + "](";
+        if (length > 0) {
+            ret += "data = 0x";
+        }
+        for (int i = 0; i < Math.min(length, DEBUG_LOG_NUM_BYTES); i++) {
+            ret += Byte.toHexString(mMessageBody[i], true /* upperCase */);
+
+            if ((i + 1) % 4 == 0) {
+                ret += " ";
+            }
+        }
+        if (length > DEBUG_LOG_NUM_BYTES) {
+            ret += "...";
+        }
+        ret += ")";
+
+        return ret;
+    }
 }
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
index 3fe531f..790c80b 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -45,5 +45,5 @@
 
     void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId);
 
-    void removeTransportModeTransforms(in ParcelFileDescriptor socket, int transformId);
+    void removeTransportModeTransforms(in ParcelFileDescriptor socket);
 }
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 005dd6e..10667ae 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -18,10 +18,9 @@
 
 /** {@hide} */
 oneway interface INetworkPolicyListener {
-
     void onUidRulesChanged(int uid, int uidRules);
     void onMeteredIfacesChanged(in String[] meteredIfaces);
     void onRestrictBackgroundChanged(boolean restrictBackground);
     void onUidPoliciesChanged(int uid, int uidPolicies);
-
+    void onSubscriptionOverride(int subId, int overrideMask, int overrideValue);
 }
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 2202df3..2cda58c 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -405,62 +405,56 @@
     /**
      * Remove an IPsec transform from a stream socket.
      *
-     * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
-     * regardless of the state of the transform. Removing a transform from a socket allows the
-     * socket to be reused for communication in the clear.
+     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
+     * socket allows the socket to be reused for communication in the clear.
      *
      * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
      * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
      * is called.
      *
      * @param socket a socket that previously had a transform applied to it
-     * @param transform the IPsec Transform that was previously applied to the given socket
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(Socket socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(Socket socket)
             throws IOException {
-        removeTransportModeTransforms(socket.getFileDescriptor$(), transform);
+        removeTransportModeTransforms(socket.getFileDescriptor$());
     }
 
     /**
      * Remove an IPsec transform from a datagram socket.
      *
-     * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
-     * regardless of the state of the transform. Removing a transform from a socket allows the
-     * socket to be reused for communication in the clear.
+     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
+     * socket allows the socket to be reused for communication in the clear.
      *
      * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
      * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
      * is called.
      *
      * @param socket a socket that previously had a transform applied to it
-     * @param transform the IPsec Transform that was previously applied to the given socket
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(DatagramSocket socket)
             throws IOException {
-        removeTransportModeTransforms(socket.getFileDescriptor$(), transform);
+        removeTransportModeTransforms(socket.getFileDescriptor$());
     }
 
     /**
      * Remove an IPsec transform from a socket.
      *
-     * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
-     * regardless of the state of the transform. Removing a transform from a socket allows the
-     * socket to be reused for communication in the clear.
+     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
+     * socket allows the socket to be reused for communication in the clear.
      *
      * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
      * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
      * is called.
      *
      * @param socket a socket that previously had a transform applied to it
-     * @param transform the IPsec Transform that was previously applied to the given socket
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(FileDescriptor socket)
             throws IOException {
         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
-            mService.removeTransportModeTransforms(pfd, transform.getResourceId());
+            mService.removeTransportModeTransforms(pfd);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 4e474c8..f525b1f 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -50,6 +50,8 @@
     private String mIfaceName;
     private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
     private ArrayList<InetAddress> mDnses = new ArrayList<InetAddress>();
+    private boolean mUsePrivateDns;
+    private String mPrivateDnsServerName;
     private String mDomains;
     private ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
     private ProxyInfo mHttpProxy;
@@ -165,6 +167,8 @@
             mIfaceName = source.getInterfaceName();
             for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
             for (InetAddress i : source.getDnsServers()) mDnses.add(i);
+            mUsePrivateDns = source.mUsePrivateDns;
+            mPrivateDnsServerName = source.mPrivateDnsServerName;
             mDomains = source.getDomains();
             for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
             mHttpProxy = (source.getHttpProxy() == null)  ?
@@ -391,6 +395,59 @@
     }
 
     /**
+     * Set whether private DNS is currently in use on this network.
+     *
+     * @param usePrivateDns The private DNS state.
+     * @hide
+     */
+    public void setUsePrivateDns(boolean usePrivateDns) {
+        mUsePrivateDns = usePrivateDns;
+    }
+
+    /**
+     * Returns whether private DNS is currently in use on this network. When
+     * private DNS is in use, applications must not send unencrypted DNS
+     * queries as doing so could reveal private user information. Furthermore,
+     * if private DNS is in use and {@link #getPrivateDnsServerName} is not
+     * {@code null}, DNS queries must be sent to the specified DNS server.
+     *
+     * @return {@code true} if private DNS is in use, {@code false} otherwise.
+     */
+    public boolean isPrivateDnsActive() {
+        return mUsePrivateDns;
+    }
+
+    /**
+     * Set the name of the private DNS server to which private DNS queries
+     * should be sent when in strict mode. This value should be {@code null}
+     * when private DNS is off or in opportunistic mode.
+     *
+     * @param privateDnsServerName The private DNS server name.
+     * @hide
+     */
+    public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
+        mPrivateDnsServerName = privateDnsServerName;
+    }
+
+    /**
+     * Returns the private DNS server name that is in use. If not {@code null},
+     * private DNS is in strict mode. In this mode, applications should ensure
+     * that all DNS queries are encrypted and sent to this hostname and that
+     * queries are only sent if the hostname's certificate is valid. If
+     * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private
+     * DNS is in opportunistic mode, and applications should ensure that DNS
+     * queries are encrypted and sent to a DNS server returned by
+     * {@link #getDnsServers}. System DNS will handle each of these cases
+     * correctly, but applications implementing their own DNS lookups must make
+     * sure to follow these requirements.
+     *
+     * @return The private DNS server name.
+     */
+    public @Nullable String getPrivateDnsServerName() {
+        return mPrivateDnsServerName;
+    }
+
+    /**
      * Sets the DNS domain search path used on this link.
      *
      * @param domains A {@link String} listing in priority order the comma separated
@@ -622,6 +679,8 @@
         mIfaceName = null;
         mLinkAddresses.clear();
         mDnses.clear();
+        mUsePrivateDns = false;
+        mPrivateDnsServerName = null;
         mDomains = null;
         mRoutes.clear();
         mHttpProxy = null;
@@ -649,6 +708,13 @@
         for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
         dns += "] ";
 
+        String usePrivateDns = "UsePrivateDns: " + mUsePrivateDns + " ";
+
+        String privateDnsServerName = "";
+        if (privateDnsServerName != null) {
+            privateDnsServerName = "PrivateDnsServerName: " + mPrivateDnsServerName + " ";
+        }
+
         String domainName = "Domains: " + mDomains;
 
         String mtu = " MTU: " + mMtu;
@@ -671,8 +737,9 @@
             }
             stacked += "] ";
         }
-        return "{" + ifaceName + linkAddresses + routes + dns + domainName + mtu
-            + tcpBuffSizes + proxy + stacked + "}";
+        return "{" + ifaceName + linkAddresses + routes + dns + usePrivateDns
+            + privateDnsServerName + domainName + mtu + tcpBuffSizes + proxy
+            + stacked + "}";
     }
 
     /**
@@ -896,6 +963,20 @@
     }
 
     /**
+     * Compares this {@code LinkProperties} private DNS settings against the
+     * target.
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isIdenticalPrivateDns(LinkProperties target) {
+        return (isPrivateDnsActive() == target.isPrivateDnsActive()
+                && TextUtils.equals(getPrivateDnsServerName(),
+                target.getPrivateDnsServerName()));
+    }
+
+    /**
      * Compares this {@code LinkProperties} Routes against the target
      *
      * @param target LinkProperties to compare.
@@ -989,14 +1070,15 @@
          * stacked interfaces are not so much a property of the link as a
          * description of connections between links.
          */
-        return isIdenticalInterfaceName(target) &&
-                isIdenticalAddresses(target) &&
-                isIdenticalDnses(target) &&
-                isIdenticalRoutes(target) &&
-                isIdenticalHttpProxy(target) &&
-                isIdenticalStackedLinks(target) &&
-                isIdenticalMtu(target) &&
-                isIdenticalTcpBufferSizes(target);
+        return isIdenticalInterfaceName(target)
+                && isIdenticalAddresses(target)
+                && isIdenticalDnses(target)
+                && isIdenticalPrivateDns(target)
+                && isIdenticalRoutes(target)
+                && isIdenticalHttpProxy(target)
+                && isIdenticalStackedLinks(target)
+                && isIdenticalMtu(target)
+                && isIdenticalTcpBufferSizes(target);
     }
 
     /**
@@ -1091,7 +1173,9 @@
                 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
                 + mStackedLinks.hashCode() * 47)
                 + mMtu * 51
-                + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode());
+                + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
+                + (mUsePrivateDns ? 57 : 0)
+                + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode());
     }
 
     /**
@@ -1108,6 +1192,8 @@
         for(InetAddress d : mDnses) {
             dest.writeByteArray(d.getAddress());
         }
+        dest.writeBoolean(mUsePrivateDns);
+        dest.writeString(mPrivateDnsServerName);
         dest.writeString(mDomains);
         dest.writeInt(mMtu);
         dest.writeString(mTcpBufferSizes);
@@ -1148,6 +1234,8 @@
                         netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
                     } catch (UnknownHostException e) { }
                 }
+                netProp.setUsePrivateDns(in.readBoolean());
+                netProp.setPrivateDnsServerName(in.readString());
                 netProp.setDomains(in.readString());
                 netProp.setMtu(in.readInt());
                 netProp.setTcpBufferSizes(in.readString());
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8b03fa8..214ff64 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -108,6 +108,7 @@
             NET_CAPABILITY_CAPTIVE_PORTAL,
             NET_CAPABILITY_NOT_ROAMING,
             NET_CAPABILITY_FOREGROUND,
+            NET_CAPABILITY_NOT_CONGESTED,
     })
     public @interface NetCapability { }
 
@@ -235,8 +236,17 @@
      */
     public static final int NET_CAPABILITY_FOREGROUND = 19;
 
+    /**
+     * Indicates that this network is not congested.
+     * <p>
+     * When a network is congested, the device should defer network traffic that
+     * can be done at a later time without breaking developer contracts.
+     * @hide
+     */
+    public static final int NET_CAPABILITY_NOT_CONGESTED = 20;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_CONGESTED;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -249,7 +259,8 @@
             (1 << NET_CAPABILITY_VALIDATED) |
             (1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
             (1 << NET_CAPABILITY_NOT_ROAMING) |
-            (1 << NET_CAPABILITY_FOREGROUND);
+            (1 << NET_CAPABILITY_FOREGROUND) |
+            (1 << NET_CAPABILITY_NOT_CONGESTED);
 
     /**
      * Network capabilities that are not allowed in NetworkRequests. This exists because the
@@ -387,12 +398,9 @@
      * @hide
      */
     public String describeFirstNonRequestableCapability() {
-        if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED";
-        if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL";
-        if (hasCapability(NET_CAPABILITY_FOREGROUND)) return "NET_CAPABILITY_FOREGROUND";
-        // This cannot happen unless the preceding checks are incomplete.
-        if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) {
-            return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities);
+        final long nonRequestable = (mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES);
+        if (nonRequestable != 0) {
+            return capabilityNameOf(BitUtils.unpackBits(nonRequestable)[0]);
         }
         if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth";
         if (hasSignalStrength()) return "signalStrength";
@@ -1080,6 +1088,7 @@
             case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL";
             case NET_CAPABILITY_NOT_ROAMING:    return "NOT_ROAMING";
             case NET_CAPABILITY_FOREGROUND:     return "FOREGROUND";
+            case NET_CAPABILITY_NOT_CONGESTED:  return "NOT_CONGESTED";
             default:                            return Integer.toString(capability);
         }
     }
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 9ef26a9..2c5a021 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -113,6 +113,9 @@
      */
     public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
 
+    public static final int OVERRIDE_UNMETERED = 1 << 0;
+    public static final int OVERRIDE_CONGESTED = 1 << 1;
+
     private final Context mContext;
     private INetworkPolicyManager mService;
 
@@ -347,4 +350,13 @@
     public static String resolveNetworkId(String ssid) {
         return WifiInfo.removeDoubleQuotes(ssid);
     }
+
+    /** {@hide} */
+    public static class Listener extends INetworkPolicyListener.Stub {
+        @Override public void onUidRulesChanged(int uid, int uidRules) { }
+        @Override public void onMeteredIfacesChanged(String[] meteredIfaces) { }
+        @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { }
+        @Override public void onUidPoliciesChanged(int uid, int uidPolicies) { }
+        @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) { }
+    }
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 0874d93..e6cf5e6 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -269,6 +269,15 @@
     public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;
 
     /**
+     * Standard priority of video threads.  Applications can not normally
+     * change to this priority.
+     * Use with {@link #setThreadPriority(int)} and
+     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
+     * {@link java.lang.Thread} class.
+     */
+    public static final int THREAD_PRIORITY_VIDEO = -10;
+
+    /**
      * Standard priority of audio threads.  Applications can not normally
      * change to this priority.
      * Use with {@link #setThreadPriority(int)} and
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7b0c153..13b5b5c9 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -791,6 +791,7 @@
      * @see #getUserRestrictions()
      * @hide
      */
+    @SystemApi
     public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6d91f59..956e8f6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6562,6 +6562,14 @@
         public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
 
         /**
+         * If nonzero, crashes in foreground processes will bring up a dialog.
+         * Otherwise, the process will be silently killed.
+         * @hide
+         */
+        public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION =
+                "show_first_crash_dialog_dev_option";
+
+        /**
          * The {@link ComponentName} string of the service to be used as the voice recognition
          * service.
          *
@@ -7398,6 +7406,7 @@
             SCREENSAVER_ACTIVATE_ON_DOCK,
             SCREENSAVER_ACTIVATE_ON_SLEEP,
             LOCKDOWN_IN_POWER_MENU,
+            SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
         };
 
         /** @hide */
@@ -11300,6 +11309,20 @@
          */
         public static final String ZRAM_ENABLED =
                 "zram_enabled";
+
+        /**
+         * Whether smart replies in notifications are enabled.
+         * @hide
+         */
+        public static final String ENABLE_SMART_REPLIES_IN_NOTIFICATIONS =
+                "enable_smart_replies_in_notifications";
+
+        /**
+         * If nonzero, crashes in foreground processes will bring up a dialog.
+         * Otherwise, the process will be silently killed.
+         * @hide
+         */
+        public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
     }
 
     /**
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index 57477f5..b5496e4 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -51,7 +51,6 @@
     String grant(String name, int granteeUid);
     int ungrant(String name, int granteeUid);
     long getmtime(String name, int uid);
-    int duplicate(String srcKey, int srcUid, String destKey, int destUid);
     int is_hardware_backed(String string);
     int clear_uid(long uid);
 
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/security/keystore/BadCertificateFormatException.java
similarity index 65%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/security/keystore/BadCertificateFormatException.java
index 4200de1..ddc7bd2 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/security/keystore/BadCertificateFormatException.java
@@ -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.
@@ -16,5 +16,13 @@
 
 package android.security.keystore;
 
-/* @hide */
-parcelable RecoveryData;
+/**
+ * Error thrown when the recovery agent supplies an invalid X509 certificate.
+ *
+ * @hide
+ */
+public class BadCertificateFormatException extends RecoveryControllerException {
+    public BadCertificateFormatException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/DecryptionFailedException.java b/core/java/android/security/keystore/DecryptionFailedException.java
new file mode 100644
index 0000000..945fcf6
--- /dev/null
+++ b/core/java/android/security/keystore/DecryptionFailedException.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 android.security.keystore;
+
+/**
+ * Error thrown when decryption failed, due to an agent error. i.e., using the incorrect key,
+ * trying to decrypt garbage data, trying to decrypt data that has somehow been corrupted, etc.
+ *
+ * @hide
+ */
+public class DecryptionFailedException extends RecoveryControllerException {
+
+    public DecryptionFailedException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/EntryRecoveryData.aidl b/core/java/android/security/keystore/EntryRecoveryData.aidl
deleted file mode 100644
index c6c20e3..0000000
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ /dev/null
@@ -1,20 +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.keystore;
-
-/* @hide */
-parcelable EntryRecoveryData;
diff --git a/core/java/android/security/keystore/InternalRecoveryServiceException.java b/core/java/android/security/keystore/InternalRecoveryServiceException.java
new file mode 100644
index 0000000..85829be
--- /dev/null
+++ b/core/java/android/security/keystore/InternalRecoveryServiceException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security.keystore;
+
+/**
+ * An error thrown when something went wrong internally in the recovery service.
+ *
+ * <p>This is an unexpected error, and indicates a problem with the service itself, rather than the
+ * caller having performed some kind of illegal action.
+ *
+ * @hide
+ */
+public class InternalRecoveryServiceException extends RecoveryControllerException {
+    public InternalRecoveryServiceException(String msg) {
+        super(msg);
+    }
+
+    public InternalRecoveryServiceException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/security/keystore/KeychainProtectionParams.aidl
similarity index 94%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/security/keystore/KeychainProtectionParams.aidl
index 4200de1..0341223 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/security/keystore/KeychainProtectionParams.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable RecoveryData;
+parcelable KeychainProtectionParams;
diff --git a/core/java/android/security/keystore/RecoveryMetadata.java b/core/java/android/security/keystore/KeychainProtectionParams.java
similarity index 79%
rename from core/java/android/security/keystore/RecoveryMetadata.java
rename to core/java/android/security/keystore/KeychainProtectionParams.java
index 3f09455..a3cd431 100644
--- a/core/java/android/security/keystore/RecoveryMetadata.java
+++ b/core/java/android/security/keystore/KeychainProtectionParams.java
@@ -28,12 +28,26 @@
 import java.util.Arrays;
 
 /**
- * Helper class with data necessary to recover Keystore on a new device.
- * It defines UI shown to the user and a way to derive a cryptographic key from user output.
+ * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This
+ * class wraps all the data necessary to derive the same key on a recovering device:
+ *
+ * <ul>
+ *     <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern,
+ *         the recovering device can display the pattern UI to the user when asking them to enter
+ *         the lock screen from their previous device.
+ *     <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt.
+ * </ul>
+ *
+ * <p>As such, this data is sent along with the {@link KeychainSnapshot} when syncing the current
+ * version of the keychain.
+ *
+ * <p>For now, the recoverable keychain only supports a single layer of protection, which is the
+ * user's lock screen. In the future, the keychain will support multiple layers of protection
+ * (e.g. an additional keychain password, along with the lock screen).
  *
  * @hide
  */
-public final class RecoveryMetadata implements Parcelable {
+public final class KeychainProtectionParams implements Parcelable {
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
@@ -88,7 +102,7 @@
      * @link {#clearSecret} to overwrite its value in memory.
      * @hide
      */
-    public RecoveryMetadata(@UserSecretType int userSecretType,
+    public KeychainProtectionParams(@UserSecretType int userSecretType,
             @LockScreenUiFormat int lockScreenUiFormat,
             @NonNull KeyDerivationParams keyDerivationParams,
             @NonNull byte[] secret) {
@@ -98,7 +112,7 @@
         mSecret = Preconditions.checkNotNull(secret);
     }
 
-    private RecoveryMetadata() {
+    private KeychainProtectionParams() {
 
     }
 
@@ -141,10 +155,10 @@
     }
 
     /**
-     * Builder for creating {@link RecoveryMetadata}.
+     * Builder for creating {@link KeychainProtectionParams}.
      */
     public static class Builder {
-        private RecoveryMetadata mInstance = new RecoveryMetadata();
+        private KeychainProtectionParams mInstance = new KeychainProtectionParams();
 
         /**
          * Sets user secret type.
@@ -198,14 +212,14 @@
 
 
         /**
-         * Creates a new {@link RecoveryMetadata} instance.
+         * Creates a new {@link KeychainProtectionParams} instance.
          * The instance will include default values, if {@link setSecret}
          * or {@link setUserSecretType} were not called.
          *
          * @return new instance
          * @throws NullPointerException if some required fields were not set.
          */
-        public @NonNull RecoveryMetadata build() {
+        @NonNull public KeychainProtectionParams build() {
             if (mInstance.mUserSecretType == null) {
                 mInstance.mUserSecretType = TYPE_LOCKSCREEN;
             }
@@ -235,14 +249,14 @@
         Arrays.fill(mSecret, (byte) 0);
     }
 
-    public static final Parcelable.Creator<RecoveryMetadata> CREATOR =
-            new Parcelable.Creator<RecoveryMetadata>() {
-        public RecoveryMetadata createFromParcel(Parcel in) {
-            return new RecoveryMetadata(in);
+    public static final Parcelable.Creator<KeychainProtectionParams> CREATOR =
+            new Parcelable.Creator<KeychainProtectionParams>() {
+        public KeychainProtectionParams createFromParcel(Parcel in) {
+            return new KeychainProtectionParams(in);
         }
 
-        public RecoveryMetadata[] newArray(int length) {
-            return new RecoveryMetadata[length];
+        public KeychainProtectionParams[] newArray(int length) {
+            return new KeychainProtectionParams[length];
         }
     };
 
@@ -260,7 +274,7 @@
     /**
      * @hide
      */
-    protected RecoveryMetadata(Parcel in) {
+    protected KeychainProtectionParams(Parcel in) {
         mUserSecretType = in.readInt();
         mLockScreenUiFormat = in.readInt();
         mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/security/keystore/KeychainSnapshot.aidl
similarity index 95%
rename from core/java/android/security/keystore/RecoveryData.aidl
rename to core/java/android/security/keystore/KeychainSnapshot.aidl
index 4200de1..b35713f 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/security/keystore/KeychainSnapshot.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable RecoveryData;
+parcelable KeychainSnapshot;
diff --git a/core/java/android/security/keystore/KeychainSnapshot.java b/core/java/android/security/keystore/KeychainSnapshot.java
new file mode 100644
index 0000000..e03dd4a
--- /dev/null
+++ b/core/java/android/security/keystore/KeychainSnapshot.java
@@ -0,0 +1,291 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot:
+ *
+ * <ul>
+ *     <li>The user's lock screen changes. (A key derived from the user's lock screen is used to
+ *         protected the keychain, which is why this forces a new snapshot.)
+ *     <li>A key is added to or removed from the recoverable keychain.
+ * </ul>
+ *
+ * <p>The snapshot data is also encrypted with the remote trusted hardware's public key, so even
+ * the recovery agent itself should not be able to decipher the data. The recovery agent sends an
+ * instance of this to the remote trusted hardware whenever a new snapshot is generated. During a
+ * recovery flow, the recovery agent retrieves a snapshot from the remote trusted hardware. It then
+ * sends it to the framework, where it is decrypted using the user's lock screen from their previous
+ * device.
+ *
+ * @hide
+ */
+public final class KeychainSnapshot implements Parcelable {
+    private static final int DEFAULT_MAX_ATTEMPTS = 10;
+    private static final long DEFAULT_COUNTER_ID = 1L;
+
+    private int mSnapshotVersion;
+    private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS;
+    private long mCounterId = DEFAULT_COUNTER_ID;
+    private byte[] mServerParams;
+    private byte[] mPublicKey;
+    private List<KeychainProtectionParams> mKeychainProtectionParams;
+    private List<WrappedApplicationKey> mEntryRecoveryData;
+    private byte[] mEncryptedRecoveryKeyBlob;
+
+    /**
+     * @hide
+     * Deprecated, consider using builder.
+     */
+    public KeychainSnapshot(
+            int snapshotVersion,
+            @NonNull List<KeychainProtectionParams> keychainProtectionParams,
+            @NonNull List<WrappedApplicationKey> wrappedApplicationKeys,
+            @NonNull byte[] encryptedRecoveryKeyBlob) {
+        mSnapshotVersion = snapshotVersion;
+        mKeychainProtectionParams =
+                Preconditions.checkCollectionElementsNotNull(keychainProtectionParams,
+                        "keychainProtectionParams");
+        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys,
+                "wrappedApplicationKeys");
+        mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
+    }
+
+    private KeychainSnapshot() {
+
+    }
+
+    /**
+     * Snapshot version for given account. It is incremented when user secret or list of application
+     * keys changes.
+     */
+    public int getSnapshotVersion() {
+        return mSnapshotVersion;
+    }
+
+    /**
+     * Number of user secret guesses allowed during Keychain recovery.
+     */
+    public int getMaxAttempts() {
+        return mMaxAttempts;
+    }
+
+    /**
+     * CounterId which is rotated together with user secret.
+     */
+    public long getCounterId() {
+        return mCounterId;
+    }
+
+    /**
+     * Server parameters.
+     */
+    public @NonNull byte[] getServerParams() {
+        return mServerParams;
+    }
+
+    /**
+     * Public key used to encrypt {@code encryptedRecoveryKeyBlob}.
+     *
+     * See implementation for binary key format
+     */
+    // TODO: document key format.
+    public @NonNull byte[] getTrustedHardwarePublicKey() {
+        return mPublicKey;
+    }
+
+    /**
+     * UI and key derivation parameters. Note that combination of secrets may be used.
+     */
+    public @NonNull List<KeychainProtectionParams> getKeychainProtectionParams() {
+        return mKeychainProtectionParams;
+    }
+
+    /**
+     * List of application keys, with key material encrypted by
+     * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
+     */
+    public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() {
+        return mEntryRecoveryData;
+    }
+
+    /**
+     * Recovery key blob, encrypted by user secret and recovery service public key.
+     */
+    public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
+        return mEncryptedRecoveryKeyBlob;
+    }
+
+    public static final Parcelable.Creator<KeychainSnapshot> CREATOR =
+            new Parcelable.Creator<KeychainSnapshot>() {
+        public KeychainSnapshot createFromParcel(Parcel in) {
+            return new KeychainSnapshot(in);
+        }
+
+        public KeychainSnapshot[] newArray(int length) {
+            return new KeychainSnapshot[length];
+        }
+    };
+
+    /**
+     * Builder for creating {@link KeychainSnapshot}.
+     */
+    public static class Builder {
+        private KeychainSnapshot mInstance = new KeychainSnapshot();
+
+        /**
+         * Snapshot version for given account.
+         *
+         * @param snapshotVersion The snapshot version
+         * @return This builder.
+         */
+        public Builder setSnapshotVersion(int snapshotVersion) {
+            mInstance.mSnapshotVersion = snapshotVersion;
+            return this;
+        }
+
+        /**
+         * Sets the number of user secret guesses allowed during Keychain recovery.
+         *
+         * @param maxAttempts The maximum number of guesses.
+         * @return This builder.
+         */
+        public Builder setMaxAttempts(int maxAttempts) {
+            mInstance.mMaxAttempts = maxAttempts;
+            return this;
+        }
+
+        /**
+         * Sets counter id.
+         *
+         * @param counterId The counter id.
+         * @return This builder.
+         */
+        public Builder setCounterId(long counterId) {
+            mInstance.mCounterId = counterId;
+            return this;
+        }
+
+        /**
+         * Sets server parameters.
+         *
+         * @param serverParams The server parameters
+         * @return This builder.
+         */
+        public Builder setServerParams(byte[] serverParams) {
+            mInstance.mServerParams = serverParams;
+            return this;
+        }
+
+        /**
+         * Sets public key used to encrypt recovery blob.
+         *
+         * @param publicKey The public key
+         * @return This builder.
+         */
+        public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
+            mInstance.mPublicKey = publicKey;
+            return this;
+        }
+
+        /**
+         * Sets UI and key derivation parameters
+         *
+         * @param recoveryMetadata The UI and key derivation parameters
+         * @return This builder.
+         */
+        public Builder setKeychainProtectionParams(
+                @NonNull List<KeychainProtectionParams> recoveryMetadata) {
+            mInstance.mKeychainProtectionParams = recoveryMetadata;
+            return this;
+        }
+
+        /**
+         * List of application keys.
+         *
+         * @param entryRecoveryData List of application keys
+         * @return This builder.
+         */
+        public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) {
+            mInstance.mEntryRecoveryData = entryRecoveryData;
+            return this;
+        }
+
+        /**
+         * Sets recovery key blob
+         *
+         * @param encryptedRecoveryKeyBlob The recovery key blob.
+         * @return This builder.
+         */
+        public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
+            mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
+            return this;
+        }
+
+
+        /**
+         * Creates a new {@link KeychainSnapshot} instance.
+         *
+         * @return new instance
+         * @throws NullPointerException if some required fields were not set.
+         */
+        @NonNull public KeychainSnapshot build() {
+            Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams,
+                    "recoveryMetadata");
+            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
+                    "entryRecoveryData");
+            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
+            Preconditions.checkNotNull(mInstance.mServerParams);
+            Preconditions.checkNotNull(mInstance.mPublicKey);
+            return mInstance;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mSnapshotVersion);
+        out.writeTypedList(mKeychainProtectionParams);
+        out.writeByteArray(mEncryptedRecoveryKeyBlob);
+        out.writeTypedList(mEntryRecoveryData);
+    }
+
+    /**
+     * @hide
+     */
+    protected KeychainSnapshot(Parcel in) {
+        mSnapshotVersion = in.readInt();
+        mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParams.CREATOR);
+        mEncryptedRecoveryKeyBlob = in.createByteArray();
+        mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/security/keystore/LockScreenRequiredException.java b/core/java/android/security/keystore/LockScreenRequiredException.java
new file mode 100644
index 0000000..b07fb9c
--- /dev/null
+++ b/core/java/android/security/keystore/LockScreenRequiredException.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 android.security.keystore;
+
+/**
+ * Error thrown when trying to generate keys for a profile that has no lock screen set.
+ *
+ * <p>A lock screen must be set, as the lock screen is used to encrypt the snapshot.
+ *
+ * @hide
+ */
+public class LockScreenRequiredException extends RecoveryControllerException {
+    public LockScreenRequiredException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryClaim.java b/core/java/android/security/keystore/RecoveryClaim.java
new file mode 100644
index 0000000..6f566af
--- /dev/null
+++ b/core/java/android/security/keystore/RecoveryClaim.java
@@ -0,0 +1,54 @@
+/*
+ * 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.security.keystore;
+
+/**
+ * An attempt to recover a keychain protected by remote secure hardware.
+ *
+ * @hide
+ */
+public class RecoveryClaim {
+
+    private final RecoverySession mRecoverySession;
+    private final byte[] mClaimBytes;
+
+    RecoveryClaim(RecoverySession recoverySession, byte[] claimBytes) {
+        mRecoverySession = recoverySession;
+        mClaimBytes = claimBytes;
+    }
+
+    /**
+     * Returns the session associated with the recovery attempt. This is used to match the symmetric
+     * key, which remains internal to the framework, for decrypting the claim response.
+     *
+     * @return The session data.
+     */
+    public RecoverySession getRecoverySession() {
+        return mRecoverySession;
+    }
+
+    /**
+     * Returns the encrypted claim's bytes.
+     *
+     * <p>This should be sent by the recovery agent to the remote secure hardware, which will use
+     * it to decrypt the keychain, before sending it re-encrypted with the session's symmetric key
+     * to the device.
+     */
+    public byte[] getClaimBytes() {
+        return mClaimBytes;
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryController.java b/core/java/android/security/keystore/RecoveryController.java
new file mode 100644
index 0000000..87283cb
--- /dev/null
+++ b/core/java/android/security/keystore/RecoveryController.java
@@ -0,0 +1,535 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.util.Log;
+
+import com.android.internal.widget.ILockSettings;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An assistant for generating {@link javax.crypto.SecretKey} instances that can be recovered by
+ * other Android devices belonging to the user. The exported keychain is protected by the user's
+ * lock screen.
+ *
+ * <p>The RecoveryController must be paired with a recovery agent. The recovery agent is responsible
+ * for transporting the keychain to remote trusted hardware. This hardware must prevent brute force
+ * attempts against the user's lock screen by limiting the number of allowed guesses (to, e.g., 10).
+ * After  that number of incorrect guesses, the trusted hardware no longer allows access to the
+ * key chain.
+ *
+ * <p>For now only the recovery agent itself is able to create keys, so it is expected that the
+ * recovery agent is itself the system app.
+ *
+ * <p>A recovery agent requires the privileged permission
+ * {@code android.Manifest.permission#RECOVER_KEYSTORE}.
+ *
+ * @hide
+ */
+public class RecoveryController {
+    private static final String TAG = "RecoveryController";
+
+    /** Key has been successfully synced. */
+    public static final int RECOVERY_STATUS_SYNCED = 0;
+    /** Waiting for recovery agent to sync the key. */
+    public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1;
+    /** Recovery account is not available. */
+    public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2;
+    /** Key cannot be synced. */
+    public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3;
+
+    /**
+     * Failed because no snapshot is yet pending to be synced for the user.
+     *
+     * @hide
+     */
+    public static final int ERROR_NO_SNAPSHOT_PENDING = 21;
+
+    /**
+     * Failed due to an error internal to the recovery service. This is unexpected and indicates
+     * either a problem with the logic in the service, or a problem with a dependency of the
+     * service (such as AndroidKeyStore).
+     *
+     * @hide
+     */
+    public static final int ERROR_SERVICE_INTERNAL_ERROR = 22;
+
+    /**
+     * Failed because the user does not have a lock screen set.
+     *
+     * @hide
+     */
+    public static final int ERROR_INSECURE_USER = 23;
+
+    /**
+     * Error thrown when attempting to use a recovery session that has since been closed.
+     *
+     * @hide
+     */
+    public static final int ERROR_SESSION_EXPIRED = 24;
+
+    /**
+     * Failed because the provided certificate was not a valid X509 certificate.
+     *
+     * @hide
+     */
+    public static final int ERROR_BAD_CERTIFICATE_FORMAT = 25;
+
+    /**
+     * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong,
+     * the data has become corrupted, the data has been tampered with, etc.
+     *
+     * @hide
+     */
+    public static final int ERROR_DECRYPTION_FAILED = 26;
+
+
+    private final ILockSettings mBinder;
+
+    private RecoveryController(ILockSettings binder) {
+        mBinder = binder;
+    }
+
+    /**
+     * Gets a new instance of the class.
+     */
+    public static RecoveryController getInstance() {
+        ILockSettings lockSettings =
+                ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
+        return new RecoveryController(lockSettings);
+    }
+
+    /**
+     * Initializes key recovery service for the calling application. RecoveryController
+     * randomly chooses one of the keys from the list and keeps it to use for future key export
+     * operations. Collection of all keys in the list must be signed by the provided {@code
+     * rootCertificateAlias}, which must also be present in the list of root certificates
+     * preinstalled on the device. The random selection allows RecoveryController to select
+     * which of a set of remote recovery service devices will be used.
+     *
+     * <p>In addition, RecoveryController enforces a delay of three months between
+     * consecutive initialization attempts, to limit the ability of an attacker to often switch
+     * remote recovery devices and significantly increase number of recovery attempts.
+     *
+     * @param rootCertificateAlias alias of a root certificate preinstalled on the device
+     * @param signedPublicKeyList binary blob a list of X509 certificates and signature
+     * @throws BadCertificateFormatException if the {@code signedPublicKeyList} is in a bad format.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void initRecoveryService(
+            @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList)
+            throws BadCertificateFormatException, InternalRecoveryServiceException {
+        try {
+            mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+                throw new BadCertificateFormatException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns data necessary to store all recoverable keys for given account. Key material is
+     * encrypted with user secret and recovery public key.
+     *
+     * @param account specific to Recovery agent.
+     * @return Data necessary to recover keystore.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account)
+            throws InternalRecoveryServiceException {
+        try {
+            return mBinder.getRecoveryData(account);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) {
+                return null;
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Sets a listener which notifies recovery agent that new recovery snapshot is available. {@link
+     * #getRecoveryData} can be used to get the snapshot. Note that every recovery agent can have at
+     * most one registered listener at any time.
+     *
+     * @param intent triggered when new snapshot is available. Unregisters listener if the value is
+     *     {@code null}.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
+            throws InternalRecoveryServiceException {
+        try {
+            mBinder.setSnapshotCreatedPendingIntent(intent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns a map from recovery agent accounts to corresponding KeyStore recovery snapshot
+     * version. Version zero is used, if no snapshots were created for the account.
+     *
+     * @return Map from recovery agent accounts to snapshot versions.
+     * @see KeychainSnapshot#getSnapshotVersion
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
+            throws InternalRecoveryServiceException {
+        try {
+            // IPC doesn't support generic Maps.
+            @SuppressWarnings("unchecked")
+            Map<byte[], Integer> result =
+                    (Map<byte[], Integer>) mBinder.getRecoverySnapshotVersions();
+            return result;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Server parameters used to generate new recovery key blobs. This value will be included in
+     * {@code KeychainSnapshot.getEncryptedRecoveryKeyBlob()}. The same value must be included
+     * in vaultParams {@link #startRecoverySession}
+     *
+     * @param serverParams included in recovery key blob.
+     * @see #getRecoveryData
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void setServerParams(byte[] serverParams) throws InternalRecoveryServiceException {
+        try {
+            mBinder.setServerParams(serverParams);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Updates recovery status for given keys. It is used to notify keystore that key was
+     * successfully stored on the server or there were an error. Application can check this value
+     * using {@code getRecoveyStatus}.
+     *
+     * @param packageName Application whose recoverable keys' statuses are to be updated.
+     * @param aliases List of application-specific key aliases. If the array is empty, updates the
+     *     status for all existing recoverable keys.
+     * @param status Status specific to recovery agent.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void setRecoveryStatus(
+            @NonNull String packageName, @Nullable String[] aliases, int status)
+            throws NameNotFoundException, InternalRecoveryServiceException {
+        try {
+            mBinder.setRecoveryStatus(packageName, aliases, status);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns a {@code Map} from Application's KeyStore key aliases to their recovery status.
+     * Negative status values are reserved for recovery agent specific codes. List of common codes:
+     *
+     * <ul>
+     *   <li>{@link #RECOVERY_STATUS_SYNCED}
+     *   <li>{@link #RECOVERY_STATUS_SYNC_IN_PROGRESS}
+     *   <li>{@link #RECOVERY_STATUS_MISSING_ACCOUNT}
+     *   <li>{@link #RECOVERY_STATUS_PERMANENT_FAILURE}
+     * </ul>
+     *
+     * @return {@code Map} from KeyStore alias to recovery status.
+     * @see #setRecoveryStatus
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public Map<String, Integer> getRecoveryStatus() throws InternalRecoveryServiceException {
+        try {
+            // IPC doesn't support generic Maps.
+            @SuppressWarnings("unchecked")
+            Map<String, Integer> result =
+                    (Map<String, Integer>) mBinder.getRecoveryStatus(/*packageName=*/ null);
+            return result;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them
+     * is necessary to recover data.
+     *
+     * @param secretTypes {@link KeychainProtectionParams#TYPE_LOCKSCREEN} or {@link
+     *     KeychainProtectionParams#TYPE_CUSTOM_PASSWORD}
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void setRecoverySecretTypes(
+            @NonNull @KeychainProtectionParams.UserSecretType int[] secretTypes)
+            throws InternalRecoveryServiceException {
+        try {
+            mBinder.setRecoverySecretTypes(secretTypes);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
+     * necessary to generate KeychainSnapshot.
+     *
+     * @return list of recovery secret types
+     * @see KeychainSnapshot
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public @NonNull @KeychainProtectionParams.UserSecretType int[] getRecoverySecretTypes()
+            throws InternalRecoveryServiceException {
+        try {
+            return mBinder.getRecoverySecretTypes();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Returns a list of recovery secret types, necessary to create a pending recovery snapshot.
+     * When user enters a secret of a pending type {@link #recoverySecretAvailable} should be
+     * called.
+     *
+     * @return list of recovery secret types
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @NonNull
+    public @KeychainProtectionParams.UserSecretType int[] getPendingRecoverySecretTypes()
+            throws InternalRecoveryServiceException {
+        try {
+            return mBinder.getPendingRecoverySecretTypes();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Method notifies KeyStore that a user-generated secret is available. This method generates a
+     * symmetric session key which a trusted remote device can use to return a recovery key. Caller
+     * should use {@link KeychainProtectionParams#clearSecret} to override the secret value in
+     * memory.
+     *
+     * @param recoverySecret user generated secret together with parameters necessary to regenerate
+     *     it on a new device.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
+            throws InternalRecoveryServiceException {
+        try {
+            mBinder.recoverySecretAvailable(recoverySecret);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Initializes recovery session and returns a blob with proof of recovery secrets possession.
+     * The method generates symmetric key for a session, which trusted remote device can use to
+     * return recovery key.
+     *
+     * @param verifierPublicKey Encoded {@code java.security.cert.X509Certificate} with Public key
+     * used to create the recovery blob on the source device.
+     * Keystore will verify the certificate using root of trust.
+     * @param vaultParams Must match the parameters in the corresponding field in the recovery blob.
+     *     Used to limit number of guesses.
+     * @param vaultChallenge Data passed from server for this recovery session and used to prevent
+     *     replay attacks
+     * @param secrets Secrets provided by user, the method only uses type and secret fields.
+     * @return The recovery claim. Claim provides a b binary blob with recovery claim. It is
+     *     encrypted with verifierPublicKey and contains a proof of user secrets, session symmetric
+     *     key and parameters necessary to identify the counter with the number of failed recovery
+     *     attempts.
+     * @throws BadCertificateFormatException if the {@code verifierPublicKey} is in an incorrect
+     *     format.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    @NonNull public RecoveryClaim startRecoverySession(
+            @NonNull byte[] verifierPublicKey,
+            @NonNull byte[] vaultParams,
+            @NonNull byte[] vaultChallenge,
+            @NonNull List<KeychainProtectionParams> secrets)
+            throws BadCertificateFormatException, InternalRecoveryServiceException {
+        try {
+            RecoverySession recoverySession = RecoverySession.newInstance(this);
+            byte[] recoveryClaim =
+                    mBinder.startRecoverySession(
+                            recoverySession.getSessionId(),
+                            verifierPublicKey,
+                            vaultParams,
+                            vaultChallenge,
+                            secrets);
+            return new RecoveryClaim(recoverySession, recoveryClaim);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+                throw new BadCertificateFormatException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Imports keys.
+     *
+     * @param session Related recovery session, as originally created by invoking
+     *        {@link #startRecoverySession(byte[], byte[], byte[], List)}.
+     * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
+     * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
+     *     and session. KeyStore only uses package names from the application info in {@link
+     *     WrappedApplicationKey}. Caller is responsibility to perform certificates check.
+     * @return Map from alias to raw key material.
+     * @throws SessionExpiredException if {@code session} has since been closed.
+     * @throws DecryptionFailedException if unable to decrypt the snapshot.
+     * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service.
+     */
+    public Map<String, byte[]> recoverKeys(
+            @NonNull RecoverySession session,
+            @NonNull byte[] recoveryKeyBlob,
+            @NonNull List<WrappedApplicationKey> applicationKeys)
+            throws SessionExpiredException, DecryptionFailedException,
+            InternalRecoveryServiceException {
+        try {
+            return (Map<String, byte[]>) mBinder.recoverKeys(
+                    session.getSessionId(), recoveryKeyBlob, applicationKeys);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_DECRYPTION_FAILED) {
+                throw new DecryptionFailedException(e.getMessage());
+            }
+            if (e.errorCode == ERROR_SESSION_EXPIRED) {
+                throw new SessionExpiredException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Deletes all data associated with {@code session}. Should not be invoked directly but via
+     * {@link RecoverySession#close()}.
+     *
+     * @hide
+     */
+    void closeSession(RecoverySession session) {
+        try {
+            mBinder.closeSession(session.getSessionId());
+        } catch (RemoteException | ServiceSpecificException e) {
+            Log.e(TAG, "Unexpected error trying to close session", e);
+        }
+    }
+
+    /**
+     * Generates a key called {@code alias} and loads it into the recoverable key store. Returns the
+     * raw material of the key.
+     *
+     * @param alias The key alias.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     * @throws LockScreenRequiredException if the user has not set a lock screen. This is required
+     *     to generate recoverable keys, as the snapshots are encrypted using a key derived from the
+     *     lock screen.
+     */
+    public byte[] generateAndStoreKey(@NonNull String alias)
+            throws InternalRecoveryServiceException, LockScreenRequiredException {
+        try {
+            return mBinder.generateAndStoreKey(alias);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ERROR_INSECURE_USER) {
+                throw new LockScreenRequiredException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    /**
+     * Removes a key called {@code alias} from the recoverable key store.
+     *
+     * @param alias The key alias.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
+     */
+    public void removeKey(@NonNull String alias) throws InternalRecoveryServiceException {
+        try {
+            mBinder.removeKey(alias);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw wrapUnexpectedServiceSpecificException(e);
+        }
+    }
+
+    private InternalRecoveryServiceException wrapUnexpectedServiceSpecificException(
+            ServiceSpecificException e) {
+        if (e.errorCode == ERROR_SERVICE_INTERNAL_ERROR) {
+            return new InternalRecoveryServiceException(e.getMessage());
+        }
+
+        // Should never happen. If it does, it's a bug, and we need to update how the method that
+        // called this throws its exceptions.
+        return new InternalRecoveryServiceException("Unexpected error code for method: "
+                + e.errorCode, e);
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryControllerException.java b/core/java/android/security/keystore/RecoveryControllerException.java
new file mode 100644
index 0000000..5b806b7
--- /dev/null
+++ b/core/java/android/security/keystore/RecoveryControllerException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.security.keystore;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Base exception for errors thrown by {@link RecoveryController}.
+ *
+ * @hide
+ */
+public abstract class RecoveryControllerException extends GeneralSecurityException {
+    RecoveryControllerException() { }
+
+    RecoveryControllerException(String msg) {
+        super(msg);
+    }
+
+    public RecoveryControllerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryData.java b/core/java/android/security/keystore/RecoveryData.java
deleted file mode 100644
index 897aa18..0000000
--- a/core/java/android/security/keystore/RecoveryData.java
+++ /dev/null
@@ -1,200 +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.keystore;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.List;
-
-/**
- * Helper class which returns data necessary to recover keys.
- * Contains
- *
- * <ul>
- * <li>Snapshot version.
- * <li>Recovery metadata with UI and key derivation parameters.
- * <li>List of application keys encrypted by recovery key.
- * <li>Encrypted recovery key.
- * </ul>
- *
- * @hide
- */
-public final class RecoveryData implements Parcelable {
-    private int mSnapshotVersion;
-    private List<RecoveryMetadata> mRecoveryMetadata;
-    private List<EntryRecoveryData> mEntryRecoveryData;
-    private byte[] mEncryptedRecoveryKeyBlob;
-
-    /**
-     * @hide
-     * Deprecated, consider using builder.
-     */
-    public RecoveryData(
-            int snapshotVersion,
-            @NonNull List<RecoveryMetadata> recoveryMetadata,
-            @NonNull List<EntryRecoveryData> entryRecoveryData,
-            @NonNull byte[] encryptedRecoveryKeyBlob) {
-        mSnapshotVersion = snapshotVersion;
-        mRecoveryMetadata =
-                Preconditions.checkCollectionElementsNotNull(recoveryMetadata, "recoveryMetadata");
-        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(entryRecoveryData,
-                "entryRecoveryData");
-        mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
-    }
-
-    private RecoveryData() {
-
-    }
-
-    /**
-     * Snapshot version for given account. It is incremented when user secret or list of application
-     * keys changes.
-     */
-    public int getSnapshotVersion() {
-        return mSnapshotVersion;
-    }
-
-    /**
-     * UI and key derivation parameters. Note that combination of secrets may be used.
-     */
-    public @NonNull List<RecoveryMetadata> getRecoveryMetadata() {
-        return mRecoveryMetadata;
-    }
-
-    /**
-     * List of application keys, with key material encrypted by
-     * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
-     */
-    public @NonNull List<EntryRecoveryData> getEntryRecoveryData() {
-        return mEntryRecoveryData;
-    }
-
-    /**
-     * Recovery key blob, encrypted by user secret and recovery service public key.
-     */
-    public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
-        return mEncryptedRecoveryKeyBlob;
-    }
-
-    public static final Parcelable.Creator<RecoveryData> CREATOR =
-            new Parcelable.Creator<RecoveryData>() {
-        public RecoveryData createFromParcel(Parcel in) {
-            return new RecoveryData(in);
-        }
-
-        public RecoveryData[] newArray(int length) {
-            return new RecoveryData[length];
-        }
-    };
-
-    /**
-     * Builder for creating {@link RecoveryData}.
-     */
-    public static class Builder {
-        private RecoveryData mInstance = new RecoveryData();
-
-        /**
-         * Snapshot version for given account.
-         *
-         * @param snapshotVersion The snapshot version
-         * @return This builder.
-         */
-        public Builder setSnapshotVersion(int snapshotVersion) {
-            mInstance.mSnapshotVersion = snapshotVersion;
-            return this;
-        }
-
-        /**
-         * Sets UI and key derivation parameters
-         *
-         * @param recoveryMetadata The UI and key derivation parameters
-         * @return This builder.
-         */
-        public Builder setRecoveryMetadata(@NonNull List<RecoveryMetadata> recoveryMetadata) {
-            mInstance.mRecoveryMetadata = recoveryMetadata;
-            return this;
-        }
-
-        /**
-         * List of application keys.
-         *
-         * @param entryRecoveryData List of application keys
-         * @return This builder.
-         */
-        public Builder setEntryRecoveryData(List<EntryRecoveryData> entryRecoveryData) {
-            mInstance.mEntryRecoveryData = entryRecoveryData;
-            return this;
-        }
-
-        /**
-         * Sets recovery key blob
-         *
-         * @param encryptedRecoveryKeyBlob The recovery key blob.
-         * @return This builder.
-         */
-        public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
-            mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
-            return this;
-        }
-
-
-        /**
-         * Creates a new {@link RecoveryData} instance.
-         *
-         * @return new instance
-         * @throws NullPointerException if some required fields were not set.
-         */
-        public @NonNull RecoveryData build() {
-            Preconditions.checkCollectionElementsNotNull(mInstance.mRecoveryMetadata,
-                    "recoveryMetadata");
-            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
-                    "entryRecoveryData");
-            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
-            return mInstance;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mSnapshotVersion);
-        out.writeTypedList(mRecoveryMetadata);
-        out.writeByteArray(mEncryptedRecoveryKeyBlob);
-        out.writeTypedList(mEntryRecoveryData);
-    }
-
-    /**
-     * @hide
-     */
-    protected RecoveryData(Parcel in) {
-        mSnapshotVersion = in.readInt();
-        mRecoveryMetadata = in.createTypedArrayList(RecoveryMetadata.CREATOR);
-        mEncryptedRecoveryKeyBlob = in.createByteArray();
-        mEntryRecoveryData = in.createTypedArrayList(EntryRecoveryData.CREATOR);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/core/java/android/security/keystore/RecoveryManager.java b/core/java/android/security/keystore/RecoveryManager.java
deleted file mode 100644
index 99bd284..0000000
--- a/core/java/android/security/keystore/RecoveryManager.java
+++ /dev/null
@@ -1,406 +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.keystore;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
-
-import com.android.internal.widget.ILockSettings;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * A wrapper around KeyStore which lets key be exported to trusted hardware on server side and
- * recovered later.
- *
- * @hide
- */
-public class RecoveryManager {
-
-    /** Key has been successfully synced. */
-    public static final int RECOVERY_STATUS_SYNCED = 0;
-    /** Waiting for recovery agent to sync the key. */
-    public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1;
-    /** Recovery account is not available. */
-    public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2;
-    /** Key cannot be synced. */
-    public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3;
-
-    private final ILockSettings mBinder;
-
-    private RecoveryManager(ILockSettings binder) {
-        mBinder = binder;
-    }
-
-    /**
-     * Gets a new instance of the class.
-     */
-    public static RecoveryManager getInstance() {
-        ILockSettings lockSettings =
-                ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
-        return new RecoveryManager(lockSettings);
-    }
-
-    /**
-     * Initializes key recovery service for the calling application. RecoveryManager
-     * randomly chooses one of the keys from the list and keeps it to use for future key export
-     * operations. Collection of all keys in the list must be signed by the provided {@code
-     * rootCertificateAlias}, which must also be present in the list of root certificates
-     * preinstalled on the device. The random selection allows RecoveryManager to select
-     * which of a set of remote recovery service devices will be used.
-     *
-     * <p>In addition, RecoveryManager enforces a delay of three months between
-     * consecutive initialization attempts, to limit the ability of an attacker to often switch
-     * remote recovery devices and significantly increase number of recovery attempts.
-     *
-     * @param rootCertificateAlias alias of a root certificate preinstalled on the device
-     * @param signedPublicKeyList binary blob a list of X509 certificates and signature
-     * @throws RecoveryManagerException if signature is invalid, or key rotation was rate
-     *     limited.
-     * @hide
-     */
-    public void initRecoveryService(
-            @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList)
-            throws RecoveryManagerException {
-        try {
-            mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Returns data necessary to store all recoverable keys for given account. Key material is
-     * encrypted with user secret and recovery public key.
-     *
-     * @param account specific to Recovery agent.
-     * @return Data necessary to recover keystore.
-     * @hide
-     */
-    public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
-            throws RecoveryManagerException {
-        try {
-            RecoveryData recoveryData = mBinder.getRecoveryData(account);
-            return recoveryData;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Sets a listener which notifies recovery agent that new recovery snapshot is available. {@link
-     * #getRecoveryData} can be used to get the snapshot. Note that every recovery agent can have at
-     * most one registered listener at any time.
-     *
-     * @param intent triggered when new snapshot is available. Unregisters listener if the value is
-     *     {@code null}.
-     * @hide
-     */
-    public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
-            throws RecoveryManagerException {
-        try {
-            mBinder.setSnapshotCreatedPendingIntent(intent);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Returns a map from recovery agent accounts to corresponding KeyStore recovery snapshot
-     * version. Version zero is used, if no snapshots were created for the account.
-     *
-     * @return Map from recovery agent accounts to snapshot versions.
-     * @see RecoveryData#getSnapshotVersion
-     * @hide
-     */
-    public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
-            throws RecoveryManagerException {
-        try {
-            // IPC doesn't support generic Maps.
-            @SuppressWarnings("unchecked")
-            Map<byte[], Integer> result =
-                    (Map<byte[], Integer>) mBinder.getRecoverySnapshotVersions();
-            return result;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Server parameters used to generate new recovery key blobs. This value will be included in
-     * {@code RecoveryData.getEncryptedRecoveryKeyBlob()}. The same value must be included
-     * in vaultParams {@link #startRecoverySession}
-     *
-     * @param serverParams included in recovery key blob.
-     * @see #getRecoveryData
-     * @throws RecoveryManagerException If parameters rotation is rate limited.
-     * @hide
-     */
-    public void setServerParams(byte[] serverParams) throws RecoveryManagerException {
-        try {
-            mBinder.setServerParams(serverParams);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Updates recovery status for given keys. It is used to notify keystore that key was
-     * successfully stored on the server or there were an error. Application can check this value
-     * using {@code getRecoveyStatus}.
-     *
-     * @param packageName Application whose recoverable keys' statuses are to be updated.
-     * @param aliases List of application-specific key aliases. If the array is empty, updates the
-     *     status for all existing recoverable keys.
-     * @param status Status specific to recovery agent.
-     */
-    public void setRecoveryStatus(
-            @NonNull String packageName, @Nullable String[] aliases, int status)
-            throws NameNotFoundException, RecoveryManagerException {
-        try {
-            mBinder.setRecoveryStatus(packageName, aliases, status);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Returns a {@code Map} from Application's KeyStore key aliases to their recovery status.
-     * Negative status values are reserved for recovery agent specific codes. List of common codes:
-     *
-     * <ul>
-     *   <li>{@link #RECOVERY_STATUS_SYNCED}
-     *   <li>{@link #RECOVERY_STATUS_SYNC_IN_PROGRESS}
-     *   <li>{@link #RECOVERY_STATUS_MISSING_ACCOUNT}
-     *   <li>{@link #RECOVERY_STATUS_PERMANENT_FAILURE}
-     * </ul>
-     *
-     * @return {@code Map} from KeyStore alias to recovery status.
-     * @see #setRecoveryStatus
-     * @hide
-     */
-    public Map<String, Integer> getRecoveryStatus()
-            throws RecoveryManagerException {
-        try {
-            // IPC doesn't support generic Maps.
-            @SuppressWarnings("unchecked")
-            Map<String, Integer> result =
-                    (Map<String, Integer>) mBinder.getRecoveryStatus(/*packageName=*/ null);
-            return result;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them
-     * is necessary to recover data.
-     *
-     * @param secretTypes {@link RecoveryMetadata#TYPE_LOCKSCREEN} or {@link
-     *     RecoveryMetadata#TYPE_CUSTOM_PASSWORD}
-     */
-    public void setRecoverySecretTypes(
-            @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
-            throws RecoveryManagerException {
-        try {
-            mBinder.setRecoverySecretTypes(secretTypes);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
-     * necessary to generate RecoveryData.
-     *
-     * @return list of recovery secret types
-     * @see RecoveryData
-     */
-    public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes()
-            throws RecoveryManagerException {
-        try {
-            return mBinder.getRecoverySecretTypes();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Returns a list of recovery secret types, necessary to create a pending recovery snapshot.
-     * When user enters a secret of a pending type {@link #recoverySecretAvailable} should be
-     * called.
-     *
-     * @return list of recovery secret types
-     * @hide
-     */
-    public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes()
-            throws RecoveryManagerException {
-        try {
-            return mBinder.getPendingRecoverySecretTypes();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Method notifies KeyStore that a user-generated secret is available. This method generates a
-     * symmetric session key which a trusted remote device can use to return a recovery key. Caller
-     * should use {@link RecoveryMetadata#clearSecret} to override the secret value in
-     * memory.
-     *
-     * @param recoverySecret user generated secret together with parameters necessary to regenerate
-     *     it on a new device.
-     * @hide
-     */
-    public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
-            throws RecoveryManagerException {
-        try {
-            mBinder.recoverySecretAvailable(recoverySecret);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Initializes recovery session and returns a blob with proof of recovery secrets possession.
-     * The method generates symmetric key for a session, which trusted remote device can use to
-     * return recovery key.
-     *
-     * @param sessionId ID for recovery session.
-     * @param verifierPublicKey Encoded {@code java.security.cert.X509Certificate} with Public key
-     * used to create the recovery blob on the source device.
-     * Keystore will verify the certificate using root of trust.
-     * @param vaultParams Must match the parameters in the corresponding field in the recovery blob.
-     *     Used to limit number of guesses.
-     * @param vaultChallenge Data passed from server for this recovery session and used to prevent
-     *     replay attacks
-     * @param secrets Secrets provided by user, the method only uses type and secret fields.
-     * @return Binary blob with recovery claim. It is encrypted with verifierPublicKey and contains
-     *     a proof of user secrets, session symmetric key and parameters necessary to identify the
-     *     counter with the number of failed recovery attempts.
-     */
-    public @NonNull byte[] startRecoverySession(
-            @NonNull String sessionId,
-            @NonNull byte[] verifierPublicKey,
-            @NonNull byte[] vaultParams,
-            @NonNull byte[] vaultChallenge,
-            @NonNull List<RecoveryMetadata> secrets)
-            throws RecoveryManagerException {
-        try {
-            byte[] recoveryClaim =
-                    mBinder.startRecoverySession(
-                            sessionId,
-                            verifierPublicKey,
-                            vaultParams,
-                            vaultChallenge,
-                            secrets);
-            return recoveryClaim;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Imports keys.
-     *
-     * @param sessionId Id for recovery session, same as in
-     *     {@link #startRecoverySession(String, byte[], byte[], byte[], List)}.
-     * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
-     * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
-     *     and session. KeyStore only uses package names from the application info in {@link
-     *     EntryRecoveryData}. Caller is responsibility to perform certificates check.
-     * @return Map from alias to raw key material.
-     */
-    public Map<String, byte[]> recoverKeys(
-            @NonNull String sessionId,
-            @NonNull byte[] recoveryKeyBlob,
-            @NonNull List<EntryRecoveryData> applicationKeys)
-            throws RecoveryManagerException {
-        try {
-            return (Map<String, byte[]>) mBinder.recoverKeys(
-                    sessionId, recoveryKeyBlob, applicationKeys);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Generates a key called {@code alias} and loads it into the recoverable key store. Returns the
-     * raw material of the key.
-     *
-     * @param alias The key alias.
-     * @throws RecoveryManagerException if an error occurred generating and storing the
-     *     key.
-     */
-    public byte[] generateAndStoreKey(@NonNull String alias)
-            throws RecoveryManagerException {
-        try {
-            return mBinder.generateAndStoreKey(alias);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Removes a key called {@code alias} from the recoverable key store.
-     *
-     * @param alias The key alias.
-     */
-    public void removeKey(@NonNull String alias) throws RecoveryManagerException {
-        try {
-            mBinder.removeKey(alias);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
-        }
-    }
-}
diff --git a/core/java/android/security/keystore/RecoveryManagerException.java b/core/java/android/security/keystore/RecoveryManagerException.java
deleted file mode 100644
index 344718a..0000000
--- a/core/java/android/security/keystore/RecoveryManagerException.java
+++ /dev/null
@@ -1,111 +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.keystore;
-
-import android.os.ServiceSpecificException;
-
-/**
- * Exception thrown by {@link RecoveryManager} methods.
- *
- * @hide
- */
-public class RecoveryManagerException extends Exception {
-    /**
-     * Failed because the loader has not been initialized with a recovery public key yet.
-     */
-    public static final int ERROR_UNINITIALIZED_RECOVERY_PUBLIC_KEY = 20;
-
-    /**
-     * Failed because no snapshot is yet pending to be synced for the user.
-     */
-    public static final int ERROR_NO_SNAPSHOT_PENDING = 21;
-
-    /**
-     * Failed due to an error internal to AndroidKeyStore.
-     */
-    public static final int ERROR_KEYSTORE_INTERNAL_ERROR = 22;
-
-    /**
-     * Failed because the user does not have a lock screen set.
-     */
-    public static final int ERROR_INSECURE_USER = 24;
-
-    /**
-     * Failed because of an internal database error.
-     */
-    public static final int ERROR_DATABASE_ERROR = 25;
-
-    /**
-     * Failed because the provided certificate was not a valid X509 certificate.
-     */
-    public static final int ERROR_BAD_X509_CERTIFICATE = 26;
-
-    /**
-     * Should never be thrown - some algorithm that all AOSP implementations must support is
-     * not available.
-     */
-    public static final int ERROR_UNEXPECTED_MISSING_ALGORITHM = 27;
-
-    /**
-     * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong,
-     * the data has become corrupted, the data has been tampered with, etc.
-     */
-    public static final int ERROR_DECRYPTION_FAILED = 28;
-
-    /**
-     * Rate limit is enforced to prevent using too many trusted remote devices, since each device
-     * can have its own number of user secret guesses allowed.
-     *
-     * @hide
-     */
-    public static final int ERROR_RATE_LIMIT_EXCEEDED = 29;
-
-    private int mErrorCode;
-
-    /**
-     * Creates new {@link #RecoveryManagerException} instance from the error code.
-     *
-     * @param errorCode An error code, as listed at the top of this file.
-     * @param message The associated error message.
-     * @hide
-     */
-    public static RecoveryManagerException fromErrorCode(
-            int errorCode, String message) {
-        return new RecoveryManagerException(errorCode, message);
-    }
-    /**
-     * Creates new {@link #RecoveryManagerException} from {@link
-     * ServiceSpecificException}.
-     *
-     * @param e exception thrown on service side.
-     * @hide
-     */
-    static RecoveryManagerException fromServiceSpecificException(
-            ServiceSpecificException e) throws RecoveryManagerException {
-        throw RecoveryManagerException.fromErrorCode(e.errorCode, e.getMessage());
-    }
-
-    private RecoveryManagerException(int errorCode, String message) {
-        super(message);
-        mErrorCode = errorCode;
-    }
-
-    /** Returns errorCode. */
-    public int getErrorCode() {
-        return mErrorCode;
-    }
-}
diff --git a/core/java/android/security/keystore/RecoveryMetadata.aidl b/core/java/android/security/keystore/RecoveryMetadata.aidl
deleted file mode 100644
index 8e342b4..0000000
--- a/core/java/android/security/keystore/RecoveryMetadata.aidl
+++ /dev/null
@@ -1,20 +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.keystore;
-
-/* @hide */
-parcelable RecoveryMetadata;
diff --git a/core/java/android/security/keystore/RecoverySession.java b/core/java/android/security/keystore/RecoverySession.java
new file mode 100644
index 0000000..ae8d91a
--- /dev/null
+++ b/core/java/android/security/keystore/RecoverySession.java
@@ -0,0 +1,71 @@
+/*
+ * 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.security.keystore;
+
+import java.security.SecureRandom;
+
+/**
+ * Session to recover a {@link KeychainSnapshot} from the remote trusted hardware, initiated by a
+ * recovery agent.
+ *
+ * @hide
+ */
+public class RecoverySession implements AutoCloseable {
+
+    private static final int SESSION_ID_LENGTH_BYTES = 16;
+
+    private final String mSessionId;
+    private final RecoveryController mRecoveryController;
+
+    private RecoverySession(RecoveryController recoveryController, String sessionId) {
+        mRecoveryController = recoveryController;
+        mSessionId = sessionId;
+    }
+
+    /**
+     * A new session, started by {@code recoveryManager}.
+     */
+    static RecoverySession newInstance(RecoveryController recoveryController) {
+        return new RecoverySession(recoveryController, newSessionId());
+    }
+
+    /**
+     * Returns a new random session ID.
+     */
+    private static String newSessionId() {
+        SecureRandom secureRandom = new SecureRandom();
+        byte[] sessionId = new byte[SESSION_ID_LENGTH_BYTES];
+        secureRandom.nextBytes(sessionId);
+        StringBuilder sb = new StringBuilder();
+        for (byte b : sessionId) {
+            sb.append(Byte.toHexString(b, /*upperCase=*/ false));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * An internal session ID, used by the framework to match recovery claims to snapshot responses.
+     */
+    String getSessionId() {
+        return mSessionId;
+    }
+
+    @Override
+    public void close() {
+        mRecoveryController.closeSession(this);
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/security/keystore/SessionExpiredException.java
similarity index 65%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/security/keystore/SessionExpiredException.java
index 4200de1..f13e206 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/security/keystore/SessionExpiredException.java
@@ -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.
@@ -16,5 +16,13 @@
 
 package android.security.keystore;
 
-/* @hide */
-parcelable RecoveryData;
+/**
+ * Error thrown when attempting to use a {@link RecoverySession} that has since expired.
+ *
+ * @hide
+ */
+public class SessionExpiredException extends RecoveryControllerException {
+    public SessionExpiredException(String msg) {
+        super(msg);
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/security/keystore/WrappedApplicationKey.aidl
similarity index 94%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/security/keystore/WrappedApplicationKey.aidl
index 4200de1..a6294fe 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/security/keystore/WrappedApplicationKey.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable RecoveryData;
+parcelable WrappedApplicationKey;
diff --git a/core/java/android/security/keystore/EntryRecoveryData.java b/core/java/android/security/keystore/WrappedApplicationKey.java
similarity index 78%
rename from core/java/android/security/keystore/EntryRecoveryData.java
rename to core/java/android/security/keystore/WrappedApplicationKey.java
index aaca3fe..522bb95 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.java
+++ b/core/java/android/security/keystore/WrappedApplicationKey.java
@@ -35,16 +35,16 @@
  *
  * @hide
  */
-public final class EntryRecoveryData implements Parcelable {
+public final class WrappedApplicationKey implements Parcelable {
     private String mAlias;
     // The only supported format is AES-256 symmetric key.
     private byte[] mEncryptedKeyMaterial;
 
     /**
-     * Builder for creating {@link EntryRecoveryData}.
+     * Builder for creating {@link WrappedApplicationKey}.
      */
     public static class Builder {
-        private EntryRecoveryData mInstance = new EntryRecoveryData();
+        private WrappedApplicationKey mInstance = new WrappedApplicationKey();
 
         /**
          * Sets Application-specific alias of the key.
@@ -70,19 +70,19 @@
         }
 
         /**
-         * Creates a new {@link EntryRecoveryData} instance.
+         * Creates a new {@link WrappedApplicationKey} instance.
          *
          * @return new instance
          * @throws NullPointerException if some required fields were not set.
          */
-        public @NonNull EntryRecoveryData build() {
+        @NonNull public WrappedApplicationKey build() {
             Preconditions.checkNotNull(mInstance.mAlias);
             Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
             return mInstance;
         }
     }
 
-    private EntryRecoveryData() {
+    private WrappedApplicationKey() {
 
     }
 
@@ -90,7 +90,7 @@
      * Deprecated - consider using Builder.
      * @hide
      */
-    public EntryRecoveryData(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
+    public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
         mAlias = Preconditions.checkNotNull(alias);
         mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
     }
@@ -109,14 +109,14 @@
         return mEncryptedKeyMaterial;
     }
 
-    public static final Parcelable.Creator<EntryRecoveryData> CREATOR =
-            new Parcelable.Creator<EntryRecoveryData>() {
-                public EntryRecoveryData createFromParcel(Parcel in) {
-                    return new EntryRecoveryData(in);
+    public static final Parcelable.Creator<WrappedApplicationKey> CREATOR =
+            new Parcelable.Creator<WrappedApplicationKey>() {
+                public WrappedApplicationKey createFromParcel(Parcel in) {
+                    return new WrappedApplicationKey(in);
                 }
 
-                public EntryRecoveryData[] newArray(int length) {
-                    return new EntryRecoveryData[length];
+                public WrappedApplicationKey[] newArray(int length) {
+                    return new WrappedApplicationKey[length];
                 }
             };
 
@@ -132,7 +132,7 @@
     /**
      * @hide
      */
-    protected EntryRecoveryData(Parcel in) {
+    protected WrappedApplicationKey(Parcel in) {
         mAlias = in.readString();
         mEncryptedKeyMaterial = in.createByteArray();
     }
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
new file mode 100644
index 0000000..18f6dab
--- /dev/null
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -0,0 +1,284 @@
+/*
+ * 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.service.autofill;
+
+import static android.view.autofill.AutofillManager.EXTRA_AVAILABLE_ALGORITHMS;
+import static android.view.autofill.AutofillManager.EXTRA_DEFAULT_ALGORITHM;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A service that calculates field classification scores.
+ *
+ * <p>A field classification score is a {@code float} representing how well an
+ * {@link AutofillValue} filled matches a expected value predicted by an autofill service
+ * &mdash;a full-match is {@code 1.0} (representing 100%), while a full mismatch is {@code 0.0}.
+ *
+ * <p>The exact score depends on the algorithm used to calculate it&mdash; the service must provide
+ * at least one default algorithm (which is used when the algorithm is not specified or is invalid),
+ * but it could provide more (in which case the algorithm name should be specifiied by the caller
+ * when calculating the scores).
+ *
+ * {@hide}
+ */
+@SystemApi
+public abstract class AutofillFieldClassificationService extends Service {
+
+    private static final String TAG = "AutofillFieldClassificationService";
+
+    private static final int MSG_GET_AVAILABLE_ALGORITHMS = 1;
+    private static final int MSG_GET_DEFAULT_ALGORITHM = 2;
+    private static final int MSG_GET_SCORES = 3;
+
+    /**
+     * The {@link Intent} action that must be declared as handled by a service
+     * in its manifest for the system to recognize it as a quota providing service.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.service.autofill.AutofillFieldClassificationService";
+
+    /** {@hide} **/
+    public static final String EXTRA_SCORES = "scores";
+
+    private AutofillFieldClassificationServiceWrapper mWrapper;
+
+    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+        final int action = msg.what;
+        final Bundle data = new Bundle();
+        final RemoteCallback callback;
+        switch (action) {
+            case MSG_GET_AVAILABLE_ALGORITHMS:
+                callback = (RemoteCallback) msg.obj;
+                final List<String> availableAlgorithms = onGetAvailableAlgorithms();
+                String[] asArray = null;
+                if (availableAlgorithms != null) {
+                    asArray = new String[availableAlgorithms.size()];
+                    availableAlgorithms.toArray(asArray);
+                }
+                data.putStringArray(EXTRA_AVAILABLE_ALGORITHMS, asArray);
+                break;
+            case MSG_GET_DEFAULT_ALGORITHM:
+                callback = (RemoteCallback) msg.obj;
+                final String defaultAlgorithm = onGetDefaultAlgorithm();
+                data.putString(EXTRA_DEFAULT_ALGORITHM, defaultAlgorithm);
+                break;
+            case MSG_GET_SCORES:
+                final SomeArgs args = (SomeArgs) msg.obj;
+                callback = (RemoteCallback) args.arg1;
+                final String algorithmName = (String) args.arg2;
+                final Bundle algorithmArgs = (Bundle) args.arg3;
+                @SuppressWarnings("unchecked")
+                final List<AutofillValue> actualValues = ((List<AutofillValue>) args.arg4);
+                @SuppressWarnings("unchecked")
+                final String[] userDataValues = (String[]) args.arg5;
+                final Scores scores = onGetScores(algorithmName, algorithmArgs, actualValues,
+                        Arrays.asList(userDataValues));
+                data.putParcelable(EXTRA_SCORES, scores);
+                break;
+            default:
+                Log.w(TAG, "Handling unknown message: " + action);
+                return;
+        }
+        callback.sendResult(data);
+    };
+
+    private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(),
+            mHandlerCallback, true);
+
+    /** @hide */
+    public AutofillFieldClassificationService() {
+
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWrapper = new AutofillFieldClassificationServiceWrapper();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mWrapper;
+    }
+
+    /**
+     * Gets the name of all available algorithms.
+     *
+     * @throws UnsupportedOperationException if not implemented by service.
+     */
+    // TODO(b/70939974): rename to onGetAvailableAlgorithms if not removed
+    @NonNull
+    public List<String> onGetAvailableAlgorithms() {
+        throw new UnsupportedOperationException("Must be implemented by external service");
+    }
+
+    /**
+     * Gets the default algorithm that's used when an algorithm is not specified or is invalid.
+     *
+     * @throws UnsupportedOperationException if not implemented by service.
+     */
+    @NonNull
+    public String onGetDefaultAlgorithm() {
+        throw new UnsupportedOperationException("Must be implemented by external service");
+    }
+
+    /**
+     * Calculates field classification scores in a batch.
+     *
+     * <p>See {@link AutofillFieldClassificationService} for more info about field classification
+     * scores.
+     *
+     * @param algorithm name of the algorithm to be used to calculate the scores. If invalid, the
+     * default algorithm will be used instead.
+     * @param args optional arguments to be passed to the algorithm.
+     * @param actualValues values entered by the user.
+     * @param userDataValues values predicted from the user data.
+     * @return the calculated scores and the algorithm used.
+     *
+     * {@hide}
+     */
+    @Nullable
+    @SystemApi
+    public Scores onGetScores(@Nullable String algorithm,
+            @Nullable Bundle args, @NonNull List<AutofillValue> actualValues,
+            @NonNull List<String> userDataValues) {
+        throw new UnsupportedOperationException("Must be implemented by external service");
+    }
+
+    private final class AutofillFieldClassificationServiceWrapper
+            extends IAutofillFieldClassificationService.Stub {
+
+        @Override
+        public void getAvailableAlgorithms(RemoteCallback callback) throws RemoteException {
+            mHandlerCaller.obtainMessageO(MSG_GET_AVAILABLE_ALGORITHMS, callback).sendToTarget();
+        }
+
+        @Override
+        public void getDefaultAlgorithm(RemoteCallback callback) throws RemoteException {
+            mHandlerCaller.obtainMessageO(MSG_GET_DEFAULT_ALGORITHM, callback).sendToTarget();
+        }
+
+        @Override
+        public void getScores(RemoteCallback callback, String algorithmName, Bundle algorithmArgs,
+                List<AutofillValue> actualValues, String[] userDataValues)
+                        throws RemoteException {
+            // TODO(b/70939974): refactor to use PooledLambda
+            mHandlerCaller.obtainMessageOOOOO(MSG_GET_SCORES, callback, algorithmName,
+                    algorithmArgs, actualValues, userDataValues).sendToTarget();
+        }
+    }
+
+
+    // TODO(b/70939974): it might be simpler to remove this class and return the float[][] directly,
+    // ignoring the request if the algorithm name is invalid.
+    /**
+     * Represents field classification scores used in a batch calculation.
+     *
+     * {@hide}
+     */
+    @SystemApi
+    public static final class Scores implements Parcelable {
+        private final String mAlgorithmName;
+        private final float[][] mScores;
+
+        /* @hide */
+        public Scores(String algorithmName, int size1, int size2) {
+            mAlgorithmName = algorithmName;
+            mScores = new float[size1][size2];
+        }
+
+        public Scores(Parcel parcel) {
+            mAlgorithmName = parcel.readString();
+            final int size1 = parcel.readInt();
+            final int size2 = parcel.readInt();
+            mScores = new float[size1][size2];
+            for (int i = 0; i < size1; i++) {
+                for (int j = 0; j < size2; j++) {
+                    mScores[i][j] = parcel.readFloat();
+                }
+            }
+        }
+
+        /**
+         * Gets the name of algorithm used to calculate the score.
+         */
+        @NonNull
+        public String getAlgorithm() {
+            return mAlgorithmName;
+        }
+
+        /**
+         * Gets the resulting scores, with the 1st dimension representing actual values and the 2nd
+         * dimension values from {@link UserData}.
+         */
+        @NonNull
+        public float[][] getScores() {
+            return mScores;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeString(mAlgorithmName);
+            int size1 = mScores.length;
+            int size2 = mScores[0].length;
+            parcel.writeInt(size1);
+            parcel.writeInt(size2);
+            for (int i = 0; i < size1; i++) {
+                for (int j = 0; j < size2; j++) {
+                    parcel.writeFloat(mScores[i][j]);
+                }
+            }
+        }
+
+        public static final Creator<Scores> CREATOR = new Creator<Scores>() {
+
+            @Override
+            public Scores createFromParcel(Parcel parcel) {
+                return new Scores(parcel);
+            }
+
+            @Override
+            public Scores[] newArray(int size) {
+                return new Scores[size];
+            }
+
+        };
+    }
+}
diff --git a/core/java/android/service/autofill/CharSequenceTransformation.java b/core/java/android/service/autofill/CharSequenceTransformation.java
index 2413e97..f52ac85 100644
--- a/core/java/android/service/autofill/CharSequenceTransformation.java
+++ b/core/java/android/service/autofill/CharSequenceTransformation.java
@@ -22,7 +22,6 @@
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 import android.view.autofill.AutofillId;
@@ -31,6 +30,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -62,7 +63,9 @@
 public final class CharSequenceTransformation extends InternalTransformation implements
         Transformation, Parcelable {
     private static final String TAG = "CharSequenceTransformation";
-    @NonNull private final ArrayMap<AutofillId, Pair<Pattern, String>> mFields;
+
+    // Must use LinkedHashMap to preserve insertion order.
+    @NonNull private final LinkedHashMap<AutofillId, Pair<Pattern, String>> mFields;
 
     private CharSequenceTransformation(Builder builder) {
         mFields = builder.mFields;
@@ -76,9 +79,9 @@
         final StringBuilder converted = new StringBuilder();
         final int size = mFields.size();
         if (sDebug) Log.d(TAG, size + " multiple fields on id " + childViewId);
-        for (int i = 0; i < size; i++) {
-            final AutofillId id = mFields.keyAt(i);
-            final Pair<Pattern, String> field = mFields.valueAt(i);
+        for (Entry<AutofillId, Pair<Pattern, String>> entry : mFields.entrySet()) {
+            final AutofillId id = entry.getKey();
+            final Pair<Pattern, String> field = entry.getValue();
             final String value = finder.findByAutofillId(id);
             if (value == null) {
                 Log.w(TAG, "No value for id " + id);
@@ -107,8 +110,10 @@
      * Builder for {@link CharSequenceTransformation} objects.
      */
     public static class Builder {
-        @NonNull private final ArrayMap<AutofillId, Pair<Pattern, String>> mFields =
-                new ArrayMap<>();
+
+        // Must use LinkedHashMap to preserve insertion order.
+        @NonNull private final LinkedHashMap<AutofillId, Pair<Pattern, String>> mFields =
+                new LinkedHashMap<>();
         private boolean mDestroyed;
 
         /**
@@ -186,12 +191,15 @@
         final Pattern[] regexs = new Pattern[size];
         final String[] substs = new String[size];
         Pair<Pattern, String> pair;
-        for (int i = 0; i < size; i++) {
-            ids[i] = mFields.keyAt(i);
-            pair = mFields.valueAt(i);
+        int i = 0;
+        for (Entry<AutofillId, Pair<Pattern, String>> entry : mFields.entrySet()) {
+            ids[i] = entry.getKey();
+            pair = entry.getValue();
             regexs[i] = pair.first;
             substs[i] = pair.second;
+            i++;
         }
+
         parcel.writeParcelableArray(ids, flags);
         parcel.writeSerializable(regexs);
         parcel.writeStringArray(substs);
diff --git a/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl b/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl
new file mode 100644
index 0000000..d8e829d
--- /dev/null
+++ b/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl
@@ -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.
+ */
+
+package android.service.autofill;
+
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.view.autofill.AutofillValue;
+import java.util.List;
+
+/**
+ * Service used to calculate match scores for Autofill Field Classification.
+ *
+ * @hide
+ */
+oneway interface IAutofillFieldClassificationService {
+    void getAvailableAlgorithms(in RemoteCallback callback);
+    void getDefaultAlgorithm(in RemoteCallback callback);
+    void getScores(in RemoteCallback callback, String algorithmName, in Bundle algorithmArgs,
+                  in List<AutofillValue> actualValues, in String[] userDataValues);
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 20cd906..b7b2b2d 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -55,6 +55,7 @@
 import android.widget.RemoteViews;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 
 import java.lang.annotation.Retention;
@@ -1543,7 +1544,11 @@
             return mShowBadge;
         }
 
-        private void populate(String key, int rank, boolean matchesInterruptionFilter,
+        /**
+         * @hide
+         */
+        @VisibleForTesting
+        public void populate(String key, int rank, boolean matchesInterruptionFilter,
                 int visibilityOverride, int suppressedVisualEffects, int importance,
                 CharSequence explanation, String overrideGroupKey,
                 NotificationChannel channel, ArrayList<String> overridePeople,
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index c93e036..c7d4a4a 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -356,6 +356,7 @@
             @IntRange(from = 0) int start,
             @IntRange(from = 0) int end,
             @NonNull TextDirectionHeuristic textDir,
+            boolean computeHyphenation,
             @Nullable MeasuredParagraph recycle) {
         final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
         mt.resetAndAnalyzeBidi(text, start, end, textDir);
@@ -365,7 +366,8 @@
             long nativeBuilderPtr = nInitBuilder();
             try {
                 mt.bindNativeObject(
-                        nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer));
+                        nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer,
+                              computeHyphenation));
             } finally {
                 nFreeBuilder(nativeBuilderPtr);
             }
@@ -394,7 +396,8 @@
                     mt.mSpanEndCache.append(spanEnd);
                 }
             }
-            mt.bindNativeObject(nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer));
+            mt.bindNativeObject(nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer,
+                      computeHyphenation));
         } finally {
             nFreeBuilder(nativeBuilderPtr);
         }
@@ -668,7 +671,8 @@
                                                   @FloatRange(from = 0) float width);
 
     private static native long nBuildNativeMeasuredParagraph(/* Non Zero */ long nativeBuilderPtr,
-                                                 @NonNull char[] text);
+                                                 @NonNull char[] text,
+                                                 boolean computeHyphenation);
 
     private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
 
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index 2c30360..b96b489 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -52,70 +52,147 @@
     // The sorted paragraph end offsets.
     private final @NonNull int[] mParagraphBreakPoints;
 
-    /**
-     * Build MeasuredText from the text.
-     *
-     * @param text The text to be measured.
-     * @param paint The paint to be used for drawing.
-     * @param textDir The text direction.
-     * @return The measured text.
-     */
-    public static @NonNull MeasuredText build(@NonNull CharSequence text,
-                                              @NonNull TextPaint paint,
-                                              @NonNull TextDirectionHeuristic textDir) {
-        return MeasuredText.build(text, paint, textDir, 0, text.length());
-    }
+    // The break strategy for this measured text.
+    private final @Layout.BreakStrategy int mBreakStrategy;
+
+    // The hyphenation frequency for this measured text.
+    private final @Layout.HyphenationFrequency int mHyphenationFrequency;
 
     /**
-     * Build MeasuredText from the specific range of the text..
-     *
-     * @param text The text to be measured.
-     * @param paint The paint to be used for drawing.
-     * @param textDir The text direction.
-     * @param start The inclusive start offset of the text.
-     * @param end The exclusive start offset of the text.
-     * @return The measured text.
+     * A Builder for MeasuredText
      */
-    public static @NonNull MeasuredText build(@NonNull CharSequence text,
-                                              @NonNull TextPaint paint,
-                                              @NonNull TextDirectionHeuristic textDir,
-                                              @IntRange(from = 0) int start,
-                                              @IntRange(from = 0) int end) {
-        Preconditions.checkNotNull(text);
-        Preconditions.checkNotNull(paint);
-        Preconditions.checkNotNull(textDir);
-        Preconditions.checkArgumentInRange(start, 0, text.length(), "start");
-        Preconditions.checkArgumentInRange(end, 0, text.length(), "end");
+    public static final class Builder {
+        // Mandatory parameters.
+        private final @NonNull CharSequence mText;
+        private final @NonNull TextPaint mPaint;
 
-        final IntArray paragraphEnds = new IntArray();
-        final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();
+        // Members to be updated by setters.
+        private @IntRange(from = 0) int mStart;
+        private @IntRange(from = 0) int mEnd;
+        private TextDirectionHeuristic mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
+        private @Layout.BreakStrategy int mBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
+        private @Layout.HyphenationFrequency int mHyphenationFrequency =
+                Layout.HYPHENATION_FREQUENCY_NORMAL;
 
-        int paraEnd = 0;
-        for (int paraStart = start; paraStart < end; paraStart = paraEnd) {
-            paraEnd = TextUtils.indexOf(text, LINE_FEED, paraStart, end);
-            if (paraEnd < 0) {
-                // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph end.
-                paraEnd = end;
-            } else {
-                paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
-            }
 
-            paragraphEnds.add(paraEnd);
-            measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
-                    paint, text, paraStart, paraEnd, textDir, null /* no recycle */));
+        /**
+         * Builder constructor
+         *
+         * @param text The text to be measured.
+         * @param paint The paint to be used for drawing.
+         */
+        public Builder(@NonNull CharSequence text, @NonNull TextPaint paint) {
+            Preconditions.checkNotNull(text);
+            Preconditions.checkNotNull(paint);
+
+            mText = text;
+            mPaint = paint;
+            mStart = 0;
+            mEnd = text.length();
         }
 
-        return new MeasuredText(text, start, end, paint, textDir,
-                                measuredTexts.toArray(new MeasuredParagraph[measuredTexts.size()]),
-                                paragraphEnds.toArray());
-    }
+        /**
+         * Set the range of measuring target.
+         *
+         * @param start The measuring target start offset in the text.
+         * @param end The measuring target end offset in the text.
+         */
+        public @NonNull Builder setRange(@IntRange(from = 0) int start,
+                                         @IntRange(from = 0) int end) {
+            Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
+            Preconditions.checkArgumentInRange(end, 0, mText.length(), "end");
+            Preconditions.checkArgument(start <= end, "The range is reversed.");
 
-    // Use MeasuredText.build instead.
+            mStart = start;
+            mEnd = end;
+            return this;
+        }
+
+        /**
+         * Set the text direction heuristic
+         *
+         * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}.
+         *
+         * @param textDir The text direction heuristic for resolving bidi behavior.
+         * @return this builder, useful for chaining.
+         */
+        public @NonNull Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {
+            Preconditions.checkNotNull(textDir);
+            mTextDir = textDir;
+            return this;
+        }
+
+        /**
+         * Set the break strategy
+         *
+         * The default value is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}.
+         *
+         * @param breakStrategy The break strategy.
+         * @return this builder, useful for chaining.
+         */
+        public @NonNull Builder setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
+            mBreakStrategy = breakStrategy;
+            return this;
+        }
+
+        /**
+         * Set the hyphenation frequency
+         *
+         * The default value is {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
+         *
+         * @param hyphenationFrequency The hyphenation frequency.
+         * @return this builder, useful for chaining.
+         */
+        public @NonNull Builder setHyphenationFrequency(
+                @Layout.HyphenationFrequency int hyphenationFrequency) {
+            mHyphenationFrequency = hyphenationFrequency;
+            return this;
+        }
+
+        /**
+         * Build the measured text
+         *
+         * @return the measured text.
+         */
+        public @NonNull MeasuredText build() {
+            final boolean needHyphenation = mBreakStrategy != Layout.BREAK_STRATEGY_SIMPLE
+                    && mHyphenationFrequency != Layout.HYPHENATION_FREQUENCY_NONE;
+
+            final IntArray paragraphEnds = new IntArray();
+            final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();
+
+            int paraEnd = 0;
+            for (int paraStart = mStart; paraStart < mEnd; paraStart = paraEnd) {
+                paraEnd = TextUtils.indexOf(mText, LINE_FEED, paraStart, mEnd);
+                if (paraEnd < 0) {
+                    // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph
+                    // end.
+                    paraEnd = mEnd;
+                } else {
+                    paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
+                }
+
+                paragraphEnds.add(paraEnd);
+                measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
+                        mPaint, mText, paraStart, paraEnd, mTextDir, needHyphenation,
+                        null /* no recycle */));
+            }
+
+            return new MeasuredText(mText, mStart, mEnd, mPaint, mTextDir, mBreakStrategy,
+                                    mHyphenationFrequency, measuredTexts.toArray(
+                                            new MeasuredParagraph[measuredTexts.size()]),
+                                    paragraphEnds.toArray());
+        }
+    };
+
+    // Use MeasuredText.Builder instead.
     private MeasuredText(@NonNull CharSequence text,
                          @IntRange(from = 0) int start,
                          @IntRange(from = 0) int end,
                          @NonNull TextPaint paint,
                          @NonNull TextDirectionHeuristic textDir,
+                         @Layout.BreakStrategy int breakStrategy,
+                         @Layout.HyphenationFrequency int frequency,
                          @NonNull MeasuredParagraph[] measuredTexts,
                          @NonNull int[] paragraphBreakPoints) {
         mText = text;
@@ -125,6 +202,8 @@
         mMeasuredParagraphs = measuredTexts;
         mParagraphBreakPoints = paragraphBreakPoints;
         mTextDir = textDir;
+        mBreakStrategy = breakStrategy;
+        mHyphenationFrequency = frequency;
     }
 
     /**
@@ -190,6 +269,20 @@
         return mMeasuredParagraphs[paraIndex];
     }
 
+    /**
+     * Returns the break strategy for this text.
+     */
+    public @Layout.BreakStrategy int getBreakStrategy() {
+        return mBreakStrategy;
+    }
+
+    /**
+     * Returns the hyphenation frequency for this text.
+     */
+    public @Layout.HyphenationFrequency int getHyphenationFrequency() {
+        return mHyphenationFrequency;
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////////////////
     // Spanned overrides
     //
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 36bec86..70d6486 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -653,26 +653,40 @@
 
         MeasuredText measured = null;
         final Spanned spanned;
+        final boolean canUseMeasuredText;
         if (source instanceof MeasuredText) {
             measured = (MeasuredText) source;
 
-            final CharSequence original = measured.getText();
-            spanned = (original instanceof Spanned) ? (Spanned) original : null;
-
             if (bufStart != measured.getStart() || bufEnd != measured.getEnd()) {
                 // The buffer position has changed. Re-measure here.
-                measured = MeasuredText.build(original, paint, textDir, bufStart, bufEnd);
+                canUseMeasuredText = false;
+            } else if (b.mBreakStrategy != measured.getBreakStrategy()
+                    || b.mHyphenationFrequency != measured.getHyphenationFrequency()) {
+                // The computed hyphenation pieces may not be able to used. Re-measure it.
+                canUseMeasuredText = false;
             } else {
                 // We can use measured information.
-
-                // Overwrite with the one when emeasured.
-                // TODO: Give an option for developer not to overwrite and measure again here?
-                textDir = measured.getTextDir();
-                paint = measured.getPaint();
+                canUseMeasuredText = true;
             }
         } else {
-            measured = MeasuredText.build(source, paint, textDir, bufStart, bufEnd);
+            canUseMeasuredText = false;
+        }
+
+        if (!canUseMeasuredText) {
+            measured = new MeasuredText.Builder(source, paint)
+                    .setRange(bufStart, bufEnd)
+                    .setTextDirection(textDir)
+                    .setBreakStrategy(b.mBreakStrategy)
+                    .setHyphenationFrequency(b.mHyphenationFrequency)
+                    .build();
             spanned = (source instanceof Spanned) ? (Spanned) source : null;
+        } else {
+            final CharSequence original = measured.getText();
+            spanned = (original instanceof Spanned) ? (Spanned) original : null;
+            // Overwrite with the one when measured.
+            // TODO: Give an option for developer not to overwrite and measure again here?
+            textDir = measured.getTextDir();
+            paint = measured.getPaint();
         }
 
         try {
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index bbd9c9c..562ae7a 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -358,7 +358,7 @@
     }
 
     /**
-     * Return the current time in YYYYMMDDTHHMMSS<tz> format
+     * Return the current time in YYYYMMDDTHHMMSS&lt;tz&gt; format
      */
     @Override
     public String toString() {
@@ -738,6 +738,7 @@
      * <p>
      * You should also use <tt>toMillis(false)</tt> if you want
      * to read back the same milliseconds that you set with {@link #set(long)}
+     * or {@link #set(Time)} or after parsing a date string.
      *
      * <p>
      * This method can return {@code -1} when the date / time fields have been
@@ -745,8 +746,6 @@
      * For example, when daylight savings transitions cause an hour to be
      * skipped: times within that hour will return {@code -1} if isDst =
      * {@code -1}.
-     *
-     * or {@link #set(Time)} or after parsing a date string.
      */
     public long toMillis(boolean ignoreDst) {
         calculator.copyFieldsFromTime(this);
diff --git a/core/java/android/util/DataUnit.java b/core/java/android/util/DataUnit.java
index 3cc1bd8..ea4266e 100644
--- a/core/java/android/util/DataUnit.java
+++ b/core/java/android/util/DataUnit.java
@@ -20,12 +20,15 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Constants for common byte-related units. Note that both SI and IEC units are
- * supported, and you'll need to pick the correct one for your use-case.
+ * A {@code DataUnit} represents data sizes at a given unit of granularity and
+ * provides utility methods to convert across units.
+ * <p>
+ * Note that both SI units (powers of 10) and IEC units (powers of 2) are
+ * supported, and you'll need to pick the correct one for your use-case. For
+ * example, Wikipedia defines a "kilobyte" as an SI unit of 1000 bytes, and a
+ * "kibibyte" as an IEC unit of 1024 bytes.
  * <p>
  * This design is mirrored after {@link TimeUnit} and {@link ChronoUnit}.
- *
- * @hide
  */
 public enum DataUnit {
     KILOBYTES { @Override public long toBytes(long v) { return v * 1_000; } },
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 8242156..e94f91a 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -44,6 +44,7 @@
         DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
         DEFAULT_FLAGS.put("settings_security_settings_v2", "true");
         DEFAULT_FLAGS.put("settings_zone_picker_v2", "false");
+        DEFAULT_FLAGS.put("settings_suggestion_ui_v2", "false");
     }
 
     /**
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 33fbf73..1caea57 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -373,6 +373,7 @@
      * @see #removeCallbacks
      * @hide
      */
+    @TestApi
     public void postCallback(int callbackType, Runnable action, Object token) {
         postCallbackDelayed(callbackType, action, token, 0);
     }
@@ -391,6 +392,7 @@
      * @see #removeCallback
      * @hide
      */
+    @TestApi
     public void postCallbackDelayed(int callbackType,
             Runnable action, Object token, long delayMillis) {
         if (action == null) {
@@ -440,6 +442,7 @@
      * @see #postCallbackDelayed
      * @hide
      */
+    @TestApi
     public void removeCallbacks(int callbackType, Runnable action, Object token) {
         if (callbackType < 0 || callbackType > CALLBACK_LAST) {
             throw new IllegalArgumentException("callbackType is invalid");
diff --git a/core/java/android/os/Seccomp.java b/core/java/android/view/IRemoteAnimationFinishedCallback.aidl
similarity index 62%
copy from core/java/android/os/Seccomp.java
copy to core/java/android/view/IRemoteAnimationFinishedCallback.aidl
index f14e93f..ae58b22 100644
--- a/core/java/android/os/Seccomp.java
+++ b/core/java/android/view/IRemoteAnimationFinishedCallback.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.
@@ -11,14 +11,17 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.os;
+package android.view;
 
 /**
- * @hide
+ * Interface to be invoked by the controlling process when a remote animation has finished.
+ *
+ * @see IRemoteAnimationRunner
+ * {@hide}
  */
-public final class Seccomp {
-    public static final native void setPolicy();
+interface IRemoteAnimationFinishedCallback {
+    void onAnimationFinished();
 }
diff --git a/core/java/android/view/IRemoteAnimationRunner.aidl b/core/java/android/view/IRemoteAnimationRunner.aidl
new file mode 100644
index 0000000..1350ebf
--- /dev/null
+++ b/core/java/android/view/IRemoteAnimationRunner.aidl
@@ -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.view;
+
+import android.view.RemoteAnimationTarget;
+import android.view.IRemoteAnimationFinishedCallback;
+
+/**
+ * Interface that is used to callback from window manager to the process that runs a remote
+ * animation to start or cancel it.
+ *
+ * {@hide}
+ */
+oneway interface IRemoteAnimationRunner {
+
+    /**
+     * Called when the process needs to start the remote animation.
+     *
+     * @param apps The list of apps to animate.
+     * @param finishedCallback The callback to invoke when the animation is finished.
+     */
+    void onAnimationStart(in RemoteAnimationTarget[] apps,
+            in IRemoteAnimationFinishedCallback finishedCallback);
+
+    /**
+     * Called when the animation was cancelled. From this point on, any updates onto the leashes
+     * won't have any effect anymore.
+     */
+    void onAnimationCancelled();
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index bfcf285..4adcb8f 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -38,6 +38,7 @@
 import android.view.IDockedStackListener;
 import android.view.IOnKeyguardExitResult;
 import android.view.IPinnedStackListener;
+import android.view.RemoteAnimationAdapter;
 import android.view.IRotationWatcher;
 import android.view.IWallpaperVisibilityListener;
 import android.view.IWindowSession;
@@ -124,6 +125,7 @@
     void overridePendingAppTransitionMultiThumbFuture(
             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback,
             boolean scaleUp);
+    void overridePendingAppTransitionRemote(in RemoteAnimationAdapter remoteAnimationAdapter);
     void executeAppTransition();
 
     /** Used by system ui to report that recents has shown itself. */
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index ed167c8..17b6ddc 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -29,6 +29,7 @@
 import android.view.MotionEvent;
 import android.view.WindowManager;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 /**
  * System private per-application interface to the window manager.
@@ -150,25 +151,32 @@
     boolean performHapticFeedback(IWindow window, int effectId, boolean always);
 
     /**
-     * Allocate the drag's thumbnail surface.  Also assigns a token that identifies
-     * the drag to the OS and passes that as the return value.  A return value of
-     * null indicates failure.
-     */
-    IBinder prepareDrag(IWindow window, int flags,
-            int thumbnailWidth, int thumbnailHeight, out Surface outSurface);
-
-    /**
      * Initiate the drag operation itself
+     *
+     * @param window Window which initiates drag operation.
+     * @param flags See {@code View#startDragAndDrop}
+     * @param surface Surface containing drag shadow image
+     * @param touchSource See {@code InputDevice#getSource()}
+     * @param touchX TODO (b/72072998): Fix the issue that the system server misuse the arguments as
+     *         initial touch point while the framework passes drag shadow size.
+     * @param touchY TODO (b/72072998): Fix the issue that the system server misuse the arguments as
+     *         initial touch point while the framework passes drag shadow size.
+     * @param thumbCenterX X coordinate for the position within the shadow image that should be
+     *         underneath the touch point during the drag and drop operation.
+     * @param thumbCenterY Y coordinate for the position within the shadow image that should be
+     *         underneath the touch point during the drag and drop operation.
+     * @param data Data transferred by drag and drop
+     * @return Token of drag operation which will be passed to cancelDragAndDrop.
      */
-    boolean performDrag(IWindow window, IBinder dragToken, int touchSource,
+    IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource,
             float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data);
 
-   /**
+    /**
      * Report the result of a drop action targeted to the given window.
      * consumed is 'true' when the drop was accepted by a valid recipient,
      * 'false' otherwise.
      */
-	void reportDropResult(IWindow window, boolean consumed);
+    void reportDropResult(IWindow window, boolean consumed);
 
     /**
      * Cancel the current drag operation.
@@ -236,4 +244,12 @@
     boolean startMovingTask(IWindow window, float startX, float startY);
 
     void updatePointerIcon(IWindow window);
+
+    /**
+     * Update a tap exclude region with a rectangular area identified by provided id in the window.
+     * Touches on this region will not switch focus to this window. Passing an empty rect will
+     * remove the area from the exclude region of this window.
+     */
+    void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
+            int height);
 }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/view/RemoteAnimationAdapter.aidl
similarity index 76%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/view/RemoteAnimationAdapter.aidl
index 4200de1..855bc74 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/view/RemoteAnimationAdapter.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.
@@ -11,10 +11,9 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.security.keystore;
+package android.view;
 
-/* @hide */
-parcelable RecoveryData;
+parcelable RemoteAnimationAdapter;
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
new file mode 100644
index 0000000..d597e59
--- /dev/null
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -0,0 +1,108 @@
+/*
+ * 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.view;
+
+import android.app.ActivityOptions;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Object that describes how to run a remote animation.
+ * <p>
+ * A remote animation lets another app control the entire app transition. It does so by
+ * <ul>
+ *     <li>using {@link ActivityOptions#makeRemoteAnimation}</li>
+ *     <li>using {@link IWindowManager#overridePendingAppTransitionRemote}</li>
+ * </ul>
+ * to register a {@link RemoteAnimationAdapter} that describes how the animation should be run:
+ * Along some meta-data, this object contains a callback that gets invoked from window manager when
+ * the transition is ready to be started.
+ * <p>
+ * Window manager supplies a list of {@link RemoteAnimationTarget}s into the callback. Each target
+ * contains information about the activity that is animating as well as
+ * {@link RemoteAnimationTarget#leash}. The controlling app can modify the leash like any other
+ * {@link SurfaceControl}, including the possibility to synchronize updating the leash's surface
+ * properties with a frame to be drawn using
+ * {@link SurfaceControl.Transaction#deferTransactionUntil}.
+ * <p>
+ * When the animation is done, the controlling app can invoke
+ * {@link IRemoteAnimationFinishedCallback} that gets supplied into
+ * {@link IRemoteAnimationRunner#onStartAnimation}
+ *
+ * @hide
+ */
+public class RemoteAnimationAdapter implements Parcelable {
+
+    private final IRemoteAnimationRunner mRunner;
+    private final long mDuration;
+    private final long mStatusBarTransitionDelay;
+
+    /**
+     * @param runner The interface that gets notified when we actually need to start the animation.
+     * @param duration The duration of the animation.
+     * @param statusBarTransitionDelay The desired delay for all visual animations in the
+     *        status bar caused by this app animation in millis.
+     */
+    public RemoteAnimationAdapter(IRemoteAnimationRunner runner, long duration,
+            long statusBarTransitionDelay) {
+        mRunner = runner;
+        mDuration = duration;
+        mStatusBarTransitionDelay = statusBarTransitionDelay;
+    }
+
+    public RemoteAnimationAdapter(Parcel in) {
+        mRunner = IRemoteAnimationRunner.Stub.asInterface(in.readStrongBinder());
+        mDuration = in.readLong();
+        mStatusBarTransitionDelay = in.readLong();
+    }
+
+    public IRemoteAnimationRunner getRunner() {
+        return mRunner;
+    }
+
+    public long getDuration() {
+        return mDuration;
+    }
+
+    public long getStatusBarTransitionDelay() {
+        return mStatusBarTransitionDelay;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStrongInterface(mRunner);
+        dest.writeLong(mDuration);
+        dest.writeLong(mStatusBarTransitionDelay);
+    }
+
+    public static final Creator<RemoteAnimationAdapter> CREATOR
+            = new Creator<RemoteAnimationAdapter>() {
+        public RemoteAnimationAdapter createFromParcel(Parcel in) {
+            return new RemoteAnimationAdapter(in);
+        }
+
+        public RemoteAnimationAdapter[] newArray(int size) {
+            return new RemoteAnimationAdapter[size];
+        }
+    };
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/view/RemoteAnimationDefinition.aidl
similarity index 76%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/view/RemoteAnimationDefinition.aidl
index 4200de1..32ecd01 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/view/RemoteAnimationDefinition.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.
@@ -11,10 +11,9 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.security.keystore;
+package android.view;
 
-/* @hide */
-parcelable RecoveryData;
+parcelable RemoteAnimationDefinition;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
new file mode 100644
index 0000000..381f692
--- /dev/null
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -0,0 +1,93 @@
+/*
+ * 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.view;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.view.WindowManager.TransitionType;
+
+/**
+ * Defines which animation types should be overridden by which remote animation.
+ *
+ * @hide
+ */
+public class RemoteAnimationDefinition implements Parcelable {
+
+    private final SparseArray<RemoteAnimationAdapter> mTransitionAnimationMap;
+
+    public RemoteAnimationDefinition() {
+        mTransitionAnimationMap = new SparseArray<>();
+    }
+
+    /**
+     * Registers a remote animation for a specific transition.
+     *
+     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param adapter The adapter that described how to run the remote animation.
+     */
+    public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
+        mTransitionAnimationMap.put(transition, adapter);
+    }
+
+    /**
+     * Checks whether a remote animation for specific transition is defined.
+     *
+     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @return Whether this definition has defined a remote animation for the specified transition.
+     */
+    public boolean hasTransition(@TransitionType int transition) {
+        return mTransitionAnimationMap.get(transition) != null;
+    }
+
+    /**
+     * Retrieves the remote animation for a specific transition.
+     *
+     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @return The remote animation adapter for the specified transition.
+     */
+    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition) {
+        return mTransitionAnimationMap.get(transition);
+    }
+
+    public RemoteAnimationDefinition(Parcel in) {
+        mTransitionAnimationMap = in.readSparseArray(null /* loader */);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeSparseArray((SparseArray) mTransitionAnimationMap);
+    }
+
+    public static final Creator<RemoteAnimationDefinition> CREATOR =
+            new Creator<RemoteAnimationDefinition>() {
+        public RemoteAnimationDefinition createFromParcel(Parcel in) {
+            return new RemoteAnimationDefinition(in);
+        }
+
+        public RemoteAnimationDefinition[] newArray(int size) {
+            return new RemoteAnimationDefinition[size];
+        }
+    };
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/view/RemoteAnimationTarget.aidl
similarity index 76%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/view/RemoteAnimationTarget.aidl
index 4200de1..769bf5e 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/view/RemoteAnimationTarget.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.
@@ -11,10 +11,9 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.security.keystore;
+package android.view;
 
-/* @hide */
-parcelable RecoveryData;
+parcelable RemoteAnimationTarget;
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
new file mode 100644
index 0000000..f39e618
--- /dev/null
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -0,0 +1,151 @@
+/*
+ * 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.view;
+
+import android.annotation.IntDef;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Describes an activity to be animated as part of a remote animation.
+ *
+ * @hide
+ */
+public class RemoteAnimationTarget implements Parcelable {
+
+    /**
+     * The app is in the set of opening apps of this transition.
+     */
+    public static final int MODE_OPENING = 0;
+
+    /**
+     * The app is in the set of closing apps of this transition.
+     */
+    public static final int MODE_CLOSING = 1;
+
+    @IntDef(prefix = { "MODE_" }, value = {
+            MODE_OPENING,
+            MODE_CLOSING
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Mode {}
+
+    /**
+     * The {@link Mode} to describe whether this app is opening or closing.
+     */
+    public final @Mode int mode;
+
+    /**
+     * The id of the task this app belongs to.
+     */
+    public final int taskId;
+
+    /**
+     * The {@link SurfaceControl} object to actually control the transform of the app.
+     */
+    public final SurfaceControl leash;
+
+    /**
+     * Whether the app is translucent and may reveal apps behind.
+     */
+    public final boolean isTranslucent;
+
+    /**
+     * The clip rect window manager applies when clipping the app's main surface in screen space
+     * coordinates. This is just a hint to the animation runner: If running a clip-rect animation,
+     * anything that extends beyond these bounds will not have any effect. This implies that any
+     * clip-rect animation should likely stop at these bounds.
+     */
+    public final Rect clipRect;
+
+    /**
+     * 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.
+     */
+    public final int prefixOrderIndex;
+
+    /**
+     * The source position of the app, in screen spaces coordinates. If the position of the leash
+     * is modified from the controlling app, any animation transform needs to be offset by this
+     * amount.
+     */
+    public final Point position;
+
+    /**
+     * The bounds of the source container the app lives in, in screen space coordinates. If the crop
+     * of the leash is modified from the controlling app, it needs to take the source container
+     * bounds into account when calculating the crop.
+     */
+    public final Rect sourceContainerBounds;
+
+    public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
+            Rect clipRect, int prefixOrderIndex, Point position, Rect sourceContainerBounds) {
+        this.mode = mode;
+        this.taskId = taskId;
+        this.leash = leash;
+        this.isTranslucent = isTranslucent;
+        this.clipRect = new Rect(clipRect);
+        this.prefixOrderIndex = prefixOrderIndex;
+        this.position = new Point(position);
+        this.sourceContainerBounds = new Rect(sourceContainerBounds);
+    }
+
+    public RemoteAnimationTarget(Parcel in) {
+        taskId = in.readInt();
+        mode = in.readInt();
+        leash = in.readParcelable(null);
+        isTranslucent = in.readBoolean();
+        clipRect = in.readParcelable(null);
+        prefixOrderIndex = in.readInt();
+        position = in.readParcelable(null);
+        sourceContainerBounds = in.readParcelable(null);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(taskId);
+        dest.writeInt(mode);
+        dest.writeParcelable(leash, 0 /* flags */);
+        dest.writeBoolean(isTranslucent);
+        dest.writeParcelable(clipRect, 0 /* flags */);
+        dest.writeInt(prefixOrderIndex);
+        dest.writeParcelable(position, 0 /* flags */);
+        dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
+    }
+
+    public static final Creator<RemoteAnimationTarget> CREATOR
+            = new Creator<RemoteAnimationTarget>() {
+        public RemoteAnimationTarget createFromParcel(Parcel in) {
+            return new RemoteAnimationTarget(in);
+        }
+
+        public RemoteAnimationTarget[] newArray(int size) {
+            return new RemoteAnimationTarget[size];
+        }
+    };
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/view/SurfaceControl.aidl
similarity index 88%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/java/android/view/SurfaceControl.aidl
index 4200de1..744ead2 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/java/android/view/SurfaceControl.aidl
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.view;
 
-/* @hide */
-parcelable RecoveryData;
+parcelable SurfaceControl;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bd3be1b..05770c3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4210,6 +4210,11 @@
      */
     private static boolean sCanFocusZeroSized;
 
+    /**
+     * Always assign focus if a focusable View is available.
+     */
+    private static boolean sAlwaysAssignFocus;
+
     private String mTransitionName;
 
     static class TintInfo {
@@ -4827,6 +4832,8 @@
 
             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
 
+            sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
+
             sCompatibilityDone = true;
         }
     }
@@ -7017,8 +7024,8 @@
      * Called when this view wants to give up focus. If focus is cleared
      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
      * <p>
-     * <strong>Note:</strong> When a View clears focus the framework is trying
-     * to give focus to the first focusable View from the top. Hence, if this
+     * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
+     * to the first focusable View from the top after focus is cleared. Hence, if this
      * View is the first from the top that can take focus, then all callbacks
      * related to clearing focus will be invoked after which the framework will
      * give focus to this view.
@@ -7029,7 +7036,8 @@
             System.out.println(this + " clearFocus()");
         }
 
-        clearFocusInternal(null, true, true);
+        final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
+        clearFocusInternal(null, true, refocus);
     }
 
     /**
@@ -7224,20 +7232,24 @@
         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
     }
 
-    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
-        if (isAutofillable() && isAttachedToWindow()) {
+    /** @hide */
+    public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
+        if (canNotifyAutofillEnterExitEvent()) {
             AutofillManager afm = getAutofillManager();
             if (afm != null) {
-                if (enter && hasWindowFocus() && isFocused()) {
+                if (enter && isFocused()) {
                     // We have not been laid out yet, hence cannot evaluate
                     // whether this view is visible to the user, we will do
                     // the evaluation once layout is complete.
                     if (!isLaidOut()) {
                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
                     } else if (isVisibleToUser()) {
+                        // TODO This is a potential problem that View gets focus before it's visible
+                        // to User. Ideally View should handle the event when isVisibleToUser()
+                        // becomes true where it should issue notifyViewEntered().
                         afm.notifyViewEntered(this);
                     }
-                } else if (!hasWindowFocus() || !isFocused()) {
+                } else if (!isFocused()) {
                     afm.notifyViewExited(this);
                 }
             }
@@ -8309,6 +8321,11 @@
                 && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
     }
 
+    /** @hide */
+    public boolean canNotifyAutofillEnterExitEvent() {
+        return isAutofillable() && isAttachedToWindow();
+    }
+
     private void populateVirtualStructure(ViewStructure structure,
             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
@@ -12443,8 +12460,6 @@
             imm.focusIn(this);
         }
 
-        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
-
         refreshDrawableState();
     }
 
@@ -17871,6 +17886,15 @@
     }
 
     /**
+     * Return the window this view is currently attached to. Used in
+     * {@link android.app.ActivityView} to communicate with WM.
+     * @hide
+     */
+    protected IWindow getWindow() {
+        return mAttachInfo != null ? mAttachInfo.mWindow : null;
+    }
+
+    /**
      * Return the visibility value of the least visible component passed.
      */
     int combineVisibility(int vis1, int vis2) {
@@ -23538,15 +23562,13 @@
             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
         }
 
-        boolean okay = false;
-
         Point shadowSize = new Point();
         Point shadowTouchPoint = new Point();
         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
 
-        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
-                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
-            throw new IllegalStateException("Drag shadow dimensions must not be negative");
+        if ((shadowSize.x <= 0) || (shadowSize.y <= 0)
+                || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
+            throw new IllegalStateException("Drag shadow dimensions must be positive");
         }
 
         if (ViewDebug.DEBUG_DRAG) {
@@ -23557,40 +23579,50 @@
             mAttachInfo.mDragSurface.release();
         }
         mAttachInfo.mDragSurface = new Surface();
+        mAttachInfo.mDragToken = null;
+
+        final ViewRootImpl root = mAttachInfo.mViewRootImpl;
+        final SurfaceSession session = new SurfaceSession(root.mSurface);
+        final SurfaceControl surface = new SurfaceControl.Builder(session)
+                .setName("drag surface")
+                .setSize(shadowSize.x, shadowSize.y)
+                .setFormat(PixelFormat.TRANSLUCENT)
+                .build();
         try {
-            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
-                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
-            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
-                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
-            if (mAttachInfo.mDragToken != null) {
-                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
-                try {
-                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
-                    shadowBuilder.onDrawShadow(canvas);
-                } finally {
-                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
-                }
-
-                final ViewRootImpl root = getViewRootImpl();
-
-                // Cache the local state object for delivery with DragEvents
-                root.setLocalDragState(myLocalState);
-
-                // repurpose 'shadowSize' for the last touch point
-                root.getLastTouchPoint(shadowSize);
-
-                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
-                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
-                        shadowTouchPoint.x, shadowTouchPoint.y, data);
-                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
+            mAttachInfo.mDragSurface.copyFrom(surface);
+            final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
+            try {
+                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+                shadowBuilder.onDrawShadow(canvas);
+            } finally {
+                mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
             }
+
+            // Cache the local state object for delivery with DragEvents
+            root.setLocalDragState(myLocalState);
+
+            // repurpose 'shadowSize' for the last touch point
+            root.getLastTouchPoint(shadowSize);
+
+            mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag(
+                    mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(),
+                    shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
+            if (ViewDebug.DEBUG_DRAG) {
+                Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken);
+            }
+
+            return mAttachInfo.mDragToken != null;
         } catch (Exception e) {
             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
-            mAttachInfo.mDragSurface.destroy();
-            mAttachInfo.mDragSurface = null;
+            return false;
+        } finally {
+            if (mAttachInfo.mDragToken == null) {
+                mAttachInfo.mDragSurface.destroy();
+                mAttachInfo.mDragSurface = null;
+                root.setLocalDragState(null);
+            }
+            session.kill();
         }
-
-        return okay;
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fe3b696..30f584c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -530,7 +530,7 @@
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
 
         if (!sCompatibilityDone) {
-            sAlwaysAssignFocus = true;
+            sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;
 
             sCompatibilityDone = true;
         }
@@ -2337,7 +2337,7 @@
         }
 
         if (mFirst) {
-            if (sAlwaysAssignFocus) {
+            if (sAlwaysAssignFocus || !isInTouchMode()) {
                 // handle first focus request
                 if (DEBUG_INPUT_RESIZE) {
                     Log.v(mTag, "First: mView.hasFocus()=" + mView.hasFocus());
@@ -3608,7 +3608,7 @@
         checkThread();
         if (mView != null) {
             if (!mView.hasFocus()) {
-                if (sAlwaysAssignFocus) {
+                if (sAlwaysAssignFocus || !isInTouchMode()) {
                     v.requestFocus();
                 }
             } else {
@@ -4211,10 +4211,7 @@
 
             // find the best view to give focus to in this brave new non-touch-mode
             // world
-            final View focused = focusSearch(null, View.FOCUS_DOWN);
-            if (focused != null) {
-                return focused.requestFocus(View.FOCUS_DOWN);
-            }
+            return mView.restoreDefaultFocus();
         }
         return false;
     }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index ae3c4f09..3bb3a4c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -21,7 +21,6 @@
 import static android.view.WindowLayoutParamsProto.BUTTON_BRIGHTNESS;
 import static android.view.WindowLayoutParamsProto.COLOR_MODE;
 import static android.view.WindowLayoutParamsProto.FLAGS;
-import static android.view.WindowLayoutParamsProto.FLAGS_EXTRA;
 import static android.view.WindowLayoutParamsProto.FORMAT;
 import static android.view.WindowLayoutParamsProto.GRAVITY;
 import static android.view.WindowLayoutParamsProto.HAS_SYSTEM_UI_LISTENERS;
@@ -46,7 +45,6 @@
 
 import android.Manifest.permission;
 import android.annotation.IntDef;
-import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
@@ -107,6 +105,191 @@
     final static String INPUT_CONSUMER_WALLPAPER = "wallpaper_input_consumer";
 
     /**
+     * Not set up for a transition.
+     * @hide
+     */
+    int TRANSIT_UNSET = -1;
+
+    /**
+     * No animation for transition.
+     * @hide
+     */
+    int TRANSIT_NONE = 0;
+
+    /**
+     * A window in a new activity is being opened on top of an existing one in the same task.
+     * @hide
+     */
+    int TRANSIT_ACTIVITY_OPEN = 6;
+
+    /**
+     * The window in the top-most activity is being closed to reveal the previous activity in the
+     * same task.
+     * @hide
+     */
+    int TRANSIT_ACTIVITY_CLOSE = 7;
+
+    /**
+     * A window in a new task is being opened on top of an existing one in another activity's task.
+     * @hide
+     */
+    int TRANSIT_TASK_OPEN = 8;
+
+    /**
+     * A window in the top-most activity is being closed to reveal the previous activity in a
+     * different task.
+     * @hide
+     */
+    int TRANSIT_TASK_CLOSE = 9;
+
+    /**
+     * A window in an existing task is being displayed on top of an existing one in another
+     * activity's task.
+     * @hide
+     */
+    int TRANSIT_TASK_TO_FRONT = 10;
+
+    /**
+     * A window in an existing task is being put below all other tasks.
+     * @hide
+     */
+    int TRANSIT_TASK_TO_BACK = 11;
+
+    /**
+     * A window in a new activity that doesn't have a wallpaper is being opened on top of one that
+     * does, effectively closing the wallpaper.
+     * @hide
+     */
+    int TRANSIT_WALLPAPER_CLOSE = 12;
+
+    /**
+     * A window in a new activity that does have a wallpaper is being opened on one that didn't,
+     * effectively opening the wallpaper.
+     * @hide
+     */
+    int TRANSIT_WALLPAPER_OPEN = 13;
+
+    /**
+     * A window in a new activity is being opened on top of an existing one, and both are on top
+     * of the wallpaper.
+     * @hide
+     */
+    int TRANSIT_WALLPAPER_INTRA_OPEN = 14;
+
+    /**
+     * The window in the top-most activity is being closed to reveal the previous activity, and
+     * both are on top of the wallpaper.
+     * @hide
+     */
+    int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
+
+    /**
+     * A window in a new task is being opened behind an existing one in another activity's task.
+     * The new window will show briefly and then be gone.
+     * @hide
+     */
+    int TRANSIT_TASK_OPEN_BEHIND = 16;
+
+    /**
+     * A window in a task is being animated in-place.
+     * @hide
+     */
+    int TRANSIT_TASK_IN_PLACE = 17;
+
+    /**
+     * An activity is being relaunched (e.g. due to configuration change).
+     * @hide
+     */
+    int TRANSIT_ACTIVITY_RELAUNCH = 18;
+
+    /**
+     * A task is being docked from recents.
+     * @hide
+     */
+    int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
+
+    /**
+     * Keyguard is going away.
+     * @hide
+     */
+    int TRANSIT_KEYGUARD_GOING_AWAY = 20;
+
+    /**
+     * Keyguard is going away with showing an activity behind that requests wallpaper.
+     * @hide
+     */
+    int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
+
+    /**
+     * Keyguard is being occluded.
+     * @hide
+     */
+    int TRANSIT_KEYGUARD_OCCLUDE = 22;
+
+    /**
+     * Keyguard is being unoccluded.
+     * @hide
+     */
+    int TRANSIT_KEYGUARD_UNOCCLUDE = 23;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "TRANSIT_" }, value = {
+            TRANSIT_UNSET,
+            TRANSIT_NONE,
+            TRANSIT_ACTIVITY_OPEN,
+            TRANSIT_ACTIVITY_CLOSE,
+            TRANSIT_TASK_OPEN,
+            TRANSIT_TASK_CLOSE,
+            TRANSIT_TASK_TO_FRONT,
+            TRANSIT_TASK_TO_BACK,
+            TRANSIT_WALLPAPER_CLOSE,
+            TRANSIT_WALLPAPER_OPEN,
+            TRANSIT_WALLPAPER_INTRA_OPEN,
+            TRANSIT_WALLPAPER_INTRA_CLOSE,
+            TRANSIT_TASK_OPEN_BEHIND,
+            TRANSIT_TASK_IN_PLACE,
+            TRANSIT_ACTIVITY_RELAUNCH,
+            TRANSIT_DOCK_TASK_FROM_RECENTS,
+            TRANSIT_KEYGUARD_GOING_AWAY,
+            TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+            TRANSIT_KEYGUARD_OCCLUDE,
+            TRANSIT_KEYGUARD_UNOCCLUDE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface TransitionType {}
+
+    /**
+     * Transition flag: Keyguard is going away, but keeping the notification shade open
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE = 0x1;
+
+    /**
+     * Transition flag: Keyguard is going away, but doesn't want an animation for it
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION = 0x2;
+
+    /**
+     * Transition flag: Keyguard is going away while it was showing the system wallpaper.
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER = 0x4;
+
+    /**
+     * @hide
+     */
+    @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
+            TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE,
+            TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION,
+            TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface TransitionFlags {}
+
+    /**
      * Exception that is thrown when trying to add view whose
      * {@link LayoutParams} {@link LayoutParams#token}
      * is invalid.
@@ -1300,18 +1483,6 @@
         }, formatToHexString = true)
         public int flags;
 
-        /** @hide */
-        @Retention(RetentionPolicy.SOURCE)
-        @LongDef(
-            flag = true,
-            value = {})
-        @interface Flags2 {}
-
-        /**
-         * Various behavioral options/flags.  Default is none.
-         */
-        @Flags2 public long flags2;
-
         /**
          * If the window has requested hardware acceleration, but this is not
          * allowed in the process it is in, then still render it as if it is
@@ -2334,7 +2505,6 @@
             out.writeInt(y);
             out.writeInt(type);
             out.writeInt(flags);
-            out.writeLong(flags2);
             out.writeInt(privateFlags);
             out.writeInt(softInputMode);
             out.writeInt(layoutInDisplayCutoutMode);
@@ -2391,7 +2561,6 @@
             y = in.readInt();
             type = in.readInt();
             flags = in.readInt();
-            flags2 = in.readLong();
             privateFlags = in.readInt();
             softInputMode = in.readInt();
             layoutInDisplayCutoutMode = in.readInt();
@@ -2525,10 +2694,6 @@
                 flags = o.flags;
                 changes |= FLAGS_CHANGED;
             }
-            if (flags2 != o.flags2) {
-                flags2 = o.flags2;
-                changes |= FLAGS_CHANGED;
-            }
             if (privateFlags != o.privateFlags) {
                 privateFlags = o.privateFlags;
                 changes |= PRIVATE_FLAGS_CHANGED;
@@ -2790,11 +2955,6 @@
             sb.append(System.lineSeparator());
             sb.append(prefix).append("  fl=").append(
                     ViewDebug.flagsToString(LayoutParams.class, "flags", flags));
-            if (flags2 != 0) {
-                sb.append(System.lineSeparator());
-                // TODO(roosa): add a long overload for ViewDebug.flagsToString.
-                sb.append(prefix).append("  fl2=0x").append(Long.toHexString(flags2));
-            }
             if (privateFlags != 0) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  pfl=").append(ViewDebug.flagsToString(
@@ -2842,7 +3002,6 @@
             proto.write(NEEDS_MENU_KEY, needsMenuKey);
             proto.write(COLOR_MODE, mColorMode);
             proto.write(FLAGS, flags);
-            proto.write(FLAGS_EXTRA, flags2);
             proto.write(PRIVATE_FLAGS, privateFlags);
             proto.write(SYSTEM_UI_VISIBILITY_FLAGS, systemUiVisibility);
             proto.write(SUBTREE_SYSTEM_UI_VISIBILITY_FLAGS, subtreeSystemUiVisibility);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 311dd4b..3ee282e 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -639,6 +639,8 @@
 
     private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
 
+    private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x0200000;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -2409,6 +2411,30 @@
     }
 
     /**
+     * Returns whether node represents a heading.
+     *
+     * @return {@code true} if the node is a heading, {@code false} otherwise.
+     */
+    public boolean isHeading() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING);
+    }
+
+    /**
+     * Sets whether the node represents a heading.
+     *
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param isHeading {@code true} if the node is a heading, {@code false} otherwise.
+     */
+    public void setHeading(boolean isHeading) {
+        setBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING, isHeading);
+    }
+
+    /**
      * Gets the package this node comes from.
      *
      * @return The package name.
@@ -4597,7 +4623,8 @@
          * @param rowSpan The number of rows the item spans.
          * @param columnIndex The column index at which the item is located.
          * @param columnSpan The number of columns the item spans.
-         * @param heading Whether the item is a heading.
+         * @param heading Whether the item is a heading. (Prefer
+         *                {@link AccessibilityNodeInfo#setHeading(boolean)}).
          */
         public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
                 int columnIndex, int columnSpan, boolean heading) {
@@ -4611,7 +4638,8 @@
          * @param rowSpan The number of rows the item spans.
          * @param columnIndex The column index at which the item is located.
          * @param columnSpan The number of columns the item spans.
-         * @param heading Whether the item is a heading.
+         * @param heading Whether the item is a heading. (Prefer
+         *                {@link AccessibilityNodeInfo#setHeading(boolean)})
          * @param selected Whether the item is selected.
          */
         public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
@@ -4698,6 +4726,7 @@
          * heading, table header, etc.
          *
          * @return If the item is a heading.
+         * @deprecated Use {@link AccessibilityNodeInfo#isHeading()}
          */
         public boolean isHeading() {
             return mHeading;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 78b41c6..f54561b 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -33,6 +33,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcelable;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.service.autofill.AutofillService;
 import android.service.autofill.FillEventHistory;
@@ -53,9 +54,12 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 // TODO: use java.lang.ref.Cleaner once Android supports Java 9
 import sun.misc.Cleaner;
@@ -169,11 +173,15 @@
     public static final String EXTRA_CLIENT_STATE =
             "android.view.autofill.extra.CLIENT_STATE";
 
-
     /** @hide */
     public static final String EXTRA_RESTORE_SESSION_TOKEN =
             "android.view.autofill.extra.RESTORE_SESSION_TOKEN";
 
+    /** @hide */
+    public static final String EXTRA_AVAILABLE_ALGORITHMS = "available_algorithms";
+    /** @hide */
+    public static final String EXTRA_DEFAULT_ALGORITHM = "default_algorithm";
+
     private static final String SESSION_ID_TAG = "android:sessionId";
     private static final String STATE_TAG = "android:state";
     private static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData";
@@ -259,6 +267,12 @@
     public static final int STATE_DISABLED_BY_SERVICE = 4;
 
     /**
+     * Timeout in ms for calls to the field classification service.
+     * @hide
+     */
+    public static final int FC_SERVICE_TIMEOUT = 5000;
+
+    /**
      * Makes an authentication id from a request id and a dataset id.
      *
      * @param requestId The request id.
@@ -341,6 +355,10 @@
     @GuardedBy("mLock")
     @Nullable private AutofillId mSaveTriggerId;
 
+    /** set to true when onInvisibleForAutofill is called, used by onAuthenticationResult */
+    @GuardedBy("mLock")
+    private boolean mOnInvisibleCalled;
+
     /** If set, session is commited when the activity is finished; otherwise session is canceled. */
     @GuardedBy("mLock")
     private boolean mSaveOnFinish;
@@ -397,6 +415,11 @@
         boolean isVisibleForAutofill();
 
         /**
+         * Client might disable enter/exit event e.g. when activity is paused.
+         */
+        boolean isDisablingEnterExitEventForAutofill();
+
+        /**
          * Finds views by traversing the hierarchies of the client.
          *
          * @param viewIds The autofill ids of the views to find
@@ -499,6 +522,19 @@
     }
 
     /**
+     * Called once the client becomes invisible.
+     *
+     * @see AutofillClient#isVisibleForAutofill()
+     *
+     * {@hide}
+     */
+    public void onInvisibleForAutofill() {
+        synchronized (mLock) {
+            mOnInvisibleCalled = true;
+        }
+    }
+
+    /**
      * Save state before activity lifecycle
      *
      * @param outState Place to store the state
@@ -623,21 +659,45 @@
         return false;
     }
 
+    private boolean isClientVisibleForAutofillLocked() {
+        final AutofillClient client = getClient();
+        return client != null && client.isVisibleForAutofill();
+    }
+
+    private boolean isClientDisablingEnterExitEvent() {
+        final AutofillClient client = getClient();
+        return client != null && client.isDisablingEnterExitEventForAutofill();
+    }
+
     private void notifyViewEntered(@NonNull View view, int flags) {
         if (!hasAutofillFeature()) {
             return;
         }
-        AutofillCallback callback = null;
+        AutofillCallback callback;
         synchronized (mLock) {
-            if (shouldIgnoreViewEnteredLocked(view, flags)) return;
+            callback = notifyViewEnteredLocked(view, flags);
+        }
 
-            ensureServiceClientAddedIfNeededLocked();
+        if (callback != null) {
+            mCallback.onAutofillEvent(view, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
+        }
+    }
 
-            if (!mEnabled) {
-                if (mCallback != null) {
-                    callback = mCallback;
-                }
-            } else {
+    /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */
+    private AutofillCallback notifyViewEnteredLocked(@NonNull View view, int flags) {
+        if (shouldIgnoreViewEnteredLocked(view, flags)) return null;
+
+        AutofillCallback callback = null;
+
+        ensureServiceClientAddedIfNeededLocked();
+
+        if (!mEnabled) {
+            if (mCallback != null) {
+                callback = mCallback;
+            }
+        } else {
+            // don't notify entered when Activity is already in background
+            if (!isClientDisablingEnterExitEvent()) {
                 final AutofillId id = getAutofillId(view);
                 final AutofillValue value = view.getAutofillValue();
 
@@ -650,10 +710,7 @@
                 }
             }
         }
-
-        if (callback != null) {
-            mCallback.onAutofillEvent(view, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
-        }
+        return callback;
     }
 
     /**
@@ -666,9 +723,16 @@
             return;
         }
         synchronized (mLock) {
-            ensureServiceClientAddedIfNeededLocked();
+            notifyViewExitedLocked(view);
+        }
+    }
 
-            if (mEnabled && isActiveLocked()) {
+    void notifyViewExitedLocked(@NonNull View view) {
+        ensureServiceClientAddedIfNeededLocked();
+
+        if (mEnabled && isActiveLocked()) {
+            // dont notify exited when Activity is already in background
+            if (!isClientDisablingEnterExitEvent()) {
                 final AutofillId id = getAutofillId(view);
 
                 // Update focus on existing session.
@@ -719,7 +783,7 @@
                     }
                 }
                 if (mTrackedViews != null) {
-                    mTrackedViews.notifyViewVisibilityChanged(id, isVisible);
+                    mTrackedViews.notifyViewVisibilityChangedLocked(id, isVisible);
                 }
             }
         }
@@ -752,17 +816,32 @@
         if (!hasAutofillFeature()) {
             return;
         }
-        AutofillCallback callback = null;
+        AutofillCallback callback;
         synchronized (mLock) {
-            if (shouldIgnoreViewEnteredLocked(view, flags)) return;
+            callback = notifyViewEnteredLocked(view, virtualId, bounds, flags);
+        }
 
-            ensureServiceClientAddedIfNeededLocked();
+        if (callback != null) {
+            callback.onAutofillEvent(view, virtualId,
+                    AutofillCallback.EVENT_INPUT_UNAVAILABLE);
+        }
+    }
 
-            if (!mEnabled) {
-                if (mCallback != null) {
-                    callback = mCallback;
-                }
-            } else {
+    /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */
+    private AutofillCallback notifyViewEnteredLocked(View view, int virtualId, Rect bounds,
+                                                     int flags) {
+        AutofillCallback callback = null;
+        if (shouldIgnoreViewEnteredLocked(view, flags)) return callback;
+
+        ensureServiceClientAddedIfNeededLocked();
+
+        if (!mEnabled) {
+            if (mCallback != null) {
+                callback = mCallback;
+            }
+        } else {
+            // don't notify entered when Activity is already in background
+            if (!isClientDisablingEnterExitEvent()) {
                 final AutofillId id = getAutofillId(view, virtualId);
 
                 if (!isActiveLocked()) {
@@ -774,11 +853,7 @@
                 }
             }
         }
-
-        if (callback != null) {
-            callback.onAutofillEvent(view, virtualId,
-                    AutofillCallback.EVENT_INPUT_UNAVAILABLE);
-        }
+        return callback;
     }
 
     /**
@@ -792,9 +867,16 @@
             return;
         }
         synchronized (mLock) {
-            ensureServiceClientAddedIfNeededLocked();
+            notifyViewExitedLocked(view, virtualId);
+        }
+    }
 
-            if (mEnabled && isActiveLocked()) {
+    private void notifyViewExitedLocked(@NonNull View view, int virtualId) {
+        ensureServiceClientAddedIfNeededLocked();
+
+        if (mEnabled && isActiveLocked()) {
+            // don't notify exited when Activity is already in background
+            if (!isClientDisablingEnterExitEvent()) {
                 final AutofillId id = getAutofillId(view, virtualId);
 
                 // Update focus on existing session.
@@ -1092,10 +1174,22 @@
      * and it's ignored if the caller currently doesn't have an enabled autofill service for
      * the user.
      */
+    // TODO(b/70939974): refactor this method to be "purely" sync by getting the info from the
+    // the ExtService manifest (instead of calling the service)
     @Nullable
     public String getDefaultFieldClassificationAlgorithm() {
+        final SyncRemoteCallbackListener<String> listener =
+                new SyncRemoteCallbackListener<String>() {
+
+            @Override
+            String getResult(Bundle result) {
+                return result == null ? null : result.getString(EXTRA_DEFAULT_ALGORITHM);
+            }
+        };
+
         try {
-            return mService.getDefaultFieldClassificationAlgorithm();
+            mService.getDefaultFieldClassificationAlgorithm(new RemoteCallback(listener));
+            return listener.getResult(FC_SERVICE_TIMEOUT);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
@@ -1107,17 +1201,32 @@
      * <a href="AutofillService.html#FieldClassification">field classification</a>.
      *
      * <p><b>Note:</b> This method should only be called by an app providing an autofill service,
-     * and it's ignored if the caller currently doesn't have an enabled autofill service for
-     * the user.
-     *
-     * @return list of all algorithms currently available, or an empty list if the caller currently
-     * does not have an enabled autofill service for the user.
+     * and it returns an empty list if the caller currently doesn't have an enabled autofill service
+     * for the user.
      */
+    // TODO(b/70939974): refactor this method to be "purely" sync by getting the info from the
+    // the ExtService manifest (instead of calling the service)
     @NonNull
     public List<String> getAvailableFieldClassificationAlgorithms() {
+        final SyncRemoteCallbackListener<List<String>> listener =
+                new SyncRemoteCallbackListener<List<String>>() {
+
+            @Override
+            List<String> getResult(Bundle result) {
+                List<String> algorithms = null;
+                if (result != null) {
+                    final String[] asArray = result.getStringArray(EXTRA_AVAILABLE_ALGORITHMS);
+                    if (asArray != null) {
+                        algorithms = Arrays.asList(asArray);
+                    }
+                }
+                return algorithms != null ? algorithms : Collections.emptyList();
+            }
+        };
+
         try {
-            final List<String> names = mService.getAvailableFieldClassificationAlgorithms();
-            return names != null ? names : Collections.emptyList();
+            mService.getAvailableFieldClassificationAlgorithms(new RemoteCallback(listener));
+            return listener.getResult(FC_SERVICE_TIMEOUT);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
@@ -1155,7 +1264,7 @@
     }
 
     /** @hide */
-    public void onAuthenticationResult(int authenticationId, Intent data) {
+    public void onAuthenticationResult(int authenticationId, Intent data, View focusView) {
         if (!hasAutofillFeature()) {
             return;
         }
@@ -1167,9 +1276,24 @@
         if (sDebug) Log.d(TAG, "onAuthenticationResult(): d=" + data);
 
         synchronized (mLock) {
-            if (!isActiveLocked() || data == null) {
+            if (!isActiveLocked()) {
                 return;
             }
+            // If authenticate activity closes itself during onCreate(), there is no onStop/onStart
+            // of app activity.  We enforce enter event to re-show fill ui in such case.
+            // CTS example:
+            //     LoginActivityTest#testDatasetAuthTwoFieldsUserCancelsFirstAttempt
+            //     LoginActivityTest#testFillResponseAuthBothFieldsUserCancelsFirstAttempt
+            if (!mOnInvisibleCalled && focusView != null
+                    && focusView.canNotifyAutofillEnterExitEvent()) {
+                notifyViewExitedLocked(focusView);
+                notifyViewEnteredLocked(focusView, 0);
+            }
+            if (data == null) {
+                // data is set to null when result is not RESULT_OK
+                return;
+            }
+
             final Parcelable result = data.getParcelableExtra(EXTRA_AUTHENTICATION_RESULT);
             final Bundle responseData = new Bundle();
             responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result);
@@ -1402,6 +1526,9 @@
             if (sessionId == mSessionId) {
                 final AutofillClient client = getClient();
                 if (client != null) {
+                    // clear mOnInvisibleCalled and we will see if receive onInvisibleForAutofill()
+                    // before onAuthenticationResult()
+                    mOnInvisibleCalled = false;
                     client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent);
                 }
             }
@@ -1767,6 +1894,7 @@
         pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);
         pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);
         pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null);
+        pw.print(pfx); pw.print("onInvisibleCalled "); pw.println(mOnInvisibleCalled);
         pw.print(pfx); pw.print("last autofilled data: "); pw.println(mLastAutofilledData);
         pw.print(pfx); pw.print("tracked views: ");
         if (mTrackedViews == null) {
@@ -1937,15 +2065,13 @@
          * @param id the id of the view/virtual view whose visibility changed.
          * @param isVisible visible if the view is visible in the view hierarchy.
          */
-        void notifyViewVisibilityChanged(@NonNull AutofillId id, boolean isVisible) {
-            AutofillClient client = getClient();
-
+        void notifyViewVisibilityChangedLocked(@NonNull AutofillId id, boolean isVisible) {
             if (sDebug) {
                 Log.d(TAG, "notifyViewVisibilityChanged(): id=" + id + " isVisible="
                         + isVisible);
             }
 
-            if (client != null && client.isVisibleForAutofill()) {
+            if (isClientVisibleForAutofillLocked()) {
                 if (isVisible) {
                     if (isInSet(mInvisibleTrackedIds, id)) {
                         mInvisibleTrackedIds = removeFromSet(mInvisibleTrackedIds, id);
@@ -2196,4 +2322,36 @@
             }
         }
     }
+
+    private abstract static class SyncRemoteCallbackListener<T>
+            implements RemoteCallback.OnResultListener {
+
+        private final CountDownLatch mLatch = new CountDownLatch(1);
+        private T mResult;
+
+        @Override
+        public void onResult(Bundle result) {
+            if (sVerbose) Log.w(TAG, "SyncRemoteCallbackListener.onResult(): " + result);
+            mResult = getResult(result);
+            mLatch.countDown();
+        }
+
+        T getResult(int timeoutMs) {
+            T result = null;
+            try {
+                if (mLatch.await(timeoutMs, TimeUnit.MILLISECONDS)) {
+                    result = mResult;
+                } else {
+                    Log.w(TAG, "SyncRemoteCallbackListener not called in " + timeoutMs + "ms");
+                }
+            } catch (InterruptedException e) {
+                Log.w(TAG, "SyncRemoteCallbackListener interrupted: " + e);
+                Thread.currentThread().interrupt();
+            }
+            if (sVerbose) Log.w(TAG, "SyncRemoteCallbackListener: returning " + result);
+            return result;
+        }
+
+        abstract T getResult(Bundle result);
+    }
 }
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index 5cba21e..e80fdd9 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -78,8 +78,10 @@
     public AutofillPopupWindow(@NonNull IAutofillWindowPresenter presenter) {
         mWindowPresenter = new WindowPresenter(presenter);
 
+        setTouchModal(false);
         setOutsideTouchable(true);
-        setInputMethodMode(INPUT_METHOD_NEEDED);
+        setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
+        setFocusable(true);
     }
 
     @Override
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 1afa35e..41672e7 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.RemoteCallback;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.UserData;
 import android.view.autofill.AutofillId;
@@ -58,6 +59,6 @@
     void setUserData(in UserData userData);
     boolean isFieldClassificationEnabled();
     ComponentName getAutofillServiceComponentName();
-    List<String> getAvailableFieldClassificationAlgorithms();
-    String getDefaultFieldClassificationAlgorithm();
+    void getAvailableFieldClassificationAlgorithms(in RemoteCallback callback);
+    void getDefaultFieldClassificationAlgorithm(in RemoteCallback callback);
 }
diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java
index 003f221..1eb300e 100644
--- a/core/java/android/view/inputmethod/ExtractedText.java
+++ b/core/java/android/view/inputmethod/ExtractedText.java
@@ -29,6 +29,8 @@
 public class ExtractedText implements Parcelable {
     /**
      * The text that has been extracted.
+     *
+     * @see android.widget.TextView#getText()
      */
     public CharSequence text;
 
@@ -88,6 +90,8 @@
 
     /**
      * The hint that has been extracted.
+     *
+     * @see android.widget.TextView#getHint()
      */
     public CharSequence hint;
 
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index b602095..e9715c5 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -277,8 +277,8 @@
     /**
      * Returns a {@link Collection} of the entity types in the specified preset.
      *
-     * @see #ENTITIES_ALL
-     * @see #ENTITIES_NONE
+     * @see #ENTITY_PRESET_ALL
+     * @see #ENTITY_PRESET_NONE
      */
     default Collection<String> getEntitiesForPreset(@EntityPreset int entityPreset) {
         return Collections.EMPTY_LIST;
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 336c20c..728824c 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -106,6 +106,10 @@
     @Override
     public Editable getText() {
         CharSequence text = super.getText();
+        // This can only happen during construction.
+        if (text == null) {
+            return null;
+        }
         if (text instanceof Editable) {
             return (Editable) super.getText();
         }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 247c806..7bb0db1 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3673,6 +3673,8 @@
                 mIsShowingUp = true;
                 super.show();
             }
+
+            mSuggestionListView.setVisibility(mNumberOfSuggestions == 0 ? View.GONE : View.VISIBLE);
         }
 
         @Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 8c4e422..7d3fcf4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -27,8 +27,10 @@
 import android.annotation.DrawableRes;
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Px;
 import android.annotation.Size;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
@@ -52,6 +54,7 @@
 import android.graphics.Canvas;
 import android.graphics.Insets;
 import android.graphics.Paint;
+import android.graphics.Paint.FontMetricsInt;
 import android.graphics.Path;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
@@ -306,6 +309,7 @@
  * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
  * @attr ref android.R.styleable#TextView_autoSizeStepGranularity
  * @attr ref android.R.styleable#TextView_autoSizePresetSizes
+ * @attr ref android.R.styleable#TextView_accessibilityHeading
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -400,6 +404,7 @@
     private int mCurTextColor;
     private int mCurHintTextColor;
     private boolean mFreezesText;
+    private boolean mIsAccessibilityHeading;
 
     private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
     private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
@@ -924,6 +929,9 @@
         int inputType = EditorInfo.TYPE_NULL;
         a = theme.obtainStyledAttributes(
                     attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes);
+        int firstBaselineToTopHeight = -1;
+        int lastBaselineToBottomHeight = -1;
+        int lineHeight = -1;
 
         readTextAppearance(context, a, attributes, true /* styleArray */);
 
@@ -1249,6 +1257,20 @@
                 case com.android.internal.R.styleable.TextView_justificationMode:
                     mJustificationMode = a.getInt(attr, Layout.JUSTIFICATION_MODE_NONE);
                     break;
+
+                case com.android.internal.R.styleable.TextView_firstBaselineToTopHeight:
+                    firstBaselineToTopHeight = a.getDimensionPixelSize(attr, -1);
+                    break;
+
+                case com.android.internal.R.styleable.TextView_lastBaselineToBottomHeight:
+                    lastBaselineToBottomHeight = a.getDimensionPixelSize(attr, -1);
+                    break;
+
+                case com.android.internal.R.styleable.TextView_lineHeight:
+                    lineHeight = a.getDimensionPixelSize(attr, -1);
+                    break;
+                case com.android.internal.R.styleable.TextView_accessibilityHeading:
+                    mIsAccessibilityHeading = a.getBoolean(attr, false);
             }
         }
 
@@ -1563,6 +1585,16 @@
         } else {
             mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_NONE;
         }
+
+        if (firstBaselineToTopHeight >= 0) {
+            setFirstBaselineToTopHeight(firstBaselineToTopHeight);
+        }
+        if (lastBaselineToBottomHeight >= 0) {
+            setLastBaselineToBottomHeight(lastBaselineToBottomHeight);
+        }
+        if (lineHeight >= 0) {
+            setLineHeight(lineHeight);
+        }
     }
 
     /**
@@ -3165,6 +3197,12 @@
         }
     }
 
+    /**
+     * @inheritDoc
+     *
+     * @see #setFirstBaselineToTopHeight(int)
+     * @see #setLastBaselineToBottomHeight(int)
+     */
     @Override
     public void setPadding(int left, int top, int right, int bottom) {
         if (left != mPaddingLeft
@@ -3179,6 +3217,12 @@
         invalidate();
     }
 
+    /**
+     * @inheritDoc
+     *
+     * @see #setFirstBaselineToTopHeight(int)
+     * @see #setLastBaselineToBottomHeight(int)
+     */
     @Override
     public void setPaddingRelative(int start, int top, int end, int bottom) {
         if (start != getPaddingStart()
@@ -3194,6 +3238,97 @@
     }
 
     /**
+     * Updates the top padding of the TextView so that {@code firstBaselineToTopHeight} is
+     * equal to the distance between the firt text baseline and the top of this TextView.
+     * <strong>Note</strong> that if {@code FontMetrics.top} or {@code FontMetrics.ascent} was
+     * already greater than {@code firstBaselineToTopHeight}, the top padding is not updated.
+     *
+     * @param firstBaselineToTopHeight distance between first baseline to top of the container
+     *      in pixels
+     *
+     * @see #getFirstBaselineToTopHeight()
+     * @see #setPadding(int, int, int, int)
+     * @see #setPaddingRelative(int, int, int, int)
+     *
+     * @attr ref android.R.styleable#TextView_firstBaselineToTopHeight
+     */
+    public void setFirstBaselineToTopHeight(@Px @IntRange(from = 0) int firstBaselineToTopHeight) {
+        Preconditions.checkArgumentNonnegative(firstBaselineToTopHeight);
+
+        final FontMetricsInt fontMetrics = getPaint().getFontMetricsInt();
+        final int fontMetricsTop;
+        if (getIncludeFontPadding()) {
+            fontMetricsTop = fontMetrics.top;
+        } else {
+            fontMetricsTop = fontMetrics.ascent;
+        }
+
+        // TODO: Decide if we want to ignore density ratio (i.e. when the user changes font size
+        // in settings). At the moment, we don't.
+
+        if (firstBaselineToTopHeight > Math.abs(fontMetricsTop)) {
+            final int paddingTop = firstBaselineToTopHeight - (-fontMetricsTop);
+            setPadding(getPaddingLeft(), paddingTop, getPaddingRight(), getPaddingBottom());
+        }
+    }
+
+    /**
+     * Updates the bottom padding of the TextView so that {@code lastBaselineToBottomHeight} is
+     * equal to the distance between the last text baseline and the bottom of this TextView.
+     * <strong>Note</strong> that if {@code FontMetrics.bottom} or {@code FontMetrics.descent} was
+     * already greater than {@code lastBaselineToBottomHeight}, the bottom padding is not updated.
+     *
+     * @param lastBaselineToBottomHeight distance between last baseline to bottom of the container
+     *      in pixels
+     *
+     * @see #getLastBaselineToBottomHeight()
+     * @see #setPadding(int, int, int, int)
+     * @see #setPaddingRelative(int, int, int, int)
+     *
+     * @attr ref android.R.styleable#TextView_lastBaselineToBottomHeight
+     */
+    public void setLastBaselineToBottomHeight(
+            @Px @IntRange(from = 0) int lastBaselineToBottomHeight) {
+        Preconditions.checkArgumentNonnegative(lastBaselineToBottomHeight);
+
+        final FontMetricsInt fontMetrics = getPaint().getFontMetricsInt();
+        final int fontMetricsBottom;
+        if (getIncludeFontPadding()) {
+            fontMetricsBottom = fontMetrics.bottom;
+        } else {
+            fontMetricsBottom = fontMetrics.descent;
+        }
+
+        // TODO: Decide if we want to ignore density ratio (i.e. when the user changes font size
+        // in settings). At the moment, we don't.
+
+        if (lastBaselineToBottomHeight > Math.abs(fontMetricsBottom)) {
+            final int paddingBottom = lastBaselineToBottomHeight - fontMetricsBottom;
+            setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+        }
+    }
+
+    /**
+     * Returns the distance between the first text baseline and the top of this TextView.
+     *
+     * @see #setFirstBaselineToTopHeight(int)
+     * @attr ref android.R.styleable#TextView_firstBaselineToTopHeight
+     */
+    public int getFirstBaselineToTopHeight() {
+        return getPaddingTop() - getPaint().getFontMetricsInt().top;
+    }
+
+    /**
+     * Returns the distance between the last text baseline and the bottom of this TextView.
+     *
+     * @see #setLastBaselineToBottomHeight(int)
+     * @attr ref android.R.styleable#TextView_lastBaselineToBottomHeight
+     */
+    public int getLastBaselineToBottomHeight() {
+        return getPaddingBottom() + getPaint().getFontMetricsInt().bottom;
+    }
+
+    /**
      * Gets the autolink mask of the text.  See {@link
      * android.text.util.Linkify#ALL Linkify.ALL} and peers for
      * possible values.
@@ -3756,6 +3891,7 @@
      *
      * @param elegant set the paint's elegant metrics flag.
      *
+     * @see #isElegantTextHeight()
      * @see Paint#isElegantTextHeight()
      *
      * @attr ref android.R.styleable#TextView_elegantTextHeight
@@ -4974,6 +5110,53 @@
     }
 
     /**
+     * Sets an explicit line height for this TextView. This is equivalent to the vertical distance
+     * between subsequent baselines in the TextView.
+     *
+     * @param lineHeight the line height in pixels
+     *
+     * @see #setLineSpacing(float, float)
+     * @see #getLineSpacing()
+     *
+     * @attr ref android.R.styleable#TextView_lineHeight
+     */
+    public void setLineHeight(@Px @IntRange(from = 0) int lineHeight) {
+        Preconditions.checkArgumentNonnegative(lineHeight);
+
+        final int fontHeight = getPaint().getFontMetricsInt(null);
+        // Make sure we don't setLineSpacing if it's not needed to avoid unnecessary redraw.
+        if (lineHeight != fontHeight) {
+            // Set lineSpacingExtra by the difference of lineSpacing with lineHeight
+            setLineSpacing(lineHeight - fontHeight, 1f);
+        }
+    }
+
+    /**
+     * Gets whether this view is a heading for accessibility purposes.
+     *
+     * @return {@code true} if the view is a heading, {@code false} otherwise.
+     *
+     * @attr ref android.R.styleable#TextView_accessibilityHeading
+     */
+    public boolean isAccessibilityHeading() {
+        return mIsAccessibilityHeading;
+    }
+
+    /**
+     * Set if view is a heading for a section of content for accessibility purposes.
+     *
+     * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
+     *
+     * @attr ref android.R.styleable#TextView_accessibilityHeading
+     */
+    public void setAccessibilityHeading(boolean isHeading) {
+        if (isHeading != mIsAccessibilityHeading) {
+            mIsAccessibilityHeading = isHeading;
+            notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+        }
+    }
+
+    /**
      * Convenience method to append the specified text to the TextView's
      * display buffer, upgrading it to {@link android.widget.TextView.BufferType#EDITABLE}
      * if it was not already editable.
@@ -9125,8 +9308,7 @@
 
     /**
      *
-     * Checks whether the transformation method applied to this TextView is set to ALL CAPS. This
-     * settings is internally ignored if this field is editable or selectable.
+     * Checks whether the transformation method applied to this TextView is set to ALL CAPS.
      * @return Whether the current transformation method is for ALL CAPS.
      *
      * @see #setAllCaps(boolean)
@@ -10524,6 +10706,7 @@
         info.setText(getTextForAccessibility());
         info.setHintText(mHint);
         info.setShowingHintText(isShowingHint());
+        info.setHeading(mIsAccessibilityHeading);
 
         if (mBufferType == BufferType.EDITABLE) {
             info.setEditable(true);
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index e765ab1..8a456d1 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -25,6 +25,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.dex.DexMetadataHelper;
 import android.os.Environment;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -415,6 +416,9 @@
             sizeBytes += codeFile.length();
         }
 
+        // Include raw dex metadata files
+        sizeBytes += DexMetadataHelper.getPackageDexMetadataSize(pkg);
+
         // Include all relevant native code
         sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 439e5df..ac5dbc4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4062,8 +4062,6 @@
 
     public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
             String tag) {
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         if (workSource != null) {
             for (int i = 0; i < workSource.size(); ++i) {
                 uid = workSource.get(i);
@@ -4074,9 +4072,8 @@
                             workSourceName != null ? workSourceName : packageName);
                     pkg.noteWakeupAlarmLocked(tag);
                 }
-                uids[0] = workSource.get(i);
-                tags[0] = workSource.getName(i);
-                StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uids, tags, tag);
+                StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, workSource.get(i),
+                        workSource.getName(i), tag);
             }
 
             ArrayList<WorkChain> workChains = workSource.getWorkChains();
@@ -4097,9 +4094,7 @@
                 BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
                 pkg.noteWakeupAlarmLocked(tag);
             }
-            uids[0] = uid;
-            tags[0] = null;
-            StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uids, tags, tag);
+            StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, uid, null, tag);
         }
     }
 
@@ -4224,9 +4219,8 @@
                 StatsLog.write(
                         StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), type, name, 1);
             } else {
-                final int[] uids = new int[] { uid };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, type, name, 1);
+                StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null, type, name,
+                        1);
             }
         }
     }
@@ -4268,9 +4262,8 @@
                 StatsLog.write(
                         StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), type, name, 0);
             } else {
-                final int[] uids = new int[] { uid };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, type, name, 0);
+                StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null, type, name,
+                        0);
             }
         }
     }
@@ -4364,10 +4357,8 @@
     }
 
     public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
-        final int[] uids = new int[] { uid };
-        final String[] tags = new String[] { null };
-        StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
-                uids, tags, name, historyName, 1);
+        StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
+                uid, null, name, historyName, 1);
 
         uid = mapUid(uid);
         noteLongPartialWakeLockStartInternal(name, historyName, uid);
@@ -4376,15 +4367,11 @@
     public void noteLongPartialWakelockStartFromSource(String name, String historyName,
             WorkSource workSource) {
         final int N = workSource.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i = 0; i < N; ++i) {
             final int uid = mapUid(workSource.get(i));
             noteLongPartialWakeLockStartInternal(name, historyName, uid);
-            uids[0] = workSource.get(i);
-            tags[0] = workSource.getName(i);
-            StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED, uids, tags, name,
-                    historyName, 1);
+            StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
+                    workSource.get(i), workSource.getName(i), name, historyName, 1);
         }
 
         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
@@ -4415,10 +4402,8 @@
     }
 
     public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
-        int[] uids = new int[] { uid };
-        String[] tags = new String[] { null };
-        StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
-                uids, tags, name, historyName, 0);
+        StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
+                uid, null, name, historyName, 0);
 
         uid = mapUid(uid);
         noteLongPartialWakeLockFinishInternal(name, historyName, uid);
@@ -4427,15 +4412,11 @@
     public void noteLongPartialWakelockFinishFromSource(String name, String historyName,
             WorkSource workSource) {
         final int N = workSource.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i = 0; i < N; ++i) {
             final int uid = mapUid(workSource.get(i));
             noteLongPartialWakeLockFinishInternal(name, historyName, uid);
-            uids[0] = workSource.get(i);
-            tags[0] = workSource.getName(i);
-            StatsLog.write(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
-                    uids, tags, name, historyName, 0);
+            StatsLog.write_non_chained(StatsLog.LONG_PARTIAL_WAKELOCK_STATE_CHANGED,
+                    workSource.get(i), workSource.getName(i), name, historyName, 0);
         }
 
         final ArrayList<WorkChain> workChains = workSource.getWorkChains();
@@ -5420,11 +5401,10 @@
                         workChain.getUids(), workChain.getTags(), 1);
             }
         } else {
-            final int[] uids = new int[] {uid};
-            final String[] tags = new String[] {null};
-            StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null, 1);
             if (isUnoptimized) {
-                StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uids, tags, 1);
+                StatsLog.write_non_chained(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uid, null,
+                        1);
             }
         }
 
@@ -5470,11 +5450,10 @@
                         workChain.getUids(), workChain.getTags(), 0);
             }
         } else {
-            final int[] uids = new int[] { uid };
-            final String[] tags = new String[] {null};
-            StatsLog.write(StatsLog.BLE_SCAN_STATE_CHANGED, uids, tags, 0);
+            StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, uid, null, 0);
             if (isUnoptimized) {
-                StatsLog.write(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uids, tags, 0);
+                StatsLog.write_non_chained(StatsLog.BLE_UNOPTIMIZED_SCAN_STATE_CHANGED, uid, null,
+                        0);
             }
         }
 
@@ -5547,14 +5526,11 @@
 
     public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
         final int N = ws.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i = 0; i < N; i++) {
             int uid = mapUid(ws.get(i));
             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
-            uids[0] = ws.get(i);
-            tags[0] = ws.getName(i);
-            StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED, uids, tags, numNewResults);
+            StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
+                    numNewResults);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5879,14 +5855,10 @@
 
     public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
         int N = ws.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i=0; i<N; i++) {
             final int uid = mapUid(ws.get(i));
             noteFullWifiLockAcquiredLocked(uid);
-            uids[0] = ws.get(i);
-            tags[0] = ws.getName(i);
-            StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i), 1);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5903,14 +5875,10 @@
 
     public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i=0; i<N; i++) {
             final int uid = mapUid(ws.get(i));
             noteFullWifiLockReleasedLocked(uid);
-            uids[0] = ws.get(i);
-            tags[0] = ws.getName(i);
-            StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED, uids, tags, 0);
+            StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i), 0);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5927,14 +5895,11 @@
 
     public void noteWifiScanStartedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i=0; i<N; i++) {
             final int uid = mapUid(ws.get(i));
             noteWifiScanStartedLocked(uid);
-            uids[0] = ws.get(i);
-            tags[0] = ws.getName(i);
-            StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
+                    1);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5951,14 +5916,11 @@
 
     public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) {
         int N = ws.size();
-        final int[] uids = new int[1];
-        final String[] tags = new String[1];
         for (int i=0; i<N; i++) {
             final int uid = mapUid(ws.get(i));
             noteWifiScanStoppedLocked(uid);
-            uids[0] = ws.get(i);
-            tags[0] = ws.getName(i);
-            StatsLog.write(StatsLog.WIFI_SCAN_STATE_CHANGED, uids, tags, 0);
+            StatsLog.write_non_chained(StatsLog.WIFI_SCAN_STATE_CHANGED, ws.get(i), ws.getName(i),
+                    0);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -6934,18 +6896,14 @@
 
         public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
             createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
-            final int[] uids = new int[] { getUid() };
-            final String[] tags = new String[] { null };
-            StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, 1);
         }
 
         public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
             if (mAudioTurnedOnTimer != null) {
                 mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
                 if (!mAudioTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
-                    StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, uids, tags, 0);
+                    StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, 0);
                 }
             }
         }
@@ -6953,9 +6911,7 @@
         public void noteResetAudioLocked(long elapsedRealtimeMs) {
             if (mAudioTurnedOnTimer != null) {
                 mAudioTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
-                final int[] uids = new int[] { getUid() };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, uids, tags, 0);
+                StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, getUid(), null, 0);
             }
         }
 
@@ -6969,18 +6925,15 @@
 
         public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
             createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
-            final int[] uids = new int[] { getUid() };
-            final String[] tags = new String[] { null };
-            StatsLog.write(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null, 1);
         }
 
         public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
             if (mVideoTurnedOnTimer != null) {
                 mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
                 if (!mVideoTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
-                    StatsLog.write(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, uids, tags, 0);
+                    StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(),
+                            null, 0);
                 }
             }
         }
@@ -6988,9 +6941,8 @@
         public void noteResetVideoLocked(long elapsedRealtimeMs) {
             if (mVideoTurnedOnTimer != null) {
                 mVideoTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
-                final int[] uids = new int[] { getUid() };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, uids, tags, 0);
+                StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_ACTIVITY_CHANGED, getUid(), null,
+                        0);
             }
         }
 
@@ -7004,18 +6956,15 @@
 
         public void noteFlashlightTurnedOnLocked(long elapsedRealtimeMs) {
             createFlashlightTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
-            final int[] uids = new int[] { getUid() };
-            final String[] tags = new String[] { null };
-            StatsLog.write(StatsLog.FLASHLIGHT_STATE_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,1);
         }
 
         public void noteFlashlightTurnedOffLocked(long elapsedRealtimeMs) {
             if (mFlashlightTurnedOnTimer != null) {
                 mFlashlightTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
                 if (!mFlashlightTurnedOnTimer.isRunningLocked()) {
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
-                    StatsLog.write(StatsLog.FLASHLIGHT_STATE_CHANGED, uids, tags, 0);
+                    StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null,
+                            0);
                 }
             }
         }
@@ -7023,9 +6972,7 @@
         public void noteResetFlashlightLocked(long elapsedRealtimeMs) {
             if (mFlashlightTurnedOnTimer != null) {
                 mFlashlightTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
-                final int[] uids = new int[] { getUid() };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.FLASHLIGHT_STATE_CHANGED, uids, tags, 0);
+                StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, getUid(), null, 0);
             }
         }
 
@@ -7039,18 +6986,14 @@
 
         public void noteCameraTurnedOnLocked(long elapsedRealtimeMs) {
             createCameraTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
-            final int[] uids = new int[] { getUid() };
-            final String[] tags = new String[] { null };
-            StatsLog.write(StatsLog.CAMERA_STATE_CHANGED, uids, tags, 1);
+            StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, 1);
         }
 
         public void noteCameraTurnedOffLocked(long elapsedRealtimeMs) {
             if (mCameraTurnedOnTimer != null) {
                 mCameraTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
                 if (!mCameraTurnedOnTimer.isRunningLocked()) { // only tell statsd if truly stopped
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
-                    StatsLog.write(StatsLog.CAMERA_STATE_CHANGED, uids, tags, 0);
+                    StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, 0);
                 }
             }
         }
@@ -7058,9 +7001,7 @@
         public void noteResetCameraLocked(long elapsedRealtimeMs) {
             if (mCameraTurnedOnTimer != null) {
                 mCameraTurnedOnTimer.stopAllRunningLocked(elapsedRealtimeMs);
-                final int[] uids = new int[] { getUid() };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.CAMERA_STATE_CHANGED, uids, tags, 0);
+                StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, getUid(), null, 0);
             }
         }
 
@@ -9622,9 +9563,7 @@
             DualTimer t = mSyncStats.startObject(name);
             if (t != null) {
                 t.startRunningLocked(elapsedRealtimeMs);
-                final int[] uids = new int[] { getUid() };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.SYNC_STATE_CHANGED, uids, tags, name, 1);
+                StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name, 1);
             }
         }
 
@@ -9633,9 +9572,7 @@
             if (t != null) {
                 t.stopRunningLocked(elapsedRealtimeMs);
                 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
-                    StatsLog.write(StatsLog.SYNC_STATE_CHANGED, uids, tags, name, 0);
+                    StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, getUid(), null, name, 0);
                 }
             }
         }
@@ -9644,9 +9581,8 @@
             DualTimer t = mJobStats.startObject(name);
             if (t != null) {
                 t.startRunningLocked(elapsedRealtimeMs);
-                final int[] uids = new int[] { getUid() };
-                final String[] tags = new String[] { null };
-                StatsLog.write(StatsLog.SCHEDULED_JOB_STATE_CHANGED, uids, tags, name, 1);
+                StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
+                        name, 1);
             }
         }
 
@@ -9655,9 +9591,8 @@
             if (t != null) {
                 t.stopRunningLocked(elapsedRealtimeMs);
                 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
-                    StatsLog.write(StatsLog.SCHEDULED_JOB_STATE_CHANGED, uids, tags, name, 0);
+                    StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
+                            name, 0);
                 }
             }
             if (mBsi.mOnBatteryTimeBase.isRunning()) {
@@ -9768,12 +9703,11 @@
         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
             DualTimer t = getSensorTimerLocked(sensor, /* create= */ true);
             t.startRunningLocked(elapsedRealtimeMs);
-            final int[] uids = new int[] { getUid() };
-            final String[] tags = new String[] { null };
             if (sensor == Sensor.GPS) {
-                StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, uids, tags, 1);
+                StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), null, 1);
             } else {
-                StatsLog.write(StatsLog.SENSOR_STATE_CHANGED, uids, tags, sensor, 1);
+                StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null, sensor,
+                        1);
             }
         }
 
@@ -9783,13 +9717,12 @@
             if (t != null) {
                 t.stopRunningLocked(elapsedRealtimeMs);
                 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
-                    // TODO(statsd): Possibly use a worksource instead of a uid.
-                    final int[] uids = new int[] { getUid() };
-                    final String[] tags = new String[] { null };
                     if (sensor == Sensor.GPS) {
-                        StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, uids, tags, 0);
+                        StatsLog.write_non_chained(StatsLog.GPS_SCAN_STATE_CHANGED, getUid(), null,
+                                0);
                     } else {
-                        StatsLog.write(StatsLog.SENSOR_STATE_CHANGED, uids, tags, sensor, 0);
+                        StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, getUid(), null,
+                                sensor, 0);
                     }
                 }
             }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index cbc63cf..079ba0b 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -67,6 +67,9 @@
 
     private Zygote() {}
 
+    /** Called for some security initialization before any fork. */
+    native static void nativeSecurityInit();
+
     /**
      * Forks a new VM instance.  The current VM must have been started
      * with the -Xzygote flag. <b>NOTE: new instance keeps all
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index c5fe4cb..2671f29 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -30,7 +30,6 @@
 import android.os.Environment;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.Seccomp;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
 import android.os.SystemClock;
@@ -572,10 +571,12 @@
                 final String seInfo = null;
                 final String classLoaderContext =
                         getSystemServerClassLoaderContext(classPathForElement);
+                final int targetSdkVersion = 0;  // SystemServer targets the system's SDK version
                 try {
                     installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
                             instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
-                            uuid, classLoaderContext, seInfo, false /* downgrade */);
+                            uuid, classLoaderContext, seInfo, false /* downgrade */,
+                            targetSdkVersion);
                 } 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: "
@@ -779,12 +780,11 @@
             // Zygote.
             Trace.setTracingEnabled(false, 0);
 
+            Zygote.nativeSecurityInit();
+
             // Zygote process unmounts root storage spaces.
             Zygote.nativeUnmountStorageOnInit();
 
-            // Set seccomp policy
-            Seccomp.setPolicy();
-
             ZygoteHooks.stopZygoteNoThreadCreation();
 
             if (startSystemServer) {
diff --git a/core/java/com/android/internal/print/DualDumpOutputStream.java b/core/java/com/android/internal/print/DualDumpOutputStream.java
new file mode 100644
index 0000000..4b10ef2
--- /dev/null
+++ b/core/java/com/android/internal/print/DualDumpOutputStream.java
@@ -0,0 +1,276 @@
+/*
+ * 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.print;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+
+/**
+ * Dump either to a proto or a print writer using the same interface.
+ *
+ * <p>This mirrors the interface of {@link ProtoOutputStream}.
+ */
+public class DualDumpOutputStream {
+    private static final String LOG_TAG = DualDumpOutputStream.class.getSimpleName();
+
+    // When writing to a proto, the proto
+    private final @Nullable ProtoOutputStream mProtoStream;
+
+    // When printing in clear text, the writer
+    private final @Nullable IndentingPrintWriter mIpw;
+    // Temporary storage of data when printing to mIpw
+    private final LinkedList<DumpObject> mDumpObjects = new LinkedList<>();
+
+    private static abstract class Dumpable {
+        final String name;
+
+        private Dumpable(String name) {
+            this.name = name;
+        }
+
+        abstract void print(IndentingPrintWriter ipw, boolean printName);
+    }
+
+    private static class DumpObject extends Dumpable {
+        private final LinkedHashMap<String, ArrayList<Dumpable>> mSubObjects = new LinkedHashMap<>();
+
+        private DumpObject(String name) {
+            super(name);
+        }
+
+        @Override
+        void print(IndentingPrintWriter ipw, boolean printName) {
+            if (printName) {
+                ipw.println(name + "={");
+            } else {
+                ipw.println("{");
+            }
+            ipw.increaseIndent();
+
+            for (ArrayList<Dumpable> subObject: mSubObjects.values()) {
+                int numDumpables = subObject.size();
+
+                if (numDumpables == 1) {
+                    subObject.get(0).print(ipw, true);
+                } else {
+                    ipw.println(subObject.get(0).name + "=[");
+                    ipw.increaseIndent();
+
+                    for (int i = 0; i < numDumpables; i++) {
+                        subObject.get(i).print(ipw, false);
+                    }
+
+                    ipw.decreaseIndent();
+                    ipw.println("]");
+                }
+            }
+
+            ipw.decreaseIndent();
+            ipw.println("}");
+        }
+
+        /**
+         * Add new field / subobject to this object.
+         *
+         * <p>If a name is added twice, they will be printed as a array
+         *
+         * @param fieldName name of the field added
+         * @param d The dumpable to add
+         */
+        public void add(String fieldName, Dumpable d) {
+            ArrayList<Dumpable> l = mSubObjects.get(fieldName);
+
+            if (l == null) {
+                l = new ArrayList<>(1);
+                mSubObjects.put(fieldName, l);
+            }
+
+            l.add(d);
+        }
+    }
+
+    private static class DumpField extends Dumpable {
+        private final String mValue;
+
+        private DumpField(String name, String value) {
+            super(name);
+            this.mValue = value;
+        }
+
+        @Override
+        void print(IndentingPrintWriter ipw, boolean printName) {
+            if (printName) {
+                ipw.println(name + "=" + mValue);
+            } else {
+                ipw.println(mValue);
+            }
+        }
+    }
+
+
+    /**
+     * Create a new DualDumpOutputStream. Only one output should be set.
+     *
+     * @param proto If dumping to proto the {@link ProtoOutputStream}
+     * @param ipw If dumping to a print writer, the {@link IndentingPrintWriter}
+     */
+    public DualDumpOutputStream(@Nullable ProtoOutputStream proto,
+            @Nullable IndentingPrintWriter ipw) {
+        if ((proto == null) == (ipw == null)) {
+            Log.e(LOG_TAG, "Cannot dump to clear text and proto at once. Ignoring proto");
+            proto = null;
+        }
+
+        mProtoStream = proto;
+        mIpw = ipw;
+
+        if (!isProto()) {
+            // Add root object
+            mDumpObjects.add(new DumpObject(null));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, double val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, String.valueOf(val)));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, boolean val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, String.valueOf(val)));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, int val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, String.valueOf(val)));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, float val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, String.valueOf(val)));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, byte[] val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, Arrays.toString(val)));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, long val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, String.valueOf(val)));
+        }
+    }
+
+    public void write(@NonNull String fieldName, long fieldId, @Nullable String val) {
+        if (mProtoStream != null) {
+            mProtoStream.write(fieldId, val);
+        } else {
+            mDumpObjects.getLast().add(fieldName, new DumpField(fieldName, String.valueOf(val)));
+        }
+    }
+
+    public long start(@NonNull String fieldName, long fieldId) {
+        if (mProtoStream != null) {
+            return mProtoStream.start(fieldId);
+        } else {
+            DumpObject d = new DumpObject(fieldName);
+            mDumpObjects.getLast().add(fieldName, d);
+            mDumpObjects.addLast(d);
+            return System.identityHashCode(d);
+        }
+    }
+
+    public void end(long token) {
+        if (mProtoStream != null) {
+            mProtoStream.end(token);
+        } else {
+            if (System.identityHashCode(mDumpObjects.getLast()) != token) {
+                Log.w(LOG_TAG, "Unexpected token for ending " + mDumpObjects.getLast().name
+                                + " at " + Arrays.toString(Thread.currentThread().getStackTrace()));
+            }
+            mDumpObjects.removeLast();
+        }
+    }
+
+    public void flush() {
+        if (mProtoStream != null) {
+            mProtoStream.flush();
+        } else {
+            if (mDumpObjects.size() == 1) {
+                mDumpObjects.getFirst().print(mIpw, false);
+
+                // Reset root object
+                mDumpObjects.clear();
+                mDumpObjects.add(new DumpObject(null));
+            }
+
+            mIpw.flush();
+        }
+    }
+
+    /**
+     * Add a dump from a different service into this dump.
+     *
+     * <p>Only for clear text dump. For proto dump use {@link #write(String, long, byte[])}.
+     *
+     * @param fieldName The name of the field
+     * @param nestedState The state of the dump
+     */
+    public void writeNested(@NonNull String fieldName, byte[] nestedState) {
+        if (mIpw == null) {
+            Log.w(LOG_TAG, "writeNested does not work for proto logging");
+            return;
+        }
+
+        mDumpObjects.getLast().add(fieldName,
+                new DumpField(fieldName, (new String(nestedState, StandardCharsets.UTF_8)).trim()));
+    }
+
+    /**
+     * @return {@code true} iff we are dumping to a proto
+     */
+    public boolean isProto() {
+        return mProtoStream != null;
+    }
+}
diff --git a/core/java/com/android/internal/print/DumpUtils.java b/core/java/com/android/internal/print/DumpUtils.java
index 28c7fc2..3192d5c 100644
--- a/core/java/com/android/internal/print/DumpUtils.java
+++ b/core/java/com/android/internal/print/DumpUtils.java
@@ -39,7 +39,6 @@
 import android.service.print.PrinterIdProto;
 import android.service.print.PrinterInfoProto;
 import android.service.print.ResolutionProto;
-import android.util.proto.ProtoOutputStream;
 
 /**
  * Utilities for dumping print related proto buffer
@@ -49,13 +48,14 @@
      * Write a string to a proto if the string is not {@code null}.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the string
      * @param string The string to write
      */
-    public static void writeStringIfNotNull(@NonNull ProtoOutputStream proto, long id,
-            @Nullable String string) {
+    public static void writeStringIfNotNull(@NonNull DualDumpOutputStream proto, String idName,
+            long id, @Nullable String string) {
         if (string != null) {
-            proto.write(id, string);
+            proto.write(idName, id, string);
         }
     }
 
@@ -63,14 +63,15 @@
      * Write a {@link ComponentName} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param component The component name to write
      */
-    public static void writeComponentName(@NonNull ProtoOutputStream proto, long id,
-            @NonNull ComponentName component) {
-        long token = proto.start(id);
-        proto.write(ComponentNameProto.PACKAGE_NAME, component.getPackageName());
-        proto.write(ComponentNameProto.CLASS_NAME, component.getClassName());
+    public static void writeComponentName(@NonNull DualDumpOutputStream proto, String idName,
+            long id, @NonNull ComponentName component) {
+        long token = proto.start(idName, id);
+        proto.write("package_name", ComponentNameProto.PACKAGE_NAME, component.getPackageName());
+        proto.write("class_name", ComponentNameProto.CLASS_NAME, component.getClassName());
         proto.end(token);
     }
 
@@ -78,14 +79,16 @@
      * Write a {@link PrinterId} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param printerId The printer id to write
      */
-    public static void writePrinterId(@NonNull ProtoOutputStream proto, long id,
+    public static void writePrinterId(@NonNull DualDumpOutputStream proto, String idName, long id,
             @NonNull PrinterId printerId) {
-        long token = proto.start(id);
-        writeComponentName(proto, PrinterIdProto.SERVICE_NAME, printerId.getServiceName());
-        proto.write(PrinterIdProto.LOCAL_ID, printerId.getLocalId());
+        long token = proto.start(idName, id);
+        writeComponentName(proto, "service_name", PrinterIdProto.SERVICE_NAME,
+                printerId.getServiceName());
+        proto.write("local_id", PrinterIdProto.LOCAL_ID, printerId.getLocalId());
         proto.end(token);
     }
 
@@ -93,71 +96,76 @@
      * Write a {@link PrinterCapabilitiesInfo} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param cap The capabilities to write
      */
     public static void writePrinterCapabilities(@NonNull Context context,
-            @NonNull ProtoOutputStream proto, long id, @NonNull PrinterCapabilitiesInfo cap) {
-        long token = proto.start(id);
-        writeMargins(proto, PrinterCapabilitiesProto.MIN_MARGINS, cap.getMinMargins());
+            @NonNull DualDumpOutputStream proto, String idName, long id,
+            @NonNull PrinterCapabilitiesInfo cap) {
+        long token = proto.start(idName, id);
+        writeMargins(proto, "min_margins", PrinterCapabilitiesProto.MIN_MARGINS,
+                cap.getMinMargins());
 
         int numMediaSizes = cap.getMediaSizes().size();
         for (int i = 0; i < numMediaSizes; i++) {
-            writeMediaSize(context, proto, PrinterCapabilitiesProto.MEDIA_SIZES,
+            writeMediaSize(context, proto, "media_sizes", PrinterCapabilitiesProto.MEDIA_SIZES,
                     cap.getMediaSizes().get(i));
         }
 
         int numResolutions = cap.getResolutions().size();
         for (int i = 0; i < numResolutions; i++) {
-            writeResolution(proto, PrinterCapabilitiesProto.RESOLUTIONS,
+            writeResolution(proto, "resolutions", PrinterCapabilitiesProto.RESOLUTIONS,
                     cap.getResolutions().get(i));
         }
 
         if ((cap.getColorModes() & PrintAttributes.COLOR_MODE_MONOCHROME) != 0) {
-            proto.write(PrinterCapabilitiesProto.COLOR_MODES,
+            proto.write("color_modes", PrinterCapabilitiesProto.COLOR_MODES,
                     PrintAttributesProto.COLOR_MODE_MONOCHROME);
         }
         if ((cap.getColorModes() & PrintAttributes.COLOR_MODE_COLOR) != 0) {
-            proto.write(PrinterCapabilitiesProto.COLOR_MODES,
+            proto.write("color_modes", PrinterCapabilitiesProto.COLOR_MODES,
                     PrintAttributesProto.COLOR_MODE_COLOR);
         }
 
         if ((cap.getDuplexModes() & PrintAttributes.DUPLEX_MODE_NONE) != 0) {
-            proto.write(PrinterCapabilitiesProto.DUPLEX_MODES,
+            proto.write("duplex_modes", PrinterCapabilitiesProto.DUPLEX_MODES,
                     PrintAttributesProto.DUPLEX_MODE_NONE);
         }
         if ((cap.getDuplexModes() & PrintAttributes.DUPLEX_MODE_LONG_EDGE) != 0) {
-            proto.write(PrinterCapabilitiesProto.DUPLEX_MODES,
+            proto.write("duplex_modes", PrinterCapabilitiesProto.DUPLEX_MODES,
                     PrintAttributesProto.DUPLEX_MODE_LONG_EDGE);
         }
         if ((cap.getDuplexModes() & PrintAttributes.DUPLEX_MODE_SHORT_EDGE) != 0) {
-            proto.write(PrinterCapabilitiesProto.DUPLEX_MODES,
+            proto.write("duplex_modes", PrinterCapabilitiesProto.DUPLEX_MODES,
                     PrintAttributesProto.DUPLEX_MODE_SHORT_EDGE);
         }
 
         proto.end(token);
     }
 
-
     /**
      * Write a {@link PrinterInfo} to a proto.
      *
      * @param context The context used to resolve resources
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param info The printer info to write
      */
-    public static void writePrinterInfo(@NonNull Context context, @NonNull ProtoOutputStream proto,
-            long id, @NonNull PrinterInfo info) {
-        long token = proto.start(id);
-        writePrinterId(proto, PrinterInfoProto.ID, info.getId());
-        proto.write(PrinterInfoProto.NAME, info.getName());
-        proto.write(PrinterInfoProto.STATUS, info.getStatus());
-        proto.write(PrinterInfoProto.DESCRIPTION, info.getDescription());
+    public static void writePrinterInfo(@NonNull Context context,
+            @NonNull DualDumpOutputStream proto, String idName, long id,
+            @NonNull PrinterInfo info) {
+        long token = proto.start(idName, id);
+        writePrinterId(proto, "id", PrinterInfoProto.ID, info.getId());
+        proto.write("name", PrinterInfoProto.NAME, info.getName());
+        proto.write("status", PrinterInfoProto.STATUS, info.getStatus());
+        proto.write("description", PrinterInfoProto.DESCRIPTION, info.getDescription());
 
         PrinterCapabilitiesInfo cap = info.getCapabilities();
         if (cap != null) {
-            writePrinterCapabilities(context, proto, PrinterInfoProto.CAPABILITIES, cap);
+            writePrinterCapabilities(context, proto, "capabilities", PrinterInfoProto.CAPABILITIES,
+                    cap);
         }
 
         proto.end(token);
@@ -168,16 +176,17 @@
      *
      * @param context The context used to resolve resources
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param mediaSize The media size to write
      */
-    public static void writeMediaSize(@NonNull Context context, @NonNull ProtoOutputStream proto,
-            long id, @NonNull PrintAttributes.MediaSize mediaSize) {
-        long token = proto.start(id);
-        proto.write(MediaSizeProto.ID, mediaSize.getId());
-        proto.write(MediaSizeProto.LABEL, mediaSize.getLabel(context.getPackageManager()));
-        proto.write(MediaSizeProto.HEIGHT_MILS, mediaSize.getHeightMils());
-        proto.write(MediaSizeProto.WIDTH_MILS, mediaSize.getWidthMils());
+    public static void writeMediaSize(@NonNull Context context, @NonNull DualDumpOutputStream proto,
+            String idName, long id, @NonNull PrintAttributes.MediaSize mediaSize) {
+        long token = proto.start(idName, id);
+        proto.write("id", MediaSizeProto.ID, mediaSize.getId());
+        proto.write("label", MediaSizeProto.LABEL, mediaSize.getLabel(context.getPackageManager()));
+        proto.write("height_mils", MediaSizeProto.HEIGHT_MILS, mediaSize.getHeightMils());
+        proto.write("width_mils", MediaSizeProto.WIDTH_MILS, mediaSize.getWidthMils());
         proto.end(token);
     }
 
@@ -185,16 +194,17 @@
      * Write a {@link PrintAttributes.Resolution} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param res The resolution to write
      */
-    public static void writeResolution(@NonNull ProtoOutputStream proto, long id,
+    public static void writeResolution(@NonNull DualDumpOutputStream proto, String idName, long id,
             @NonNull PrintAttributes.Resolution res) {
-        long token = proto.start(id);
-        proto.write(ResolutionProto.ID, res.getId());
-        proto.write(ResolutionProto.LABEL, res.getLabel());
-        proto.write(ResolutionProto.HORIZONTAL_DPI, res.getHorizontalDpi());
-        proto.write(ResolutionProto.VERTICAL_DPI, res.getVerticalDpi());
+        long token = proto.start(idName, id);
+        proto.write("id", ResolutionProto.ID, res.getId());
+        proto.write("label", ResolutionProto.LABEL, res.getLabel());
+        proto.write("horizontal_DPI", ResolutionProto.HORIZONTAL_DPI, res.getHorizontalDpi());
+        proto.write("veritical_DPI", ResolutionProto.VERTICAL_DPI, res.getVerticalDpi());
         proto.end(token);
     }
 
@@ -202,16 +212,17 @@
      * Write a {@link PrintAttributes.Margins} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param margins The margins to write
      */
-    public static void writeMargins(@NonNull ProtoOutputStream proto, long id,
+    public static void writeMargins(@NonNull DualDumpOutputStream proto, String idName, long id,
             @NonNull PrintAttributes.Margins margins) {
-        long token = proto.start(id);
-        proto.write(MarginsProto.TOP_MILS, margins.getTopMils());
-        proto.write(MarginsProto.LEFT_MILS, margins.getLeftMils());
-        proto.write(MarginsProto.RIGHT_MILS, margins.getRightMils());
-        proto.write(MarginsProto.BOTTOM_MILS, margins.getBottomMils());
+        long token = proto.start(idName, id);
+        proto.write("top_mils", MarginsProto.TOP_MILS, margins.getTopMils());
+        proto.write("left_mils", MarginsProto.LEFT_MILS, margins.getLeftMils());
+        proto.write("right_mils", MarginsProto.RIGHT_MILS, margins.getRightMils());
+        proto.write("bottom_mils", MarginsProto.BOTTOM_MILS, margins.getBottomMils());
         proto.end(token);
     }
 
@@ -220,32 +231,34 @@
      *
      * @param context The context used to resolve resources
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param attributes The attributes to write
      */
     public static void writePrintAttributes(@NonNull Context context,
-            @NonNull ProtoOutputStream proto, long id, @NonNull PrintAttributes attributes) {
-        long token = proto.start(id);
+            @NonNull DualDumpOutputStream proto, String idName, long id,
+            @NonNull PrintAttributes attributes) {
+        long token = proto.start(idName, id);
 
         PrintAttributes.MediaSize mediaSize = attributes.getMediaSize();
         if (mediaSize != null) {
-            writeMediaSize(context, proto, PrintAttributesProto.MEDIA_SIZE, mediaSize);
+            writeMediaSize(context, proto, "media_size", PrintAttributesProto.MEDIA_SIZE, mediaSize);
         }
 
-        proto.write(PrintAttributesProto.IS_PORTRAIT, attributes.isPortrait());
+        proto.write("is_portrait", PrintAttributesProto.IS_PORTRAIT, attributes.isPortrait());
 
         PrintAttributes.Resolution res = attributes.getResolution();
         if (res != null) {
-            writeResolution(proto, PrintAttributesProto.RESOLUTION, res);
+            writeResolution(proto, "resolution", PrintAttributesProto.RESOLUTION, res);
         }
 
         PrintAttributes.Margins minMargins = attributes.getMinMargins();
         if (minMargins != null) {
-            writeMargins(proto, PrintAttributesProto.MIN_MARGINS, minMargins);
+            writeMargins(proto, "min_margings", PrintAttributesProto.MIN_MARGINS, minMargins);
         }
 
-        proto.write(PrintAttributesProto.COLOR_MODE, attributes.getColorMode());
-        proto.write(PrintAttributesProto.DUPLEX_MODE, attributes.getDuplexMode());
+        proto.write("color_mode", PrintAttributesProto.COLOR_MODE, attributes.getColorMode());
+        proto.write("duplex_mode", PrintAttributesProto.DUPLEX_MODE, attributes.getDuplexMode());
         proto.end(token);
     }
 
@@ -253,21 +266,22 @@
      * Write a {@link PrintDocumentInfo} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param info The info to write
      */
-    public static void writePrintDocumentInfo(@NonNull ProtoOutputStream proto, long id,
-            @NonNull PrintDocumentInfo info) {
-        long token = proto.start(id);
-        proto.write(PrintDocumentInfoProto.NAME, info.getName());
+    public static void writePrintDocumentInfo(@NonNull DualDumpOutputStream proto, String idName,
+            long id, @NonNull PrintDocumentInfo info) {
+        long token = proto.start(idName, id);
+        proto.write("name", PrintDocumentInfoProto.NAME, info.getName());
 
         int pageCount = info.getPageCount();
         if (pageCount != PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
-            proto.write(PrintDocumentInfoProto.PAGE_COUNT, pageCount);
+            proto.write("page_count", PrintDocumentInfoProto.PAGE_COUNT, pageCount);
         }
 
-        proto.write(PrintDocumentInfoProto.CONTENT_TYPE, info.getContentType());
-        proto.write(PrintDocumentInfoProto.DATA_SIZE, info.getDataSize());
+        proto.write("content_type", PrintDocumentInfoProto.CONTENT_TYPE, info.getContentType());
+        proto.write("data_size", PrintDocumentInfoProto.DATA_SIZE, info.getDataSize());
         proto.end(token);
     }
 
@@ -275,14 +289,15 @@
      * Write a {@link PageRange} to a proto.
      *
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param range The range to write
      */
-    public static void writePageRange(@NonNull ProtoOutputStream proto, long id,
+    public static void writePageRange(@NonNull DualDumpOutputStream proto, String idName, long id,
             @NonNull PageRange range) {
-        long token = proto.start(id);
-        proto.write(PageRangeProto.START, range.getStart());
-        proto.write(PageRangeProto.END, range.getEnd());
+        long token = proto.start(idName, id);
+        proto.write("start", PageRangeProto.START, range.getStart());
+        proto.write("end", PageRangeProto.END, range.getEnd());
         proto.end(token);
     }
 
@@ -291,64 +306,70 @@
      *
      * @param context The context used to resolve resources
      * @param proto The proto to write to
+     * @param idName Clear text name of the proto-id
      * @param id The proto-id of the component name
      * @param printJobInfo The print job info to write
      */
-    public static void writePrintJobInfo(@NonNull Context context, @NonNull ProtoOutputStream proto,
-            long id, @NonNull PrintJobInfo printJobInfo) {
-        long token = proto.start(id);
-        proto.write(PrintJobInfoProto.LABEL, printJobInfo.getLabel());
+    public static void writePrintJobInfo(@NonNull Context context,
+            @NonNull DualDumpOutputStream proto, String idName, long id,
+            @NonNull PrintJobInfo printJobInfo) {
+        long token = proto.start(idName, id);
+        proto.write("label", PrintJobInfoProto.LABEL, printJobInfo.getLabel());
 
         PrintJobId printJobId = printJobInfo.getId();
         if (printJobId != null) {
-            proto.write(PrintJobInfoProto.PRINT_JOB_ID, printJobId.flattenToString());
+            proto.write("print_job_id", PrintJobInfoProto.PRINT_JOB_ID,
+                    printJobId.flattenToString());
         }
 
         int state = printJobInfo.getState();
         if (state >= PrintJobInfoProto.STATE_CREATED && state <= PrintJobInfoProto.STATE_CANCELED) {
-            proto.write(PrintJobInfoProto.STATE, state);
+            proto.write("state", PrintJobInfoProto.STATE, state);
         } else {
-            proto.write(PrintJobInfoProto.STATE, PrintJobInfoProto.STATE_UNKNOWN);
+            proto.write("state", PrintJobInfoProto.STATE, PrintJobInfoProto.STATE_UNKNOWN);
         }
 
         PrinterId printer = printJobInfo.getPrinterId();
         if (printer != null) {
-            writePrinterId(proto, PrintJobInfoProto.PRINTER, printer);
+            writePrinterId(proto, "printer", PrintJobInfoProto.PRINTER, printer);
         }
 
         String tag = printJobInfo.getTag();
         if (tag != null) {
-            proto.write(PrintJobInfoProto.TAG, tag);
+            proto.write("tag", PrintJobInfoProto.TAG, tag);
         }
 
-        proto.write(PrintJobInfoProto.CREATION_TIME, printJobInfo.getCreationTime());
+        proto.write("creation_time", PrintJobInfoProto.CREATION_TIME,
+                printJobInfo.getCreationTime());
 
         PrintAttributes attributes = printJobInfo.getAttributes();
         if (attributes != null) {
-            writePrintAttributes(context, proto, PrintJobInfoProto.ATTRIBUTES, attributes);
+            writePrintAttributes(context, proto, "attributes", PrintJobInfoProto.ATTRIBUTES,
+                    attributes);
         }
 
         PrintDocumentInfo docInfo = printJobInfo.getDocumentInfo();
         if (docInfo != null) {
-            writePrintDocumentInfo(proto, PrintJobInfoProto.DOCUMENT_INFO, docInfo);
+            writePrintDocumentInfo(proto, "document_info", PrintJobInfoProto.DOCUMENT_INFO,
+                    docInfo);
         }
 
-        proto.write(PrintJobInfoProto.IS_CANCELING, printJobInfo.isCancelling());
+        proto.write("is_canceling", PrintJobInfoProto.IS_CANCELING, printJobInfo.isCancelling());
 
         PageRange[] pages = printJobInfo.getPages();
         if (pages != null) {
             for (int i = 0; i < pages.length; i++) {
-                writePageRange(proto, PrintJobInfoProto.PAGES, pages[i]);
+                writePageRange(proto, "pages", PrintJobInfoProto.PAGES, pages[i]);
             }
         }
 
-        proto.write(PrintJobInfoProto.HAS_ADVANCED_OPTIONS,
+        proto.write("has_advanced_options", PrintJobInfoProto.HAS_ADVANCED_OPTIONS,
                 printJobInfo.getAdvancedOptions() != null);
-        proto.write(PrintJobInfoProto.PROGRESS, printJobInfo.getProgress());
+        proto.write("progress", PrintJobInfoProto.PROGRESS, printJobInfo.getProgress());
 
         CharSequence status = printJobInfo.getStatus(context.getPackageManager());
         if (status != null) {
-            proto.write(PrintJobInfoProto.STATUS, status.toString());
+            proto.write("status", PrintJobInfoProto.STATUS, status.toString());
         }
 
         proto.end(token);
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 31d22e0..e3f1f47 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -19,9 +19,9 @@
 import android.app.PendingIntent;
 import android.app.trust.IStrongAuthTracker;
 import android.os.Bundle;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.KeychainProtectionParams;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.VerifyCredentialResponse;
 
@@ -60,11 +60,11 @@
             in byte[] token, int requestedQuality, int userId);
     void unlockUserWithToken(long tokenHandle, in byte[] token, int userId);
 
-    // Keystore RecoveryManager methods.
+    // Keystore RecoveryController methods.
     // {@code ServiceSpecificException} may be thrown to signal an error, which caller can
     // convert to  {@code RecoveryManagerException}.
     void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
-    RecoveryData getRecoveryData(in byte[] account);
+    KeychainSnapshot getRecoveryData(in byte[] account);
     byte[] generateAndStoreKey(String alias);
     void removeKey(String alias);
     void setSnapshotCreatedPendingIntent(in PendingIntent intent);
@@ -75,10 +75,11 @@
     void setRecoverySecretTypes(in int[] secretTypes);
     int[] getRecoverySecretTypes();
     int[] getPendingRecoverySecretTypes();
-    void recoverySecretAvailable(in RecoveryMetadata recoverySecret);
+    void recoverySecretAvailable(in KeychainProtectionParams recoverySecret);
     byte[] startRecoverySession(in String sessionId,
             in byte[] verifierPublicKey, in byte[] vaultParams, in byte[] vaultChallenge,
-            in List<RecoveryMetadata> secrets);
+            in List<KeychainProtectionParams> secrets);
     Map/*<String, byte[]>*/ recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
-            in List<EntryRecoveryData> applicationKeys);
+            in List<WrappedApplicationKey> applicationKeys);
+    void closeSession(in String sessionId);
 }
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 20f05e6..33977f3 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -60,6 +60,7 @@
     private boolean mFirstLayout;
     private boolean mIsHidingAnimated;
     private boolean mNeedsGeneratedAvatar;
+    private Notification.Person mSender;
 
     public MessagingGroup(@NonNull Context context) {
         super(context);
@@ -89,6 +90,7 @@
     }
 
     public void setSender(Notification.Person sender) {
+        mSender = sender;
         mSenderName.setText(sender.getName());
         mNeedsGeneratedAvatar = sender.getIcon() == null;
         if (!mNeedsGeneratedAvatar) {
@@ -355,7 +357,7 @@
         return 0;
     }
 
-    public View getSender() {
+    public View getSenderView() {
         return mSenderName;
     }
 
@@ -370,4 +372,8 @@
     public boolean needsGeneratedAvatar() {
         return mNeedsGeneratedAvatar;
     }
+
+    public Notification.Person getSender() {
+        return mSender;
+    }
 }
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 834c93a..7a64cad 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -35,7 +35,6 @@
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.RemotableViewMethod;
-import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
@@ -135,9 +134,24 @@
         if (headerText != null) {
             mConversationTitle = headerText.getText();
         }
+        addRemoteInputHistoryToMessages(newMessages,
+                extras.getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY));
         bind(newMessages, newHistoricMessages);
     }
 
+    private void addRemoteInputHistoryToMessages(
+            List<Notification.MessagingStyle.Message> newMessages,
+            CharSequence[] remoteInputHistory) {
+        if (remoteInputHistory == null || remoteInputHistory.length == 0) {
+            return;
+        }
+        for (int i = remoteInputHistory.length - 1; i >= 0; i--) {
+            CharSequence message = remoteInputHistory[i];
+            newMessages.add(new Notification.MessagingStyle.Message(
+                    message, 0, (Notification.Person) null));
+        }
+    }
+
     private void bind(List<Notification.MessagingStyle.Message> newMessages,
             List<Notification.MessagingStyle.Message> newHistoricMessages) {
 
@@ -189,9 +203,10 @@
         for (int i = 0; i < mGroups.size(); i++) {
             // Let's now set the avatars
             MessagingGroup group = mGroups.get(i);
+            boolean isOwnMessage = group.getSender() == mUser;
             CharSequence senderName = group.getSenderName();
             if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)
-                    || (mIsOneToOne && mLargeIcon != null)) {
+                    || (mIsOneToOne && mLargeIcon != null && !isOwnMessage)) {
                 continue;
             }
             String symbol = uniqueNames.get(senderName);
@@ -209,7 +224,7 @@
             if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
                 continue;
             }
-            if (mIsOneToOne && mLargeIcon != null) {
+            if (mIsOneToOne && mLargeIcon != null && group.getSender() != mUser) {
                 group.setAvatar(mLargeIcon);
             } else {
                 Icon cachedIcon = cachedAvatars.get(senderName);
@@ -271,6 +286,12 @@
 
     public void setUser(Notification.Person user) {
         mUser = user;
+        if (mUser.getIcon() == null) {
+            Icon userIcon = Icon.createWithResource(getContext(),
+                    com.android.internal.R.drawable.messaging_user);
+            userIcon.setTint(mLayoutColor);
+            mUser.setIcon(userIcon);
+        }
     }
 
     private void addMessagesToGroups(List<MessagingMessage> historicMessages,
@@ -410,7 +431,7 @@
                             continue;
                         }
                         MessagingPropertyAnimator.fadeIn(group.getAvatar());
-                        MessagingPropertyAnimator.fadeIn(group.getSender());
+                        MessagingPropertyAnimator.fadeIn(group.getSenderView());
                         MessagingPropertyAnimator.startLocalTranslationFrom(group,
                                 group.getHeight(), LINEAR_OUT_SLOW_IN);
                     }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 96f3308..543acc7 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -97,7 +97,6 @@
         "android_os_MessageQueue.cpp",
         "android_os_Parcel.cpp",
         "android_os_SELinux.cpp",
-        "android_os_seccomp.cpp",
         "android_os_SharedMemory.cpp",
         "android_os_SystemClock.cpp",
         "android_os_SystemProperties.cpp",
@@ -120,6 +119,7 @@
         "android_util_jar_StrictJarFile.cpp",
         "android_graphics_Canvas.cpp",
         "android_graphics_Picture.cpp",
+        "android/graphics/AnimatedImageDrawable.cpp",
         "android/graphics/Bitmap.cpp",
         "android/graphics/BitmapFactory.cpp",
         "android/graphics/ByteBufferStreamAdaptor.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6569b47..aa9a824 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -63,6 +63,7 @@
 extern int register_android_graphics_GraphicBuffer(JNIEnv* env);
 extern int register_android_graphics_Graphics(JNIEnv* env);
 extern int register_android_graphics_ImageDecoder(JNIEnv*);
+extern int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv*);
 extern int register_android_graphics_Interpolator(JNIEnv* env);
 extern int register_android_graphics_MaskFilter(JNIEnv* env);
 extern int register_android_graphics_Movie(JNIEnv* env);
@@ -166,7 +167,6 @@
 extern int register_android_os_SELinux(JNIEnv* env);
 extern int register_android_os_VintfObject(JNIEnv *env);
 extern int register_android_os_VintfRuntimeInfo(JNIEnv *env);
-extern int register_android_os_seccomp(JNIEnv* env);
 extern int register_android_os_SystemProperties(JNIEnv *env);
 extern int register_android_os_SystemClock(JNIEnv* env);
 extern int register_android_os_Trace(JNIEnv* env);
@@ -1397,6 +1397,7 @@
     REG_JNI(register_android_graphics_FontFamily),
     REG_JNI(register_android_graphics_GraphicBuffer),
     REG_JNI(register_android_graphics_ImageDecoder),
+    REG_JNI(register_android_graphics_drawable_AnimatedImageDrawable),
     REG_JNI(register_android_graphics_Interpolator),
     REG_JNI(register_android_graphics_MaskFilter),
     REG_JNI(register_android_graphics_Matrix),
@@ -1427,7 +1428,6 @@
     REG_JNI(register_android_os_GraphicsEnvironment),
     REG_JNI(register_android_os_MessageQueue),
     REG_JNI(register_android_os_SELinux),
-    REG_JNI(register_android_os_seccomp),
     REG_JNI(register_android_os_Trace),
     REG_JNI(register_android_os_UEventObserver),
     REG_JNI(register_android_net_LocalSocketImpl),
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
new file mode 100644
index 0000000..12feaab
--- /dev/null
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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 "GraphicsJNI.h"
+#include "ImageDecoder.h"
+#include "core_jni_helpers.h"
+
+#include <hwui/Canvas.h>
+#include <SkAndroidCodec.h>
+#include <SkAnimatedImage.h>
+#include <SkColorFilter.h>
+#include <SkPicture.h>
+#include <SkPictureRecorder.h>
+
+using namespace android;
+
+struct AnimatedImageDrawable {
+    sk_sp<SkAnimatedImage> mDrawable;
+    SkPaint                mPaint;
+};
+
+// Note: jpostProcess holds a handle to the ImageDecoder.
+static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
+                                           jlong nativeImageDecoder, jobject jpostProcess,
+                                           jint width, jint height, jobject jsubset) {
+    if (nativeImageDecoder == 0) {
+        doThrowIOE(env, "Cannot create AnimatedImageDrawable from null!");
+        return 0;
+    }
+
+    auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder);
+    auto info = imageDecoder->mCodec->getInfo();
+    const SkISize scaledSize = SkISize::Make(width, height);
+    SkIRect subset;
+    if (jsubset) {
+        GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
+    } else {
+        subset = SkIRect::MakeWH(width, height);
+    }
+
+    sk_sp<SkPicture> picture;
+    if (jpostProcess) {
+        SkRect bounds = SkRect::MakeWH(subset.width(), subset.height());
+
+        SkPictureRecorder recorder;
+        SkCanvas* skcanvas = recorder.beginRecording(bounds);
+        std::unique_ptr<Canvas> canvas(Canvas::create_canvas(skcanvas));
+        postProcessAndRelease(env, jpostProcess, std::move(canvas), bounds.width(),
+                              bounds.height());
+        if (env->ExceptionCheck()) {
+            return 0;
+        }
+        picture = recorder.finishRecordingAsPicture();
+    }
+
+    std::unique_ptr<AnimatedImageDrawable> drawable(new AnimatedImageDrawable);
+    drawable->mDrawable = SkAnimatedImage::Make(std::move(imageDecoder->mCodec),
+                scaledSize, subset, std::move(picture));
+    if (!drawable->mDrawable) {
+        doThrowIOE(env, "Failed to create drawable");
+        return 0;
+    }
+    drawable->mDrawable->start();
+
+    return reinterpret_cast<jlong>(drawable.release());
+}
+
+static void AnimatedImageDrawable_destruct(AnimatedImageDrawable* drawable) {
+    delete drawable;
+}
+
+static jlong AnimatedImageDrawable_nGetNativeFinalizer(JNIEnv* /*env*/, jobject /*clazz*/) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&AnimatedImageDrawable_destruct));
+}
+
+static jlong AnimatedImageDrawable_nDraw(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
+                                         jlong canvasPtr, jlong msecs) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    double timeToNextUpdate = drawable->mDrawable->update(msecs);
+    auto* canvas = reinterpret_cast<Canvas*>(canvasPtr);
+    canvas->drawAnimatedImage(drawable->mDrawable.get(), 0, 0, &drawable->mPaint);
+    return (jlong) timeToNextUpdate;
+}
+
+static void AnimatedImageDrawable_nSetAlpha(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
+                                            jint alpha) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    drawable->mPaint.setAlpha(alpha);
+}
+
+static jlong AnimatedImageDrawable_nGetAlpha(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    return drawable->mPaint.getAlpha();
+}
+
+static void AnimatedImageDrawable_nSetColorFilter(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
+                                                  jlong nativeFilter) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    auto* filter = reinterpret_cast<SkColorFilter*>(nativeFilter);
+    drawable->mPaint.setColorFilter(sk_ref_sp(filter));
+}
+
+static jboolean AnimatedImageDrawable_nIsRunning(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    return drawable->mDrawable->isRunning();
+}
+
+static void AnimatedImageDrawable_nStart(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    drawable->mDrawable->start();
+}
+
+static void AnimatedImageDrawable_nStop(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    drawable->mDrawable->stop();
+}
+
+static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+    auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+    // FIXME: Report the size of the internal SkBitmap etc.
+    return sizeof(drawable);
+}
+
+static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
+    { "nCreate",             "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate },
+    { "nGetNativeFinalizer", "()J",                                                          (void*) AnimatedImageDrawable_nGetNativeFinalizer },
+    { "nDraw",               "(JJJ)J",                                                       (void*) AnimatedImageDrawable_nDraw },
+    { "nSetAlpha",           "(JI)V",                                                        (void*) AnimatedImageDrawable_nSetAlpha },
+    { "nGetAlpha",           "(J)I",                                                         (void*) AnimatedImageDrawable_nGetAlpha },
+    { "nSetColorFilter",     "(JJ)V",                                                        (void*) AnimatedImageDrawable_nSetColorFilter },
+    { "nIsRunning",          "(J)Z",                                                         (void*) AnimatedImageDrawable_nIsRunning },
+    { "nStart",              "(J)V",                                                         (void*) AnimatedImageDrawable_nStart },
+    { "nStop",               "(J)V",                                                         (void*) AnimatedImageDrawable_nStop },
+    { "nNativeByteSize",     "(J)J",                                                         (void*) AnimatedImageDrawable_nNativeByteSize },
+};
+
+int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) {
+    return android::RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedImageDrawable",
+            gAnimatedImageDrawableMethods, NELEM(gAnimatedImageDrawableMethods));
+}
+
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 79aa5ac..685fcaf 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -237,10 +237,22 @@
 
     // Create the codec.
     NinePatchPeeker peeker;
-    std::unique_ptr<SkAndroidCodec> codec = SkAndroidCodec::MakeFromStream(
-            std::move(stream), &peeker);
-    if (!codec.get()) {
-        return nullObjectReturn("SkAndroidCodec::MakeFromStream returned null");
+    std::unique_ptr<SkAndroidCodec> codec;
+    {
+        SkCodec::Result result;
+        std::unique_ptr<SkCodec> c = SkCodec::MakeFromStream(std::move(stream), &result,
+                                                             &peeker);
+        if (!c) {
+            SkString msg;
+            msg.printf("Failed to create image decoder with message '%s'",
+                       SkCodec::ResultToString(result));
+            return nullObjectReturn(msg.c_str());
+        }
+
+        codec = SkAndroidCodec::MakeFromCodec(std::move(c));
+        if (!codec) {
+            return nullObjectReturn("SkAndroidCodec::MakeFromCodec returned null");
+        }
     }
 
     // Do not allow ninepatch decodes to 565.  In the past, decodes to 565
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index a0a4be4..1c2528f 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -19,12 +19,11 @@
 #include "ByteBufferStreamAdaptor.h"
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "GraphicsJNI.h"
-#include "NinePatchPeeker.h"
+#include "ImageDecoder.h"
 #include "Utils.h"
 #include "core_jni_helpers.h"
 
 #include <hwui/Bitmap.h>
-#include <hwui/Canvas.h>
 
 #include <SkAndroidCodec.h>
 #include <SkEncodedImageFormat.h>
@@ -43,53 +42,51 @@
 static jclass    gCorrupt_class;
 static jclass    gCanvas_class;
 static jmethodID gImageDecoder_constructorMethodID;
+static jmethodID gImageDecoder_postProcessMethodID;
 static jmethodID gPoint_constructorMethodID;
 static jmethodID gIncomplete_constructorMethodID;
 static jmethodID gCorrupt_constructorMethodID;
 static jmethodID gCallback_onPartialImageMethodID;
-static jmethodID gPostProcess_postProcessMethodID;
 static jmethodID gCanvas_constructorMethodID;
 static jmethodID gCanvas_releaseMethodID;
 
-struct ImageDecoder {
-    // These need to stay in sync with ImageDecoder.java's Allocator constants.
-    enum Allocator {
-        kDefault_Allocator      = 0,
-        kSoftware_Allocator     = 1,
-        kSharedMemory_Allocator = 2,
-        kHardware_Allocator     = 3,
-    };
-
-    // These need to stay in sync with PixelFormat.java's Format constants.
-    enum PixelFormat {
-        kUnknown     =  0,
-        kTranslucent = -3,
-        kOpaque      = -1,
-    };
-
-    NinePatchPeeker mPeeker;
-    std::unique_ptr<SkAndroidCodec> mCodec;
-};
-
 static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream) {
     if (!stream.get()) {
         doThrowIOE(env, "Failed to create a stream");
         return nullptr;
     }
     std::unique_ptr<ImageDecoder> decoder(new ImageDecoder);
-    decoder->mCodec = SkAndroidCodec::MakeFromStream(std::move(stream), &decoder->mPeeker);
-    if (!decoder->mCodec.get()) {
-        // FIXME: (b/71578461) Use the error message from
-        // SkCodec::MakeFromStream to report a more informative error message.
-        doThrowIOE(env, "Failed to create an SkCodec");
+    SkCodec::Result result;
+    auto codec = SkCodec::MakeFromStream(std::move(stream), &result, decoder->mPeeker.get());
+    if (!codec) {
+        switch (result) {
+            case SkCodec::kIncompleteInput:
+                env->ThrowNew(gIncomplete_class, "Incomplete input");
+                break;
+            default:
+                SkString msg;
+                msg.printf("Failed to create image decoder with message '%s'",
+                           SkCodec::ResultToString(result));
+                doThrowIOE(env, msg.c_str());
+                break;
+
+        }
         return nullptr;
     }
 
+    // FIXME: Avoid parsing the whole image?
+    const bool animated = codec->getFrameCount() > 1;
+    decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
+    if (!decoder->mCodec.get()) {
+        doThrowIOE(env, "Could not create AndroidCodec");
+        return nullptr;
+    }
     const auto& info = decoder->mCodec->getInfo();
     const int width = info.width();
     const int height = info.height();
     return env->NewObject(gImageDecoder_class, gImageDecoder_constructorMethodID,
-                          reinterpret_cast<jlong>(decoder.release()), width, height);
+                          reinterpret_cast<jlong>(decoder.release()), width, height,
+                          animated);
 }
 
 static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
@@ -160,11 +157,24 @@
     return native_create(env, std::move(stream));
 }
 
-static bool supports_any_down_scale(const SkAndroidCodec* codec) {
-    return codec->getEncodedFormat() == SkEncodedImageFormat::kWEBP;
+jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas,
+                           int width, int height) {
+    jobject jcanvas = env->NewObject(gCanvas_class, gCanvas_constructorMethodID,
+                                     reinterpret_cast<jlong>(canvas.get()));
+    if (!jcanvas) {
+        doThrowOOME(env, "Failed to create Java Canvas for PostProcess!");
+        return ImageDecoder::kUnknown;
+    }
+
+    // jcanvas now owns canvas.
+    canvas.release();
+
+    return env->CallIntMethod(jimageDecoder, gImageDecoder_postProcessMethodID,
+                              jcanvas, width, height);
 }
 
-// This method should never return null. Instead, it should throw an exception.
+// Note: jpostProcess points to an ImageDecoder object if it has a PostProcess object, and nullptr
+// otherwise.
 static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
                                           jobject jcallback, jobject jpostProcess,
                                           jint desiredWidth, jint desiredHeight, jobject jsubset,
@@ -173,33 +183,14 @@
                                           jboolean asAlphaMask) {
     auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr);
     SkAndroidCodec* codec = decoder->mCodec.get();
-    SkImageInfo decodeInfo = codec->getInfo();
-    bool scale = false;
-    int sampleSize = 1;
-    if (desiredWidth != decodeInfo.width() || desiredHeight != decodeInfo.height()) {
-        bool match = false;
-        if (desiredWidth < decodeInfo.width() && desiredHeight < decodeInfo.height()) {
-            if (supports_any_down_scale(codec)) {
-                match = true;
-                decodeInfo = decodeInfo.makeWH(desiredWidth, desiredHeight);
-            } else {
-                int sampleX = decodeInfo.width()  / desiredWidth;
-                int sampleY = decodeInfo.height() / desiredHeight;
-                sampleSize = std::min(sampleX, sampleY);
-                SkISize sampledSize = codec->getSampledDimensions(sampleSize);
-                decodeInfo = decodeInfo.makeWH(sampledSize.width(), sampledSize.height());
-                if (decodeInfo.width() == desiredWidth && decodeInfo.height() == desiredHeight) {
-                    match = true;
-                }
-            }
-        }
-        if (!match) {
-            scale = true;
-            if (requireUnpremul && kOpaque_SkAlphaType != decodeInfo.alphaType()) {
-                doThrowISE(env, "Cannot scale unpremultiplied pixels!");
-                return nullptr;
-            }
-        }
+    const SkISize desiredSize = SkISize::Make(desiredWidth, desiredHeight);
+    SkISize decodeSize = desiredSize;
+    const int sampleSize = codec->computeSampleSize(&decodeSize);
+    const bool scale = desiredSize != decodeSize;
+    SkImageInfo decodeInfo = codec->getInfo().makeWH(decodeSize.width(), decodeSize.height());
+    if (scale && requireUnpremul && kOpaque_SkAlphaType != decodeInfo.alphaType()) {
+        doThrowISE(env, "Cannot scale unpremultiplied pixels!");
+        return nullptr;
     }
 
     switch (decodeInfo.alphaType()) {
@@ -330,23 +321,23 @@
     // Ignore ninepatch when post-processing.
     if (!jpostProcess) {
         // FIXME: Share more code with BitmapFactory.cpp.
-        if (decoder->mPeeker.mPatch != nullptr) {
+        if (decoder->mPeeker->mPatch != nullptr) {
             if (scale) {
-                decoder->mPeeker.scale(scaleX, scaleY, desiredWidth, desiredHeight);
+                decoder->mPeeker->scale(scaleX, scaleY, desiredWidth, desiredHeight);
             }
-            size_t ninePatchArraySize = decoder->mPeeker.mPatch->serializedSize();
+            size_t ninePatchArraySize = decoder->mPeeker->mPatch->serializedSize();
             ninePatchChunk = env->NewByteArray(ninePatchArraySize);
             if (ninePatchChunk == nullptr) {
                 doThrowOOME(env, "Failed to allocate nine patch chunk.");
                 return nullptr;
             }
 
-            env->SetByteArrayRegion(ninePatchChunk, 0, decoder->mPeeker.mPatchSize,
-                                    reinterpret_cast<jbyte*>(decoder->mPeeker.mPatch));
+            env->SetByteArrayRegion(ninePatchChunk, 0, decoder->mPeeker->mPatchSize,
+                                    reinterpret_cast<jbyte*>(decoder->mPeeker->mPatch));
         }
 
-        if (decoder->mPeeker.mHasInsets) {
-            ninePatchInsets = decoder->mPeeker.createNinePatchInsets(env, 1.0f);
+        if (decoder->mPeeker->mHasInsets) {
+            ninePatchInsets = decoder->mPeeker->createNinePatchInsets(env, 1.0f);
             if (ninePatchInsets == nullptr) {
                 doThrowOOME(env, "Failed to allocate nine patch insets.");
                 return nullptr;
@@ -402,28 +393,14 @@
         canvas.drawBitmap(bm, 0.0f, 0.0f, &paint);
 
         bm.swap(scaledBm);
-        nativeBitmap = scaledPixelRef;
+        nativeBitmap = std::move(scaledPixelRef);
     }
 
     if (jpostProcess) {
         std::unique_ptr<Canvas> canvas(Canvas::create_canvas(bm));
-        jobject jcanvas = env->NewObject(gCanvas_class, gCanvas_constructorMethodID,
-                                         reinterpret_cast<jlong>(canvas.get()));
-        if (!jcanvas) {
-            doThrowOOME(env, "Failed to create Java Canvas for PostProcess!");
-            return nullptr;
-        }
-        // jcanvas will now own canvas.
-        canvas.release();
 
-        jint pixelFormat = env->CallIntMethod(jpostProcess, gPostProcess_postProcessMethodID,
-                                              jcanvas, bm.width(), bm.height());
-        if (env->ExceptionCheck()) {
-            return nullptr;
-        }
-
-        // The Canvas objects are no longer needed, and will not remain valid.
-        env->CallVoidMethod(jcanvas, gCanvas_releaseMethodID);
+        jint pixelFormat = postProcessAndRelease(env, jpostProcess, std::move(canvas),
+                                                 bm.width(), bm.height());
         if (env->ExceptionCheck()) {
             return nullptr;
         }
@@ -501,7 +478,7 @@
 static void ImageDecoder_nGetPadding(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
                                      jobject outPadding) {
     auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr);
-    decoder->mPeeker.getPadding(env, outPadding);
+    decoder->mPeeker->getPadding(env, outPadding);
 }
 
 static void ImageDecoder_nClose(JNIEnv* /*env*/, jobject /*clazz*/, jlong nativePtr) {
@@ -519,7 +496,7 @@
     { "nCreate",        "([BII)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
     { "nCreate",        "(Ljava/io/InputStream;[B)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream },
     { "nCreate",        "(Ljava/io/FileDescriptor;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
-    { "nDecodeBitmap",  "(JLandroid/graphics/ImageDecoder$OnPartialImageListener;Landroid/graphics/PostProcess;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;",
+    { "nDecodeBitmap",  "(JLandroid/graphics/ImageDecoder$OnPartialImageListener;Landroid/graphics/ImageDecoder;IILandroid/graphics/Rect;ZIZZZ)Landroid/graphics/Bitmap;",
                                                                  (void*) ImageDecoder_nDecodeBitmap },
     { "nGetSampledSize","(JI)Landroid/graphics/Point;",          (void*) ImageDecoder_nGetSampledSize },
     { "nGetPadding",    "(JLandroid/graphics/Rect;)V",           (void*) ImageDecoder_nGetPadding },
@@ -529,7 +506,8 @@
 
 int register_android_graphics_ImageDecoder(JNIEnv* env) {
     gImageDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder"));
-    gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JII)V");
+    gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JIIZ)V");
+    gImageDecoder_postProcessMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "postProcessAndRelease", "(Landroid/graphics/Canvas;II)I");
 
     gPoint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Point"));
     gPoint_constructorMethodID = GetMethodIDOrDie(env, gPoint_class, "<init>", "(II)V");
@@ -543,9 +521,6 @@
     jclass callback_class = FindClassOrDie(env, "android/graphics/ImageDecoder$OnPartialImageListener");
     gCallback_onPartialImageMethodID = GetMethodIDOrDie(env, callback_class, "onPartialImage", "(Ljava/io/IOException;)Z");
 
-    jclass postProcess_class = FindClassOrDie(env, "android/graphics/PostProcess");
-    gPostProcess_postProcessMethodID = GetMethodIDOrDie(env, postProcess_class, "postProcess", "(Landroid/graphics/Canvas;II)I");
-
     gCanvas_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Canvas"));
     gCanvas_constructorMethodID = GetMethodIDOrDie(env, gCanvas_class, "<init>", "(J)V");
     gCanvas_releaseMethodID = GetMethodIDOrDie(env, gCanvas_class, "release", "()V");
diff --git a/core/jni/android/graphics/ImageDecoder.h b/core/jni/android/graphics/ImageDecoder.h
new file mode 100644
index 0000000..2df71eb
--- /dev/null
+++ b/core/jni/android/graphics/ImageDecoder.h
@@ -0,0 +1,55 @@
+/*
+ * 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 "NinePatchPeeker.h"
+
+#include <hwui/Canvas.h>
+
+#include <jni.h>
+
+class SkAndroidCodec;
+
+using namespace android;
+
+struct ImageDecoder {
+    // These need to stay in sync with ImageDecoder.java's Allocator constants.
+    enum Allocator {
+        kDefault_Allocator      = 0,
+        kSoftware_Allocator     = 1,
+        kSharedMemory_Allocator = 2,
+        kHardware_Allocator     = 3,
+    };
+
+    // These need to stay in sync with PixelFormat.java's Format constants.
+    enum PixelFormat {
+        kUnknown     =  0,
+        kTranslucent = -3,
+        kOpaque      = -1,
+    };
+
+    std::unique_ptr<SkAndroidCodec> mCodec;
+    sk_sp<NinePatchPeeker> mPeeker;
+
+    ImageDecoder()
+        :mPeeker(new NinePatchPeeker)
+    {}
+};
+
+// Creates a Java Canvas object from canvas, calls jimageDecoder's PostProcess on it, and then
+// releases the Canvas.
+// Caller needs to check for exceptions.
+jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas,
+                           int width, int height);
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 1676d4b..f3aeb32 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -27,6 +27,7 @@
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
+#include <GLES3/gl3.h>
 #include <ETC1/etc1.h>
 
 #include <SkBitmap.h>
@@ -641,7 +642,7 @@
             }
             break;
         case kRGBA_F16_SkColorType:
-            if (type == GL_HALF_FLOAT_OES && format == PIXEL_FORMAT_RGBA_FP16)
+            if (type == GL_HALF_FLOAT && format == GL_RGBA16F)
                 return 0;
             break;
         default:
@@ -662,7 +663,7 @@
         case kRGB_565_SkColorType:
             return GL_RGB;
         case kRGBA_F16_SkColorType:
-            return PIXEL_FORMAT_RGBA_FP16;
+            return GL_RGBA16F;
         default:
             return -1;
     }
@@ -680,7 +681,7 @@
         case kRGB_565_SkColorType:
             return GL_UNSIGNED_SHORT_5_6_5;
         case kRGBA_F16_SkColorType:
-            return GL_HALF_FLOAT_OES;
+            return GL_HALF_FLOAT;
         default:
             return -1;
     }
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 9494fb8..061349a 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -391,6 +391,10 @@
     Status status;
     status_t err = ::android::hardware::readFromParcel(&status, *parcel);
     signalExceptionForError(env, err);
+
+    if (!status.isOk()) {
+        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
+    }
 }
 
 static void JHwParcel_native_release(
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
deleted file mode 100644
index 06e2a16..0000000
--- a/core/jni/android_os_seccomp.cpp
+++ /dev/null
@@ -1,47 +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 "core_jni_helpers.h"
-#include <nativehelper/JniConstants.h>
-#include "utils/Log.h"
-#include <selinux/selinux.h>
-
-#include "seccomp_policy.h"
-
-static void Seccomp_setPolicy(JNIEnv* /*env*/) {
-    if (security_getenforce() == 0) {
-        ALOGI("seccomp disabled by setenforce 0");
-        return;
-    }
-
-    if (!set_seccomp_filter()) {
-        ALOGE("Failed to set seccomp policy - killing");
-        exit(1);
-    }
-}
-
-static const JNINativeMethod method_table[] = {
-    NATIVE_METHOD(Seccomp, setPolicy, "()V"),
-};
-
-namespace android {
-
-int register_android_os_seccomp(JNIEnv* env) {
-    return android::RegisterMethodsOrDie(env, "android/os/Seccomp",
-                                         method_table, NELEM(method_table));
-}
-
-}
diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android_text_MeasuredParagraph.cpp
index bdae0b2..58c05b4 100644
--- a/core/jni/android_text_MeasuredParagraph.cpp
+++ b/core/jni/android_text_MeasuredParagraph.cpp
@@ -85,12 +85,12 @@
 
 // Regular JNI
 static jlong nBuildNativeMeasuredParagraph(JNIEnv* env, jclass /* unused */, jlong builderPtr,
-                                      jcharArray javaText) {
+                                      jcharArray javaText, jboolean computeHyphenation) {
     ScopedCharArrayRO text(env, javaText);
     const minikin::U16StringPiece textBuffer(text.get(), text.size());
 
     // Pass the ownership to Java.
-    return toJLong(toBuilder(builderPtr)->build(textBuffer).release());
+    return toJLong(toBuilder(builderPtr)->build(textBuffer, computeHyphenation).release());
 }
 
 // Regular JNI
@@ -108,7 +108,7 @@
     {"nInitBuilder", "()J", (void*) nInitBuilder},
     {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun},
     {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun},
-    {"nBuildNativeMeasuredParagraph", "(J[C)J", (void*) nBuildNativeMeasuredParagraph},
+    {"nBuildNativeMeasuredParagraph", "(J[CZ)J", (void*) nBuildNativeMeasuredParagraph},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
 
     // MeasuredParagraph native functions.
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1407ae4..13e6fcd 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -53,6 +53,7 @@
 #include <private/android_filesystem_config.h>
 #include <utils/String8.h>
 #include <selinux/android.h>
+#include <seccomp_policy.h>
 #include <processgroup/processgroup.h>
 
 #include "core_jni_helpers.h"
@@ -76,6 +77,8 @@
 static jclass gZygoteClass;
 static jmethodID gCallPostForkChildHooks;
 
+static bool g_is_security_enforced = true;
+
 // Must match values in com.android.internal.os.Zygote.
 enum MountExternalKind {
   MOUNT_EXTERNAL_NONE = 0,
@@ -229,6 +232,20 @@
   mallopt(M_DECAY_TIME, 1);
 }
 
+static void SetUpSeccompFilter(uid_t uid) {
+  if (!g_is_security_enforced) {
+    ALOGI("seccomp disabled by setenforce 0");
+    return;
+  }
+
+  // Apply system or app filter based on uid.
+  if (getuid() >= AID_APP_START) {
+    set_app_seccomp_filter();
+  } else {
+    set_system_seccomp_filter();
+  }
+}
+
 static void EnableKeepCapabilities(JNIEnv* env) {
   int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
   if (rc == -1) {
@@ -541,6 +558,11 @@
       RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
     }
 
+    // Must be called when the new process still has CAP_SYS_ADMIN.  The other alternative is to
+    // call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see
+    // b/71859146).
+    SetUpSeccompFilter(uid);
+
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
       EnableKeepCapabilities(env);
@@ -698,6 +720,12 @@
 
 namespace android {
 
+static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
+  // security_getenforce is not allowed on app process. Initialize and cache the value before
+  // zygote forks.
+  g_is_security_enforced = security_getenforce();
+}
+
 static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jclass) {
   PreApplicationInit();
 }
@@ -835,6 +863,8 @@
 }
 
 static const JNINativeMethod gMethods[] = {
+    { "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",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index d4bdb9b..8d6df12 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -389,8 +389,10 @@
     optional SettingProto notification_snooze_options = 341;
     optional SettingProto enable_gnss_raw_meas_full_tracking = 346;
     optional SettingProto zram_enabled = 347;
+    optional SettingProto enable_smart_replies_in_notifications = 348;
+    optional SettingProto show_first_crash_dialog = 349;
 
-    // Next tag = 348;
+    // Next tag = 350;
 }
 
 message SecureSettingsProto {
@@ -592,8 +594,9 @@
     optional SettingProto qs_auto_added_tiles = 193;
     optional SettingProto lockdown_in_power_menu = 194;
     optional SettingProto backup_manager_constants = 169;
+    optional SettingProto show_first_crash_dialog_dev_option = 195;
 
-    // Next tag = 195
+    // Next tag = 196
 }
 
 message SystemSettingsProto {
diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto
index f725e8a..3c7a0e3 100644
--- a/core/proto/android/service/diskstats.proto
+++ b/core/proto/android/service/diskstats.proto
@@ -43,6 +43,8 @@
     optional EncryptionType encryption = 5;
     // Cached values of folder sizes, etc.
     optional DiskStatsCachedValuesProto cached_folder_sizes = 6;
+    // Average write speed of storaged benchmark for last 24 hours
+    optional int32 benchmarked_write_speed_kbps = 7;
 }
 
 message DiskStatsCachedValuesProto {
diff --git a/core/proto/android/view/windowlayoutparams.proto b/core/proto/android/view/windowlayoutparams.proto
index b81cd1f..f079e1e 100644
--- a/core/proto/android/view/windowlayoutparams.proto
+++ b/core/proto/android/view/windowlayoutparams.proto
@@ -58,7 +58,6 @@
   optional NeedsMenuState needs_menu_key = 22;
   optional .android.view.DisplayProto.ColorMode color_mode = 23;
   optional uint32 flags = 24;
-  optional uint64 flags_extra = 25;
   optional uint32 private_flags = 26;
   optional uint32 system_ui_visibility_flags = 27;
   optional uint32 subtree_system_ui_visibility_flags = 28;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a3e8f1e..547e83c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -554,8 +554,6 @@
     <protected-broadcast android:name="android.intent.action.DEVICE_LOCKED_CHANGED" />
 
     <!-- Added in O -->
-    <!-- TODO: temporary broadcast used by AutoFillManagerServiceImpl; will be removed -->
-    <protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
     <protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
     <protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
     <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
@@ -2684,6 +2682,13 @@
     <permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link android.service.autofill.AutofillFieldClassificationService}
+         to ensure that only the system can bind to it.
+         @hide This is not a third-party API (intended for OEMs and system apps).
+    -->
+    <permission android:name="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
@@ -3692,6 +3697,12 @@
     <permission android:name="android.permission.MODIFY_QUIET_MODE"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to control remote animations. See
+         {@link ActivityOptions#makeRemoteAnimation}
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"
+        android:protectionLevel="signature|privileged" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/drawable/messaging_user.xml b/core/res/res/drawable/messaging_user.xml
new file mode 100644
index 0000000..3137698
--- /dev/null
+++ b/core/res/res/drawable/messaging_user.xml
@@ -0,0 +1,28 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportHeight="192.0"
+        android:viewportWidth="192.0">
+    <path android:fillColor="#000000"
+          android:fillAlpha="0.125"
+          android:pathData="M96,0C43.01,0 0,43.01 0,96s43.01,96 96,96s96,-43.01 96,-96S148.99,0 96,0z"/>
+    <path android:fillColor="#BDBDBD"
+          android:pathData="M96,85.09c13.28,0 24,-10.72 24,-24c0,-13.28 -10.72,-24 -24,-24s-24,10.72 -24,24C72,74.37 82.72,85.09 96,85.09z"/>
+    <path android:fillColor="#BDBDBD"
+          android:pathData="M96,99.27c-29.33,0 -52.36,14.18 -52.36,27.27c11.09,17.06 30.51,28.36 52.36,28.36s41.27,-11.3 52.36,-28.36C148.36,113.45 125.33,99.27 96,99.27z"/>
+</vector>
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 528efca..a88836e 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -24,6 +24,8 @@
         android:id="@+id/autofill_dataset_list"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
+        android:drawSelectorOnTop="true"
+        android:clickable="true"
         android:divider="@null"
         android:visibility="gone">
     </ListView>
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 353a1a5..445b19b 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -39,6 +39,10 @@
             android:layout_height="@dimen/notification_progress_bar_height"
             android:layout_marginTop="@dimen/notification_progress_margin_top"
             layout="@layout/notification_template_progress" />
+        <include layout="@layout/notification_template_smart_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/notification_content_margin_bottom" />
     </LinearLayout>
     <include layout="@layout/notification_template_right_icon" />
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index 6b1049a..d47bff6 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -56,6 +56,12 @@
             android:id="@+id/notification_material_reply_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
+        <include layout="@layout/notification_template_smart_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_content_margin_start"
+            android:layout_marginEnd="@dimen/notification_content_margin_end"
+            android:layout_marginBottom="@dimen/notification_content_margin_bottom" />
     </LinearLayout>
     <include layout="@layout/notification_material_action_list" />
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index e94e646..76c0a67 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -64,6 +64,12 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 />
+        <include layout="@layout/notification_template_smart_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_content_margin_start"
+            android:layout_marginEnd="@dimen/notification_content_margin_end"
+            android:layout_marginBottom="@dimen/notification_content_margin_bottom" />
     </LinearLayout>
     <include layout="@layout/notification_material_action_list" />
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 3c87f92..ac4c052 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -67,6 +67,12 @@
                 android:id="@+id/notification_material_reply_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
+        <include layout="@layout/notification_template_smart_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_content_margin_start"
+            android:layout_marginEnd="@dimen/notification_content_margin_end"
+            android:layout_marginBottom="@dimen/notification_content_margin_bottom" />
     </LinearLayout>
     <include layout="@layout/notification_material_action_list" />
     <include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index e4c91a4..718cf16 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -119,6 +119,12 @@
                 android:id="@+id/notification_material_reply_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
+        <include layout="@layout/notification_template_smart_reply_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_content_margin_start"
+            android:layout_marginEnd="@dimen/notification_content_margin_end"
+            android:layout_marginBottom="@dimen/notification_content_margin_bottom" />
     </LinearLayout>
     <include layout="@layout/notification_material_action_list" />
     <include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index a72ad53..34f5ae8 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -47,6 +47,10 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:spacing="@dimen/notification_messaging_spacing" />
+            <include layout="@layout/notification_template_smart_reply_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/notification_content_margin_bottom" />
         </LinearLayout>
     </LinearLayout>
     <include layout="@layout/notification_material_action_list" />
diff --git a/core/res/res/layout/notification_template_smart_reply_container.xml b/core/res/res/layout/notification_template_smart_reply_container.xml
new file mode 100644
index 0000000..637241e
--- /dev/null
+++ b/core/res/res/layout/notification_template_smart_reply_container.xml
@@ -0,0 +1,24 @@
+<?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
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:id="@+id/smart_reply_container"
+              android:visibility="gone"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="horizontal">
+    <!-- SmartReplyView will be added here. -->
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0a996ca..ee287c3 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"ድንገተኛ አደጋ"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"የሳንካ ሪፖርት"</string>
     <string name="global_action_logout" msgid="935179188218826050">"ክፍለ-ጊዜን አብቃ"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ቅጽበታዊ ገጽ እይታ"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"የሳንካ ሪፖርት ውሰድ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ይሄ እንደ የኢሜይል መልዕክት አድርጎ የሚልከውን ስለመሣሪያዎ የአሁኑ ሁኔታ መረጃ ይሰበስባል። የሳንካ ሪፖርቱን ከመጀመር ጀምሮ እስኪላክ ድረስ ትንሽ ጊዜ ይወስዳል፤ እባክዎ ይታገሱ።"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"መስተጋብራዊ ሪፖርት"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi በራስ-ሰር ይበራል"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ከፍተኛ ጥራት ያለው የተቀመጠ አውታረ መረብ አቅራቢያ ሲሆኑ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"መልሰህ አታብራ"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi በራስ-ሰር በርቷል"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"ከተቀመጠ አውታረ መረብ አቅራቢያ ነዎት፦ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"ወደ አውታረ መረብ በመለያ ይግቡ"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"አቋራጭ ተሰናክሏል"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"አራግፍ"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"የሆነው ሆኖ አስጀምር"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"ጎጂ መተግበሪያ ይራገፍ?"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 684c257..6b5f1c8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -221,6 +221,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Stav nouze"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hlášení chyb"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Ukončit relaci"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Snímek obrazovky"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Vytvořit chybové hlášení"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Shromažďuje informace o aktuálním stavu zařízení. Tyto informace je následně možné poslat v e-mailové zprávě, chvíli však potrvá, než bude hlášení o chybě připraveno k odeslání. Buďte prosím trpěliví."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivní přehled"</string>
@@ -1167,6 +1168,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi se zapne automaticky"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Když budete v dosahu kvalitní uložené sítě"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Znovu nezapínat"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Automaticky se zapnulo připojení Wi-Fi"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Jste v dosahu uložené sítě: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Přihlásit se k síti Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Přihlásit se k síti"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1877,6 +1880,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Zkratku nelze obnovit, protože aplikace nepodporuje zálohování a obnovu"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Zkratku nelze obnovit, protože se neshoduje podpis aplikace"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Zkratku nelze obnovit"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Zkratka nefunguje"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Odinstalovat"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Přesto spustit"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Odinstalovat škodlivou aplikaci?"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 9d317eb..b94cc90 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Notfall"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Fehlerbericht"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Sitzung beenden"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"Fehlerbericht abrufen"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Bei diesem Fehlerbericht werden Daten zum aktuellen Status deines Geräts erfasst und als E-Mail versandt. Vom Start des Berichts bis zu seinem Versand kann es eine Weile dauern. Bitte habe etwas Geduld."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiver Bericht"</string>
@@ -379,7 +381,7 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Ermöglicht der App, die Anrufliste deines Tablets zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so deine Anrufliste löschen oder ändern."</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Ermöglicht der App, die Anrufliste deines Fernsehers zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so deine Anrufliste löschen oder ändern."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Ermöglicht der App, die Anrufliste deines Telefons zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so deine Anrufliste löschen oder ändern."</string>
-    <string name="permlab_bodySensors" msgid="4683341291818520277">"Auf Körpersensoren wie z. B. Herzfrequenzmesser zugreifen"</string>
+    <string name="permlab_bodySensors" msgid="4683341291818520277">"Auf Körpersensoren wie z. B. Pulsmesser zugreifen"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Ermöglicht der App, auf Daten von Sensoren zuzugreifen, die deine körperliche Verfassung überwachen, beispielsweise deinen Puls"</string>
     <string name="permlab_readCalendar" msgid="6716116972752441641">"Kalendertermine und Details lesen"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"Diese App kann alle auf deinem Tablet gespeicherten Kalendertermine lesen und deine Kalenderdaten teilen oder speichern."</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WLAN wird automatisch aktiviert"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wenn du in der Nähe eines sicheren gespeicherten Netzwerks bist"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nicht wieder aktivieren"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN anmelden"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Im Netzwerk anmelden"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1813,11 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Verknüpfung konnte nicht wiederhergestellt werden, weil die App keine Sicherung und keine Wiederherstellung unterstützt"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Verknüpfung konnte nicht wiederhergestellt werden, weil die App-Signatur nicht übereinstimmt"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Verknüpfung konnte nicht wiederhergestellt werden"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Verknüpfung ist deaktiviert"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 700641e..2910067 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergency"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="global_action_logout" msgid="935179188218826050">"End session"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi turned on automatically"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</string>
 </resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 700641e..2910067 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergency"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="global_action_logout" msgid="935179188218826050">"End session"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi turned on automatically"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 700641e..2910067 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergency"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="global_action_logout" msgid="935179188218826050">"End session"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi turned on automatically"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 700641e..2910067 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergency"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Bug report"</string>
     <string name="global_action_logout" msgid="935179188218826050">"End session"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Take bug report"</string>
     <string name="bugreport_message" msgid="398447048750350456">"This will collect information about your current device state, to send as an email message. It will take a little time from starting the bug report until it is ready to be sent. Please be patient."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi turned on automatically"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"You\'re near a saved network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Couldn’t restore shortcut because app doesn’t support backup and restore"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</string>
 </resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index ba21245..5f7f19c 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎Emergency‎‏‎‎‏‎"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎Bug report‎‏‎‎‏‎"</string>
     <string name="global_action_logout" msgid="935179188218826050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎End session‎‏‎‎‏‎"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎Screenshot‎‏‎‎‏‎"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‎Take bug report‎‏‎‎‏‎"</string>
     <string name="bugreport_message" msgid="398447048750350456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎This will collect information about your current device state, to send as an e-mail message. It will take a little time from starting the bug report until it is ready to be sent; please be patient.‎‏‎‎‏‎"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎Interactive report‎‏‎‎‏‎"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎Wi‑Fi will turn on automatically‎‏‎‎‏‎"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎When you\'re near a high quality saved network‎‏‎‎‏‎"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎Don\'t turn back on‎‏‎‎‏‎"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎Wi‑Fi turned on automatically‎‏‎‎‏‎"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎You\'re near a saved network: ‎‏‎‎‏‏‎<xliff:g id="NETWORK_SSID">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎‎Sign in to Wi-Fi network‎‏‎‎‏‎"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎Sign in to network‎‏‎‎‏‎"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‏‏‎‎Couldn’t restore shortcut because app doesn’t support backup and restore‎‏‎‎‏‎"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎Couldn’t restore shortcut because of app signature mismatch‎‏‎‎‏‎"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎Couldn’t restore shortcut‎‏‎‎‏‎"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‎Shortcut is disabled‎‏‎‎‏‎"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎Uninstall‎‏‎‎‏‎"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎Launch anyway‎‏‎‎‏‎"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎Uninstall harmful app?‎‏‎‎‏‎"</string>
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 100ed1e..960dfd8 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -86,7 +86,7 @@
     <string name="NetworkPreferenceSwitchSummary" msgid="7056776609127756440">"Seinalea hobea izan dadin, aldatu sare mota Ezarpenak &gt; Sareak eta Internet &gt; Sare mugikorrak &gt; Sare mota hobetsia atalean."</string>
     <string name="EmergencyCallWarningTitle" msgid="4790413876281901612">"Wi‑Fi bidezko deiak aktibo daude"</string>
     <string name="EmergencyCallWarningSummary" msgid="8973232888021643293">"Sare mugikorrera konektatuta egon behar da larrialdi-deiak egin ahal izateko."</string>
-    <string name="notification_channel_network_alert" msgid="4427736684338074967">"Abisuak"</string>
+    <string name="notification_channel_network_alert" msgid="4427736684338074967">"Alertak"</string>
     <string name="notification_channel_call_forward" msgid="2419697808481833249">"Dei-desbideratzea"</string>
     <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Larrialdi-deiak soilik jasotzeko modua"</string>
     <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Datu mugikorren egoera"</string>
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Larrialdi-deiak"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Akatsen txostena"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Amaitu saioa"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"Sortu akatsen txostena"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Txosten dinamikoa"</string>
@@ -251,7 +253,7 @@
     <string name="notification_channel_network_available" msgid="4531717914138179517">"Sare bat erabilgarri dago"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN egoera"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Gailuen administrazioa"</string>
-    <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertak"</string>
     <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Saltzaileentzako demoa"</string>
     <string name="notification_channel_usb" msgid="9006850475328924681">"USB konexioa"</string>
     <string name="notification_channel_heavy_weight_app" msgid="6218742927792852607">"Aplikazio bat abian da"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi konexioa automatikoki aktibatuko da"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Gordeta daukazun kalitate handiko sare batetik gertu zaudenean"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ez aktibatu berriro"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Hasi saioa Wi-Fi sarean"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Hasi saioa sarean"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Desgaituta dago lasterbidea"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 9af3ed7..aa6608a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Urgence"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bogue"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Fermer la session"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Capture d\'écran"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bogue"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme de courriel. Merci de patienter pendant la préparation du rapport de bogue. Cette opération peut prendre quelques instants."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapport interactif"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Le Wi-Fi s\'activera automatiquement"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Lorsque vous êtes près d\'un réseau enregistré de haute qualité"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne pas réactiver"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi activé automatiquement"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Vous êtes à proximité d\'un réseau enregistré : <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Connectez-vous au réseau"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Le raccourci est désactivé"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Désinstaller"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Lancer quand même"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Désinstaller l\'application nuisible?"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 97cc0ec..06a5684 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Urgences"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bug"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Fermer la session"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Capture d\'écran"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme d\'e-mail. Merci de patienter pendant la préparation du rapport de bug. Cette opération peut prendre quelques instants."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapport interactif"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Le Wi-Fi sera activé automatiquement"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Lorsque vous êtes à proximité d\'un réseau enregistré de haute qualité"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne pas réactiver"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi activé automatiquement"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Vous vous trouvez à proximité d\'un réseau enregistré : <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Se connecter au réseau"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Le raccourci ne peut pas être restauré car l\'application n\'accepte pas la sauvegarde et la restauration"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Le raccourci ne peut pas être restauré car la signature de l\'application est différente"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossible de restaurer le raccourci"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Le raccourci est désactivé"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Désinstaller"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Lancer quand même"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Désinstaller l\'application malveillante ?"</string>
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 81e5f4f..2af95ce 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"કટોકટી"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"બગ રિપોર્ટ"</string>
     <string name="global_action_logout" msgid="935179188218826050">"સત્ર સમાપ્ત કરો"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"બગ રિપોર્ટ લો"</string>
     <string name="bugreport_message" msgid="398447048750350456">"આ, એક ઇ-મેઇલ સંદેશ તરીકે મોકલવા માટે, તમારા વર્તમાન ઉપકરણ સ્થિતિ વિશેની માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટ પ્રારંભ કરીને તે મોકલવા માટે તૈયાર ન થઈ જાય ત્યાં સુધી તેમાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ક્રિયાપ્રતિક્રિયાત્મક રિપોર્ટ"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"વાઇ-ફાઇ આપમેળે ચાલુ થઈ જશે"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"જ્યારે તમે એક ઉચ્ચ ક્વૉલિટીવાળા સાચવેલ નેટવર્કની નજીક હોવ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"પાછું ચાલુ કરશો નહીં"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"નેટવર્ક પર સાઇન ઇન કરો"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"શૉર્ટકટને બંધ કરવામાં આવ્યો છે"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 2349583..251ec84 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"आपातकाल"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"गड़बड़ी की रिपोर्ट"</string>
     <string name="global_action_logout" msgid="935179188218826050">"सत्र खत्म करें"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"गड़बड़ी की रिपोर्ट लें"</string>
     <string name="bugreport_message" msgid="398447048750350456">"इससे ईमेल भेजने के लिए, आपके डिवाइस की मौजूदा स्थिति से जुड़ी जानकारी इकट्ठा की जाएगी. गड़बड़ी की रिपोर्ट बनना शुरू होने से लेकर भेजने के लिए तैयार होने तक कुछ समय लगेगा; कृपया इंतज़ार करें."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"सहभागी रिपोर्ट"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"वाई-फ़ाई अपने आप चालू हो जाएगा"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"जब आप किसी अच्छी क्वालिटी वाले सेव किए गए नेटवर्क के पास हों"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"वापस चालू न करें"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"वाई-फ़ाई  नेटवर्क में साइन इन करें"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्क में साइन इन करें"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1813,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"शॉर्टकट बंद है"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index cb2b8a5..e3df0c8 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Darurat"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Laporan bug"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Akhiri sesi"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Ambil laporan bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Ini akan mengumpulkan informasi status perangkat Anda saat ini, untuk dikirimkan sebagai pesan email. Harap bersabar, mungkin perlu waktu untuk memulai laporan bug hingga siap dikirim."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Laporan interaktif"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi akan aktif otomatis"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Saat berada di dekat jaringan berkualitas tinggi yang tersimpan"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Jangan aktifkan kembali"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi diaktifkan otomatis"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Anda berada di dekat jaringan yang tersimpan: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Masuk ke jaringan Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Masuk ke jaringan"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Tidak dapat memulihkan pintasan karena aplikasi tidak mendukung backup dan pulihkan"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tidak dapat memulihkan pintasan karena tanda tangan aplikasi tidak cocok"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Tidak dapat memulihkan pintasan."</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Pintasan dinonaktifkan"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstal"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Tetap luncurkan"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstal aplikasi berbahaya?"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3c9745f..c1ef402 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergenza"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Segnalazione di bug"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Termina sessione"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Apri segnalazione bug"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Verranno raccolte informazioni sullo stato corrente del dispositivo che saranno inviate sotto forma di messaggio email. Passerà un po\' di tempo prima che la segnalazione di bug aperta sia pronta per essere inviata; ti preghiamo di avere pazienza."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapporto interattivo"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Il Wi‑Fi verrà attivato automaticamente"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando ti trovi nell\'area di una rete salvata di alta qualità"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Non riattivare"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi attivato automaticamente"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ti trovi nell\'area di copertura di una rete salvata: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Accedi a rete Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Accedi alla rete"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Impossibile ripristinare la scorciatoia perché l\'app non supporta il backup e il ripristino"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Impossibile ripristinare la scorciatoia perché la firma dell\'app non corrisponde"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossibile ripristinare la scorciatoia"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"La scorciatoia è disattivata"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Disinstalla"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Avvia comunque"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Disinstallare l\'app dannosa?"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2fb35f8..3b124ff 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"緊急通報"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"バグレポート"</string>
     <string name="global_action_logout" msgid="935179188218826050">"セッションを終了"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"スクリーンショット"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"バグレポートを取得"</string>
     <string name="bugreport_message" msgid="398447048750350456">"現在の端末の状態に関する情報が収集され、その内容がメールで送信されます。バグレポートが開始してから送信可能な状態となるまでには多少の時間がかかりますのでご了承ください。"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"対話型レポート"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi は自動的にオンになります"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"高品質の保存済みネットワークの検出時"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"再度オンにしない"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi が自動的に ON になりました"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"保存済みネットワーク「<xliff:g id="NETWORK_SSID">%1$s</xliff:g>」の近くにいます"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fiネットワークにログイン"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"ネットワークにログインしてください"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"ショートカットは無効になっています"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"アンインストール"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"このまま起動"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"有害なアプリをアンインストールしますか?"</string>
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 2fe14dc..b9539ea 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"ತುರ್ತು"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"ದೋಷದ ವರದಿ"</string>
     <string name="global_action_logout" msgid="935179188218826050">"ಸೆಷನ್ ಅಂತ್ಯಗೊಳಿಸಿ"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"ದೋಷ ವರದಿ ರಚಿಸಿ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ನಿಮ್ಮ ಸಾಧನದ ಪ್ರಸ್ತುತ ಸ್ಥಿತಿಯ ಕುರಿತು ಮಾಹಿತಿಯನ್ನು ಸಂಗ್ರಹಿಸಿಕೊಳ್ಳುವುದರ ಜೊತೆ ಇ-ಮೇಲ್ ರೂಪದಲ್ಲಿ ನಿಮಗೆ ರವಾನಿಸುತ್ತದೆ. ಇದು ದೋಷ ವರದಿಯನ್ನು ಪ್ರಾರಂಭಿಸಿದ ಸಮಯದಿಂದ ಅದನ್ನು ಕಳುಹಿಸುವವರೆಗೆ ಸ್ವಲ್ಪ ಸಮಯವನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ; ದಯವಿಟ್ಟು ತಾಳ್ಮೆಯಿಂದಿರಿ."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ಪರಸ್ಪರ ಸಂವಹನ ವರದಿ"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ವೈ‑ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗುತ್ತದೆ"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ನೀವು ಉಳಿಸಿದ ಅಧಿಕ ಗುಣಮಟ್ಟದ ನೆಟ್‌ವರ್ಕ್‌ ಸಮೀಪದಲ್ಲಿದ್ದಾಗ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ಮತ್ತೆ ಆನ್ ಮಾಡಲು ಹಿಂತಿರುಗಬೇಡಿ"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"ಶಾರ್ಟ್‌ಕಟ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 57745c2..e248f45 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -221,6 +221,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Skambutis pagalbos numeriu"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Pranešimas apie riktą"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Baigti seansą"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Ekrano kopija"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Pranešti apie riktą"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Bus surinkta informacija apie dabartinę įrenginio būseną ir išsiųsta el. pašto pranešimu. Šiek tiek užtruks, kol pranešimas apie riktą bus paruoštas siųsti; būkite kantrūs."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interakt. ataskaita"</string>
@@ -1167,6 +1168,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"„Wi‑Fi“ bus įjungtas automatiškai"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kai būsite netoli išsaugoto aukštos kokybės tinklo"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Neįjunkite vėl"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"„Wi‑Fi“ įjungtas automatiškai"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Esate netoli išsaugoto tinklo: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Prisijungti prie „Wi-Fi“ tinklo"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Prisijungti prie tinklo"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1877,6 +1880,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nepavyko atkurti sparčiojo klavišo, nes programa nepalaiko atsarginės kopijos kūrimo ir atkūrimo funkcijų"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nepavyko atkurti sparčiojo klavišo, nes programos parašas neatitinka"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nepavyko atkurti sparčiojo klavišo"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Spartusis klavišas išjungtas"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Pašalinti"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Vis tiek paleisti"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Pašalinti žalingą programą?"</string>
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 69c0fed..ed2dc02 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"അടിയന്തിരാവശ്യം"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"ബഗ് റിപ്പോർട്ട്"</string>
     <string name="global_action_logout" msgid="935179188218826050">"സെഷൻ അവസാനിപ്പിക്കുക"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"ബഗ് റിപ്പോർട്ട് എടുക്കുക"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ഒരു ഇമെയിൽ സന്ദേശമായി അയയ്‌ക്കുന്നതിന്, ഇത് നിങ്ങളുടെ നിലവിലെ ഉപകരണ നിലയെക്കുറിച്ചുള്ള വിവരങ്ങൾ ശേഖരിക്കും. ബഗ് റിപ്പോർട്ട് ആരംഭിക്കുന്നതിൽ നിന്ന് ഇത് അയയ്‌ക്കാനായി തയ്യാറാകുന്നതുവരെ അൽപ്പസമയമെടുക്കും; ക്ഷമയോടെ കാത്തിരിക്കുക."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ഇന്റരാക്റ്റീവ് റിപ്പോർട്ട്"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"വൈഫൈ സ്വമേധയാ ഓണാകും"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"നിങ്ങൾ ഉയർന്ന നിലവാരമുള്ള സംരക്ഷിക്കപ്പെട്ട നെറ്റ്‌വർക്കിനരികിലെത്തുമ്പോൾ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"തിരികെ ഓണാക്കരുത്"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"കുറുക്കുവഴി പ്രവർത്തനരഹിതമാണ്"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index addb2d1..9e36c1d 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"आणीबाणी"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"बग रीपोर्ट"</string>
     <string name="global_action_logout" msgid="935179188218826050">"सेशन समाप्त करा"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"बग रीपोर्ट घ्या"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डिव्हाइस स्थितीविषयी माहिती संकलित करेल. बग रीपोर्ट सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"परस्परसंवादी अहवाल"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"वाय-फाय आपोआप चालू होईल"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"तुम्ही जेव्हा सेव्ह केलेल्या उच्च दर्जाच्या नेटवर्कजवळ असाल तेव्हा"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"पुन्हा चालू करू नका"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"वाय-फाय नेटवर्कमध्‍ये साइन इन करा"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्कवर साइन इन करा"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"शॉर्टकट बंद केलेला आहे"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 1777b26..5f67641 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"အရေးပေါ်"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"အမှားရှာဖွေပြင်ဆင်မှုမှတ်တမ်း"</string>
     <string name="global_action_logout" msgid="935179188218826050">"သတ်မှတ်ပေးထားသည့်အချိန် ပြီးဆုံးပြီ"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"အမှားရှာဖွေပြင်ဆင်မှုမှတ်တမ်းအား ယူရန်"</string>
     <string name="bugreport_message" msgid="398447048750350456">"သင့်ရဲ့ လက်ရှိ စက်အခြေအနေ အချက်အလက်များကို အီးမေးလ် အနေဖြင့် ပေးပို့ရန် စုဆောင်းပါမည်။ အမှားရှာဖွေပြင်ဆင်မှုမှတ်တမ်းမှ ပေးပို့ရန် အသင့်ဖြစ်သည်အထိ အချိန် အနည်းငယ်ကြာမြင့်မှာ ဖြစ်သဖြင့် သည်းခံပြီး စောင့်ပါရန်"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"လက်ငင်းတုံ့ပြန်နိုင်သည့် အစီရင်ခံချက်"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ကို အလိုအလျောက်​ ပြန်ဖွင့်ပေးလိမ့်ပါမည်"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"သိမ်းဆည်းထားသည့် အရည်အသွေးမြင့်ကွန်ရက်များအနီးသို့ ရောက်ရှိသည့်အခါ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ပြန်မဖွင့်ပါနှင့်"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi ကို အလိုအလျောက် ဖွင့်ထားသည်"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"သင်သည် သိမ်းထားသည့် ကွန်ရက်အနီးတွင် ရှိသည်− <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1811,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"ဖြတ်လမ်းလင့်ခ် ပိတ်ထားသည်"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"ဖြုတ်ရန်"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"မည်သို့ပင်ဖြစ်စေ ဖွင့်ရန်"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"အန္တရာယ်ရှိသည့် အက်ပ်ကို ဖြုတ်လိုပါသလား။"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 873967a..c3deb3e 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Nødsituasjon"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Feilrapport"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Avslutt økten"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"Utfør feilrapport"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Informasjon om tilstanden til enheten din samles inn og sendes som en e-post. Det tar litt tid fra du starter feilrapporten til e-posten er klar, så vær tålmodig."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi slås på automatisk"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Når du er i nærheten av et lagret nettverk av høy kvalitet"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ikke slå på igjen"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Logg på Wi-Fi-nettverket"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Logg på nettverk"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1813,11 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Kunne ikke gjenopprette snarveien fordi appen ikke støtter sikkerhetskopiering og gjenoppretting"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kunne ikke gjenopprette snarveien på grunn av manglende samsvar for appsignaturen"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kunne ikke gjenopprette snarveien"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Snarveien er slått av"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 3e0e04b..71e1258 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"आपतकालीन"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"बग रिपोर्ट"</string>
     <string name="global_action_logout" msgid="935179188218826050">"सत्रको अन्त्य गर्नुहोस्"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट लिनुहोस्"</string>
     <string name="bugreport_message" msgid="398447048750350456">"एउटा इमेल सन्देशको रूपमा पठाउनलाई यसले तपाईँको हालैको उपकरणको अवस्थाको बारेमा सूचना जम्मा गर्ने छ। बग रिपोर्ट सुरु गरेदेखि पठाउन तयार नभएसम्म यसले केही समय लिन्छ; कृपया धैर्य गर्नुहोस्।"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"अन्तरक्रियामूलक रिपोर्ट"</string>
@@ -1129,6 +1131,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi स्वतः सक्रिय हुनेछ"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"तपाईं कुनै सुरक्षित गरिएको उच्च गुणस्तरीय नेटवर्कको नजिक हुनुभएको अवस्थामा"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"फेरि सक्रिय नगर्नुहोला"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"सञ्जालमा साइन इन गर्नुहोस्"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1813,6 +1819,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"सर्टकट असक्षम पारिएको छ"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index b08b1b2..8a11b9f 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"ਸੰਕਟਕਾਲ"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"ਬਗ ਰਿਪੋਰਟ"</string>
     <string name="global_action_logout" msgid="935179188218826050">"ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"ਬਗ ਰਿਪੋਰਟ ਲਓ"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ਇਹ ਇੱਕ ਈਮੇਲ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ, ਤੁਹਾਡੇ ਵਰਤਮਾਨ ਡੀਵਾਈਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਕੱਠੀ ਕਰੇਗਾ। ਬੱਗ ਰਿਪੋਰਟ ਸ਼ੁਰੂ ਕਰਨ ਵਿੱਚ ਥੋੜ੍ਹਾ ਸਮਾਂ ਲੱਗੇਗਾ ਜਦੋਂ ਤੱਕ ਇਹ ਭੇਜੇ ਜਾਣ ਲਈ ਤਿਆਰ ਨਾ ਹੋਵੇ, ਕਿਰਪਾ ਕਰਕੇ ਧੀਰਜ ਰੱਖੋ।"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ਅੰਤਰਕਿਰਿਆਤਮਕ ਰਿਪੋਰਟ"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"ਵਾਈ‑ਫਾਈ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਚੱਲ ਪਵੇਗਾ"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਰੱਖਿਅਤ ਕੀਤੇ ਉੱਚ-ਗੁਣਵੱਤਾ ਵਾਲੇ ਨੈੱਟਵਰਕ ਦੇ ਨੇੜੇ ਹੋਵੋ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"ਵਾਪਸ ਚਾਲੂ ਨਾ ਕਰੋ"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"ਸ਼ਾਰਟਕੱਟ ਬੰਦ ਕੀਤਾ ਹੋਇਆ ਹੈ"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 35cbd28..5201f14 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergência"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Finalizar sessão"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de tela"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Obter relatório de bugs"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando você estiver perto de uma rede salva de alta qualidade"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não ativar novamente"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi ativado automaticamente"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Você está perto de uma rede salva: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Fazer login na rede"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Não foi possível restaurar o atalho porque o app não é compatível com backup e restauração"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"O atalho está desativado"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Desinstalar"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Iniciar mesmo assim"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Desinstalar app nocivo?"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index a9a4a91..d6b888a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergência"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de erros"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Terminar sessão"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de ecrã"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Criar relatório de erros"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Será recolhida informação sobre o estado atual do seu dispositivo a enviar através de uma mensagem de email. Demorará algum tempo até que o relatório de erro esteja pronto para ser enviado. Aguarde um pouco."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
@@ -804,8 +805,8 @@
     <string name="granularity_label_link" msgid="5815508880782488267">"link"</string>
     <string name="granularity_label_line" msgid="5764267235026120888">"linha"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"O teste de fábrica falhou"</string>
-    <string name="factorytest_not_system" msgid="4435201656767276723">"A acção FACTORY_TEST apenas é suportada para pacotes instalados em /system/app."</string>
-    <string name="factorytest_no_action" msgid="872991874799998561">"Não foi localizado qualquer pacote que forneça a acção FACTORY_TEST."</string>
+    <string name="factorytest_not_system" msgid="4435201656767276723">"A ação FACTORY_TEST apenas é suportada para pacotes instalados em /system/app."</string>
+    <string name="factorytest_no_action" msgid="872991874799998561">"Não foi localizado qualquer pacote que forneça a ação FACTORY_TEST."</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"Reiniciar"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"A página em \"<xliff:g id="TITLE">%s</xliff:g>\" indica:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
@@ -1023,7 +1024,7 @@
     <string name="whichImageCaptureApplication" msgid="3680261417470652882">"Capturar imagem com"</string>
     <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"Capturar imagem com o %1$s"</string>
     <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"Capturar imagem"</string>
-    <string name="alwaysUse" msgid="4583018368000610438">"Utilizar por predefinição para esta acção."</string>
+    <string name="alwaysUse" msgid="4583018368000610438">"Utilizar por predefinição para esta ação."</string>
     <string name="use_a_different_app" msgid="8134926230585710243">"Utilizar outra aplicação"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Limpar a predefinição nas Definições do Sistema &gt; Aplicações &gt; Transferidas."</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Escolha uma ação"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando estiver próximo de uma rede de alta qualidade guardada."</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não reativar"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi ativado automaticamente"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Está perto de uma rede guardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sessão na rede Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Início de sessão na rede"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Não foi possível restaurar o atalho porque a aplicação não é compatível com a funcionalidade de cópia de segurança e restauro."</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido a uma falha de correspondência entre as assinaturas das aplicações."</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho."</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"O atalho está desativado."</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Desinstalar"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Iniciar mesmo assim"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Pretende desinstalar a aplicação prejudicial?"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 35cbd28..5201f14 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Emergência"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Relatório de bugs"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Finalizar sessão"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de tela"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Obter relatório de bugs"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Isto coletará informações sobre o estado atual do dispositivo para enviá-las em uma mensagem de e-mail. Após iniciar o relatório de bugs, será necessário aguardar algum tempo até que esteja pronto para ser enviado."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"O Wi‑Fi será ativado automaticamente"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quando você estiver perto de uma rede salva de alta qualidade"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Não ativar novamente"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi ativado automaticamente"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Você está perto de uma rede salva: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Fazer login na rede"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Não foi possível restaurar o atalho porque o app não é compatível com backup e restauração"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"O atalho está desativado"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Desinstalar"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Iniciar mesmo assim"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Desinstalar app nocivo?"</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0104894..22b1bde 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -219,6 +219,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Urgență"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Raport despre erori"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Încheiați sesiunea"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captură de ecran"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Executați un raport despre erori"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Acest raport va colecta informații despre starea actuală a dispozitivului, pentru a le trimite într-un e-mail. Aveți răbdare după pornirea raportului despre erori până când va fi gata de trimis."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interactiv"</string>
@@ -1145,6 +1146,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi se va activa automat"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Când vă aflați lângă o rețea salvată, de înaltă calitate"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nu reactivați"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi s-a activat automat"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Vă aflați lângă o rețea salvată: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Conectați-vă la rețeaua Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Conectați-vă la rețea"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1842,6 +1845,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nu s-a putut restabili comanda rapidă deoarece aplicația nu acceptă backupul și restabilirea"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nu s-a putut restabili comanda rapidă din cauza nepotrivirii semnăturii aplicației"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nu s-a putut restabili comanda rapidă"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Comanda rapidă este dezactivată"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Dezinstalați"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Lansați oricum"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Dezinstalați aplicația dăunătoare?"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 460e0c7..70dc651 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -221,6 +221,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Экстренный вызов"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Отчет об ошибке"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Закончить сеанс"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Отчет об ошибке"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Информация о текущем состоянии вашего устройства будет собрана и отправлена по электронной почте. Подготовка отчета займет некоторое время."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивный отчет"</string>
@@ -1167,6 +1168,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi включится автоматически"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Когда вы будете в зоне действия сохраненной сети с хорошим сигналом."</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не включать снова"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi включен автоматически"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Вы находитесь в зоне действия сохраненной сети <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Подключение к Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Регистрация в сети"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1877,6 +1880,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Ярлык отключен"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Удалить"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Запустить все равно"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Удалите опасное приложение"</string>
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 4188a41..609f99f 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"හදිසි"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"දෝෂ වර්තාව"</string>
     <string name="global_action_logout" msgid="935179188218826050">"සැසිය අවසන් කරන්න"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"තිර රුව"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"දෝෂ වාර්තාවක් ගන්න"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ඊ-තැපැල් පණිවිඩයක් ලෙස යැවීමට මෙය ඔබගේ වත්මන් උපාංග තත්වය ගැන තොරතුරු එකතු කරනු ඇත. දෝෂ වාර්තාව ආරම්භ කර එය යැවීමට සූදානම් කරන තෙක් එයට කිසියම් කාලයක් ගතවනු ඇත; කරුණාකර ඉවසන්න."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"අන්තර්ක්‍රියා වාර්."</string>
@@ -1125,6 +1126,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi ස්වයංක්‍රියව ක්‍රියාත්මක වනු ඇත"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"ඔබ උසස් තත්ත්වයේ සුරැකි ජාලයක් අවට සිටින විට"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"නැවත ක්‍රියාත්මක නොකරන්න"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi ස්වයංක්‍රියව ක්‍රියාත්මක කරන ලදි"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"ඔබ සුරැකි ජාලයක් අවට සිටී: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ජාලයට පුරනය වන්න"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"ජාලයට පුරනය වන්න"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1809,6 +1812,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"කෙටි මග අබල කර ඇත"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"අස්ථාපනය කරන්න"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"කෙසේ වුවත් ආරම්භ කරන්න"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"හානිකර යෙදුම අස්ථාපනය කරන්නද?"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index df3c3e7..3c89e75 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -221,6 +221,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Klic v sili"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Poročilo o napakah"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Končaj sejo"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Posnetek zaslona"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Ustvari poročilo o napakah"</string>
     <string name="bugreport_message" msgid="398447048750350456">"S tem bodo zbrani podatki o trenutnem stanju naprave, ki bodo poslani v e-poštnem sporočilu. Izvedba poročila o napakah in priprava trajata nekaj časa, zato bodite potrpežljivi."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivno poročilo"</string>
@@ -1167,6 +1168,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Povezava Wi‑Fi se bo samodejno vklopila"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Ko ste v bližini zanesljivega shranjenega omrežja"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne vklopi znova"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi je bil vklopljen samodejno"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ste v bližini shranjenega omrežja: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavite se v omrežje Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Prijava v omrežje"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1877,6 +1880,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Bližnjice ni bilo mogoče obnoviti, ker aplikacija ne podpira varnostnega kopiranja in obnavljanja"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Bližnjice ni bilo mogoče obnoviti zaradi neujemanja podpisa aplikacije"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Bližnjice ni bilo mogoče obnoviti"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Bližnjica je onemogočena"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Odstrani"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Vseeno zaženi"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Želite odstraniti škodljivo aplikacijo?"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index b98a5c7..748f812 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -215,6 +215,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Dharura"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Ripoti ya hitilafu"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Maliza kipindi"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Picha ya skrini"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Chukua ripoti ya hitilafu"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Hii itakusanya maelezo kuhusu hali ya kifaa chako kwa sasa, na itume kama barua pepe. Itachukua muda mfupi tangu ripoti ya hitilafu ianze kuzalishwa hadi iwe tayari kutumwa; vumilia."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Ripoti ya kushirikiana"</string>
@@ -1121,6 +1122,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi itawashwa kiotomatiki"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Unapokuwa karibu na mtandao uliohifadhiwa wenye ubora wa juu"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Usiwashe tena"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi imewashwa kiotomatiki"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Uko karibu na mtandao uliohifadhiwa: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Ingia kwa mtandao wa Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Ingia katika mtandao"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1805,6 +1808,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Imeshindwa kurejesha njia ya mkato kwa sababu programu haitumii kipengele cha hifadhi rudufu na kurejesha upya"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Imeshindwa kurejesha njia ya mkato kwa sababu ufunguo wako wa kuambatisha cheti kwenye programu haulingani"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Imeshindwa kurejesha njia ya mkato"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Njia ya mkato imezimwa"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Ondoa"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Fungua tu"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Ungependa kuondoa programu hatari?"</string>
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index a04c529..589ac91 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"అత్యవసరం"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"బగ్ నివేదిక"</string>
     <string name="global_action_logout" msgid="935179188218826050">"సెషన్‌ను ముగించు"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"బగ్ నివేదికను సిద్ధం చేయి"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ఇది ఇ-మెయిల్ సందేశం రూపంలో పంపడానికి మీ ప్రస్తుత పరికర స్థితి గురించి సమాచారాన్ని సేకరిస్తుంది. బగ్ నివేదికను ప్రారంభించడం మొదలుకొని పంపడానికి సిద్ధం చేసే వరకు ఇందుకు కొంత సమయం పడుతుంది; దయచేసి ఓపిక పట్టండి."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ప్రభావశీల నివేదిక"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi స్వయంచాలకంగా ఆన్ అవుతుంది"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"మీరు అధిక నాణ్యత గల సేవ్ చేసిన నెట్‌వర్క్‌కు సమీపంగా ఉన్నప్పుడు"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"తిరిగి ఆన్ చేయవద్దు"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"షార్ట్‌కట్ నిలిపివేయబడింది"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 788444e..0d70955 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -221,6 +221,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Екстрений виклик"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Звіт про помилки"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Завершити сеанс"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Знімок екрана"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Звіт про помилку"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Інформація про поточний стан вашого пристрою буде зібрана й надіслана електронною поштою. Підготовка звіту триватиме певний час."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Інтерактивний звіт"</string>
@@ -1167,6 +1168,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi вмикатиметься автоматично"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Коли ви поблизу збереженої мережі високої якості"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Не вмикати знову"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"З’єднання Wi-Fi увімкнулось автоматично"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ви поблизу збереженої мережі: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Вхід у мережу Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Вхід у мережу"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1877,6 +1880,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Ярлик вимкнено"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Видалити"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Усе одно запустити"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Видалити шкідливий додаток?"</string>
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 38313d6..54b25b7 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -217,6 +217,8 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"ایمرجنسی"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"بگ کی اطلاع"</string>
     <string name="global_action_logout" msgid="935179188218826050">"سیشن ختم کریں"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="bugreport_title" msgid="2667494803742548533">"بگ کی اطلاع لیں"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ایک ای میل پیغام کے بطور بھیجنے کیلئے، یہ آپ کے موجودہ آلہ کی حالت کے بارے میں معلومات جمع کرے گا۔ بگ کی اطلاع شروع کرنے سے لے کر بھیجنے کیلئے تیار ہونے تک اس میں تھوڑا وقت لگے گا؛ براہ کرم تحمل سے کام لیں۔"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"متعامل رپورٹ"</string>
@@ -1123,6 +1125,10 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"‏Wi‑Fi از خود آن ہو جائے گا"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"جب آپ اعلی معیار کے محفوظ کردہ نیٹ ورک کے قریب ہوں"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"دوبارہ آن نہ کریں"</string>
+    <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
+    <skip />
+    <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
+    <skip />
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"‏Wi-Fi نیٹ ورک میں سائن ان کریں"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"نیٹ ورک میں سائن ان کریں"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1814,11 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"شارٹ کٹ غیر فعال ہے"</string>
+    <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+    <skip />
+    <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 92ec354..ce8613f 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Favqulodda chaqiruv"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Nosozlik haqida ma’lumot berish"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Seansni yakunlash"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skrinshot"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Xatoliklar hisoboti"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Qurilmangiz holati haqidagi ma’lumotlar to‘planib, e-pochta orqali yuboriladi. Hisobotni tayyorlash biroz vaqt olishi mumkin."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv hisobot"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi avtomatik ravishda yoqiladi"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Saqlangan tarmoqlar ichidan signali yaxshisi hududida ekaningizda"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Qayta yoqilmasin"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi avtomatik ravishda yoqildi"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Saqlangan tarmoq atrofidasiz: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi tarmoqqa kirish"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Tarmoqqa kirish"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1811,8 @@
     <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>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Yorliq faolsizlantirildi"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"O‘chirib tashlash"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Baribir ishga tushirilsin"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Zararli ilova o‘chirilsinmi?"</string>
 </resources>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index f6752c2..a7736e7c 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -10,7 +10,7 @@
      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
+     See the License for the specific language gning permissions and
      limitations under the License.
 -->
 
@@ -147,6 +147,7 @@
     an activity that looks like a Dialog.-->
     <style name="Theme.DeviceDefault.Dialog" parent="Theme.Material.Dialog" >
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
         <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
 
@@ -183,6 +184,7 @@
 
     <style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -200,6 +202,7 @@
 
     <style name="Theme.DeviceDefault.Settings.CompactMenu" parent="Theme.Material.CompactMenu">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -219,6 +222,7 @@
     regular dialog. -->
     <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -237,6 +241,7 @@
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
     <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -256,6 +261,7 @@
     for a regular dialog. -->
     <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -434,6 +440,7 @@
 
     <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dialog -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
diff --git a/core/res/res/values-watch/themes_material.xml b/core/res/res/values-watch/themes_material.xml
index 0cf398b..40a249a 100644
--- a/core/res/res/values-watch/themes_material.xml
+++ b/core/res/res/values-watch/themes_material.xml
@@ -43,6 +43,7 @@
     <!-- Override behaviour to set the theme colours for dialogs, keep them the same. -->
     <style name="ThemeOverlay.Material.Dialog" parent="ThemeOverlay.Material.BaseDialog">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
     </style>
 
     <!-- Force the background and floating colours to be the default colours. -->
@@ -51,6 +52,7 @@
         <item name="colorBackgroundFloating">@color/background_floating_material_dark</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_dark</item>
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
     </style>
 
     <!-- Force the background and floating colours to be the default colours. -->
@@ -59,6 +61,7 @@
         <item name="colorBackgroundFloating">@color/background_floating_material_light</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_light</item>
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
     </style>
 
     <!-- Force all settings themes to use normal Material theme. -->
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e91e382..e97f893 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -217,6 +217,7 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"Isimo esiphuthumayo"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Umbiko wephutha"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Phothula isikhathi"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Isithombe-skrini"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Thatha umbiko wesiphazamiso"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Lokhu kuzoqoqa ulwazi mayelana nesimo samanje sedivayisi yakho, ukuthumela imilayezo ye-imeyili. Kuzothatha isikhathi esincane kusuka ekuqaleni umbiko wesiphazamiso uze ulungele ukuthunyelwa; sicela ubekezele."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Umbiko obandakanyayo"</string>
@@ -1123,6 +1124,8 @@
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"I-Wi-Fi izovuleka ngokuzenzakalela"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Uma useduze kwenethiwekhi yekhwalithi ephezulu elondoloziwe"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ungaphindi uvule"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"I-Wi‑Fi ivuleke ngokuzenzakalela"</string>
+    <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Useduzane nenethiwekhi elondoloziwe: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Ngena ngemvume kunethiwekhi ye-Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Ngena ngemvume kunethiwekhi"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1807,6 +1810,8 @@
     <string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ayikwazanga ukubuyisa isinqamuleli ngoba uhlelo lokusebenza alusekeli isipele nokubuyisa"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ayikwazanga ukubuyisa isinqamuleli ngoba isignisha yohlelo lokusebenza ayifani"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ayikwazanga ukubuyisa isinqamuleli"</string>
-    <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
-    <skip />
+    <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Isinqamuleli sikhutshaziwe"</string>
+    <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Khipha"</string>
+    <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Qalisa noma kunjalo"</string>
+    <string name="harmful_app_warning_title" msgid="2229996292333310435">"Khipha uhlelo lokusebenza oluyingozi?"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index addbbf5..4eaf93d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4739,6 +4739,15 @@
         <!-- Extra spacing between lines of text, as a multiplier. The value will not be applied
              for the last line of text.-->
         <attr name="lineSpacingMultiplier" format="float" />
+        <!-- Explicit height between lines of text. If set, this will override the values set
+             for lineSpacingExtra and lineSpacingMultiplier. -->
+        <attr name="lineHeight" format="dimension" />
+        <!-- Distance from the top of the TextView to the first text baseline. If set, this
+             overrides the value set for paddingTop. -->
+        <attr name="firstBaselineToTopHeight" format="dimension" />
+        <!-- Distance from the bottom of the TextView to the last text baseline. If set, this
+             overrides the value set for paddingBottom. -->
+        <attr name="lastBaselineToBottomHeight" format="dimension" />
         <!-- The number of times to repeat the marquee animation. Only applied if the
              TextView has marquee enabled. -->
         <attr name="marqueeRepeatLimit" format="integer">
@@ -4867,6 +4876,8 @@
             <!-- Justification by stretching word spacing. -->
             <enum name="inter_word" value = "1" />
         </attr>
+        <!-- Whether or not this view is a heading for accessibility purposes. -->
+        <attr name="accessibilityHeading" format="boolean"/>
     </declare-styleable>
     <declare-styleable name="TextViewAppearance">
         <!-- Base text color, typeface, size, and style. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e3a910f..8de3a98 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3249,4 +3249,9 @@
     <string name="config_fontFamilyButton">@string/font_family_button_material</string>
 
     <string translatable="false" name="config_batterySaverDeviceSpecificConfig"></string>
+
+    <!-- Package name that should be granted Notification Assistant access -->
+    <string name="config_defaultAssistantAccessPackage" translatable="false">android.ext.services</string>
+
+    <bool name="config_supportBluetoothPersistedState">true</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 58ae76c..9cdf553 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2862,6 +2862,10 @@
       <public name="appComponentFactory" />
       <public name="fallbackLineSpacing" />
       <public name="accessibilityPaneTitle" />
+      <public name="firstBaselineToTopHeight" />
+      <public name="lastBaselineToBottomHeight" />
+      <public name="lineHeight" />
+      <public name="accessibilityHeading" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f4ced58..90be99c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2550,6 +2550,7 @@
   <java-symbol type="bool" name="config_mainBuiltInDisplayIsRound" />
 
   <java-symbol type="id" name="actions_container" />
+  <java-symbol type="id" name="smart_reply_container" />
   <java-symbol type="id" name="remote_input_tag" />
 
   <java-symbol type="attr" name="seekBarDialogPreferenceStyle" />
@@ -3203,6 +3204,7 @@
 
   <java-symbol type="string" name="global_action_logout" />
   <java-symbol type="string" name="config_mainBuiltInDisplayCutout" />
+  <java-symbol type="drawable" name="messaging_user" />
   <java-symbol type="bool" name="config_fillMainBuiltInDisplayCutout" />
   <java-symbol type="drawable" name="ic_logout" />
 
@@ -3215,4 +3217,8 @@
   <java-symbol type="string" name="harmful_app_warning_uninstall" />
   <java-symbol type="string" name="harmful_app_warning_launch_anyway" />
   <java-symbol type="string" name="harmful_app_warning_title" />
+
+  <java-symbol type="string" name="config_defaultAssistantAccessPackage" />
+
+  <java-symbol type="bool" name="config_supportBluetoothPersistedState" />
 </resources>
diff --git a/core/tests/coretests/apks/install-split-base/Android.mk b/core/tests/coretests/apks/install-split-base/Android.mk
new file mode 100644
index 0000000..5b60e31
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-base/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := install_split_base
+
+include $(FrameworkCoreTests_BUILD_PACKAGE)
\ No newline at end of file
diff --git a/core/tests/coretests/apks/install-split-base/AndroidManifest.xml b/core/tests/coretests/apks/install-split-base/AndroidManifest.xml
new file mode 100644
index 0000000..c2bfedd
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-base/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.frameworks.coretests.install_split"
+        android:isolatedSplits="true">
+
+    <application android:label="ClassloaderSplitApp">
+        <activity android:name=".BaseActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/core/java/android/os/Seccomp.java b/core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
similarity index 74%
copy from core/java/android/os/Seccomp.java
copy to core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
index f14e93f..cb5760ce 100644
--- a/core/java/android/os/Seccomp.java
+++ b/core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
+/**
+ * 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.
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package android.os;
+package com.google.android.dexapis.splitapp;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+import android.app.Activity;
+
+/** Main activity */
+public class BaseActivity extends Activity {
 }
diff --git a/core/tests/coretests/apks/install-split-feature-a/Android.mk b/core/tests/coretests/apks/install-split-feature-a/Android.mk
new file mode 100644
index 0000000..0f37d16
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-feature-a/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := install_split_feature_a
+
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT_FLAGS += --custom-package com.google.android.dexapis.splitapp.feature_a
+LOCAL_AAPT_FLAGS += --package-id 0x80
+
+include $(FrameworkCoreTests_BUILD_PACKAGE)
\ No newline at end of file
diff --git a/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml b/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml
new file mode 100644
index 0000000..3221c75
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-feature-a/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.frameworks.coretests.install_split"
+        featureSplit="feature_a">
+
+    <application>
+        <activity android:name=".feature_a.FeatureAActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
similarity index 72%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
index 4200de1..0af5f89 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
+/**
+ * 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.
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package com.google.android.dexapis.splitapp.feature_a;
 
-/* @hide */
-parcelable RecoveryData;
+import android.app.Activity;
+
+/** Main activity */
+public class FeatureAActivity extends Activity {
+}
diff --git a/core/tests/coretests/src/android/content/pm/crossprofile/CrossProfileAppsTest.java b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
similarity index 92%
rename from core/tests/coretests/src/android/content/pm/crossprofile/CrossProfileAppsTest.java
rename to core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
index 80e4c02..0cfcd8f8 100644
--- a/core/tests/coretests/src/android/content/pm/crossprofile/CrossProfileAppsTest.java
+++ b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm.crossprofile;
+package android.content.pm;
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -42,7 +42,7 @@
 
 /**
  * Build/Install/Run:
- * bit FrameworksCoreTests:android.content.pm.crossprofile.CrossProfileAppsTest
+ * atest frameworks/base/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
  */
 @Presubmit
 @RunWith(MockitoJUnitRunner.class)
@@ -118,7 +118,7 @@
     public void getProfileSwitchingIcon_managedProfile() {
         setValidTargetProfile(MANAGED_PROFILE);
 
-        mCrossProfileApps.getProfileSwitchingIcon(MANAGED_PROFILE);
+        mCrossProfileApps.getProfileSwitchingIconDrawable(MANAGED_PROFILE);
         verify(mResources).getDrawable(R.drawable.ic_corp_badge, null);
     }
 
@@ -126,13 +126,13 @@
     public void getProfileSwitchingIcon_personalProfile() {
         setValidTargetProfile(PERSONAL_PROFILE);
 
-        mCrossProfileApps.getProfileSwitchingIcon(PERSONAL_PROFILE);
+        mCrossProfileApps.getProfileSwitchingIconDrawable(PERSONAL_PROFILE);
         verify(mResources).getDrawable(R.drawable.ic_account_circle, null);
     }
 
     @Test(expected = SecurityException.class)
     public void getProfileSwitchingIcon_securityException() {
-        mCrossProfileApps.getProfileSwitchingIcon(PERSONAL_PROFILE);
+        mCrossProfileApps.getProfileSwitchingIconDrawable(PERSONAL_PROFILE);
     }
 
     private void setValidTargetProfile(UserHandle userHandle) {
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
new file mode 100644
index 0000000..4b84429
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
@@ -0,0 +1,208 @@
+/**
+ * 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.content.pm.dex;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.Package;
+import android.content.pm.PackageParser.PackageParserException;
+import android.os.FileUtils;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.frameworks.coretests.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import libcore.io.IoUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DexMetadataHelperTest {
+    private static final String APK_FILE_EXTENSION = ".apk";
+    private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
+
+    private File mTmpDir = null;
+
+    @Before
+    public void setUp() {
+        mTmpDir = IoUtils.createTemporaryDirectory("DexMetadataHelperTest");
+    }
+
+    @After
+    public void tearDown() {
+        if (mTmpDir != null) {
+            File[] files = mTmpDir.listFiles();
+            for (File f : files) {
+                f.delete();
+            }
+        }
+    }
+
+    private File createDexMetadataFile(String apkFileName) throws IOException {
+        File dmFile = new File(mTmpDir, apkFileName.replace(APK_FILE_EXTENSION,
+                DEX_METADATA_FILE_EXTENSION));
+        try (FileOutputStream fos = new FileOutputStream(dmFile)) {
+            try (ZipOutputStream zipOs = new ZipOutputStream(fos)) {
+                zipOs.putNextEntry(new ZipEntry("primary.prof"));
+                zipOs.closeEntry();
+            }
+        }
+        return dmFile;
+    }
+
+    private File copyApkToToTmpDir(String apkFileName, int apkResourceId) throws IOException {
+        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        File outFile = new File(mTmpDir, apkFileName);
+        try (InputStream is = context.getResources().openRawResource(apkResourceId)) {
+            FileUtils.copyToFileOrThrow(is, outFile);
+        }
+        return outFile;
+    }
+
+    @Test
+    public void testParsePackageWithDmFileValid() throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        createDexMetadataFile("install_split_base.apk");
+        Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+
+        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        assertEquals(1, packageDexMetadata.size());
+        String baseDexMetadata = packageDexMetadata.get(pkg.baseCodePath);
+        assertNotNull(baseDexMetadata);
+        assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.baseCodePath));
+    }
+
+    @Test
+    public void testParsePackageSplitsWithDmFileValid()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_base.apk");
+        createDexMetadataFile("install_split_feature_a.apk");
+        Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+
+        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        assertEquals(2, packageDexMetadata.size());
+        String baseDexMetadata = packageDexMetadata.get(pkg.baseCodePath);
+        assertNotNull(baseDexMetadata);
+        assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.baseCodePath));
+
+        String splitDexMetadata = packageDexMetadata.get(pkg.splitCodePaths[0]);
+        assertNotNull(splitDexMetadata);
+        assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.splitCodePaths[0]));
+    }
+
+    @Test
+    public void testParsePackageSplitsNoBaseWithDmFileValid()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_feature_a.apk");
+        Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+
+        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        assertEquals(1, packageDexMetadata.size());
+
+        String splitDexMetadata = packageDexMetadata.get(pkg.splitCodePaths[0]);
+        assertNotNull(splitDexMetadata);
+        assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.splitCodePaths[0]));
+    }
+
+    @Test
+    public void testParsePackageWithDmFileInvalid() throws IOException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        File invalidDmFile = new File(mTmpDir, "install_split_base.dm");
+        Files.createFile(invalidDmFile.toPath());
+        try {
+            PackageParser.Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+            DexMetadataHelper.validatePackageDexMetadata(pkg);
+        } catch (PackageParserException e) {
+            assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
+        }
+    }
+
+    @Test
+    public void testParsePackageSplitsWithDmFileInvalid()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_base.apk");
+        File invalidDmFile = new File(mTmpDir, "install_split_feature_a.dm");
+        Files.createFile(invalidDmFile.toPath());
+
+        try {
+            PackageParser.Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+            DexMetadataHelper.validatePackageDexMetadata(pkg);
+        } catch (PackageParserException e) {
+            assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
+        }
+    }
+
+    @Test
+    public void testPackageWithDmFileNoMatch() throws IOException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        createDexMetadataFile("non_existent.apk");
+
+        try {
+            DexMetadataHelper.validateDexPaths(mTmpDir.list());
+            fail("Should fail validation");
+        } catch (IllegalStateException e) {
+            // expected.
+        }
+    }
+
+    @Test
+    public void testPackageSplitsWithDmFileNoMatch()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_base.apk");
+        createDexMetadataFile("install_split_feature_a.mistake.apk");
+
+        try {
+            DexMetadataHelper.validateDexPaths(mTmpDir.list());
+            fail("Should fail validation");
+        } catch (IllegalStateException e) {
+            // expected.
+        }
+    }
+
+    private static boolean isDexMetadataForApk(String dmaPath, String apkPath) {
+        return apkPath.substring(0, apkPath.length() - APK_FILE_EXTENSION.length()).equals(
+                dmaPath.substring(0, dmaPath.length() - DEX_METADATA_FILE_EXTENSION.length()));
+    }
+}
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 417faf2..eaabdc8 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -505,4 +505,84 @@
         assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
         assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
     }
+
+    @Test
+    public void testBuildSystemFallback_ElegantFallback_customFallback_missingFile() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family name='serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "    <font weight='400' style='normal' fallbackFor='serif'>NoSuchFont.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+
+        buildSystemFallback(xml, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
+    @Test
+    public void testBuildSystemFallback_ElegantFallback_customFallback_missingFile2() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family name='serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal' fallbackFor='serif'>NoSuchFont.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+
+        buildSystemFallback(xml, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 410bee0..8da7ced 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -204,6 +204,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.ENHANCED_4G_MODE_ENABLED,
                     Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
                     Settings.Global.ERROR_LOGCAT_PREFIX,
@@ -329,6 +330,7 @@
                     Settings.Global.SETUP_PREPAID_DETECTION_REDIR_HOST,
                     Settings.Global.SETUP_PREPAID_DETECTION_TARGET_URL,
                     Settings.Global.SHORTCUT_MANAGER_CONSTANTS,
+                    Settings.Global.SHOW_FIRST_CRASH_DIALOG,
                     Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
                     Settings.Global.SHOW_TEMPERATURE_WARNING,
                     Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
index 5d33397..f6300ee 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -132,7 +132,7 @@
     public void buildForStaticLayout() {
         MeasuredParagraph mt = null;
 
-        mt = MeasuredParagraph.buildForStaticLayout(PAINT, "XXX", 0, 3, LTR, null);
+        mt = MeasuredParagraph.buildForStaticLayout(PAINT, "XXX", 0, 3, LTR, false, null);
         assertNotNull(mt);
         assertNotNull(mt.getChars());
         assertEquals("XXX", charsToString(mt.getChars()));
@@ -147,7 +147,7 @@
 
         // Recycle it
         MeasuredParagraph mt2 =
-                MeasuredParagraph.buildForStaticLayout(PAINT, "_VVV_", 1, 4, RTL, mt);
+                MeasuredParagraph.buildForStaticLayout(PAINT, "_VVV_", 1, 4, RTL, false, mt);
         assertEquals(mt2, mt);
         assertNotNull(mt2.getChars());
         assertEquals("VVV", charsToString(mt.getChars()));
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index f169f22..993bae1 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -194,6 +194,10 @@
     <allow-in-power-save package="com.android.cellbroadcastreceiver" />
     <allow-in-power-save package="com.android.shell" />
 
+    <!-- Whitelist system providers -->
+    <allow-in-power-save-except-idle package="com.android.providers.calendar" />
+    <allow-in-power-save-except-idle package="com.android.providers.contacts" />
+
     <!-- These are the packages that are white-listed to be able to run as system user -->
     <system-user-whitelisted-app package="com.android.settings" />
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 4732bec..c0958cd 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -75,6 +75,7 @@
 
     <privapp-permissions package="com.android.launcher3">
         <permission name="android.permission.BIND_APPWIDGET"/>
+        <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
         <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
     </privapp-permissions>
 
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 419e2b7..05dadc9 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -26,6 +26,7 @@
 import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
+import android.graphics.drawable.AnimatedImageDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.NinePatchDrawable;
@@ -239,11 +240,12 @@
     };
 
     /**
-     *  Supplied to onPartialImage if the provided data is incomplete.
+     *  Used if the provided data is incomplete.
      *
-     *  Will never be thrown by ImageDecoder.
+     *  May be thrown if there is nothing to display.
      *
-     *  There may be a partial image to display.
+     *  If supplied to onPartialImage, there may be a correct partial image to
+     *  display.
      */
     public static class IncompleteException extends IOException {};
 
@@ -293,9 +295,10 @@
     };
 
     // Fields
-    private long      mNativePtr;
-    private final int mWidth;
-    private final int mHeight;
+    private long          mNativePtr;
+    private final int     mWidth;
+    private final int     mHeight;
+    private final boolean mAnimated;
 
     private int     mDesiredWidth;
     private int     mDesiredHeight;
@@ -321,12 +324,14 @@
      * called after decoding to delete native resources.
      */
     @SuppressWarnings("unused")
-    private ImageDecoder(long nativePtr, int width, int height) {
+    private ImageDecoder(long nativePtr, int width, int height,
+            boolean animated) {
         mNativePtr = nativePtr;
         mWidth = width;
         mHeight = height;
         mDesiredWidth = width;
         mDesiredHeight = height;
+        mAnimated = animated;
         mCloseGuard.open("close");
     }
 
@@ -676,6 +681,18 @@
         }
     }
 
+    private Bitmap decodeBitmap() throws IOException {
+        checkState();
+        // nDecodeBitmap calls postProcessAndRelease only if mPostProcess
+        // exists.
+        ImageDecoder postProcessPtr = mPostProcess == null ? null : this;
+        return nDecodeBitmap(mNativePtr, mOnPartialImageListener,
+                postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
+                mMutable, mAllocator, mRequireUnpremultiplied,
+                mPreferRamOverQuality, mAsAlphaMask);
+
+    }
+
     /**
      *  Create a {@link Drawable} from a {@code Source}.
      *
@@ -701,8 +718,6 @@
                 }
             }
 
-            decoder.checkState();
-
             if (decoder.mRequireUnpremultiplied) {
                 // Though this could be supported (ignored) for opaque images,
                 // it seems better to always report this error.
@@ -715,17 +730,22 @@
                                                 "Drawable!");
             }
 
-            Bitmap bm = nDecodeBitmap(decoder.mNativePtr,
-                                      decoder.mOnPartialImageListener,
-                                      decoder.mPostProcess,
-                                      decoder.mDesiredWidth,
-                                      decoder.mDesiredHeight,
-                                      decoder.mCropRect,
-                                      false,    // mMutable
-                                      decoder.mAllocator,
-                                      false,    // mRequireUnpremultiplied
-                                      decoder.mPreferRamOverQuality,
-                                      decoder.mAsAlphaMask);
+            if (decoder.mAnimated) {
+                // AnimatedImageDrawable calls postProcessAndRelease only if
+                // mPostProcess exists.
+                ImageDecoder postProcessPtr = decoder.mPostProcess == null ?
+                        null : decoder;
+                Drawable d = new AnimatedImageDrawable(decoder.mNativePtr,
+                        postProcessPtr, decoder.mDesiredWidth,
+                        decoder.mDesiredHeight, decoder.mCropRect,
+                        decoder.mInputStream, decoder.mAssetFd);
+                // d has taken ownership of these objects.
+                decoder.mInputStream = null;
+                decoder.mAssetFd = null;
+                return d;
+            }
+
+            Bitmap bm = decoder.decodeBitmap();
             Resources res = src.getResources();
             if (res == null) {
                 bm.setDensity(Bitmap.DENSITY_NONE);
@@ -741,7 +761,6 @@
                         opticalInsets, null);
             }
 
-            // TODO: Handle animation.
             return new BitmapDrawable(res, bm);
         }
     }
@@ -780,19 +799,7 @@
                 }
             }
 
-            decoder.checkState();
-
-            return nDecodeBitmap(decoder.mNativePtr,
-                                 decoder.mOnPartialImageListener,
-                                 decoder.mPostProcess,
-                                 decoder.mDesiredWidth,
-                                 decoder.mDesiredHeight,
-                                 decoder.mCropRect,
-                                 decoder.mMutable,
-                                 decoder.mAllocator,
-                                 decoder.mRequireUnpremultiplied,
-                                 decoder.mPreferRamOverQuality,
-                                 decoder.mAsAlphaMask);
+            return decoder.decodeBitmap();
         }
     }
 
@@ -808,6 +815,18 @@
         return decodeBitmap(src, null);
     }
 
+    /**
+     * Private method called by JNI.
+     */
+    @SuppressWarnings("unused")
+    private int postProcessAndRelease(@NonNull Canvas canvas, int width, int height) {
+        try {
+            return mPostProcess.postProcess(canvas, width, height);
+        } finally {
+            canvas.release();
+        }
+    }
+
     private static native ImageDecoder nCreate(long asset) throws IOException;
     private static native ImageDecoder nCreate(ByteBuffer buffer,
                                                int position,
@@ -819,7 +838,7 @@
     @NonNull
     private static native Bitmap nDecodeBitmap(long nativePtr,
             OnPartialImageListener listener,
-            PostProcess postProcess,
+            @Nullable ImageDecoder decoder,     // Only used if mPostProcess != null
             int width, int height,
             Rect cropRect, boolean mutable,
             int allocator, boolean requireUnpremul,
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 68b7ac2..ef41507 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1025,6 +1025,10 @@
                         xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir);
                 if (family != null) {
                     fallbackMap.valueAt(i).add(family);
+                } else if (defaultFamily != null) {
+                    fallbackMap.valueAt(i).add(defaultFamily);
+                } else {
+                    // There is no valid for for default fallback. Ignore.
                 }
             }
         }
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
new file mode 100644
index 0000000..ce3bd9a
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -0,0 +1,173 @@
+/*
+ * 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.graphics.drawable;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.SystemClock;
+
+import libcore.io.IoUtils;
+import libcore.util.NativeAllocationRegistry;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.Runnable;
+
+/**
+ * @hide
+ */
+public class AnimatedImageDrawable extends Drawable implements Animatable {
+    private final long                mNativePtr;
+    private final InputStream         mInputStream;
+    private final AssetFileDescriptor mAssetFd;
+
+    private final int                 mIntrinsicWidth;
+    private final int                 mIntrinsicHeight;
+
+    private Runnable mRunnable = new Runnable() {
+        @Override
+        public void run() {
+            invalidateSelf();
+        }
+    };
+
+    /**
+     * @hide
+     * This should only be called by ImageDecoder.
+     *
+     * decoder is only non-null if it has a PostProcess
+     */
+    public AnimatedImageDrawable(long nativeImageDecoder,
+            @Nullable ImageDecoder decoder, int width, int height, Rect cropRect,
+            InputStream inputStream, AssetFileDescriptor afd)
+            throws IOException {
+        mNativePtr = nCreate(nativeImageDecoder, decoder, width, height, cropRect);
+        mInputStream = inputStream;
+        mAssetFd = afd;
+
+        if (cropRect == null) {
+            mIntrinsicWidth  = width;
+            mIntrinsicHeight = height;
+        } else {
+            mIntrinsicWidth  = cropRect.width();
+            mIntrinsicHeight = cropRect.height();
+        }
+
+        long nativeSize = nNativeByteSize(mNativePtr);
+        NativeAllocationRegistry registry = new NativeAllocationRegistry(
+                AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
+        registry.registerNativeAllocation(this, mNativePtr);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        // FIXME: It's a shame that we have *both* a native finalizer and a Java
+        // one. The native one is necessary to report how much memory is being
+        // used natively, and this one is necessary to close the input. An
+        // alternative might be to read the entire stream ahead of time, so we
+        // can eliminate the Java finalizer.
+        try {
+            IoUtils.closeQuietly(mInputStream);
+            IoUtils.closeQuietly(mAssetFd);
+        } finally {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mIntrinsicWidth;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mIntrinsicHeight;
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        long nextUpdate = nDraw(mNativePtr, canvas.getNativeCanvasWrapper(),
+                SystemClock.uptimeMillis());
+        scheduleSelf(mRunnable, nextUpdate);
+    }
+
+    @Override
+    public void setAlpha(@IntRange(from=0,to=255) int alpha) {
+        if (alpha < 0 || alpha > 255) {
+            throw new IllegalArgumentException("Alpha must be between 0 and"
+                   + " 255! provided " + alpha);
+        }
+        nSetAlpha(mNativePtr, alpha);
+    }
+
+    @Override
+    public int getAlpha() {
+        return nGetAlpha(mNativePtr);
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+        long nativeFilter = colorFilter == null ? 0 : colorFilter.getNativeInstance();
+        nSetColorFilter(mNativePtr, nativeFilter);
+    }
+
+    @Override
+    public @PixelFormat.Opacity int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    // TODO: Add a Constant State?
+    // @Override
+    // public @Nullable ConstantState getConstantState() {}
+
+
+    // Animatable overrides
+    @Override
+    public boolean isRunning() {
+        return nIsRunning(mNativePtr);
+    }
+
+    @Override
+    public void start() {
+        nStart(mNativePtr);
+    }
+
+    @Override
+    public void stop() {
+        nStop(mNativePtr);
+    }
+
+    private static native long nCreate(long nativeImageDecoder,
+            @Nullable ImageDecoder decoder, int width, int height, Rect cropRect)
+        throws IOException;
+    private static native long nGetNativeFinalizer();
+    private static native long nDraw(long nativePtr, long canvasNativePtr, long msecs);
+    private static native void nSetAlpha(long nativePtr, int alpha);
+    private static native int nGetAlpha(long nativePtr);
+    private static native void nSetColorFilter(long nativePtr, long nativeFilter);
+    private static native boolean nIsRunning(long nativePtr);
+    private static native void nStart(long nativePtr);
+    private static native void nStop(long nativePtr);
+    private static native long nNativeByteSize(long nativePtr);
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index fabcdf0..1690e8c 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -424,15 +424,6 @@
         return getmtime(key, UID_SELF);
     }
 
-    public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
-        try {
-            return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
     // TODO: remove this when it's removed from Settings
     public boolean isHardwareBacked() {
         return isHardwareBacked("RSA");
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 3fb1c0d..fb7b246 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -495,6 +495,11 @@
                                           refPaint(paint), refBitmap(bitmap), refPatch(&patch)));
 }
 
+void RecordingCanvas::drawAnimatedImage(SkAnimatedImage*, float left, float top,
+                                        const SkPaint*) {
+    // Unimplemented
+}
+
 // Text
 void RecordingCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int glyphCount, const SkPaint& paint,
                                  float x, float y, float boundsLeft, float boundsTop,
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 3087db0..dd06ada 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -183,6 +183,8 @@
     virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, float dstLeft,
                                float dstTop, float dstRight, float dstBottom,
                                const SkPaint* paint) override;
+    virtual void drawAnimatedImage(SkAnimatedImage*, float left, float top,
+                                   const SkPaint* paint) override;
 
     // Text
     virtual bool drawTextAbsolutePos() const override { return false; }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 2e08670..dc274cf 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -23,6 +23,7 @@
 #include "hwui/MinikinUtils.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 
+#include <SkAnimatedImage.h>
 #include <SkCanvasStateUtils.h>
 #include <SkColorFilter.h>
 #include <SkColorSpaceXformCanvas.h>
@@ -32,6 +33,7 @@
 #include <SkGraphics.h>
 #include <SkImage.h>
 #include <SkImagePriv.h>
+#include <SkPicture.h>
 #include <SkRSXform.h>
 #include <SkShader.h>
 #include <SkTemplates.h>
@@ -723,6 +725,20 @@
     mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter));
 }
 
+void SkiaCanvas::drawAnimatedImage(SkAnimatedImage* image, float left, float top,
+                                   const SkPaint* paint) {
+    sk_sp<SkPicture> pic(image->newPictureSnapshot());
+    SkMatrix matrixStorage;
+    SkMatrix* matrix;
+    if (left == 0.0f && top == 0.0f) {
+        matrix = nullptr;
+    } else {
+        matrixStorage = SkMatrix::MakeTrans(left, top);
+        matrix = &matrixStorage;
+    }
+    mCanvas->drawPicture(pic.get(), matrix, paint);
+}
+
 void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
     vectorDrawable->drawStaging(this);
 }
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 99e676a..7137210 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -124,6 +124,8 @@
     virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, float dstLeft,
                                float dstTop, float dstRight, float dstBottom,
                                const SkPaint* paint) override;
+    virtual void drawAnimatedImage(SkAnimatedImage*, float left, float top,
+                                   const SkPaint* paint) override;
 
     virtual bool drawTextAbsolutePos() const override { return true; }
     virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index e682a2e..5efd357 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -28,6 +28,7 @@
 #include <SkCanvas.h>
 #include <SkMatrix.h>
 
+class SkAnimatedImage;
 class SkCanvasState;
 class SkVertices;
 
@@ -237,6 +238,9 @@
                                float dstTop, float dstRight, float dstBottom,
                                const SkPaint* paint) = 0;
 
+    virtual void drawAnimatedImage(SkAnimatedImage*, float left, float top,
+                                   const SkPaint* paint) = 0;
+
     /**
      * Specifies if the positions passed to ::drawText are absolute or relative
      * to the (x,y) value provided.
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e0289f0..d7861e3 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -180,6 +180,7 @@
     /**
      * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
      *            if applicable, as well as audioattributes.proto.
+     *            Also consider adding them to <aaudio/AAudio.h> for the NDK.
      */
 
     /**
diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
index 07483f6..b928e93 100644
--- a/media/java/android/media/update/ApiLoader.java
+++ b/media/java/android/media/update/ApiLoader.java
@@ -16,8 +16,10 @@
 
 package android.media.update;
 
+import android.content.res.Resources;
 import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager;
+import android.os.Build;
 
 /**
  * @hide
@@ -34,23 +36,25 @@
     public static StaticProvider getProvider(Context context) {
         try {
             return (StaticProvider) getMediaLibraryImpl(context);
-        } catch (NameNotFoundException | ReflectiveOperationException e) {
+        } catch (PackageManager.NameNotFoundException | ReflectiveOperationException e) {
             throw new RuntimeException(e);
         }
     }
 
     // TODO This method may do I/O; Ensure it does not violate (emit warnings in) strict mode.
-    private static synchronized Object getMediaLibraryImpl(Context appContext)
-            throws NameNotFoundException, ReflectiveOperationException {
+    private static synchronized Object getMediaLibraryImpl(Context context)
+            throws PackageManager.NameNotFoundException, ReflectiveOperationException {
         if (sMediaLibrary != null) return sMediaLibrary;
 
-        // TODO Dynamically find the package name
-        Context libContext = appContext.createPackageContext(UPDATE_PACKAGE,
+        // TODO Figure out when to use which package (query media update service)
+        int flags = Build.IS_DEBUGGABLE ? 0 : PackageManager.MATCH_FACTORY_ONLY;
+        Context libContext = context.createApplicationContext(
+                context.getPackageManager().getPackageInfo(UPDATE_PACKAGE, flags).applicationInfo,
                 Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
         sMediaLibrary = libContext.getClassLoader()
                 .loadClass(UPDATE_CLASS)
-                .getMethod(UPDATE_METHOD, Context.class, Context.class)
-                .invoke(null, appContext, libContext);
+                .getMethod(UPDATE_METHOD, Resources.class, Resources.Theme.class)
+                .invoke(null, libContext.getResources(), libContext.getTheme());
         return sMediaLibrary;
     }
 }
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 61164e0..0704e35 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -29,6 +29,13 @@
     shared_libs: [
         "libandroid_runtime",
     ],
+
+    arch: {
+        arm: {
+            // TODO: This is to work around b/24465209. Remove after root cause is fixed
+            ldflags: ["-Wl,--hash-style=both"],
+        },
+    },
 }
 
 // The headers module is in frameworks/native/Android.bp.
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 291009e..63d3623 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -51,6 +51,13 @@
             </intent-filter>
         </service>
 
+        <service android:name=".autofill.AutofillFieldClassificationServiceImpl"
+             android:permission="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.autofill.AutofillFieldClassificationService" />
+            </intent-filter>
+        </service>
+
         <library android:name="android.ext.services"/>
     </application>
 
diff --git a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
new file mode 100644
index 0000000..ea516a1
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.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 android.ext.services.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.service.autofill.AutofillFieldClassificationService;
+import android.util.Log;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassificationService {
+
+    private static final String TAG = "AutofillFieldClassificationServiceImpl";
+    private static final boolean DEBUG = false;
+    private static final List<String> sAvailableAlgorithms = Arrays.asList(EditDistanceScorer.NAME);
+
+    @Override
+    public List<String> onGetAvailableAlgorithms() {
+        return sAvailableAlgorithms;
+    }
+
+    @Override
+    public String onGetDefaultAlgorithm() {
+        return EditDistanceScorer.NAME;
+    }
+
+    @Nullable
+    @Override
+    public Scores onGetScores(@Nullable String algorithmName,
+            @Nullable Bundle algorithmArgs, @NonNull List<AutofillValue> actualValues,
+            @NonNull List<String> userDataValues) {
+        if (ArrayUtils.isEmpty(actualValues) || ArrayUtils.isEmpty(userDataValues)) {
+            Log.w(TAG, "getScores(): empty currentvalues (" + actualValues + ") or userValues ("
+                    + userDataValues + ")");
+            // TODO(b/70939974): add unit test
+            return null;
+        }
+        if (algorithmName != null && !algorithmName.equals(EditDistanceScorer.NAME)) {
+            Log.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
+                    + EditDistanceScorer.NAME + " instead");
+        }
+
+        final String actualAlgorithmName = EditDistanceScorer.NAME;
+        final int actualValuesSize = actualValues.size();
+        final int userDataValuesSize = userDataValues.size();
+        if (DEBUG) {
+            Log.d(TAG, "getScores() will return a " + actualValuesSize + "x"
+                    + userDataValuesSize + " matrix for " + actualAlgorithmName);
+        }
+        final Scores scores = new Scores(actualAlgorithmName, actualValuesSize, userDataValuesSize);
+        final float[][] scoresMatrix = scores.getScores();
+
+        final EditDistanceScorer algorithm = EditDistanceScorer.getInstance();
+        for (int i = 0; i < actualValuesSize; i++) {
+            for (int j = 0; j < userDataValuesSize; j++) {
+                final float score = algorithm.getScore(actualValues.get(i), userDataValues.get(j));
+                scoresMatrix[i][j] = score;
+            }
+        }
+        return scores;
+    }
+}
diff --git a/core/java/android/service/autofill/EditDistanceScorer.java b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
similarity index 91%
rename from core/java/android/service/autofill/EditDistanceScorer.java
rename to packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
index 97a3868..d2e804a 100644
--- a/core/java/android/service/autofill/EditDistanceScorer.java
+++ b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
@@ -13,10 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.autofill;
+package android.ext.services.autofill;
 
 import android.annotation.NonNull;
-import android.annotation.TestApi;
 import android.view.autofill.AutofillValue;
 
 /**
@@ -24,20 +23,15 @@
  * by the user and the expected value predicted by an autofill service.
  */
 // TODO(b/70291841): explain algorithm once it's fully implemented
-/** @hide */
-@TestApi
-public final class EditDistanceScorer {
+final class EditDistanceScorer {
 
     private static final EditDistanceScorer sInstance = new EditDistanceScorer();
 
-    /** @hide */
     public static final String NAME = "EDIT_DISTANCE";
 
     /**
      * Gets the singleton instance.
      */
-    @TestApi
-    /** @hide */
     public static EditDistanceScorer getInstance() {
         return sInstance;
     }
@@ -52,9 +46,7 @@
      * <p>A full-match is {@code 1.0} (representing 100%), a full mismatch is {@code 0.0} and
      * partial mathces are something in between, typically using edit-distance algorithms.
      *
-     * @hide
      */
-    @TestApi
     public float getScore(@NonNull AutofillValue actualValue, @NonNull String userDataValue) {
         if (actualValue == null || !actualValue.isText() || userDataValue == null) return 0;
         // TODO(b/70291841): implement edit distance - currently it's returning either 0, 100%, or
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
new file mode 100644
index 0000000..cc15719
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.ext.services.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.view.autofill.AutofillValue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class EditDistanceScorerTest {
+
+    private final EditDistanceScorer mScorer = EditDistanceScorer.getInstance();
+
+    @Test
+    public void testGetScore_nullValue() {
+        assertFloat(mScorer.getScore(null, "D'OH!"), 0);
+    }
+
+    @Test
+    public void testGetScore_nonTextValue() {
+        assertFloat(mScorer.getScore(AutofillValue.forToggle(true), "D'OH!"), 0);
+    }
+
+    @Test
+    public void testGetScore_nullUserData() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), null), 0);
+    }
+
+    @Test
+    public void testGetScore_fullMatch() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), "D'OH!"), 1);
+    }
+
+    @Test
+    public void testGetScore_fullMatchMixedCase() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), "D'oH!"), 1);
+    }
+
+    // TODO(b/70291841): might need to change it once it supports different sizes
+    @Test
+    public void testGetScore_mismatchDifferentSizes() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("One"), "MoreThanOne"), 0);
+        assertFloat(mScorer.getScore(AutofillValue.forText("MoreThanOne"), "One"), 0);
+    }
+
+    @Test
+    public void testGetScore_partialMatch() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "Dxxx"), 0.25F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "DUxx"), 0.50F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "DUDx"), 0.75F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dxxx"), "Dude"), 0.25F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("DUxx"), "Dude"), 0.50F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("DUDx"), "Dude"), 0.75F);
+    }
+
+    public static void assertFloat(float actualValue, float expectedValue) {
+        assertThat(actualValue).isWithin(1.0e-10f).of(expectedValue);
+    }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index e0a3f6c..6c74418 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -59,7 +59,9 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.print.DualDumpOutputStream;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.printspooler.R;
 import com.android.printspooler.util.ApprovedPrintServices;
@@ -159,44 +161,11 @@
         return new PrintSpooler();
     }
 
-    private void dumpLocked(PrintWriter pw, String[] args) {
-        String prefix = (args.length > 0) ? args[0] : "";
-        String tab = "  ";
-
-        pw.append(prefix).append("print jobs:").println();
-        final int printJobCount = mPrintJobs.size();
-        for (int i = 0; i < printJobCount; i++) {
-            PrintJobInfo printJob = mPrintJobs.get(i);
-            pw.append(prefix).append(tab).append(printJob.toString());
-            pw.println();
-        }
-
-        pw.append(prefix).append("print job files:").println();
-        File[] files = getFilesDir().listFiles();
-        if (files != null) {
-            final int fileCount = files.length;
-            for (int i = 0; i < fileCount; i++) {
-                File file = files[i];
-                if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
-                    pw.append(prefix).append(tab).append(file.getName()).println();
-                }
-            }
-        }
-
-        pw.append(prefix).append("approved print services:").println();
-        Set<String> approvedPrintServices = (new ApprovedPrintServices(this)).getApprovedServices();
-        if (approvedPrintServices != null) {
-            for (String approvedService : approvedPrintServices) {
-                pw.append(prefix).append(tab).append(approvedService).println();
-            }
-        }
-    }
-
-    private void dumpLocked(@NonNull ProtoOutputStream proto) {
+    private void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
         int numPrintJobs = mPrintJobs.size();
         for (int i = 0; i < numPrintJobs; i++) {
-            writePrintJobInfo(this, proto, PrintSpoolerInternalStateProto.PRINT_JOBS,
-                    mPrintJobs.get(i));
+            writePrintJobInfo(this, dumpStream, "print_jobs",
+                    PrintSpoolerInternalStateProto.PRINT_JOBS, mPrintJobs.get(i));
         }
 
         File[] files = getFilesDir().listFiles();
@@ -204,7 +173,8 @@
             for (int i = 0; i < files.length; i++) {
                 File file = files[i];
                 if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
-                    proto.write(PrintSpoolerInternalStateProto.PRINT_JOB_FILES, file.getName());
+                    dumpStream.write("print_job_files",
+                            PrintSpoolerInternalStateProto.PRINT_JOB_FILES, file.getName());
                 }
             }
         }
@@ -214,13 +184,13 @@
             for (String approvedService : approvedPrintServices) {
                 ComponentName componentName = ComponentName.unflattenFromString(approvedService);
                 if (componentName != null) {
-                    writeComponentName(proto, PrintSpoolerInternalStateProto.APPROVED_SERVICES,
-                            componentName);
+                    writeComponentName(dumpStream, "approved_services",
+                            PrintSpoolerInternalStateProto.APPROVED_SERVICES, componentName);
                 }
             }
         }
 
-        proto.flush();
+        dumpStream.flush();
     }
 
     @Override
@@ -244,9 +214,15 @@
         try {
             synchronized (mLock) {
                 if (dumpAsProto) {
-                    dumpLocked(new ProtoOutputStream(fd));
+                    dumpLocked(new DualDumpOutputStream(new ProtoOutputStream(fd), null));
                 } else {
-                    dumpLocked(pw, args);
+                    try (FileOutputStream out = new FileOutputStream(fd)) {
+                        try (PrintWriter w = new PrintWriter(out)) {
+                            dumpLocked(new DualDumpOutputStream(null, new IndentingPrintWriter(w,
+                                    "  ")));
+                        }
+                    } catch (IOException ignored) {
+                    }
                 }
             }
         } finally {
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
index 55c192d..e1d5c0f 100644
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml
@@ -13,34 +13,28 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<android.support.v4.widget.DrawerLayout
+<!-- The main content view -->
+<LinearLayout
+    android:id="@+id/content_parent"
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <!-- The main content view -->
-    <LinearLayout
-        android:id="@+id/content_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <Toolbar
+        android:id="@+id/action_bar"
+        style="?android:attr/actionBarStyle"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:fitsSystemWindows="true">
-        <Toolbar
-            android:id="@+id/action_bar"
-            style="?android:attr/actionBarStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:theme="?android:attr/actionBarTheme"
-            android:navigationContentDescription="@*android:string/action_bar_up_description"/>
-        <FrameLayout
-            android:id="@+id/content_header_container"
-            style="?android:attr/actionBarStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-        <FrameLayout
-            android:id="@+id/content_frame"
-            android:layout_width="match_parent"
-            android:layout_height="fill_parent"
-            android:background="?android:attr/windowBackground" />
-    </LinearLayout>
-</android.support.v4.widget.DrawerLayout>
+        android:layout_height="wrap_content"
+        android:theme="?android:attr/actionBarTheme"
+        android:navigationContentDescription="@*android:string/action_bar_up_description" />
+    <FrameLayout
+        android:id="@+id/content_header_container"
+        style="?android:attr/actionBarStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+    <FrameLayout
+        android:id="@+id/content_frame"
+        android:layout_width="match_parent"
+        android:layout_height="fill_parent"
+        android:background="?android:attr/windowBackground" />
+</LinearLayout>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b035b70..b13de2e 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -498,10 +498,6 @@
     <string name="wifi_display_certification">Wireless display certification</string>
     <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
     <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
-    <!-- Setting Checkbox title whether to enable WiFi Aggressive Handover (more actively switch from wifi to mobile data). [CHAR LIMIT=40] -->
-    <string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to mobile handover</string>
-    <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
-    <string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
     <!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
     <string name="mobile_data_always_on">Mobile data always active</string>
     <!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] -->
@@ -556,10 +552,6 @@
     <string name="wifi_display_certification_summary">Show options for wireless display certification</string>
     <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
     <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
-    <!-- Setting Checkbox summary whether to enable Wifi aggressive handover [CHAR LIMIT=130] -->
-    <string name="wifi_aggressive_handover_summary">When enabled, Wi\u2011Fi will be more aggressive in handing over the data connection to mobile, when Wi\u2011Fi signal is low</string>
-    <!-- Setting Checkbox summary whether to always allow WiFi Roam Scans [CHAR LIMIT=130] -->
-    <string name="wifi_allow_scan_with_traffic_summary">Allow/Disallow Wi\u2011Fi Roam Scans based on the amount of data traffic present at the interface</string>
     <!-- UI debug setting: limit size of Android logger buffers -->
     <string name="select_logd_size_title">Logger buffer sizes</string>
     <!-- UI debug setting: limit size of Android logger buffers [CHAR LIMIT=59] -->
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 287a888..fd4d296 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -8,6 +8,7 @@
                  android:process="system"
                  android:backupAgent="SettingsBackupAgent"
                  android:killAfterRestore="false"
+                 android:restoreAnyVersion="true"
                  android:icon="@mipmap/ic_launcher_settings"
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index ae88227..c7ba4d6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -31,10 +31,12 @@
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
+import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.BackupUtils;
 import android.util.Log;
 
@@ -50,6 +52,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -147,6 +150,13 @@
     // stored in the full-backup tarfile as well, so should not be changed.
     private static final String STAGE_FILE = "flattened-data";
 
+    // List of keys that support restore to lower version of the SDK, introduced in Android P
+    private static final ArraySet<String> RESTORE_FROM_HIGHER_SDK_INT_SUPPORTED_KEYS =
+            new ArraySet<String>(Arrays.asList(new String[] {
+                KEY_NETWORK_POLICIES,
+                KEY_WIFI_NEW_CONFIG,
+            }));
+
     private SettingsHelper mSettingsHelper;
 
     private WifiManager mWifiManager;
@@ -209,6 +219,10 @@
     public void onRestore(BackupDataInput data, int appVersionCode,
             ParcelFileDescriptor newState) throws IOException {
 
+        if (DEBUG) {
+            Log.d(TAG, "onRestore(): appVersionCode: " + appVersionCode
+                    + "; Build.VERSION.SDK_INT: " + Build.VERSION.SDK_INT);
+        }
         // versionCode of com.android.providers.settings corresponds to SDK_INT
         mRestoredFromSdkInt = appVersionCode;
 
@@ -221,6 +235,15 @@
         while (data.readNextHeader()) {
             final String key = data.getKey();
             final int size = data.getDataSize();
+
+            // bail out of restoring from higher SDK_INT version for unsupported keys
+            if (appVersionCode > Build.VERSION.SDK_INT
+                    && !RESTORE_FROM_HIGHER_SDK_INT_SUPPORTED_KEYS.contains(key)) {
+                Log.w(TAG, "Not restoring unrecognized key '"
+                        + key + "' from future version " + appVersionCode);
+                continue;
+            }
+
             switch (key) {
                 case KEY_SYSTEM :
                     restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3698132..87ed7eb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1122,6 +1122,12 @@
         dumpSetting(s, p,
                     Settings.Global.ZRAM_ENABLED,
                     GlobalSettingsProto.ZRAM_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.ENABLE_SMART_REPLIES_IN_NOTIFICATIONS,
+                GlobalSettingsProto.ENABLE_SMART_REPLIES_IN_NOTIFICATIONS);
+        dumpSetting(s, p,
+                Settings.Global.SHOW_FIRST_CRASH_DIALOG,
+                GlobalSettingsProto.SHOW_FIRST_CRASH_DIALOG);
     }
 
     /** Dump a single {@link SettingsState.Setting} to a proto buf */
@@ -1513,6 +1519,9 @@
                 Settings.Secure.ANR_SHOW_BACKGROUND,
                 SecureSettingsProto.ANR_SHOW_BACKGROUND);
         dumpSetting(s, p,
+                Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
+                SecureSettingsProto.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION);
+        dumpSetting(s, p,
                 Settings.Secure.VOICE_RECOGNITION_SERVICE,
                 SecureSettingsProto.VOICE_RECOGNITION_SERVICE);
         dumpSetting(s, p,
diff --git a/packages/Shell/res/values-eu/strings.xml b/packages/Shell/res/values-eu/strings.xml
index 78295e6..9695e41 100644
--- a/packages/Shell/res/values-eu/strings.xml
+++ b/packages/Shell/res/values-eu/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Hautatu hau akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Errore-txostenek sistemaren erregistro-fitxategietako datuak dauzkate eta, haietan, isilpekotzat jotzen duzun informazioa ager daiteke (adibidez, aplikazioen erabilera eta kokapen-datuak). Errore-txostenak partekatzen badituzu, partekatu soilik pertsona eta aplikazio fidagarriekin."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Errore-txostenek sistemaren erregistro-fitxategietako datuak dauzkate eta, haietan, kontuzkotzat jotzen duzun informazioa ager daiteke (adibidez, aplikazioen erabilera eta kokapen-datuak). Errore-txostenak partekatzen badituzu, partekatu soilik pertsona eta aplikazio fidagarriekin."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ez erakutsi berriro"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Ezin izan da irakurri akatsen txostena"</string>
diff --git a/packages/Shell/res/values-ne/strings.xml b/packages/Shell/res/values-ne/strings.xml
index 8079210..eadfeb9 100644
--- a/packages/Shell/res/values-ne/strings.xml
+++ b/packages/Shell/res/values-ne/strings.xml
@@ -23,9 +23,9 @@
     <string name="bugreport_updating_title" msgid="4423539949559634214">"बग रिपोर्टमा विवरणहरू थप्दै"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा गर्नुहोला..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"उक्त बग सम्बन्धी रिपोर्ट चाँडै नै यस फोनमा देखा पर्नेछ"</string>
-    <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"तपाईंको बग रिपोर्ट आदान-प्रदान गर्न चयन गर्नुहोस्"</string>
+    <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"तपाईंको बग रिपोर्ट आदान प्रदान गर्न चयन गर्नुहोस्"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"तपाईंको बग रिपोर्टलाई साझेदारी गर्न ट्याप गर्नुहोस्"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"तपाईंको बग रिपोर्ट स्क्रिनसट बिना आदान-प्रदान गर्नका लागि चयन गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"तपाईंको बग रिपोर्ट स्क्रिनसट बिना आदान प्रदान गर्नका लागि चयन गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"बग रिपोर्टहरूमा प्रणालीका विभिन्न लग फाइलहरूको डेटा हुन्छ जसमा तपाईँले संवेदनशील मानेको डेटा समावेश हुन सक्छ (जस्तै अनुप्रयोगको प्रयोग र स्थान सम्बन्धी डेटा)। तपाईँले विश्वास गर्ने व्यक्ति र अनुप्रयोगहरूसँग मात्र बग रिपोर्टहरूलाई साझेदारी गर्नुहोस्।"</string>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index c52c0aa..61f7fe8 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -108,6 +108,7 @@
         public Supplier<Icon> iconSupplier;
         public int state = Tile.STATE_ACTIVE;
         public CharSequence label;
+        public CharSequence secondaryLabel;
         public CharSequence contentDescription;
         public CharSequence dualLabelContentDescription;
         public boolean disabledByPolicy;
@@ -122,6 +123,7 @@
             final boolean changed = !Objects.equals(other.icon, icon)
                     || !Objects.equals(other.iconSupplier, iconSupplier)
                     || !Objects.equals(other.label, label)
+                    || !Objects.equals(other.secondaryLabel, secondaryLabel)
                     || !Objects.equals(other.contentDescription, contentDescription)
                     || !Objects.equals(other.dualLabelContentDescription,
                             dualLabelContentDescription)
@@ -135,6 +137,7 @@
             other.icon = icon;
             other.iconSupplier = iconSupplier;
             other.label = label;
+            other.secondaryLabel = secondaryLabel;
             other.contentDescription = contentDescription;
             other.dualLabelContentDescription = dualLabelContentDescription;
             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
@@ -156,6 +159,7 @@
             sb.append(",icon=").append(icon);
             sb.append(",iconSupplier=").append(iconSupplier);
             sb.append(",label=").append(label);
+            sb.append(",secondaryLabel=").append(secondaryLabel);
             sb.append(",contentDescription=").append(contentDescription);
             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
             sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 631cc0d..41dd0b3 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -67,7 +67,7 @@
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
                     android:paddingRight="0dp"
-                    android:paddingLeft="24dp"
+                    android:paddingLeft="0dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 947f27d..33f7e75 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -81,7 +81,7 @@
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
                     android:paddingRight="0dp"
-                    android:paddingLeft="24dp"
+                    android:paddingLeft="0dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 6f270b4..4b385fc 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -82,7 +82,7 @@
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
                     android:paddingRight="0dp"
-                    android:paddingLeft="24dp"
+                    android:paddingLeft="0dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
deleted file mode 100644
index 00bcaf6..0000000
--- a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_landscape_from_auto_rotate" >
-    <target
-        android:name="landscape"
-        android:animation="@anim/ic_rotate_to_landscape_landscape_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_rotate_to_landscape_arrows_animation" />
-    <target
-        android:name="arrows_0"
-        android:animation="@anim/ic_rotate_to_landscape_arrows_0_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_rotate_to_landscape_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
deleted file mode 100644
index cde6797..0000000
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?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.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="ic_landscape_to_rotate"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="device"
-        android:translateX="24"
-        android:translateY="24" >
-        <group
-            android:name="device_pivot"
-            android:translateX="-24.15"
-            android:translateY="-24.25" >
-            <group
-                android:name="landscape"
-                android:translateX="24"
-                android:translateY="24" >
-                <path
-                    android:name="device_merged"
-                    android:pathData="M -21.9799957275,-10.0 c 0.0,0.0 -0.0200042724609,20.0 -0.0200042724609,20.0 c 0.0,2.19999694824 1.80000305176,4.0 4.0,4.0 c 0.0,0.0 36.0,0.0 36.0,0.0 c 2.19999694824,0.0 4.0,-1.80000305176 4.0,-4.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,-2.19999694824 -1.80000305176,-4.0 -4.0,-4.0 c 0.0,0.0 -36.0,0.0 -36.0,0.0 c -2.19999694824,0.0 -3.97999572754,1.80000305176 -3.97999572754,4.0 Z M 14.0,10.0 c 0.0,0.0 -28.0,0.0 -28.0,0.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,0.0 28.0,0.0 28.0,0.0 c 0.0,0.0 0.0,20.0 0.0,20.0 Z"
-                    android:fillColor="#FFFFFFFF" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="arrows"
-        android:translateX="24"
-        android:translateY="24"
-        android:rotation="-90" >
-        <group
-            android:name="arrows_pivot"
-            android:translateX="-24.0798"
-            android:translateY="-24.23" >
-            <group
-                android:name="arrows_0"
-                android:translateX="12.2505"
-                android:translateY="37.2145" >
-                <path
-                    android:name="bottom_merged"
-                    android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="0" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
deleted file mode 100644
index 86dc6ce..0000000
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_landscape_to_auto_rotate" >
-    <target
-        android:name="landscape"
-        android:animation="@anim/ic_landscape_to_rotate_landscape_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_landscape_to_rotate_arrows_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_landscape_to_rotate_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
deleted file mode 100644
index b8465f4..0000000
--- a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_portrait_to_auto_rotate" >
-    <target
-        android:name="device_0"
-        android:animation="@anim/ic_portrait_to_rotate_device_0_animation" />
-    <target
-        android:name="device_merged"
-        android:animation="@anim/ic_portrait_to_rotate_device_merged_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_portrait_to_rotate_arrows_animation" />
-    <target
-        android:name="arrows_0"
-        android:animation="@anim/ic_portrait_to_rotate_arrows_0_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_portrait_to_rotate_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
deleted file mode 100644
index 0ef15f0..0000000
--- a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?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.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="ic_rotate_to_portrait"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="device"
-        android:translateX="24"
-        android:translateY="24" >
-        <group
-            android:name="device_pivot"
-            android:translateX="-24.15"
-            android:translateY="-24.25" >
-            <group
-                android:name="device_0"
-                android:translateX="24.14999"
-                android:translateY="24.25"
-                android:rotation="-135" >
-                <path
-                    android:name="device_merged"
-                    android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
-                    android:fillColor="#FFFFFFFF" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="arrows"
-        android:translateX="24"
-        android:translateY="24"
-        android:rotation="-221" >
-        <group
-            android:name="arrows_pivot"
-            android:translateX="-24.0798"
-            android:translateY="-24.23" >
-            <group
-                android:name="arrows_0"
-                android:translateX="12.2505"
-                android:translateY="37.2145"
-                android:scaleX="0.9"
-                android:scaleY="0.9" >
-                <path
-                    android:name="bottom_merged"
-                    android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="0" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
deleted file mode 100644
index 6d3fd37..0000000
--- a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_portrait_from_auto_rotate" >
-    <target
-        android:name="device_0"
-        android:animation="@anim/ic_rotate_to_portrait_device_0_animation" />
-    <target
-        android:name="device_merged"
-        android:animation="@anim/ic_rotate_to_portrait_device_merged_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_rotate_to_portrait_arrows_animation" />
-    <target
-        android:name="arrows_0"
-        android:animation="@anim/ic_rotate_to_portrait_arrows_0_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_rotate_to_portrait_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
similarity index 95%
rename from packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
rename to packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
index bce494c..fba45d1 100644
--- a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.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.
@@ -16,12 +16,10 @@
 -->
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="ic_portrait_to_rotate"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48">
     <group
         android:name="device"
         android:translateX="24"
@@ -61,4 +59,3 @@
         </group>
     </group>
 </vector>
-
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
index 5e7cd974..56223db 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
@@ -18,7 +18,7 @@
         android:height="32dp"
         android:viewportWidth="6.0"
         android:viewportHeight="24.0"
-        android:tint="?android:attr/textColorSecondary">
+        android:tint="?android:attr/colorAccent">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
index 0dca1db..12c1a7a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
@@ -18,7 +18,7 @@
         android:height="32dp"
         android:viewportWidth="6.0"
         android:viewportHeight="24.0"
-        android:tint="?android:attr/textColorSecondary">
+        android:tint="?android:attr/colorAccent">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/>
diff --git a/packages/SystemUI/res/drawable/smart_reply_button_background.xml b/packages/SystemUI/res/drawable/smart_reply_button_background.xml
new file mode 100644
index 0000000..1cd1451
--- /dev/null
+++ b/packages/SystemUI/res/drawable/smart_reply_button_background.xml
@@ -0,0 +1,27 @@
+<?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
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/notification_ripple_untinted_color">
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/smart_reply_button_corner_radius"/>
+            <solid android:color="@color/smart_reply_button_background"/>
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/SystemUI/res/layout/smart_reply_button.xml b/packages/SystemUI/res/layout/smart_reply_button.xml
new file mode 100644
index 0000000..4ac41d5
--- /dev/null
+++ b/packages/SystemUI/res/layout/smart_reply_button.xml
@@ -0,0 +1,32 @@
+<?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
+  -->
+
+<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: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:textColor="@color/smart_reply_button_text"
+        android:textStyle="normal"
+        android:singleLine="true"/>
\ 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
new file mode 100644
index 0000000..6d53386
--- /dev/null
+++ b/packages/SystemUI/res/layout/smart_reply_view.xml
@@ -0,0 +1,27 @@
+<?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
+  -->
+
+<!-- LinearLayout -->
+<com.android.systemui.statusbar.policy.SmartReplyView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/smart_reply_view"
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content"
+    android:layout_gravity="end">
+    <!-- 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/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 7f37087..4614999 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -54,6 +54,18 @@
         android:paddingStart="8dp"
         />
 
+    <ImageButton
+        android:id="@+id/helper"
+        android:layout_width="48dp"
+        android:layout_height="@*android:dimen/notification_header_height"
+        android:layout_gravity="top|end"
+        android:layout_marginEnd="6dp"
+        android:src="@drawable/ic_dnd"
+        android:tint="#FF0000"
+        android:background="@drawable/ripple_drawable"
+        android:visibility="visible"
+        />
+
     <ViewStub
         android:layout="@layout/notification_children_container"
         android:id="@+id/child_container_stub"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index f0d2346..748c9a5 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -17,130 +17,76 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:background="@android:color/transparent"
     android:theme="@style/qs_theme"
     android:clipChildren="false" >
-    <RelativeLayout
+    <LinearLayout
         android:id="@+id/volume_dialog"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingTop="@dimen/volume_row_padding_bottom"
-        android:background="@drawable/rounded_full_bg_bottom"
+        android:layout_gravity="center_vertical|end"
+        android:minWidth="@dimen/volume_dialog_panel_width"
+        android:background="@android:color/transparent"
+        android:layout_margin="12dp"
         android:translationZ="8dp"
+        android:orientation="vertical"
         android:clipChildren="false" >
 
         <LinearLayout
-            android:id="@+id/volume_dialog_content"
-            android:layout_width="match_parent"
+            android:id="@+id/volume_dialog_rows"
+            android:layout_width="@dimen/volume_dialog_panel_width"
             android:layout_height="wrap_content"
-            android:layout_toStartOf="@id/expand"
             android:clipChildren="false"
             android:clipToPadding="false"
+            android:paddingTop="12dp"
+            android:paddingBottom="12dp"
+            android:background="@drawable/rounded_bg_full"
+            android:orientation="horizontal" >
+                <!-- volume rows added and removed here! :-) -->
+        </LinearLayout>
+
+        <LinearLayout
+            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:orientation="vertical" >
 
-            <LinearLayout
-                android:id="@+id/volume_dialog_rows"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical" >
-                <!-- volume rows added and removed here! :-) -->
-            </LinearLayout>
-
-
-        </LinearLayout>
-        <LinearLayout
-            android:id="@+id/expand"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:layout_alignParentEnd="true"
-            android:layout_alignParentTop="true"
-            android:layout_marginEnd="@dimen/volume_expander_margin_end" >
             <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:textAppearance="@style/TextAppearance.Volume.Header" />
+                android:layout_centerVertical="true"
+                android:textColor="?android:attr/colorControlNormal"
+                android:textAppearance="?android:attr/textAppearanceSmall" />
+
             <com.android.keyguard.AlphaOptimizedImageButton
-                xmlns:android="http://schemas.android.com/apk/res/android"
-                xmlns:tools="http://schemas.android.com/tools"
-                android:id="@+id/volume_expand_button"
-                style="@style/VolumeButtons"
-                android:layout_width="@dimen/volume_button_size"
-                android:layout_height="@dimen/volume_button_size"
-                android:clickable="true"
-                android:soundEffectsEnabled="false"
-                android:src="@drawable/ic_volume_expand_animation"
-                android:background="@drawable/ripple_drawable"
-                tools:ignore="RtlHardcoded" />
-        </LinearLayout>
-        <RelativeLayout
-            android:id="@+id/footer"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:clipChildren="false"
-            android:clipToPadding="false"
-            android:layout_below="@id/volume_dialog_content"
-            android:layout_margin="10dp">
-            <!-- special row for ringer mode -->
-            <RelativeLayout
-                android:id="@+id/ringer_mode"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:background="@drawable/rounded_bg_full"
-                android:clipChildren="false"
-                android:clipToPadding="false"
-                android:layout_toStartOf="@id/output_chooser"
-                android:layout_margin="10dp">
-
-                <com.android.keyguard.AlphaOptimizedImageButton
-                    android:id="@+id/ringer_icon"
-                    style="@style/VolumeButtons"
-                    android:background="?android:selectableItemBackgroundBorderless"
-                    android:layout_width="@dimen/volume_button_size"
-                    android:layout_height="@dimen/volume_button_size"
-                    android:layout_alignParentStart="true"
-                    android:layout_centerVertical="true"
-                    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_alignParentStart="true"
-                    android:layout_centerVertical="true"
-                    android:layout_toEndOf="@+id/ringer_icon"
-                    android:layout_marginStart="64dp"
-                    android:textColor="?android:attr/colorControlNormal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:paddingStart="@dimen/volume_row_header_padding_start" />
-
-                <TextView
-                    android:id="@+id/ringer_status"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:ellipsize="end"
-                    android:layout_alignParentEnd="true"
-                    android:layout_centerVertical="true"
-                    android:layout_marginEnd="14dp"
-                    android:maxLines="1"
-                    android:textColor="?android:attr/colorControlNormal"
-                    android:textAppearance="?android:attr/textAppearanceSmall" />
-
-            </RelativeLayout>
-            <com.android.keyguard.AlphaOptimizedImageButton
-                android:id="@+id/output_chooser"
+                android:id="@+id/ringer_icon"
                 style="@style/VolumeButtons"
                 android:background="?android:selectableItemBackgroundBorderless"
                 android:layout_width="@dimen/volume_button_size"
                 android:layout_height="@dimen/volume_button_size"
-                android:layout_alignParentEnd="true"
-                android:layout_centerVertical="true"
-                android:src="@drawable/ic_settings_bluetooth"
+                android:tint="?android:attr/colorAccent"
                 android:soundEffectsEnabled="false" />
-        </RelativeLayout>
-    </RelativeLayout>
+
+            <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="?android:attr/textAppearanceSmall" />
+
+        </LinearLayout>
+    </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 bf76e78..3590b76 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -15,48 +15,70 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/volume_row_height"
-    android:clipChildren="false"
-    android:clipToPadding="false"
+    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" >
 
-    <TextView
-        android:id="@+id/volume_row_header"
+    <LinearLayout
+        android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:ellipsize="end"
-        android:maxLines="1"
-        android:textColor="?android:attr/colorControlNormal"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:paddingStart="@dimen/volume_row_header_padding_start" />
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/volume_row_slider_height"
-            android:orientation="horizontal"
-            android:paddingStart="@dimen/volume_row_padding_start" >
+        android:gravity="center"
+        android:padding="10dp">
+        <TextView
+            android:id="@+id/volume_row_header"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:maxLines="1"
+            android:textColor="?android:attr/colorControlNormal"
+            android:textAppearance="?android:attr/textAppearanceSmall" />
+        <TextView
+            android:id="@+id/volume_row_connected_device"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:maxLines="1"
+            android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
         <com.android.keyguard.AlphaOptimizedImageButton
-                android:id="@+id/volume_row_icon"
-                style="@style/VolumeButtons"
-                android:layout_width="@dimen/volume_button_size"
-                android:layout_height="@dimen/volume_button_size"
-                android:soundEffectsEnabled="false" />
-
-        <SeekBar
-                android:id="@+id/volume_row_slider"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_alignWithParentIfMissing="true"
-                android:focusable="true"
-                android:focusableInTouchMode="true"
-                android:paddingStart="@dimen/volume_row_slider_padding_start"/>
+            android:id="@+id/output_chooser"
+            style="@style/VolumeButtons"
+            android:background="?android:selectableItemBackgroundBorderless"
+            android:layout_width="@dimen/volume_button_size"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:src="@drawable/ic_volume_expand_animation"
+            android:soundEffectsEnabled="false" />
     </LinearLayout>
+    <FrameLayout
+        android:id="@+id/volume_row_slider_frame"
+        android:padding="10dp"
+        android:layout_width="@dimen/volume_dialog_panel_width"
+        android:layout_height="150dp">
+        <SeekBar
+            android:id="@+id/volume_row_slider"
+            android:padding="0dp"
+            android:layout_margin="0dp"
+            android:layout_width="150dp"
+            android:layout_height="@dimen/volume_dialog_panel_width"
+            android:layout_gravity="center"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            android:rotation="270" />
+    </FrameLayout>
 
-    <Space
-        android:id="@+id/spacer"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/volume_row_padding_bottom"/>
+    <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:soundEffectsEnabled="false" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 077131c..e548cae 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"በመካሄድ ላይ ያለ"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ማሳወቂያዎች"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"የባትሪ ኃይል አነስተኛ ነው"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ባትሪ ዝቅተኛ ነው። የባትሪ ቆጣቢን ያብሩ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል፣ በእርስዎ አጠቃቀም ላይ በመመረት <xliff:g id="TIME">%s</xliff:g> ገደማ ይቀራል"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል፣ <xliff:g id="TIME">%s</xliff:g> ገደማ ይቀራል"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ይቀራል። ባትሪ ቆጣቢ በርቷል።"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ኃይል መሙያ አይታገዝም።\n የቀረበውን ኃይል መሙያ ብቻ ተጠቀም።"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"የUSB ኃይል መሙላት አይደገፍም።"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"አሁን ወደዚህ መሣሪያ የገባው ተጠቃሚ የዩኤስቢ እርማትን ማብራት አይችልም። ይህን ባህሪ ለመጠቀም ወደ ዋና ተጠቃሚ ይቀይሩ።"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ማያ ለመሙለት ሳብ"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ቅጽበታዊ ገጽ እይታ"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ቅጽበታዊ ገጽ እይታ እየተቀመጠ ነው::"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"ቅጽበታዊ ገጽ እይታ ተቀርጿል"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት መታ ያድርጉ።"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ቅጽበታዊ ገጽ እይታ መቅረጽ አልተቻለም::"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ቅጽበታዊ ገጽ ዕይታን በማስቀመጥ ጊዜ ችግር አጋጥሟል።"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ባለው የተገደበ የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም።"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"ቅጽበታዊ ገጽ እይታ እየተቀመጠ ነው"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት መታ ያድርጉ"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"ቅጽበታዊ ገጽ እይታን ማንሳት አልተቻለም"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ቅጽበታዊ ገጽ ዕይታን በማስቀመጥ ላይ ሳለ ችግር አጋጥሟል"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ባለው ውሱን የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"እንደ ማህደረ አጫዋች (MTP) ሰካ"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ጠፍቷል"</string>
     <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="2139193533791840539">"እነዚህን ማሳወቂያዎች ከእንግዲህ አያገኟቸውም"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> የማሳወቂያ ምድቦች"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ይህ መተግበሪያ የማሳወቂያ ምድቦች የሉትም"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ከዚህ መተግበሪያ የሚመጡ ማሳወቂያዎች ሊጠፉ አይችሉም"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 ከ<xliff:g id="NUMBER_1">%s</xliff:g> የማሳወቂያ ምድቦች ከዚህ መተግበሪያ</item>
-      <item quantity="other">1 <xliff:g id="NUMBER_1">%s</xliff:g> የማሳወቂያ ምድቦች ከዚህ መተግበሪያ</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>፣ <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>፣ <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> እና <xliff:g id="NUMBER_5">%3$d</xliff:g> ሌሎች</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>፣ <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> እና <xliff:g id="NUMBER_5">%3$d</xliff:g> ሌሎች</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"እነዚህን ማሳወቂያዎችን ከእንግዲህ አይመለከቷቸውም"</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>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"ከዚህ መተግበሪያ ማሳወቂያዎችን ማሳየት ይቀጥል?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"እነዚህ ማሳወቂያዎች ሊጠፉ አይችሉም"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> ማሳወቂያ መቆጣጠሪያዎች ተከፍተዋል"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"የ<xliff:g id="APP_NAME">%1$s</xliff:g> ማሳወቂያ መቆጣጠሪያዎች ተዘግተዋል"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ከዚህ ሰርጥ የመጡ ሁሉንም ማሳወቂያች ፍቀድ"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ሁሉም ምድቦች"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ያብጁ፦ <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"አብጅ"</string>
     <string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
+    <string name="inline_undo" msgid="558916737624706010">"ቀልብስ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"የማሳወቂያ መቆጣጠሪያዎች"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"የማሳወቂያ ማሸለቢያ አማራጮች"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"ዘርጋ"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"አሳንስ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ዝጋ"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ቅንብሮች"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ለማሰናበት ወደ ታች ይጎትቱ"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"ምናሌ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> በስዕል-ላይ-ስዕል ውስጥ ነው"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 9c7de6a..bb0d362 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Baterie je slabá"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Baterie je téměř vybitá, zapněte spořič baterie"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>, při obvyklém využití asi <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>, asi <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g>. Spořič baterie je zapnutý."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Nabíjení pomocí rozhraní USB není podporováno.\nPoužívejte pouze nabíječku, která byla dodána se zařízením."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Nabíjení přes USB není podporováno."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout ladění USB. Chcete-li tuto funkci použít, přepněte na primárního uživatele."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Snímek obrazovky"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Ukládání snímku obrazovky..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Probíhá ukládání snímku obrazovky."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky pořízen"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Klepnutím zobrazíte snímek obrazovky."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Při ukládání snímku obrazovky došlo k problému."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímek obrazovky nelze pořídit kvůli nedostatku místa v úložišti."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Ukládání snímku obrazovky"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Snímek obrazovky byl uložen"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Klepnutím snímek obrazovky zobrazíte"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Snímek obrazovky se nepodařilo zachytit"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Při ukládání snímku obrazovky došlo k problému"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Snímek obrazovky kvůli nedostatku místa v úložišti nelze uložit"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Připojit jako přehrávač médií (MTP)"</string>
@@ -563,30 +567,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Vypnuto"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Rozšířené ovládací prvky oznámení umožňují nastavit úroveň důležitosti oznámení aplikace od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazit na začátku seznamu oznámení \n– Povolit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 4"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 3"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n\n"<b>"Úroveň 2"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat žádný zvukový signál ani nevibrovat \n\n"<b>"Úroveň 1"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat zvukový signál ani nevibrovat \n– Skrýt z obrazovky uzamčení a stavového řádku \n– Zobrazovat na konci seznamu oznámení \n\n"<b>";Úroveň 0"</b>" \n– Blokovat všechna oznámení z aplikace"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Oznámení"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Tato oznámení již nebudete dostávat"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Kategorie oznámení: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Tato aplikace nemá kategorie oznámení"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Oznámení této aplikace nelze vypnout"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="few">1 ze <xliff:g id="NUMBER_1">%s</xliff:g> kategorií oznámení z této aplikace</item>
-      <item quantity="many">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorie oznámení z této aplikace</item>
-      <item quantity="other">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorií oznámení z této aplikace</item>
-      <item quantity="one">1 z <xliff:g id="NUMBER_0">%s</xliff:g> kategorie oznámení z této aplikace</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> a <xliff:g id="NUMBER_5">%3$d</xliff:g> další</item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> a <xliff:g id="NUMBER_5">%3$d</xliff:g> dalšího</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> a <xliff:g id="NUMBER_5">%3$d</xliff:g> dalších</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> a <xliff:g id="NUMBER_2">%3$d</xliff:g> další</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Tato oznámení již nebudete dostávat"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Mají se tato oznámení nadále zobrazovat?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Přestat zobrazovat oznámení"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Nadále zobrazovat"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Mají se oznámení z této aplikace nadále zobrazovat?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Tato oznámení nelze deaktivovat"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Ovládací prvky oznámení aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> byly otevřeny"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Ovládací prvky oznámení aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> byly zavřeny"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Povolit oznámení z tohoto kanálu"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Všechny kategorie"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Přizpůsobit: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Upravit"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Zpět"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"Nastavení oznámení"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Možnosti odložení oznámení"</string>
@@ -745,8 +738,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbalit"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovat"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zavřít"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Nastavení"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nápovědu zavřete přetažením dolů"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Nabídka"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a68ad2a..77a666d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Akku ist schwach"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Noch <xliff:g id="PERCENTAGE">%s</xliff:g>. Der Energiesparmodus ist aktiviert."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-Aufladung wird nicht unterstützt.\nVerwende das mitgelieferte Aufladegerät."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Laden per USB wird nicht unterstützt."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Der momentan auf diesem Gerät angemeldete Nutzer kann das USB-Debugging nicht aktivieren. Um diese Funktion verwenden zu können, wechsle zum primären Nutzer."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Screenshot wird gespeichert..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot wird gespeichert..."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot aufgenommen"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tippe, um deinen Screenshot anzusehen."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot konnte nicht aufgenommen werden."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Beim Speichern des Screenshots ist ein Problem aufgetreten."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
@@ -561,26 +575,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Aus"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Mit den erweiterten Benachrichtigungseinstellungen kannst du für App-Benachrichtigungen eine Wichtigkeitsstufe von 0 bis 5 festlegen. \n\n"<b>"Stufe 5"</b>" \n- Auf der Benachrichtigungsleiste ganz oben anzeigen \n- Vollbildunterbrechung zulassen \n- Immer kurz einblenden \n\n"<b>"Stufe 4"</b>" \n- Keine Vollbildunterbrechung \n- Immer kurz einblenden \n\n"<b>"Stufe 3"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n\n"<b>"Stufe 2"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n\n"<b>"Stufe 1"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n- Auf Sperrbildschirm und Statusleiste verbergen \n- Auf der Benachrichtigungsleiste ganz unten anzeigen \n\n"<b>"Stufe 0"</b>" \n- Alle Benachrichtigungen der App sperren"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Benachrichtigungen"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Du erhältst diese Benachrichtigungen nicht mehr"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> Benachrichtigungskategorien"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Diese App hat keine Benachrichtigungskategorien"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Benachrichtigungen von dieser App können nicht deaktiviert werden"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 von <xliff:g id="NUMBER_1">%s</xliff:g> Benachrichtigungskategorien von dieser App</item>
-      <item quantity="one">1 von <xliff:g id="NUMBER_0">%s</xliff:g> Benachrichtigungskategorie von dieser App</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> und <xliff:g id="NUMBER_5">%3$d</xliff:g> andere</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> und <xliff:g id="NUMBER_2">%3$d</xliff:g> andere</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Benachrichtigungseinstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g> geöffnet"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Benachrichtigungseinstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g> geschlossen"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Benachrichtigungen von diesem Kanal zulassen"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Alle Kategorien"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Anpassen: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"Benachrichtigungseinstellungen"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Optionen für spätere Erinnerung bei Benachrichtigungen"</string>
@@ -735,8 +750,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Maximieren"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimieren"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Schließen"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Einstellungen"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zum Schließen nach unten ziehen"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b1b1626..ab759ed 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Battery is low"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Battery is low. Turn on Battery Saver"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB charging not supported."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Saving screenshot…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot is being saved."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tap to view your screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot is being saved"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot saved"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tap to view your screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Couldn\'t capture screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problem encountered while saving screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Off"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"You won\'t get these notifications anymore"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> notification categories"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item>
-      <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, and <xliff:g id="NUMBER_5">%3$d</xliff:g> others</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, and <xliff:g id="NUMBER_2">%3$d</xliff:g> other</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> closed"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Allow notifications from this channel"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Customise"</string>
     <string name="notification_done" msgid="5279426047273930175">"Done"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Undo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"notification snooze options"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Settings"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 420dd9d..1bd101f 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Battery is low"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Battery is low. Turn on Battery Saver"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB charging not supported."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Saving screenshot…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot is being saved."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tap to view your screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot is being saved"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot saved"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tap to view your screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Couldn\'t capture screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problem encountered while saving screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Off"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"You won\'t get these notifications anymore"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> notification categories"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item>
-      <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, and <xliff:g id="NUMBER_5">%3$d</xliff:g> others</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, and <xliff:g id="NUMBER_2">%3$d</xliff:g> other</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> closed"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Allow notifications from this channel"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Customise"</string>
     <string name="notification_done" msgid="5279426047273930175">"Done"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Undo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"notification snooze options"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Settings"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b1b1626..ab759ed 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Battery is low"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Battery is low. Turn on Battery Saver"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB charging not supported."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Saving screenshot…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot is being saved."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tap to view your screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot is being saved"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot saved"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tap to view your screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Couldn\'t capture screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problem encountered while saving screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Off"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"You won\'t get these notifications anymore"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> notification categories"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item>
-      <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, and <xliff:g id="NUMBER_5">%3$d</xliff:g> others</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, and <xliff:g id="NUMBER_2">%3$d</xliff:g> other</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> closed"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Allow notifications from this channel"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Customise"</string>
     <string name="notification_done" msgid="5279426047273930175">"Done"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Undo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"notification snooze options"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Settings"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b1b1626..ab759ed 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Battery is low"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Battery is low. Turn on Battery Saver"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left based on your usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining, about <xliff:g id="TIME">%s</xliff:g> left"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> remaining. Battery Saver is on."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB charging not supported."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Saving screenshot…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot is being saved."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tap to view your screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot is being saved"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot saved"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tap to view your screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Couldn\'t capture screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problem encountered while saving screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Off"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"You won\'t get these notifications anymore"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> notification categories"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item>
-      <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, and <xliff:g id="NUMBER_5">%3$d</xliff:g> others</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, and <xliff:g id="NUMBER_2">%3$d</xliff:g> other</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> opened"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Notification controls for <xliff:g id="APP_NAME">%1$s</xliff:g> closed"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Allow notifications from this channel"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Customise"</string>
     <string name="notification_done" msgid="5279426047273930175">"Done"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Undo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"notification snooze options"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Settings"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 4cc96c1..ad39146 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎Ongoing‎‏‎‎‏‎"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎Notifications‎‏‎‎‏‎"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎Battery is low‎‏‎‎‏‎"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‎Battery is low. Turn on Battery Saver‎‏‎‎‏‎"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎ left based on your usage‎‏‎‎‏‎"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining, about ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ remaining. Battery Saver is on.‎‏‎‎‏‎"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎USB charging not supported.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Use only the supplied charger.‎‏‎‎‏‎"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎USB charging not supported.‎‏‎‎‏‎"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‎The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user.‎‏‎‎‏‎"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‎Zoom to fill screen‎‏‎‎‏‎"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎Stretch to fill screen‎‏‎‎‏‎"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎Screenshot‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎Saving screenshot…‎‏‎‎‏‎"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎Screenshot is being saved.‎‏‎‎‏‎"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‎Screenshot captured.‎‏‎‎‏‎"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎Tap to view your screenshot.‎‏‎‎‏‎"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎Couldn\'t capture screenshot.‎‏‎‎‏‎"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎Problem encountered while saving screenshot.‎‏‎‎‏‎"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎Can\'t save screenshot due to limited storage space.‎‏‎‎‏‎"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎Screenshot is being saved‎‏‎‎‏‎"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎Screenshot saved‎‏‎‎‏‎"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‏‎Tap to view your screenshot‎‏‎‎‏‎"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎Couldn\'t capture screenshot‎‏‎‎‏‎"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‎‎‎Problem encountered while saving screenshot‎‏‎‎‏‎"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎Can\'t save screenshot due to limited storage space‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎Taking screenshots isn\'t allowed by the app or your organization‎‏‎‎‏‎"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎USB file transfer options‎‏‎‎‏‎"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎Mount as a media player (MTP)‎‏‎‎‏‎"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎Off‎‏‎‎‏‎"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Level 5‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Show at the top of the notification list ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Allow full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Always peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Level 4‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Always peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Level 3‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Level 2‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never make sound and vibration ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Level 1‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Prevent full screen interruption ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never peek ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Never make sound or vibrate ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Hide from lock screen and status bar ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Show at the bottom of the notification list ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎Level 0‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎- Block all notifications from the app‎‏‎‎‏‎"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎Notifications‎‏‎‎‏‎"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‏‎You won\'t get these notifications anymore‎‏‎‎‏‎"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ notification categories‎‏‎‎‏‎"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎This app doesn\'t have notification categories‎‏‎‎‏‎"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎Notifications from this app can\'t be turned off‎‏‎‎‏‎"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎1 out of ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%s</xliff:g>‎‏‎‎‏‏‏‎ notification categories from this app‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎1 out of ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%s</xliff:g>‎‏‎‎‏‏‏‎ notification category from this app‎‏‎‎‏‎</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="NUMBER_5">%3$d</xliff:g>‎‏‎‎‏‏‏‎ others‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ other‎‏‎‎‏‎</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎You won\'t see these notifications anymore‎‏‎‎‏‎"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‎Keep showing these notifications?‎‏‎‎‏‎"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎Stop notifications‎‏‎‎‏‎"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎Keep showing‎‏‎‎‏‎"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎Keep showing notifications from this app?‎‏‎‎‏‎"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎These notifications can\'t be turned off‎‏‎‎‏‎"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎Notification controls for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ opened‎‏‎‎‏‎"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎Notification controls for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ closed‎‏‎‎‏‎"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎Allow notifications from this channel‎‏‎‎‏‎"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎All Categories‎‏‎‎‏‎"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‎More settings‎‏‎‎‏‎"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎Customize: ‎‏‎‎‏‏‎<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎Customize‎‏‎‎‏‎"</string>
     <string name="notification_done" msgid="5279426047273930175">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎Done‎‏‎‎‏‎"</string>
+    <string name="inline_undo" msgid="558916737624706010">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎Undo‎‏‎‎‏‎"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎notification controls‎‏‎‎‏‎"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎notification snooze options‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 85d3c6e..1e5274e 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Abian"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Jakinarazpenak"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateria agortzen ari da"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da. Bateria-aurrezlea aktibatuta dago."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Ez da USB bidez kargatzea onartzen.\nErabili hornitu zaizun kargagailua soilik."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ez da USB bidez kargatzea onartzen."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Gailu honetan saioa hasita duen erabiltzaileak ezin du aktibatu USB arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Handiagotu pantaila betetzeko"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Luzatu pantaila betetzeko"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Pantaila-argazkia gordetzen…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Pantaila-argazkia gordetzen ari da."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Pantaila-argazkia atera da."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Sakatu pantaila-argazkia ikusteko."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Ezin izan da pantaila-argazkia atera."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Arazo bat izan da pantaila-argazkia gordetzean."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ezin da atera pantaila-argazkia ez delako tokirik geratzen."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Muntatu multimedia-erreproduzigailu gisa (MTP)"</string>
@@ -559,26 +573,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desaktibatuta"</string>
     <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="2139193533791840539">"Aurrerantzean ez duzu jasoko horrelako jakinarazpenik"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Jakinarazpenen <xliff:g id="NUMBER">%d</xliff:g> kategoria"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Aplikazio honek ez du jakinarazpen-kategoriarik"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Ezin dira desaktibatu aplikazio honen jakinarazpenak"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Aplikazio honen 1/<xliff:g id="NUMBER_1">%s</xliff:g> jakinarazpen-kategoria</item>
-      <item quantity="one">Aplikazio honen 1/<xliff:g id="NUMBER_0">%s</xliff:g> jakinarazpen-kategoria</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> eta beste <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> eta beste <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Ireki dira <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak kontrolatzeko aukerak"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Itxi dira <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak kontrolatzeko aukerak"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Onartu kanal honen jakinarazpenak"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Kategoria guztiak"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Pertsonalizatu: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"jakinarazpena kontrolatzeko aukerak"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"jakinarazpena atzeratzeko aukerak"</string>
@@ -733,8 +748,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Zabaldu"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizatu"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Itxi"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Ezarpenak"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Baztertzeko, arrastatu behera"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menua"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -763,7 +777,7 @@
     <string name="tuner_right" msgid="6222734772467850156">"Eskuinera"</string>
     <string name="tuner_menu" msgid="191640047241552081">"Menua"</string>
     <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> aplikazioa"</string>
-    <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertak"</string>
     <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pantaila-argazkiak"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mezu orokorrak"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1ddc394..16a4eac 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Pile faible"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"La pile est faible. Activez le mode Économie d\'énergie."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Il reste <xliff:g id="PERCENTAGE">%s</xliff:g>, environ <xliff:g id="TIME">%s</xliff:g> en fonction de votre usage"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Il reste <xliff:g id="PERCENTAGE">%s</xliff:g>, environ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants. La fonction Économie d\'énergie est activée."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Chargement USB non compatible.\nVous devez utiliser le chargeur fourni."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Le chargement par USB n\'est pas pris en charge."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'utilisateur actuellement connecté sur cet appareil ne peut pas activer le débogage USB. Pour utiliser cette fonctionnalité, l\'utilisateur principal doit se connecter."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Capture d\'écran"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Enregistrement capture écran…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Enregistrement de la capture d\'écran en cours…"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Touchez pour afficher votre capture d\'écran."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Une erreur s\'est produite lors de l\'enregistrement de la saisie d\'écran."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la saisie d\'écran, car l\'espace de stockage est limité."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Enregistrement de la capture d\'écran en cours…"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Capture d\'écran enregistrée"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Touchez pour afficher votre capture d\'écran"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Impossible de réaliser une capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Une erreur s\'est produite lors de l\'enregistrement de la capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer comme un lecteur multimédia (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Désactivé"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Avec les réglages avancés des notifications, vous pouvez définir un degré d\'importance de 0 à 5 pour les notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher dans le haut de la liste des notifications \n- Autoriser les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 4"</b>" \n- Empêcher les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 3"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n\n"<b>"Niveau 2"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n\n"<b>"Niveau 1"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n- Masquer de l\'écran de verrouillage et de la barre d\'état status bar \n- Afficher dans le bas de la liste des notifications \n\n"<b>"Level 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Vous ne recevrez plus ces notifications"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> catégories de notification"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Cette application n\'a pas de catégories de notification"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Les notifications de cette application ne peuvent pas être désactivées"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item>
-      <item quantity="other">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> et <xliff:g id="NUMBER_5">%3$d</xliff:g> autre</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> et <xliff:g id="NUMBER_5">%3$d</xliff:g> autres</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Vous ne verrez plus ces notifications"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Continuer à afficher ces notifications?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Arrêter les notifications"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuez à afficher"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuer à afficher les notifications de cette application?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ces notifications ne peuvent pas être désactivées"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Les paramètres des notifications pour <xliff:g id="APP_NAME">%1$s</xliff:g> sont ouverts"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Les paramètres des notifications pour <xliff:g id="APP_NAME">%1$s</xliff:g> sont fermés"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Autoriser les notifications de cette chaîne"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Toutes les catégories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personnaliser : <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personnaliser"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Annuler"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"paramètres des notifications"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"options de répétition des notifications"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Paramètres"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode d\'incrustation d\'image"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f6e98a3..cc8bcba 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batterie faible"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batterie faible : activez l\'économiseur de batterie"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> – Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> – Temps restant : environ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restants. L\'économiseur de batterie est activé."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Chargement USB non disponible.\nVous devez utiliser le chargeur fourni."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Chargeur USB non compatible."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'utilisateur actuellement connecté sur cet appareil ne peut pas activer le débogage USB. Pour utiliser cette fonctionnalité, l\'utilisateur principal doit se connecter."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Capture d\'écran"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Enregistrement de la capture d\'écran…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Enregistrement de la capture d\'écran en cours…"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Appuyez pour afficher votre capture d\'écran."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Erreur lors de l\'enregistrement de la capture d\'écran."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Enregistrement de la capture d\'écran…"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Capture d\'écran enregistrée"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Appuyez pour afficher votre capture d\'écran"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Impossible d\'effectuer une capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Erreur lors de l\'enregistrement de la capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer en tant que lecteur multimédia (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Désactivé"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Grâce aux commandes de gestion des notifications, vous pouvez définir le niveau d\'importance (compris entre 0 et 5) des notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher en haut de la liste des notifications \n- Autoriser l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 4"</b>" \n- Empêcher l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 3"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n\n"<b>"Niveau 2"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n\n"<b>"Niveau 1"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n- Masquer les notifications dans l\'écran de verrouillage et la barre d\'état \n- Afficher au bas de la liste des notifications \n\n"<b>"Niveau 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Vous ne recevrez plus ces notifications"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> catégories de notification"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Cette application n\'a pas de catégories de notification"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Impossible de désactiver les notifications de cette application"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item>
-      <item quantity="other">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> et <xliff:g id="NUMBER_5">%3$d</xliff:g> autre</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> et <xliff:g id="NUMBER_5">%3$d</xliff:g> autres</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Vous ne recevrez plus ces notifications"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Continuer d\'afficher ces notifications ?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Arrêter les notifications"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuer d\'afficher les notifications"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuer d\'afficher les notifications de cette application ?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ces notifications ne peuvent pas être désactivées"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Les commandes de notification sont disponibles pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Les commandes de notification sont indisponibles pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Autoriser les notifications pour cette chaîne"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Toutes les catégories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personnaliser : <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personnaliser"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Annuler"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> : <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"paramètres des notifications"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"options de répétition des notifications"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Paramètres"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index c024531..22966a7 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ચાલુ"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"નોટિફિકેશનો"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"બૅટરી ઓછી છે"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી. બૅટરી સેવર ચાલુ છે."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ચાર્જિંગ સમર્થિત નથી.\nફક્ત આપવામાં આવેલ ચાર્જરનો ઉપયોગ કરો."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB ચાર્જિંગ સમર્થિત નથી."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"હાલમાં આ ઉપકરણમાં સાઇન ઇન થયેલ વપરાશકર્તા USB ડિબગીંગ ચાલુ કરી શકતા નથી. આ સુવિધાનો ઉપયોગ કરવા માટે પ્રાથમિક વપરાશકર્તા પર સ્વિચ કરો."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"સ્ક્રીનશોટ સાચવવામાં આવી રહ્યો છે."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"સ્ક્રીનશોટ કેપ્ચર કર્યો."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"તમારા સ્ક્રીનશૉટને જોવા માટે ટૅપ કરો."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"સ્ક્રીનશોટ કેપ્ચર કરી શકાયો નથી."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"સ્ક્રીનશૉટ સાચવવામાં સમસ્યા આવી."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ સાચવી શકાતો નથી."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"મીડિયા પ્લેયર તરીકે માઉન્ટ કરો (MTP)"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"બંધ"</string>
     <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="2139193533791840539">"તમને હવે આ સૂચનાઓ મળશે નહીં"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> સૂચના કૅટેગરીઓ"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"આ ઍપ્લિકેશનમાં સૂચના કૅટેગરી નથી"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"આ ઍપ્લિકેશનની સૂચનાઓ બંધ કરી શકાતી નથી"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">આ ઍપ્લિકેશનમાંની <xliff:g id="NUMBER_1">%s</xliff:g> સૂચના કૅટેગરીમાંથી 1</item>
-      <item quantity="other">આ ઍપ્લિકેશનમાંની <xliff:g id="NUMBER_1">%s</xliff:g> સૂચના કૅટેગરીમાંથી 1</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> અને અન્ય <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> અને અન્ય <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સૂચના નિયંત્રણો ચાલુ છે"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સૂચના નિયંત્રણો બંધ છે"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"આ ચૅનલની સૂચનાઓને મંજૂરી આપો"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"બધી કૅટેગરી"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"કસ્ટમાઇઝ કરો: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"સૂચના નિયંત્રણો"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"વિસ્તૃત કરો"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"નાનું કરો"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"બંધ કરો"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"સેટિંગ"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"છોડી દેવા માટે નીચે ખેંચો"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"મેનૂ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ચિત્રમાં-ચિત્રની અંદર છે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f5f8c7c..27ed38c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"बैटरी कम है"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शेष"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> बैटरी बची है. बैटरी सेवर चालू है."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नहीं है.\nकेवल आपूर्ति किए गए चार्जर का उपयोग करें."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नहीं है."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"अभी इस डिवाइस में जिस उपयोगकर्ता ने साइन इन किया है, वो USB डीबगिंग चालू नहीं कर सकता. इस सुविधा का इस्तेमाल करने के लिए, प्राथमिक उपयोगकर्ता में बदलें."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने के लिए ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन भरने के लिए खींचें"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"स्क्रीनशॉट सहेजा जा रहा है."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"स्‍क्रीनशॉट कैप्‍चर किया गया."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"अपना स्क्रीनशॉट देखने के लिए टैप करें."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट को कैप्चर नहीं किया जा सका."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रीनशॉट सहेजने में समस्या आई"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"मेमोरी में जगह कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सकता."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेयर के रूप में माउंट करें (MTP)"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"बंद"</string>
     <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="2139193533791840539">"अब आपको ये सूचनाएं नहीं मिलेंगी"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"सूचना की <xliff:g id="NUMBER">%d</xliff:g> श्रेणियां"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"इस ऐप्लिकेशन में सूचना श्रेणियां नहीं हैं"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"इस ऐप की सूचनाएं बंद नहीं की जा सकती"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">इस ऐप की <xliff:g id="NUMBER_1">%s</xliff:g> सूचना श्रेणियों में से 1 श्रेणी</item>
-      <item quantity="other">इस ऐप की <xliff:g id="NUMBER_1">%s</xliff:g> सूचना श्रेणियों में से 1 श्रेणी</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> और <xliff:g id="NUMBER_5">%3$d</xliff:g> अन्य</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> और <xliff:g id="NUMBER_5">%3$d</xliff:g> अन्य</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण चालू हैं"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण बंद हैं"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"इस चैनल से सूचना की पाने की मंज़ूरी दें"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"सभी श्रेणियां"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"अपनी पसंद के मुताबिक बनाएं: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रण"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना को स्नूज़ (थोड़ी देर के लिए चुप करना) करने के विकल्प"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तार करें"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"छोटा करें"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"बंद करें"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"सेटिंग"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारिज करने के लिए नीचे खींचें और छोड़ें"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"मेन्यू"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> पिक्चर में पिक्चर के अंदर है"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 66ebb86..6d08308 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Berkelanjutan"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifikasi"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Baterai lemah"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Baterai hampir habis. Aktifkan Penghemat Baterai"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Sisa <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Sisa <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>. Penghemat Baterai aktif."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Pengisian daya USB tidak didukung.\nGunakan hanya pengisi daya yang disediakan."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Pengisian daya USB tidak didukung."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Pengguna yang sedang login ke perangkat ini tidak dapat mengaktifkan proses debug USB. Beralihlah ke pengguna utama untuk menggunakan fitur ini."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Menyimpan screenshot..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Menyimpan screenshot..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot sedang disimpan."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot diambil."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Ketuk untuk melihat screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat mengambil screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Terjadi masalah saat menyimpan screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot sedang disimpan"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot disimpan"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tap untuk melihat screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Tidak dapat mengambil screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Terjadi masalah saat menyimpan screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Nonaktif"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Dengan kontrol notifikasi daya, Anda dapt menyetel level kepentingan notifikasi aplikasi dari 0 sampai 5. \n\n"<b>"Level 5"</b>" \n- Muncul di atas daftar notifikasi \n- Izinkan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 4"</b>" \n- Jangan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 3"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n\n"<b>"Level 2"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara dan getaran \n\n"<b>"Level 1"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara atau getaran \n- Sembunyikan dari layar kunci dan bilah status \n- Muncul di bawah daftar notifikasi \n\n"<b>"Level 0"</b>" \n- Blokir semua notifikasi dari aplikasi"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifikasi"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Anda tidak akan mendapatkan notifikasi ini lagi"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> kategori notifikasi"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Aplikasi ini tidak memiliki kategori notifikasi"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifikasi dari aplikasi ini tidak dapat dinonaktifkan"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 dari <xliff:g id="NUMBER_1">%s</xliff:g> kategori notifikasi dari aplikasi ini</item>
-      <item quantity="one">1 dari <xliff:g id="NUMBER_0">%s</xliff:g> kategori notifikasi dari aplikasi ini</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, dan <xliff:g id="NUMBER_5">%3$d</xliff:g> lainnya</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, dan <xliff:g id="NUMBER_2">%3$d</xliff:g> lainnya</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Anda tidak akan melihat notifikasi ini lagi"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Terus tampilkan notifikasi ini?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Hentikan notifikasi"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Terus tampilkan"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Terus tampilkan notifikasi dari aplikasi ini?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Notifikasi ini tidak dapat dinonaktifkan"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Kontrol notifikasi untuk <xliff:g id="APP_NAME">%1$s</xliff:g> dibuka"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Kontrol notifikasi untuk <xliff:g id="APP_NAME">%1$s</xliff:g> ditutup"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Izinkan notifikasi dari saluran ini"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Semua Kategori"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Sesuaikan: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Sesuaikan"</string>
     <string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Urungkan"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrol notifikasi"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opsi tunda notifikasi"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Luaskan"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Setelan"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk menutup"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index fec534d..642a8dc 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batteria quasi scarica"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batteria quasi scarica. Attiva Risparmio energetico"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%s</xliff:g> circa"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Tempo rimanente: <xliff:g id="TIME">%s</xliff:g> circa"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> rimanente. Risparmio energetico attivo."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Ricarica tramite USB non supportata.\nUtilizza solo il caricatore in dotazione."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ricarica tramite USB non supportata."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'utente che ha eseguito l\'accesso a questo dispositivo non può attivare il debug USB. Per utilizzare questa funzione, passa all\'utente principale."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Salvataggio screenshot..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Salvataggio screenshot..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot in corso di salvataggio."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot acquisito."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tocca per visualizzare lo screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Impossibile acquisire lo screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Si è verificato un problema durante il salvataggio dello screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Salvataggio screenshot…"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot salvato"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tocca per visualizzare lo screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Impossibile acquisire lo screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Si è verificato un problema durante il salvataggio dello screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Monta come lettore multimediale (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Off"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n"<b>"Livello 5"</b>" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 4"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 3"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n"<b>"Livello 2"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n"<b>"Livello 1"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n"<b>"Livello 0"</b>" \n- Blocca tutte le notifiche dell\'app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifiche"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Non riceverai più queste notifiche"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorie di notifica"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Questa app non ha categorie di notifica"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Le notifiche di quest\'app non possono essere disattivate"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 categoria di notifica su <xliff:g id="NUMBER_1">%s</xliff:g> di questa app</item>
-      <item quantity="one">1 categoria di notifica su <xliff:g id="NUMBER_0">%s</xliff:g> di questa app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e altri <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> e <xliff:g id="NUMBER_2">%3$d</xliff:g> altro</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Non vedrai più queste notifiche"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Continuare a ricevere queste notifiche?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Interrompi la ricezione di notifiche"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continua a mostrare"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuare a ricevere notifiche da questa app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Queste notifiche non possono essere disattivate"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controlli di gestione delle notifiche per <xliff:g id="APP_NAME">%1$s</xliff:g> aperti"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Controlli di gestione delle notifiche per <xliff:g id="APP_NAME">%1$s</xliff:g> chiusi"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Consenti le notifiche di questo canale"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Tutte le categorie"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizza: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizza"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fine"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Annulla"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"gestione delle notifiche"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opzioni di posticipazione notifiche"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1cff43b..983c014 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"電池残量が少なくなっています"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"電池残量が少なくなっています。バッテリー セーバーを ON にしてください"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"残量が<xliff:g id="PERCENTAGE">%s</xliff:g>です"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"残量 <xliff:g id="PERCENTAGE">%s</xliff:g>、約 <xliff:g id="TIME">%s</xliff:g>(使用状況に基づく)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"残量 <xliff:g id="PERCENTAGE">%s</xliff:g>、約 <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"残量が <xliff:g id="PERCENTAGE">%s</xliff:g> です。バッテリー セーバーは ON です。"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB充電には対応していません。\n付属の充電器をお使いください。"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB充電には対応していません。"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"この端末に現在ログインしているユーザーでは、USB デバッグを ON にすることはできません。この機能を使用するには、メインユーザーに切り替えてください。"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"スクリーンショット"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"スクリーンショットを保存中..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"スクリーンショットを保存しています..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"スクリーンショットを保存しています。"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットを取得しました。"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"タップするとスクリーンショットが表示されます。"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"スクリーンショットをキャプチャできませんでした。"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"スクリーンショットの保存中に問題が発生しました。"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"空き容量が足りないため、スクリーンショットを保存できません。"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"スクリーンショットを保存しています"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"スクリーンショットを保存しました"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"タップするとスクリーンショットが表示されます"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"スクリーンショットを撮影できませんでした"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"スクリーンショットの保存中に問題が発生しました"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"空き容量が足りないため、スクリーンショットを保存できません"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"スクリーンショットの作成はアプリまたは組織で許可されていません"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"メディアプレーヤー(MTP)としてマウント"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"OFF"</string>
     <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="2139193533791840539">"今後、この通知は配信されません"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> 個の通知カテゴリ"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"このアプリでは通知カテゴリが設定されていません"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"このアプリの通知を OFF にすることはできません"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">このアプリの通知カテゴリ <xliff:g id="NUMBER_1">%s</xliff:g> 件中 1 件</item>
-      <item quantity="one">このアプリの通知カテゴリ <xliff:g id="NUMBER_0">%s</xliff:g> 件中 1 件</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>、他 <xliff:g id="NUMBER_5">%3$d</xliff:g> 件</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>、他 <xliff:g id="NUMBER_2">%3$d</xliff:g> 件</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"今後、この通知は表示されません"</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>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"このアプリからの通知を今後も表示しますか?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"この通知を OFF にすることはできません"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> の通知管理は開いています"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> の通知管理は閉じています"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"このチャンネルからの通知を許可する"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"すべてのカテゴリ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"カスタマイズ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"カスタマイズ"</string>
     <string name="notification_done" msgid="5279426047273930175">"完了"</string>
+    <string name="inline_undo" msgid="558916737624706010">"元に戻す"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"通知管理"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"通知スヌーズ設定"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"閉じる"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"設定"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"下にドラッグして閉じる"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"メニュー"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index b492fd4..3ce5e76 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ಬ್ಯಾಟರಿ ಕಡಿಮೆ ಇದೆ"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ. ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆನ್‌ ಆಗಿದೆ."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ಚಾರ್ಜಿಂಗ್ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.\nಒದಗಿಸಿರುವ ಚಾರ್ಜರ್ ಮಾತ್ರ ಬಳಸಿ."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB ಚಾರ್ಜಿಂಗ್ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ಬಳಕೆದಾರರು ಪ್ರಸ್ತುತ ಈ ಸಾಧನಕ್ಕೆ ಸೈನ್ ಇನ್ ಮಾಡಿದ್ದಾರೆ USB ಡೀಬಗ್ ಮಾಡುವುದನ್ನು ಆನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು, ಪ್ರಾಥಮಿಕ ಬಳಕೆದಾರರಿಗೆ ಬದಲಾಯಿಸಿ."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ಮೀಡಿಯಾ ಪ್ಲೇಯರ್ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (MTP)"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ಆಫ್"</string>
     <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="2139193533791840539">"ನೀವು ಇನ್ನು ಮುಂದೆ ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಪಡೆಯುವುದಿಲ್ಲ"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳು"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆ ವರ್ಗಗಳನ್ನು ಹೊಂದಿಲ್ಲ"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ <xliff:g id="NUMBER_1">%s</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳಲ್ಲಿ 1 ವರ್ಗ</item>
-      <item quantity="other">ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ <xliff:g id="NUMBER_1">%s</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳಲ್ಲಿ 1 ವರ್ಗ</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, ಮತ್ತು ಇತರ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, ಮತ್ತು ಇತರ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆರೆಯಲಾಗಿದೆ"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ಈ ಚಾನಲ್‌ನ ಅಧಿಸೂಚನೆಗಳಿಗೆ ಅನುಮತಿ ನೀಡಿ"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ಎಲ್ಲ ವರ್ಗಗಳು"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ಕಸ್ಟಮೈಸ್: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"ವಿಸ್ತೃತಗೊಳಿಸು"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ಕುಗ್ಗಿಸಿ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ಮುಚ್ಚಿ"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ವಜಾಗೊಳಿಸಲು ಕೆಳಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"ಮೆನು"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಲ್ಲಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 5530fc9..a613b23 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Vykstantys"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pranešimai"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Akumuliatorius senka"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Akumuliatorius senka. Įjunkite Akumuliatoriaus tausojimo priemonę"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Liko: <xliff:g id="PERCENTAGE">%s</xliff:g> (atsižvelgiant į naudojimą liko maždaug <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Liko: <xliff:g id="PERCENTAGE">%s</xliff:g> (liko maždaug <xliff:g id="TIME">%s</xliff:g>)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Liko <xliff:g id="PERCENTAGE">%s</xliff:g>. Akumuliatoriaus tausojimo priemonė įjungta."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB krovimas nepalaikomas.\nNaudokite tik pateiktą įkroviklį."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB įkrovimas nepalaikomas."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Šiuo metu prie įrenginio prisijungęs naudotojas negali įjungti USB derinimo. Kad galėtumėte naudoti šią funkciją, perjunkite į pagrindinį naudotoją."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Ekrano kopija"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Išsaugoma ekrano kopija..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Išsaugoma ekrano kopija."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrano kopija užfiksuota."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Palieskite, kad peržiūrėtumėte ekrano kopiją."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Išsaugant ekrano kopiją iškilo problemų."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Ekrano kopija išsaugoma"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Ekrano kopija išsaugota"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Palieskite, kad peržiūrėtumėte ekrano kopiją"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Nepavyko užfiksuoti ekrano kopijos"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Išsaugant ekrano kopiją kilo problema"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvę (MTP)"</string>
@@ -561,30 +565,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Išjungta"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Naudodami pranešimų valdiklius galite nustatyti programos pranešimų svarbos lygį nuo 0 iki 5. \n\n"<b>"5 lygis"</b>" \n– Rodyti pranešimų sąrašo viršuje \n– Leisti pertraukti, kai veikia viso ekrano režimas \n– Visada rodyti pranešimus \n\n"<b>"4 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Visada rodyti pranešimus \n\n"<b>"3 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n\n"<b>"2 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n\n"<b>"1 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n– Slėpti užrakinimo ekrane ir būsenos juostoje \n– Rodyti pranešimų sąrašo apačioje \n\n"<b>"0 lygis"</b>" \n– Blokuoti visus programos pranešimus"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Pranešimai"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Nebegausite šių pranešimų"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Pranešimų kategorijų: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Šioje programoje nėra pranešimų kategorijų"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Šios programos pranešimų negalima išjungti"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijos</item>
-      <item quantity="few">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijų</item>
-      <item quantity="many">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijos</item>
-      <item quantity="other">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijų</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"„<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>“"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one">„<xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>“ ir dar <xliff:g id="NUMBER_5">%3$d</xliff:g> kanalas</item>
-      <item quantity="few">„<xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>“ ir dar <xliff:g id="NUMBER_5">%3$d</xliff:g> kanalai</item>
-      <item quantity="many">„<xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>“ ir dar <xliff:g id="NUMBER_5">%3$d</xliff:g> kanalo</item>
-      <item quantity="other">„<xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>“ ir dar <xliff:g id="NUMBER_5">%3$d</xliff:g> kanalų</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Nebematysite šių pranešimų"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Toliau rodyti šiuos pranešimus?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Sustabdyti pranešimus"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Toliau rodyti"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Toliau rodyti iš šios programos gautus pranešimus?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Šių pranešimų negalima išjungti"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ pranešimų valdikliai atidaryti"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ pranešimų valdikliai uždaryti"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Leisti pranešimus iš šio kanalo"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Visos kategorijos"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Tinkinti: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Tinkinti"</string>
     <string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Anuliuoti"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"pranešimų valdikliai"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"pranešimų snaudimo parinktys"</string>
@@ -743,8 +736,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Išskleisti"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Sumažinti"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Uždaryti"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Nustatymai"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nuvilkite žemyn, kad atsisakytumėte"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Meniu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> rodom. vaizdo vaizde"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index aba4260..f3fa9e9 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"നടന്നുകൊണ്ടിരിക്കുന്നവ"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"അറിയിപ്പുകൾ"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ബാറ്ററി കുറവാണ്"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു. ബാറ്ററി ലാഭിക്കൽ ഓണാണ്."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണയ്ക്കുന്നില്ല.\nഅതിന്റെ അനുബന്ധ ചാർജ്ജർ മാത്രം ഉപയോഗിക്കുക."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണച്ചില്ല."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ഉപകരണത്തിൽ ഇപ്പോൾ സൈൻ ഇൻ ചെയ്‌തിരിക്കുന്ന ഉപയോക്താവിന് USB ഡീബഗ്ഗിംഗ് ഓണാക്കാനാകില്ല. ഈ ഫീച്ചർ ഉപയോഗിക്കാൻ പ്രാഥമിക ഉപയോക്താവിലേക്ക് മാറുക."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"സ്‌ക്രീൻഷോട്ട് എടുത്തു."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"നിങ്ങളുടെ സ്ക്രീൻഷോട്ട് കാണുന്നതിന് ടാപ്പുചെയ്യുക."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്ന സമയത്ത് പ്രശ്നം നേരിട്ടു."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്‌ഷനുകൾ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ഒരു മീഡിയ പ്ലേയറായി (MTP) മൗണ്ടുചെയ്യുക"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ഓഫ്"</string>
     <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="2139193533791840539">"നിങ്ങൾക്ക് ഇനി ഈ അറിയിപ്പുകൾ ലഭിക്കില്ല"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> അറിയിപ്പ് വിഭാഗങ്ങൾ"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ഈ ആപ്പിന് അറിയിപ്പ് വിഭാഗങ്ങളില്ല"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ ഓഫാക്കാൻ കഴിയില്ല"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">ഈ ആപ്പിൽ നിന്ന് 1 / <xliff:g id="NUMBER_1">%s</xliff:g> അറിയിപ്പ് വിഭാഗങ്ങൾ</item>
-      <item quantity="one">ഈ ആപ്പിൽ നിന്ന് 1 / <xliff:g id="NUMBER_0">%s</xliff:g> അറിയിപ്പ് വിഭാഗം</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> എന്നിവയും മറ്റ് <xliff:g id="NUMBER_5">%3$d</xliff:g> എണ്ണവും</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> എന്നിവയും മറ്റ് <xliff:g id="NUMBER_2">%3$d</xliff:g> എണ്ണവും</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിന്റെ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ തുറന്നു"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിന്റെ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ അടച്ചു"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ഈ ചാനലിൽ നിന്നുള്ള അറിയിപ്പുകൾ അനുവദിക്കുക"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"എല്ലാ വിഭാഗങ്ങളും"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ഇഷ്ടാനുസൃതമാക്കുക: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"അറിയിപ്പ് സ്‌നൂസ് ഓപ്ഷനുകൾ"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"വികസിപ്പിക്കുക"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ചെറുതാക്കുക‍"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"അവസാനിപ്പിക്കുക"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ക്രമീകരണം"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"തള്ളിക്കളയാൻ താഴേക്ക് വലിച്ചിടുക"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"മെനു"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിലാണ്"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index aaf907e..803366f 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"सुरु असलेले"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचना"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"बॅटरी कमी आहे"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक. बॅटरी सेव्‍हर चालू आहे."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नाही.\nफक्त पुरवठा केलेले चार्जर वापरा."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नाही."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"सध्‍या या डीव्हाइसमध्‍ये साइन इन केलेला वापरकर्ता USB डीबग करणे चालू करू शकत नाही. हे वैशिष्‍ट्य वापरण्‍यासाठी, प्राथमिक वापरकर्त्‍यावर स्विच करा."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रीन भरण्यासाठी झूम करा"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रीन भरण्यासाठी ताणा"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रीनशॉट जतन करत आहे…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रीनशॉट जतन करत आहे…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"स्क्रीनशॉट जतन केला जात आहे."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कॅप्चर केला."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"आपला स्क्रीनशॉट पाहण्यासाठी टॅप करा."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट कॅप्चर करू शकलो नाही."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रीनशॉट जतन करताना समस्या आली."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"मर्यादित संचय जागेमुळे स्क्रीनशॉट जतन करू शकत नाही."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"अ‍ॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"बंद"</string>
     <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="2139193533791840539">"तुम्हाला यापुढे या सूचना प्राप्त होणार नाहीत"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> सूचना श्रेण्या"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"या अ‍ॅपला सूचना श्रेण्या नाहीत"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"या अ‍ॅपकडून येणार्‍या सूचना बंद ठेवता येणार नाहीत"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">या अॅपकडील <xliff:g id="NUMBER_1">%s</xliff:g> पैकी 1 सूचना श्रेणी</item>
-      <item quantity="other">या अॅपकडील <xliff:g id="NUMBER_1">%s</xliff:g> पैकी 1 सूचना श्रेणी</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, आणि <xliff:g id="NUMBER_5">%3$d</xliff:g> इतर</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, आणि <xliff:g id="NUMBER_5">%3$d</xliff:g> इतर</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सूचना नियंत्रणे खुली आहेत"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सूचना नियंत्रणे बंद आहेत"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"या चॅनेलकडील सूचनांना मान्यता द्या"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"सर्व श्रेण्या"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"सानुकूल करा: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रणे"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नूझ पर्याय"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करा"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"लहान करा"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"बंद करा"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"सेटिंग्ज"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"डिसमिस करण्यासाठी खाली ड्रॅग करा"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"मेनू"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> चित्रामध्ये चित्र मध्ये आहे"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index faca352..ac6adb8 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"လက်ရှိအသုံးပြုမှု"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"အကြောင်းကြားချက်များ။"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ဘက်ထရီ အားနည်းနေ"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ဘက်ထရီ အားနည်းနေပါပြီ။ ဘက်ထရီအားထိန်းကို ဖွင့်ပါ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ရှိနေ"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သည်၊ သင့်အသုံးပြုမှုအရ <xliff:g id="TIME">%s</xliff:g> ခန့် ကျန်ပါသည်"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သည်၊ <xliff:g id="TIME">%s</xliff:g> ခန့် ကျန်ပါသည်"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်ပါတယ်။ ဘက်ထရီ အားထိန်းကို ဖွင့်ထားသည်။"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"လက်ရှိUSBအားသွင်းခြင်း အသုံးမပြုနိုင်ပါ \n ပေးထားသောအားသွင်းကိရိယာကိုသာ အသုံးပြုပါ"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB အားသွင်းမှု မပံ့ပိုးပါ။"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ဤစက်ပစ္စည်းသို့ လက်ရှိဝင်ရောက်ထားသည့် အသုံးပြုသူသည် USB အမှားပြင်ဆင်ခြင်းကို ဖွင့်၍မရပါ။ ဤဝန်ဆောင်မှုကို အသုံးပြုရန် အဓိကအသုံးပြုသူအဖြစ်သို့ ပြောင်းပါ။"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပြီးပါပြီ"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ဖမ်းယူပြီး"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"မျက်နှာပြင်ပုံဖမ်းယူခြင်းကို ကြည့်ရှုရန် တို့ပါ"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား မဖမ်းစီးနိုင်ပါ"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ဖန်သားပြင်ဓာတ်ပုံဖမ်းယူမှုကို သိမ်းဆည်းရာတွင် ပြဿနာကြုံခဲ့သည်။"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ။"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"ဖန်သားပြင်ဓါတ်ပုံကို သိမ်းနေသည်"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"ဖန်သားပြင်ဓာတ်ပုံကို ကြည့်ရန် တို့ပါ"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"ဖန်သားပြင်ဓါတ်ပုံ ရိုက်၍မရပါ"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းရာတွင် ပြဿနာရှိနေသည်"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ဖိုင်ပြောင်း ရွေးမှုများ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"မီဒီယာပလေရာအနေဖြင့် တပ်ဆင်ရန် (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ပိတ်ပါ"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများကိုအသုံးပြုပြီး အက်ပ်တစ်ခု၏ အကြောင်းကြားချက် အရေးပါမှု ၀ မှ ၅ အထိသတ်မှတ်ပေးနိုင်သည်။ \n\n"<b>"အဆင့် ၅"</b>" \n- အကြောင်းကြားချက်စာရင်း၏ ထိပ်ဆုံးတွင် ပြသည် \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်းကို ခွင့်ပြုသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၄"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၃"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n\n"<b>"အဆင့် ၂"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n\n"<b>"အဆင့် ၁"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n- လော့ခ်ချထားသည့် မျက်နှာပြင်နှင့် အခြေအနေဘားတန်းတို့တွင် မပြပါ \n- အကြောင်းကြားချက်စာရင်း အောက်ဆုံးတွင်ပြသည် \n\n"<b>"အဆင့် ၀"</b>" \n- အက်ပ်မှ အကြောင်းကြားချက်များ အားလုံးကို ပိတ်ဆို့သည်"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"အကြောင်းကြားချက်များ"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"သင်သည် ဤအကြောင်းကြားချက်များကို နောက်ထပ် လက်ခံရရှိတော့မည် မဟုတ်ပါ"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"အကြောင်းကြားချက် အမျိုးအစား <xliff:g id="NUMBER">%d</xliff:g> ခု"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ဤအက်ပ်တွင် အကြောင်းကြားချက် အမျိုးအစားများ မရှိပါ"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ဤအက်ပ်မှပို့သော အကြောင်းကြားချက်များကို ပိတ်ထား၍မရပါ"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">ဤအက်ပ်ရှိ အကြောင်းကြားချက်အမျိုးအစား <xliff:g id="NUMBER_1">%s</xliff:g> ခု အနက်မှ ၁ ခု</item>
-      <item quantity="one">ဤအက်ပ်ရှိ အကြောင်းကြားချက်အမျိုးအစား <xliff:g id="NUMBER_0">%s</xliff:g> ခု အနက်မှ ၁ ခု</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>၊ <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>၊ <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> နှင့် <xliff:g id="NUMBER_5">%3$d</xliff:g> အခြား</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>၊ <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> နှင့် <xliff:g id="NUMBER_2">%3$d</xliff:g> အခြား</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"ဤအကြောင်းကြားချက်များကို မြင်ရတော့မည် မဟုတ်ပါ"</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>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"ဤအက်ပ်ထံမှ အကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"ဤအကြောင်းကြားချက်များကို ပိတ်၍မရပါ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် အကြောင်းကြားချက်ထိန်းချုပ်မှုများကို ဖွင့်ထားသည်"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် အကြောင်းကြားချက်ထိန်းချုပ်မှုများကို ပိတ်ထားသည်"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ဤချန်နယ်မှ အကြောင်းကြားချက်များကို ခွင့်ပြုပါ"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"အုပ်စုအားလုံး"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်တင်များ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"စိတ်ကြိုက်သတ်မှတ်ရန်− <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"စိတ်ကြိုက်ပြုလုပ်ရန်"</string>
     <string name="notification_done" msgid="5279426047273930175">"ပြီးပါပြီ"</string>
+    <string name="inline_undo" msgid="558916737624706010">"တစ်ဆင့်နောက်ပြန်ရန်"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"အကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"အကြောင်းကြားချက်များကို ဆိုင်းငံ့ရန် ရွေးချယ်စရာများ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index fbcd197..1afd635 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varsler"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batterikapasiteten er lav"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår. Batterisparing er på."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-lading støttes ikke.\nBruk kun den medfølgende laderen."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Lading via USB støttes ikke."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Brukeren som for øyeblikket er logget på denne enheten, kan ikke slå på USB-feilsøking. For å bruke denne funksjonen, bytt til hovedbrukeren."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Lagrer skjermdumpen …"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Skjermdumpen lagres."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjermdumpen er lagret."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Trykk for å se skjermdumpen."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Kan ikke lagre skjermdumpen."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Det oppsto et problem under lagring av skjermdumpen."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Av"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n"<b>"Nivå 5"</b>" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 4"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 3"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n"<b>"Nivå 2"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n"<b>"Nivå 1"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n"<b>"Nivå 0"</b>" \n– Blokkér alle varsler fra appen"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Varsler"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Du får ikke disse varslene lenger"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> varselkategorier"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Denne appen har ikke varselkategorier"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Varsler fra denne appen kan ikke slås av"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 av <xliff:g id="NUMBER_1">%s</xliff:g> varselkategorier fra denne appen</item>
-      <item quantity="one">1 av <xliff:g id="NUMBER_0">%s</xliff:g> varselkategori fra denne appen</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> og <xliff:g id="NUMBER_5">%3$d</xliff:g> andre</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> og <xliff:g id="NUMBER_2">%3$d</xliff:g> annen</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Varselinnstillingene for <xliff:g id="APP_NAME">%1$s</xliff:g> er åpnet"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Varselinnstillingene for <xliff:g id="APP_NAME">%1$s</xliff:g> er lukket"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Tillat varsler fra denne kanalen"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorier"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Tilpass: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"varselinnstillinger"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"slumrealternativer for varsler"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Vis"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Lukk"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Innstillinger"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Dra ned for å avvise"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Meny"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> er i bilde-i-bilde"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index ceda3c5..a5c13f1 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"चलिरहेको"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाहरू"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ब्याट्री कम छ"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी। ब्याट्री सेभर सक्रिय छ।"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB चार्ज गर्न समर्थित छैन।\n आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्ज समर्थित छैन।"</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"हाल यस यन्त्रमा साइन इन हुनुभएको प्रयोगकर्ताले USB डिबग सक्रिय गर्न सक्नुहुन्न। यो सुविधाको प्रयोग गर्न प्राथमिक प्रयोगकर्तामा बदल्नुहोस्‌।"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रिन भर्न तन्काउनुहोस्"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रिनसट बचत गर्दै…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"स्क्रिनसट बचत हुँदैछ।"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रिनसट क्याप्चर गरियो।"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"आफ्नो स्क्रिनसट हेर्न ट्याप गर्नुहोस्।"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रिनसट क्याप्चर गर्न सकिएन।"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रिनसटलाई सुरक्षित गर्दा समस्या भयो।"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित भण्डारण स्थान उपलब्ध रहेको हुनाले स्क्रिनसटलाई सुरक्षित गर्न सकिँदैन।"</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"उक्त अनुप्रयोग वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मिडिया प्लेयर(MTP)को रूपमा माउन्ट गर्नुहोस्"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"निष्क्रिय"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- अनुप्रयोगका सबै सूचनाहरूलाई रोक्ने"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचनाहरू"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"तपाईंले अब उप्रान्त यी सूचनाहरू प्राप्त गर्नुहुने छैन"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> सूचनाका कोटिहरू"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"यस अनुप्रयोगमा सूचना सम्बन्धी कोटीहरू छैनन्"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"यस अनुप्रयोगका सूचनाहरूलाई निष्क्रिय पार्न सकिँदैन"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">यस अनुप्रयोगका <xliff:g id="NUMBER_1">%s</xliff:g> सूचना कोटिहरू मध्ये १</item>
-      <item quantity="one"> यस अनुप्रयोगको <xliff:g id="NUMBER_0">%s</xliff:g> सूचना कोटी मध्ये १</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> र <xliff:g id="NUMBER_5">%3$d</xliff:g> अन्य</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> र <xliff:g id="NUMBER_2">%3$d</xliff:g> अन्य</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> का सूचना सम्बन्धी नियन्त्रणहरूलाई खोलियो"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> का सूचना सम्बन्धी नियन्त्रणहरूलाई बन्द गरियो"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"यो च्यानलका सूचनाहरूलाई अनुमति दिनुहोस्"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"सबै कोटिहरू"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"आफू अनुकूल पार्नुहोस्: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"सम्पन्‍न भयो"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना सम्बन्धी नियन्त्रणहरू"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नुज गर्ने विकल्पहरू"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत गर्नुहोस्"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"सानो बनाउनुहोस्"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"बन्द गर्नुहोस्"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"सेटिङहरू"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारेज गर्न तल तान्नुहोस्"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"मेनु"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index b141801..b65ce97 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ਜਾਰੀ"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ਬੈਟਰੀ ਘੱਟ ਹੈ"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ। ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ।"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ਚਾਰਜਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।\nਕੇਵਲ ਸਪਲਾਈ ਕੀਤਾ ਚਾਰਜਰ ਵਰਤੋ।"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB ਚਾਰਜਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।"</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ।"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸਟੋਰੇਜ ਦੀ ਸੀਮਿਤ ਜਗ੍ਹਾ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ਇੱਕ ਮੀਡੀਆ ਪਲੇਅਰ (MTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ਬੰਦ"</string>
     <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="2139193533791840539">"ਤੁਹਾਨੂੰ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋਣਗੀਆਂ"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀਆਂ"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ਇਸ ਐਪ ਵਿੱਚ ਸੂਚਨਾ ਸ਼੍ਰੇਣੀਆਂ ਨਹੀਂ ਹਨ"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%s</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀ ਵਿੱਚੋਂ 1</item>
-      <item quantity="other">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%s</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀ ਵਿੱਚੋਂ 1</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, ਅਤੇ <xliff:g id="NUMBER_5">%3$d</xliff:g> ਹੋਰ</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, ਅਤੇ <xliff:g id="NUMBER_5">%3$d</xliff:g> ਹੋਰ</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨੂੰ ਖੋਲ੍ਹਿਆ ਗਿਆ"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ਇਸ ਚੈਨਲ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ਸਭ ਸ਼੍ਰੇਣੀਆਂ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ਵਿਉਂਤਬੱਧ ਕਰੋ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ਸੂਚਨਾ ਸਨੂਜ਼ ਵਿਕਲਪ"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ਬੰਦ ਕਰੋ"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ਖਾਰਜ ਕਰਨ ਲਈ ਹੇਠਾਂ ਘਸੀਟੋ"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"ਮੀਨੂ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ \'ਚ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8265895..5fb7b19 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateria fraca"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"A bateria está com pouca carga. Ative a Economia de bateria"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g> com base no seu uso"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s). A Economia de bateria está ativada."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"O carregamento via USB não é suportado.\nUse apenas o carregador fornecido."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"O carregamento via USB não é suportado."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O usuário conectado a este dispositivo não pode ativar a depuração USB. Para usar esse recurso, mude para o usuário principal \"NAME\"."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de tela"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Salvando captura de tela..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"A captura de tela está sendo salva."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Toque para ver sua captura de tela."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao salvar captura de tela."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"A captura de tela está sendo salva"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Captura de tela salva"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Toque para ver sua captura de tela"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Não foi possível fazer a captura de tela"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problema encontrado ao salvar captura de tela"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"O app ou a organização não permitem capturas de tela"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desativado"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Você deixará de receber essas notificações"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorias de notificação"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Este app não tem categorias de notificação"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notificações deste app não podem ser desativadas"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categoria de notificação deste app</item>
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação deste app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e <xliff:g id="NUMBER_5">%3$d</xliff:g> outro</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e <xliff:g id="NUMBER_5">%3$d</xliff:g> outros</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Você deixará de ver essas notificações"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Continuar mostrando essas notificações?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Bloquear notificações"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuar mostrando notificações desse app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Não é possível desativar essas notificações"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controles de notificação de <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Controles de notificação de <xliff:g id="APP_NAME">%1$s</xliff:g> fechados"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permitir notificações desse canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorias"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Desfazer"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"controles de notificação"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opções de adiamento de notificação"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Configurações"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arraste para baixo para dispensar"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b676a24..23a2f988 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateria fraca"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"A bateria está fraca. Ativar a Poupança de dados"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Cerca de <xliff:g id="TIME">%s</xliff:g> restante(s) com base na sua utilização."</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Cerca de <xliff:g id="TIME">%s</xliff:g> restante(s)."</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. A Poupança de bateria está ativada."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Carregamento USB não suportado. \nUtilize apenas o carregador fornecido."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"O carregamento por USB não é suportado."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O utilizador com sessão iniciada atualmente neste dispositivo não pode ativar a depuração USB. Para utilizar esta funcionalidade, mude para o utilizador principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de ecrã"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"A guardar captura de ecrã..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"A guardar captura de ecrã."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de ecrã efetuada"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Toque para ver a sua captura de ecrã."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter captura de ecrã."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao guardar a captura de ecrã."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"A guardar a captura de ecrã…"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Captura de ecrã guardada"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Toque para ver a captura de ecrã."</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Não foi possível obter a captura de ecrã."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Foi encontrado um problema ao guardar a captura de ecrã."</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"A aplicação ou a sua entidade não permitem tirar capturas de ecrã"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desativado"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Com os controlos de notificações do consumo de energia, pode definir um nível de importância de 0 a 5 para as notificações de aplicações. \n\n"<b>"Nível 5"</b>" \n- Mostrar no início da lista de notificações \n- Permitir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre \n\n"<b>"Nível 4"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre\n\n"<b>"Nível 3"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n\n"<b>"Nível 2"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n- Ocultar do ecrã de bloqueio e da barra de estado \n- Mostrar no fim da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações da aplicação"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Deixará de receber estas notificações"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorias de notificação"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicação não tem categorias de notificação"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Não é possível desativar as notificações desta aplicação"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação desta aplicação</item>
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoria de notificação desta aplicação</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e mais <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> e mais <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Nunca mais verá estas notificações."</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Pretende continuar a ver estas notificações?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Parar notificações"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuar a mostrar"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Pretende continuar a ver notificações desta aplicação?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Não é possível desativar estas notificações."</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> fechados"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permitir notificações deste canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorias"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Anular"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"controlos de notificação"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opções de suspensão de notificações"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Definições"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastar para baixo para ignorar"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"A aplicação <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8265895..5fb7b19 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateria fraca"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"A bateria está com pouca carga. Ative a Economia de bateria"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restantes"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g> com base no seu uso"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s), cerca de <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante(s). A Economia de bateria está ativada."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"O carregamento via USB não é suportado.\nUse apenas o carregador fornecido."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"O carregamento via USB não é suportado."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O usuário conectado a este dispositivo não pode ativar a depuração USB. Para usar esse recurso, mude para o usuário principal \"NAME\"."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de tela"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Salvando captura de tela..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"A captura de tela está sendo salva."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Toque para ver sua captura de tela."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao salvar captura de tela."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"A captura de tela está sendo salva"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Captura de tela salva"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Toque para ver sua captura de tela"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Não foi possível fazer a captura de tela"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problema encontrado ao salvar captura de tela"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"O app ou a organização não permitem capturas de tela"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desativado"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Você deixará de receber essas notificações"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorias de notificação"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Este app não tem categorias de notificação"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notificações deste app não podem ser desativadas"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categoria de notificação deste app</item>
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação deste app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e <xliff:g id="NUMBER_5">%3$d</xliff:g> outro</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e <xliff:g id="NUMBER_5">%3$d</xliff:g> outros</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Você deixará de ver essas notificações"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Continuar mostrando essas notificações?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Bloquear notificações"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuar mostrando notificações desse app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Não é possível desativar essas notificações"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controles de notificação de <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Controles de notificação de <xliff:g id="APP_NAME">%1$s</xliff:g> fechados"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permitir notificações desse canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorias"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Desfazer"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"controles de notificação"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opções de adiamento de notificação"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Configurações"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arraste para baixo para dispensar"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 8168dfa..f30f6d3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -34,7 +34,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"În desfășurare"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateria este aproape descărcată"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Bateria este aproape descărcată. Activați Economisirea bateriei."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Procent rămas din baterie <xliff:g id="PERCENTAGE">%s</xliff:g>, în baza utilizării, timp aproximativ rămas <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Procent rămas din baterie <xliff:g id="PERCENTAGE">%s</xliff:g>, timp aproximativ rămas <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>. Economisirea bateriei este activată."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Încărcarea USB nu este acceptată. \nUtilizați numai încărcătorul furnizat."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Încărcarea prin USB nu este acceptată."</string>
@@ -68,14 +71,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Utilizatorul conectat momentan pe acest dispozitiv nu poate activa remedierea erorilor prin USB. Pentru a folosi această funcție, comutați la utilizatorul principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captură de ecran"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Se salv. captura de ecran..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Se salvează captura de ecran..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Captura de ecran este salvată."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran salvată."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Atingeți pentru a vedea captura de ecran."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problemă întâmpinată la salvarea capturii de ecran."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Captura de ecran este în curs de salvare"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Captură de ecran salvată"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Atingeți pentru a vedea captura de ecran"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Captura de ecran nu a putut fi realizată"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Problemă întâmpinată la salvarea capturii de ecran"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opțiuni pentru transferul de fișiere prin USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montați ca player media (MTP)"</string>
@@ -561,28 +565,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Dezactivate"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Folosind comenzile de gestionare a notificărilor, puteți să setați un nivel de importanță de la 0 la 5 pentru notificările unei aplicații. \n\n"<b>"Nivelul 5"</b>" \n– Se afișează la începutul listei de notificări \n– Se permite întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 4"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 3"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n\n"<b>"Nivelul 2"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n\n"<b>"Nivelul 1"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n– Se ascunde în ecranul de blocare și în bara de stare \n– Se afișează la finalul listei de notificări \n\n"<b>"Nivelul 0"</b>" \n– Se blochează toate notificările din aplicație"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificări"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Nu veți mai primi aceste notificări"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorii de notificări"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Această aplicație nu are categorii de notificare"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notificările din această aplicație nu pot fi dezactivate"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="few">1 din <xliff:g id="NUMBER_1">%s</xliff:g> categorii de notificare din această aplicație</item>
-      <item quantity="other">1 din <xliff:g id="NUMBER_1">%s</xliff:g> de categorii de notificare din această aplicație</item>
-      <item quantity="one">1 din <xliff:g id="NUMBER_0">%s</xliff:g> categorie de notificare din această aplicație</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, și încă <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, și încă <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, și încă <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Nu veți mai vedea aceste notificări"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Doriți să continuați afișarea acestor notificări?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Opriți notificările"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuați afișarea"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Doriți să continuați afișarea notificărilor de la această aplicație?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Aceste notificări nu pot fi dezactivate"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Opțiunile privind notificările pentru <xliff:g id="APP_NAME">%1$s</xliff:g> sunt afișate"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Opțiunile privind notificările pentru <xliff:g id="APP_NAME">%1$s</xliff:g> nu sunt afișate"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permiteți notificările de la acest canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Toate categoriile"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizați: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizați"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Anulați"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"comenzile notificării"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opțiuni de amânare a notificării"</string>
@@ -739,8 +734,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Extindeți"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizați"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Închideți"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Setări"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trageți în jos pentru a închide"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Meniu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9456615..4be72ed 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Батарея почти разряжена"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батарея почти разряжена. Включите режим энергосбережения."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Осталось: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Заряд батареи – <xliff:g id="PERCENTAGE">%s</xliff:g>, осталось примерно <xliff:g id="TIME">%s</xliff:g> при текущем уровне использования."</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Заряд батареи – <xliff:g id="PERCENTAGE">%s</xliff:g>, осталось примерно <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Уровень заряда батареи: <xliff:g id="PERCENTAGE">%s</xliff:g>. Включен режим энергосбережения."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Зарядка через порт USB не поддерживается.\nИспользуйте только зарядное устройство из комплекта поставки."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Зарядка через USB не поддерживается."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"В этом аккаунте нельзя включить отладку по USB. Перейдите в аккаунт основного пользователя."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Сохранение..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Сохранение..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Сохранение..."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сохранен"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Нажмите, чтобы увидеть скриншот"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Не удалось сохранить скриншот."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Не удалось сохранить скриншот."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не удалось сохранить скриншот: недостаточно места."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Сохранение…"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Скриншот сохранен"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Нажмите, чтобы увидеть скриншот."</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Ошибка при сохранении скриншота"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Не удалось сохранить скриншот."</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Не удалось сохранить скриншот: недостаточно места."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Подключить как мультимедийный проигрыватель (MTP)"</string>
@@ -563,30 +567,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Отключено"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"С помощью этой функции вы можете устанавливать уровень важности уведомлений от 0 до 5 для каждого приложения.\n\n"<b>"Уровень 5"</b>\n"‒ Помещать уведомления в начало списка.\n‒ Показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 4\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 3\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\nУровень 2\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\nУровень 1\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\n‒ Не показывать на экране блокировки и в строке состояния.\n‒ Помещать уведомления в конец списка.\nУровень 0\n"<b></b>\n"‒ Блокировать все уведомления приложения."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Уведомления"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Вы больше не будете получать эти уведомления"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Категорий уведомлений: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"В приложении нет категорий уведомлений"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Уведомления этого приложения нельзя отключить"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категории уведомлений этого приложения</item>
-      <item quantity="few">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категорий уведомлений этого приложения</item>
-      <item quantity="many">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категорий уведомлений этого приложения</item>
-      <item quantity="other">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категории уведомлений этого приложения</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и ещё <xliff:g id="NUMBER_5">%3$d</xliff:g> канал</item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и ещё <xliff:g id="NUMBER_5">%3$d</xliff:g> канала</item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и ещё <xliff:g id="NUMBER_5">%3$d</xliff:g> каналов</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и ещё <xliff:g id="NUMBER_5">%3$d</xliff:g> канала</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Вы больше не будете получать эти уведомления."</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>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Показывать уведомления от этого приложения?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Эти уведомления нельзя отключить."</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Настройки уведомлений для приложения <xliff:g id="APP_NAME">%1$s</xliff:g> открыты"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Настройки уведомлений для приложения <xliff:g id="APP_NAME">%1$s</xliff:g> закрыты"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Показывать уведомления с этого канала"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Все категории"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>: настроить"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Настроить"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Отменить"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g>: <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"настройки уведомлений"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"параметры отсрочки уведомлений"</string>
@@ -745,8 +738,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Развернуть"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Свернуть"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Закрыть"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Настройки"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Чтобы закрыть, потяните вниз"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> находится в режиме \"Картинка в картинке\""</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 338b522..f072b73 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"දැනට පවතින"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"දැනුම්දීම්"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"බැටරිය අඩුය"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"බැටරිය අඩුයි. බැටරි සුරැකුම ක්‍රියාත්මක කරන්න"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව තිබේ"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත, ඔබගේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%s</xliff:g> පමණ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත, <xliff:g id="TIME">%s</xliff:g> පමණ ඇත"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ඉතිරිව ඇත. බැටරි සුරැකුම ක්‍රියාත්මකයි."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ආරෝපණය සහය නොදක්වයි.\nසපයන ලද ආරෝපකය පමණක් භාවිතා කරන්න."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB ආරෝපණය කිරීම සහාය නොදක්වයි."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"දැනට මෙම උපාංගයට පුරා ඇති පරිශීලකයාට USB නිදොස්කරණය ක්‍රියාත්මක කළ නොහැක. මෙම විශේෂාංගය භාවිතා කිරීම සඳහා, මූලික පරිශීලකයා වෙත මාරු වෙන්න."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"තිරය පිරවීමට විශාලනය කරන්න"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"තිරය පිරවීමට අදින්න"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"තිර රුව"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"තිර රුව සුරකිමින්…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"තිර රුව සුරැකෙමින් පවතී…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"තිර රුව සුරැකෙමින් පවතී."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"තිර රුව ග්‍රහණය කරන ලදි."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ඔබගේ තිර රුව බැලීමට තට්ටු කරන්න."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"තිර රුව ග්‍රහණය කිරීමට නොහැකි විය."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"තිර රුව සුරකින අතරතුර ගැටලුවක් ඇති විය."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"තිර රුව සුරකිමින් පවතී"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"තිර රුව සුරකින ලදී"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"ඔබගේ තිර රුව බැලීමට තට්ටු කරන්න"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"තිර රුව ග්‍රහණය කිරීමට නොහැකි විය"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"තිර රුව සුරකින අතරතුර ගැටලුවක් ඇති විය"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"මධ්‍ය ධාවකයක් (MTP) ලෙස සවි කරන්න"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ක්‍රියාවිරහිතයි"</string>
     <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="2139193533791840539">"ඔබට තවදුරටත් මෙම දැනුම්දීම් නොලැබෙනු ඇත"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"දැනුම්දීම් කාණ්ඩ <xliff:g id="NUMBER">%d</xliff:g>ක්"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"මෙම යෙදුම හට දැනුම්දීම් ප්‍රවර්ග නොමැත"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"මෙම යෙදුම වෙතින් වන දැනුම්දීම් ක්‍රියාවිරහිත කළ නොහැකිය"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">මෙම යෙදුමෙන් දැනුම්දීම් ප්‍රවර්ග <xliff:g id="NUMBER_1">%s</xliff:g>න් 1ක්</item>
-      <item quantity="other">මෙම යෙදුමෙන් දැනුම්දීම් ප්‍රවර්ග <xliff:g id="NUMBER_1">%s</xliff:g>න් 1ක්</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, සහ තවත් <xliff:g id="NUMBER_5">%3$d</xliff:g>ක්</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, සහ තවත් <xliff:g id="NUMBER_5">%3$d</xliff:g>ක්</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"ඔබට තවදුරටත් මෙම දැනුම්දීම් නොදකිනු ඇත"</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>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"මෙම යෙදුම වෙතින් දැනුම්දීම් පෙන්වමින් තබන්නද?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"මෙම දැනුම්දීම් ක්‍රියාවිරහිත කළ නොහැකිය"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා දැනුම්දීම් පාලන විවෘත කරන ලදී"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා දැනුම්දීම් පාලන වසන ලදී"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"මෙම නාලිකාව වෙතින් දැනුම්දීම් සඳහා ඉඩ දෙන්න"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"සියලු ප්‍රවර්ග"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"තව සැකසීම්"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"අභිමත කරන්න: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"අභිරුචිකරණය"</string>
     <string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
+    <string name="inline_undo" msgid="558916737624706010">"පසුගමනය කරන්න"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"දැනුම්දීම් පාලන"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"දැනුම්දීම් මදක් නතර කිරීමේ විකල්ප"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5ba1bb5..e52a43a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Trenutno"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Akumulator je skoraj izpraznjen"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Akumulator je skoraj izpraznjen. Vklopite varčevanje z energijo akumulatorja"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>, glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>, na voljo imate še približno <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Še <xliff:g id="PERCENTAGE">%s</xliff:g>. Vklopljeno je varčevanje z energijo akumulatorja."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Polnjenje po povezavi USB ni podprto.\nUporabite priloženi polnilnik."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Polnjenje prek USB-ja ni podprto."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Uporabnik, trenutno prijavljen v napravo, ne more vklopiti odpravljanja napak s povezavo USB. Če želite uporabljati to funkcijo, preklopite na primarnega uporabnika."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Posnetek zaslona"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Shranjev. posnetka zaslona ..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Shranjevanje posnetka zaslona ..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Shranjevanje posnetka zaslona."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Posnetek zaslona je shranjen."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Dotaknite se, če si želite ogledati posnetek zaslona."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Posnetka zaslona ni bilo mogoče shraniti."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Pri shranjevanju posnetka zaslona je prišlo do težave."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Shranjevanje posnetka zaslona"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Posnetek zaslona je shranjen"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Dotaknite se, če si želite ogledati posnetek zaslona"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Posnetka zaslona ni bilo mogoče shraniti"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Pri shranjevanju posnetka zaslona je prišlo do težave"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ali vaša organizacija ne dovoljuje posnetkov zaslona"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Vpni kot predvajalnik (MTP)"</string>
@@ -563,30 +567,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Izklopljeno"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"S kontrolniki za pomebnost obvestila je mogoče za obvestila aplikacije nastaviti stopnjo pomembnosti od 0 do 5. \n\n"<b>"Stopnja 5"</b>" \n– Prikaz na vrhu seznama obvestil \n– Omogočanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 4"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 3"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n\n"<b>"Stopnja 2"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n\n"<b>"Stopnja 1"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n– Skrivanje na zaklenjenem zaslonu in v vrstici stanja \n– Prikaz na dnu seznama obvestil \n\n"<b>"Stopnja 0"</b>" \n– Blokiranje vseh obvestil aplikacije"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obvestila"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Teh obvestil ne boste več prejemali"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Št. kategorij obvestil: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ta aplikacija nima kategorij obvestil"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obvestil te aplikacije ni mogoče izklopiti"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obvestil iz te aplikacije</item>
-      <item quantity="two">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorij obvestil iz te aplikacije</item>
-      <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorij obvestil iz te aplikacije</item>
-      <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorij obvestil iz te aplikacije</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> in <xliff:g id="NUMBER_5">%3$d</xliff:g> drug</item>
-      <item quantity="two"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> in <xliff:g id="NUMBER_5">%3$d</xliff:g> druga</item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> in <xliff:g id="NUMBER_5">%3$d</xliff:g> drugi</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> in <xliff:g id="NUMBER_5">%3$d</xliff:g> drugih</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Ta obvestila ne bodo več prikazana"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Želite, da so ta obvestila še naprej prikazana?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Ustavi prikazovanje obvestil"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Prikazuj še naprej"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite, da so obvestila te aplikacije še naprej prikazana?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Teh obvestil ni mogoče izklopiti"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Kontrolniki obvestil za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g> so odprti"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Kontrolniki obvestil za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g> so zaprti"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Dovoli obvestila iz tega kanala"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Vse kategorije"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Več nastavitev"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodi: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Prilagodi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Dokončano"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Razveljavi"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrolniki obvestil"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"možnosti preložitve obvestil"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 71285ad..58eac29 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Inaendelea"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Arifa"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Betri inaisha"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Chaji imepungua. Washa Kiokoa Betri"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Imebakisha <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%s</xliff:g> kulingana na jinsi unavyotumia"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>. Umewasha Kiokoa Betri."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Chaji ya USB haihamiliwi.\n Tumia chaka iliyopeanwa."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Kuchaji kwa kutumia USB hakutumiki."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Mtumiaji aliyeingia katika akaunti kwa kutumia kifaa hiki kwa sasa hawezi kuwasha utatuzi wa USB. Ili utumie kipengele hiki, tumia akaunti ya mtumiaji wa msingi."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Picha ya skrini"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Inahifadhi picha ya skrini..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Picha ya skrini inahifadhiwa"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Picha ya skrini imenaswa."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Gusa ili utazame picha ya skrini uliyohifadhi."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha ya skrini"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Hitilafu imetokea wakati wa kuhifadhi picha ya skrini."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Haina nafasi ya kutosha kuhifadhi picha ya skrini."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Inahifadhi picha ya skrini"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Imehifadhi picha ya skrini"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Gusa ili utazame picha ya skrini uliyohifadhi"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Imeshindwa kupiga picha ya skrini"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Hitilafu imetokea wakati wa kuhifadhi picha ya skrini"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Imeshindwa kuhifadhi picha ya skrini kwa sababu nafasi haitoshi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Angika kama kichezaji cha maudhui (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Imezimwa"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Ukiwa na udhibiti wa arifa, unaweza kuweka kiwango cha umuhimu wa arifa za programu kuanzia 0 hadi 5. \n\n"<b>"Kiwango cha 5"</b>" \n- Onyesha katika sehemu ya juu ya orodha ya arifa \n- Ruhusu ukatizaji wa skrini nzima \n- Ruhusu arifa za kuchungulia kila wakati\n\n"<b>"Kiwango cha 4"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Ruhusu arifa za kuchungulia kila wakati \n\n"<b>"Kiwango cha 3"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia\n\n"<b>"Kiwango cha 2"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti au mtetemo \n\n"<b>"Kiwango cha 1"</b>" \n- Zuia ukatizaji wa skrini nzima \n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti na mtetemo \n- Usionyeshe skrini iliyofungwa na sehemu ya arifa \n- Onyesha katika sehemu ya chini ya orodha ya arifa \n\n"<b>"Kiwango cha 0"</b>" \n- Zuia arifa zote kutoka programu"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Arifa"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Hutapokea arifa hizi tena"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Aina <xliff:g id="NUMBER">%d</xliff:g> za arifa"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Programu hii haina aina za arifa"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Arifa kutoka kwenye programu hii haziwezi kuzimwa"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Aina 1 ya arifa kati ya <xliff:g id="NUMBER_1">%s</xliff:g> kutoka kwenye kifaa hiki</item>
-      <item quantity="one">Aina 1 ya arifa kati ya <xliff:g id="NUMBER_0">%s</xliff:g> kutoka kwenye kifaa hiki</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> na vingine <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> na kingine <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Hutaona tena arifa hizi"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Ungependa kuendelea kuonyesha arifa hizi?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Acha kuonyesha arifa"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Endelea kuonyesha"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Ungependa kuendelea kuonyesha arifa kutoka programu hii?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Huwezi kuzima arifa hizi"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Vidhibiti vya arifa <xliff:g id="APP_NAME">%1$s</xliff:g> vimefunguliwa"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Vidhibiti vya arifa vya <xliff:g id="APP_NAME">%1$s</xliff:g> vimefungwa"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Ruhusu arifa kutoka kwenye kituo hiki"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Aina Zote"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Badilisha upendavyo: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Weka mapendeleo"</string>
     <string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Tendua"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"vidhibiti vya arifa"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"chaguo za kuahirisha arifa"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index c2e0dce..f8a14d0 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"కొనసాగుతున్నవి"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"నోటిఫికేషన్‌లు"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"బ్యాటరీ తక్కువగా ఉంది"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది. బ్యాటరీ సేవర్ ఆన్‌లో ఉంది."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ఛార్జింగ్‌కు మద్దతు లేదు.\nఅందించిన ఛార్జర్‌ను మాత్రమే ఉపయోగించండి."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB ఛార్జింగ్‌కి మద్దతు లేదు."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ఈ పరికరానికి ప్రస్తుతం సైన్ ఇన్ చేసిన వినియోగదారు USB డీబగ్గింగ్ ఆన్ చేయలేరు. ఈ ఫీచర్ ఉపయోగించడానికి, ప్రాథమిక వినియోగదారుకి మారాలి."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"స్క్రీన్‌కు నింపేలా జూమ్ చేయండి"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"స్క్రీన్‌కు నింపేలా విస్తరించండి"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"స్క్రీన్‌షాట్ సేవ్ చేయబడుతోంది."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"స్క్రీన్‌షాట్ క్యాప్చర్ చేయబడింది."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"మీ స్క్రీన్‌షాట్‌ను వీక్షించడానికి నొక్కండి."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"స్క్రీన్‌షాట్‌ను క్యాప్చర్ చేయడం సాధ్యపడలేదు."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"స్క్రీన్‌షాట్‌ని సేవ్ చేస్తున్నప్పుడు సమస్య సంభవించింది."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడదు."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"స్క్రీన్‌షాట్‌లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"మీడియా ప్లేయర్‌గా (MTP) మౌంట్ చేయి"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ఆఫ్‌లో ఉన్నాయి"</string>
     <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="2139193533791840539">"మీరు ఇకపై ఈ నోటిఫికేషన్‌లను పొందరు"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> నోటిఫికేషన్ వర్గాలు"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ఈ అనువర్తనానికి నోటిఫికేషన్ వర్గాలు లేవు"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ఈ యాప్ నుండి వచ్చే నోటిఫికేషన్‌లను ఆఫ్ చేయలేరు"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">ఈ యాప్ నుంచి <xliff:g id="NUMBER_1">%s</xliff:g> నోటిఫికేషన్ వర్గాలలో 1</item>
-      <item quantity="one">ఈ యాప్ నుంచి <xliff:g id="NUMBER_0">%s</xliff:g> నోటిఫికేషన్ వర్గంలో 1</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> మరియు మరో <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> మరియు మరో <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> యొక్క నోటిఫికేషన్ నియంత్రణలు తెరవబడ్డాయి"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> యొక్క నోటిఫికేషన్ నియంత్రణలు మూసివేయబడ్డాయి"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ఈ ఛానెల్ యొక్క నోటిఫికేషన్‌లను అనుమతించండి"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"అన్ని వర్గాలు"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్‌లు"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"అనుకూలీకరించండి: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"నోటిఫికేషన్ నియంత్రణలు"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"నోటిఫికేషన్ తాత్కాలిక ఆపివేత ఎంపికలు"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"విస్తరింపజేయి"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"కనిష్టీకరించు"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"మూసివేయి"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"సెట్టింగ్‌లు"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"తీసివేయడానికి కిందికి లాగండి"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"మెను"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> చిత్రంలో చిత్రం రూపంలో ఉంది"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 23db95b..0790847 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Поточні"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Низький рівень заряду акумулятора"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Акумулятор майже розрядився. Увімкніть режим економії заряду акумулятора"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"На основі використання залишилося <xliff:g id="PERCENTAGE">%s</xliff:g> – близько <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g> – близько <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим економії заряду акумулятора."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Заряджання USB не підтримується.\nВикористовуйте лише наданий у комплекті зарядний пристрій."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Заряджання через USB не підтримується."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Користувач поточного облікового запису не може вмикати налагодження USB. Щоб увімкнути цю функцію, увійдіть в обліковий запис основного користувача."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Знімок екрана"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Збереження знімка екрана..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Збереження знімка екрана..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Зберігається знімок екрана."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Знімок екрана зроблено."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Торкніться, щоб переглянути знімок екрана."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Не вдалося зробити знімок екрана."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Не вдалося зберегти знімок екрана."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Знімок екрана зберігається"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Знімок екрана збережено"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Торкніться, щоб переглянути знімок екрана"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Не вдалося зробити знімок екрана"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Не вдалося зберегти знімок екрана"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Підключити як медіапрогравач (MTP)"</string>
@@ -563,30 +567,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Вимк."</string>
     <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="2139193533791840539">"Ви більше не отримуватимете ці сповіщення"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Категорії сповіщень (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"У цьому додатку немає категорій сповіщень"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Сповіщення з цього додатка не можна вимкнути"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорії сповіщень із цього додатка</item>
-      <item quantity="few">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорій сповіщень із цього додатка</item>
-      <item quantity="many">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорій сповіщень із цього додатка</item>
-      <item quantity="other">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорії сповіщень із цього додатка</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і ще <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і ще <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і ще <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і ще <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Ви більше не бачитимете цих сповіщень"</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>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Чи показувати сповіщення з цього додатка надалі?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ці сповіщення не можна вимкнути"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Елементи керування сповіщеннями для додатка <xliff:g id="APP_NAME">%1$s</xliff:g> відкрито"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Елементи керування сповіщеннями для додатка <xliff:g id="APP_NAME">%1$s</xliff:g> закрито"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Дозволити сповіщення з цього каналу"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Усі категорії"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Налаштувати: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Налаштувати"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Відмінити"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"елементи керування сповіщеннями"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"параметри відкладення сповіщень"</string>
@@ -745,8 +738,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Розгорнути"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Згорнути"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Закрити"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Налаштування"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перетягніть униз, щоб закрити"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"У додатку <xliff:g id="NAME">%s</xliff:g> є функція \"Картинка в картинці\""</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index ad5ac98..e202363 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"جاری"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اطلاعات"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"بیٹری کم ہے"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے۔ بیٹری سیور آن ہے۔"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"‏USB چارجنگ تعاون یافتہ نہیں ہے.\nصرف فراہم کردہ چارجر کا ہی استعمال کریں۔"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"‏USB چارجنگ تعاون یافتہ نہیں ہے۔"</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"‏اس آلہ پر فی الحال سائن ان کردہ صارف USB ڈیبگنگ آن نہیں کر سکتا۔ اس خصوصیت کا استعمال کرنے کیلئے، ابتدائی صارف پر سوئچ کریں۔"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"پوری سکرین پر زوم کریں"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"پوری سکرین پر پھیلائیں"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"اسکرین شاٹ محفوظ کیا جا رہا ہے۔"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"اسکرین شاٹ کیپچر کیا گیا۔"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"اپنا اسکرین شاٹ دیکھنے کیلئے تھپتھپائیں۔"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"اسکرین شاٹ کیپچر نہیں کر سکے۔"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"اسکرین شاٹ محفوظ کرتے وقت مسئلہ پیش آ گیا۔"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"محدود اسٹوریج جگہ کی وجہ سے اسکرین شاٹس نہیں لئے جا سکتے۔"</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏USB فائل منتقل کرنیکے اختیارات"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏ایک میڈیا پلیئر (MTP) کے بطور ماؤنٹ کریں"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"آف"</string>
     <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="2139193533791840539">"آپ کو یہ اطلاعات مزید نہیں ملیں گی"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"اطلاع کے <xliff:g id="NUMBER">%d</xliff:g> زمرے"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"اس ایپ میں اطلاعاتی زمرے نہیں ہیں"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"اس ایپ کی اطلاعات کو آف نہیں کیا جا سکتا"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">اس ایپ کے <xliff:g id="NUMBER_1">%s</xliff:g> اطلاعاتی زمروں میں سے 1</item>
-      <item quantity="one">اس ایپ کے <xliff:g id="NUMBER_0">%s</xliff:g> اطلاعاتی زمرے میں سے 1</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> اور <xliff:g id="NUMBER_5">%3$d</xliff:g> دیگر</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> اور <xliff:g id="NUMBER_2">%3$d</xliff:g> دیگر</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے اطلاعی کنٹرولز کھلے ہیں"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے اطلاعی کنٹرولز بند کر دئے گئے ہیں"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"اس چینل سے اطلاعات کی اجازت دیں"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"سبھی زمرے"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"حسب ضرورت بنائیں: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"اطلاع کے کنٹرولز"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"اطلاع اسنوز کرنے کے اختیارات"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"پھیلائیں"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"چھوٹی کریں"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"بند کریں"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ترتیبات"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"برخاست کرنے کیلئے نیچے گھسیٹیں"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"مینو"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> تصویر میں تصویر میں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 0db8ef2..a8b5e54 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Hali bajarilmagan"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Eslatmalar"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batareya quvvati kam qoldi"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batareya quvvati kam qoldi. Quvvat tejash rejimini yoqing."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> (joriy holatda taxminan <xliff:g id="TIME">%s</xliff:g> qoldi)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> (taxminan <xliff:g id="TIME">%s</xliff:g> qoldi)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> qoldi. Quvvat tejash rejimi yoniq."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB orqali zaryadlab bo‘lmaydi.\nFaqat taklif qilingan zaryadlagichdan foydalaning."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB orqali quvvat oldirish qo‘llab-quvvatlanmaydi."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Ayni paytda ushbu qurilmaga o‘z hisobi bilan kirgan foydalanuvchi USB orqali nosozliklarni tuzatish funksiyasini yoqa olmaydi. Bu funksiyadan foydalanish uchun asosiy foydalanuvchi profiliga o‘ting."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ekranga moslashtirish"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ekran hajmida cho‘zish"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skrinshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Skrinshot saqlanmoqda…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Skrinshot saqlanmoqda."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinshot saqlandi."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Skrinshotni ko‘rish uchun bosing."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinshot saqlanmadi."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Skrinshotni saqlashda muammo yuz berdi."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Xotirada joy kamligi uchun skrinshotni saqlab bo‘lmadi."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Skrinshot saqlanmoqda"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Skrinshot saqlandi"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Skrinshotni ko‘rish uchun bosing"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Skrinshot saqlanmadi"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Skrinshotni saqlashda muammo yuz berdi"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl ko‘chirish moslamalari"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer sifatida ulash (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"O‘chiq"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Bildirishnomalar uchun kengaytirilgan boshqaruv yordamida ilova bildirishnomalarining muhimlik darajasini (0-5) sozlash mumkin. \n\n"<b>"5-daraja"</b>" \n- Bildirishnomani ro‘yxatning boshida ko‘rsatish \n- To‘liq ekranli bildirishnomalarni ko‘rsatish \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"4-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"3-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n\n"<b>"2-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n\n"<b>"1-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n- Ekran qulfi va holat qatorida ko‘rsatmaslik \n- Bildirishnomani ro‘yxatning oxirida ko‘rsatish \n\n"<b>"0-daraja"</b>" \n- Ilovadan keladigan barcha bildirishnomalarni bloklash"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirishnomalar"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Ushbu bildirishnomalar endi ko‘rsatilmaydi"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ta bildirishnoma turkumi"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Bu ilovada bildirishnomalar turkumi yo‘q"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Bu ilova bildirishnomalarini o‘chirib bo‘lmaydi"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Bu ilovadagi <xliff:g id="NUMBER_1">%s</xliff:g> ta bildirishnomalar turkumidan 1 tasi</item>
-      <item quantity="one">Bu ilovadagi <xliff:g id="NUMBER_0">%s</xliff:g> ta bildirishnomalar turkumidan 1 tasi</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> va yana <xliff:g id="NUMBER_5">%3$d</xliff:g> ta</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> va yana <xliff:g id="NUMBER_2">%3$d</xliff:g> ta</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Ushbu bildirishnomalar endi ko‘rsatilmaydi"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Mazkur bildirishnomalar ko‘rsatishda davom etilsinmi?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Bildirishnomalarni to‘xtatish"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Ko‘rsatilsin"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu ilovadan keladigan bildirishnomalar ko‘rsatishda davom etilsinmi?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ushbu bildirishnomalarni o‘chirib bo‘lmaydi"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun bildirishnoma sozlamalari ochildi"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun bildirishnoma sozlamalari yopildi"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Bu kanaldan keladigan bildirishnomalarga ruxsat berish"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Barcha turkumlar"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>: sozlash"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Moslash"</string>
     <string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Qaytarish"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"bildirishnoma sozlamalari"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"bildirishnomalarni kechiktirish parametrlari"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Yoyish"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Yig‘ish"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Yopish"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Sozlamalar"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Yopish uchun pastga torting"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> tasvir ustida tasvir rejimida"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index e5bd3a9..a0eb56f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Okuqhubekayo"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Izaziso"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Ibhethri liphansi"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Ibhethri liphansi. Vula isilondolozi sebhethri"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele, cishe u-<xliff:g id="TIME">%s</xliff:g> osele ngokusukela ekusebenziseni kwakho"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> okusele, cishe u-<xliff:g id="TIME">%s</xliff:g> osele"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> esele. Isilondolozi sebhethri sivuliwe."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Ukushaja i-USB akusekelwe.\nSebenzisa kuphela ishaja enikeziwe."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ukushaja kwe-USB akusekelwe."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Umsebenzisi manje ongene ngemvume kule divayisi entsha akakwazi ukuvula ukulungisa amaphutha ku-USB. Ukuze usebenzise lesi sici, shintshela kumsebenzisi oyinhloko."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Isithombe-skrini"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Ilondoloz umfanekiso weskrini..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Umfanekiso weskrini uyalondolozwa."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Thepha ukuze ubuke isithombe-skrini sakho."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Inkinga ivelile ngenkathi ilondoloza isithombe sikrini."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Umfanekiso weskrini uyalondolozwa"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Isithombe-skrini silondoloziwe"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Thepha ukuze ubuke isithombe-skrini sakho"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Yehlulekile ukuthwebula umfanekiso weskrini"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Inkinga ivelile ngenkathi ilondoloza isithombe sikrini"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Valiwe"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Ngezilawuli zesaziso zamandla, ungasetha ileveli ebalulekile kusuka ku-0 kuya ku-5 kusuka kuzaziso zohlelo lokusebenza. \n\n"<b>"Ileveli 5"</b>" \n- Ibonisa phezulu kuhlu lwesaziso \n- Vumela ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 4"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 3"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n\n"<b>"Ileveli 2"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo nokudlidliza \n\n"<b>"Ileveli 1"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo noma ukudlidliza \n- Fihla kusuka kusikrini sokukhiya nebha yesimo \n- Bonisa phansi kohlu lwesaziso \n\n"<b>"Ileveli 0"</b>" \n- Vimbela zonke izaziso kusuka kuhlelo lokusebenza"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Izaziso"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Ngeke usathola izaziso"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> izigaba zesaziso"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Lolu hlelo lokusebenza alunazo izigaba zesaziso"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Izaziso kusuka kulolu hlelo lokusebenza azikwazi ukuvalwa"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 isigaba kwezingu-<xliff:g id="NUMBER_1">%s</xliff:g> sezaziso kusukela kulolu hlelo lokusebenza</item>
-      <item quantity="other">1 isigaba kwezingu-<xliff:g id="NUMBER_1">%s</xliff:g> sezaziso kusukela kulolu hlelo lokusebenza</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, nabanye abangu-<xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, nabanye abangu-<xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Ngeke usabona lezi zaziso"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Qhubeka nokubonisa lezi zaziso?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Misa izaziso"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Qhubeka nokubonisa"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Qhubeka nokubonisa izaziso kusuka kulolu hlelo lokusebenza?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Lezi zaziso azikwazi ukuvalwa"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Izilawuli zesaziso ze-<xliff:g id="APP_NAME">%1$s</xliff:g> zivuliwe"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Izilawuli zesaziso ze-<xliff:g id="APP_NAME">%1$s</xliff:g> zivaliwe"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Zonke izaziso kusuka kulesi siteshi"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Zonke izigaba"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Enza ngendlela oyifisayo: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Enza ngendlela oyifisayo"</string>
     <string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Susa"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"izilawuli zesaziso"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"izinketho zokusnuza zesaziso"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f5be337..0f4c3b8 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -156,4 +156,6 @@
 
     <color name="zen_introduction">#ffffffff</color>
 
+    <color name="smart_reply_button_text">#ff4285f4</color><!-- blue 500 -->
+    <color name="smart_reply_button_background">#fff7f7f7</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 39ed08e..0134086 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -264,7 +264,7 @@
     <!-- The width of the panel that holds the quick settings. -->
     <dimen name="qs_panel_width">@dimen/notification_panel_width</dimen>
 
-    <dimen name="volume_dialog_panel_width">315dp</dimen>
+    <dimen name="volume_dialog_panel_width">120dp</dimen>
 
     <!-- Gravity for the notification panel -->
     <integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
@@ -618,6 +618,8 @@
          type icon is wide for the tile in quick settings. -->
     <dimen name="wide_type_icon_start_padding_qs">3dp</dimen>
 
+    <dimen name="signal_indicator_to_icon_frame_spacing">3dp</dimen>
+
     <!-- The maximum width of the navigation bar ripples. -->
     <dimen name="key_button_ripple_max_width">95dp</dimen>
 
@@ -882,4 +884,9 @@
     <!-- Home button padding for sizing -->
     <dimen name="home_padding">15dp</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_font_size">14sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index dde4dcf..6437903 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -775,6 +775,15 @@
     <string name="quick_settings_work_mode_label">Work mode</string>
     <!-- QuickSettings: Label for the toggle to activate Night display (renamed "Night Light" with title caps). [CHAR LIMIT=20] -->
     <string name="quick_settings_night_display_label">Night Light</string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be enabled at sunset. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_on_at_sunset">On at sunset</string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be on until sunrise. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_until_sunrise">Until sunrise</string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be enabled at some user-selected time. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_on_at">On at <xliff:g id="time" example="10 pm">%s</xliff:g></string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be on until some user-selected time. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_until">Until <xliff:g id="time" example="7 am">%s</xliff:g></string>
+
     <!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
     <string name="quick_settings_nfc_label">NFC</string>
     <!-- QuickSettings: NFC (off) [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 90c5977..4837fef 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -476,7 +476,6 @@
     <style name="TextAppearance.NotificationInfo.Button">
         <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:textSize">14sp</item>
-        <item name="android:textAllCaps">true</item>
         <item name="android:textColor">?android:attr/colorAccent</item>
         <item name="android:background">@drawable/btn_borderless_rect</item>
         <item name="android:gravity">center</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index a5d1963..13f30b2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -28,11 +28,14 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
 import android.os.Trace;
 import android.util.ArraySet;
 import android.util.IntProperty;
 import android.util.Property;
 import android.util.TypedValue;
+import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -291,6 +294,20 @@
     }
 
     /**
+     * @return The next frame name for the specified surface.
+     */
+    public static long getNextFrameNumber(Surface s) {
+        return s.getNextFrameNumber();
+    }
+
+    /**
+     * @return The surface for the specified view.
+     */
+    public static Surface getSurface(View v) {
+        return v.getViewRootImpl().mSurface;
+    }
+
+    /**
      * Returns a lightweight dump of a rect.
      */
     public static String dumpRect(Rect r) {
@@ -299,4 +316,12 @@
         }
         return r.left + "," + r.top + "-" + r.right + "," + r.bottom;
     }
+
+    /**
+     * Posts a runnable on a handler at the front of the queue ignoring any sync barriers.
+     */
+    public static void postAtFrontOfQueueAsynchronously(Handler h, Runnable r) {
+        Message msg = h.obtainMessage().setCallback(r);
+        h.sendMessageAtFrontOfQueue(msg);
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
new file mode 100644
index 0000000..0d8ce58
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
@@ -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
+ */
+
+package com.android.systemui.shared.system;
+
+import android.app.Activity;
+
+public class ActivityCompat {
+    private final Activity mWrapped;
+
+    public ActivityCompat(Activity activity) {
+        mWrapped = activity;
+    }
+
+    /**
+     * @see Activity#registerRemoteAnimations
+     */
+    public void registerRemoteAnimations(RemoteAnimationDefinitionCompat definition) {
+        mWrapped.registerRemoteAnimations(definition.getWrapped());
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
index 705a215..712cca6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
@@ -38,4 +38,9 @@
                 : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
         return options;
     }
+
+    public static ActivityOptions makeRemoteAnimation(
+            RemoteAnimationAdapterCompat remoteAnimationAdapter) {
+        return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped());
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
new file mode 100644
index 0000000..625b1de
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -0,0 +1,71 @@
+/*
+ * 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.os.RemoteException;
+import android.util.Log;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
+
+/**
+ * @see RemoteAnimationAdapter
+ */
+public class RemoteAnimationAdapterCompat {
+
+    private final RemoteAnimationAdapter mWrapped;
+
+    public RemoteAnimationAdapterCompat(RemoteAnimationRunnerCompat runner, long duration,
+            long statusBarTransitionDelay) {
+        mWrapped = new RemoteAnimationAdapter(wrapRemoteAnimationRunner(runner), duration,
+                statusBarTransitionDelay);
+    }
+
+    RemoteAnimationAdapter getWrapped() {
+        return mWrapped;
+    }
+
+    private static IRemoteAnimationRunner.Stub wrapRemoteAnimationRunner(
+            RemoteAnimationRunnerCompat remoteAnimationAdapter) {
+        return new IRemoteAnimationRunner.Stub() {
+            @Override
+            public void onAnimationStart(RemoteAnimationTarget[] apps,
+                    IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+                final RemoteAnimationTargetCompat[] appsCompat =
+                        RemoteAnimationTargetCompat.wrap(apps);
+                final Runnable animationFinishedCallback = new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            finishedCallback.onAnimationFinished();
+                        } catch (RemoteException e) {
+                            Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
+                                    + " finished callback", e);
+                        }
+                    }
+                };
+                remoteAnimationAdapter.onAnimationStart(appsCompat, animationFinishedCallback);
+            }
+
+            @Override
+            public void onAnimationCancelled() throws RemoteException {
+                remoteAnimationAdapter.onAnimationCancelled();
+            }
+        };
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java
new file mode 100644
index 0000000..5fff5fe
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java
@@ -0,0 +1,35 @@
+/*
+ * 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.view.RemoteAnimationDefinition;
+
+/**
+ * @see RemoteAnimationDefinition
+ */
+public class RemoteAnimationDefinitionCompat {
+
+    private final RemoteAnimationDefinition mWrapped = new RemoteAnimationDefinition();
+
+    public void addRemoteAnimation(int transition, RemoteAnimationAdapterCompat adapter) {
+        mWrapped.addRemoteAnimation(transition, adapter.getWrapped());
+    }
+
+    RemoteAnimationDefinition getWrapped() {
+        return mWrapped;
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
similarity index 63%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
index 4200de1..5a85df9 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
@@ -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.
@@ -11,10 +11,12 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
-package android.security.keystore;
+package com.android.systemui.shared.system;
 
-/* @hide */
-parcelable RecoveryData;
+public interface RemoteAnimationRunnerCompat {
+    void onAnimationStart(RemoteAnimationTargetCompat[] apps, Runnable finishedCallback);
+    void onAnimationCancelled();
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..3871980
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -0,0 +1,59 @@
+/*
+ * 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.graphics.Point;
+import android.graphics.Rect;
+import android.view.RemoteAnimationTarget;
+
+/**
+ * @see RemoteAnimationTarget
+ */
+public class RemoteAnimationTargetCompat {
+
+    public static final int MODE_OPENING = RemoteAnimationTarget.MODE_OPENING;
+    public static final int MODE_CLOSING = RemoteAnimationTarget.MODE_CLOSING;
+
+    public final int taskId;
+    public final int mode;
+    public final SurfaceControlCompat leash;
+    public final boolean isTranslucent;
+    public final Rect clipRect;
+    public final int prefixOrderIndex;
+    public final Point position;
+    public final Rect sourceContainerBounds;
+
+    public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
+        taskId = app.taskId;
+        mode = app.mode;
+        leash = new SurfaceControlCompat(app.leash);
+        isTranslucent = app.isTranslucent;
+        clipRect = app.clipRect;
+        position = app.position;
+        sourceContainerBounds = app.sourceContainerBounds;
+        prefixOrderIndex = app.prefixOrderIndex;
+    }
+
+    public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
+        final RemoteAnimationTargetCompat[] appsCompat =
+                new RemoteAnimationTargetCompat[apps.length];
+        for (int i = 0; i < apps.length; i++) {
+            appsCompat[i] = new RemoteAnimationTargetCompat(apps[i]);
+        }
+        return appsCompat;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceControlCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceControlCompat.java
new file mode 100644
index 0000000..cd12141
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceControlCompat.java
@@ -0,0 +1,27 @@
+/*
+ * 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.view.SurfaceControl;
+
+public class SurfaceControlCompat {
+    SurfaceControl mSurfaceControl;
+
+    public SurfaceControlCompat(SurfaceControl surfaceControl) {
+        mSurfaceControl = surfaceControl;
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
new file mode 100644
index 0000000..c82c519
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -0,0 +1,108 @@
+/*
+ * 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.graphics.Matrix;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+
+public class TransactionCompat {
+
+    private final Transaction mTransaction;
+
+    private final float[] mTmpValues = new float[9];
+
+    public TransactionCompat() {
+        mTransaction = new Transaction();
+    }
+
+    public void apply() {
+        mTransaction.apply();
+    }
+
+    public TransactionCompat show(SurfaceControlCompat surfaceControl) {
+        mTransaction.show(surfaceControl.mSurfaceControl);
+        return this;
+    }
+
+    public TransactionCompat hide(SurfaceControlCompat surfaceControl) {
+        mTransaction.hide(surfaceControl.mSurfaceControl);
+        return this;
+    }
+
+    public TransactionCompat setPosition(SurfaceControlCompat surfaceControl, float x, float y) {
+        mTransaction.setPosition(surfaceControl.mSurfaceControl, x, y);
+        return this;
+    }
+
+    public TransactionCompat setSize(SurfaceControlCompat surfaceControl, int w, int h) {
+        mTransaction.setSize(surfaceControl.mSurfaceControl, w, h);
+        return this;
+    }
+
+    public TransactionCompat setLayer(SurfaceControlCompat surfaceControl, int z) {
+        mTransaction.setLayer(surfaceControl.mSurfaceControl, z);
+        return this;
+    }
+
+    public TransactionCompat setAlpha(SurfaceControlCompat surfaceControl, float alpha) {
+        mTransaction.setAlpha(surfaceControl.mSurfaceControl, alpha);
+        return this;
+    }
+
+    public TransactionCompat setMatrix(SurfaceControlCompat surfaceControl, float dsdx, float dtdx,
+            float dtdy, float dsdy) {
+        mTransaction.setMatrix(surfaceControl.mSurfaceControl, dsdx, dtdx, dtdy, dsdy);
+        return this;
+    }
+
+    public TransactionCompat setMatrix(SurfaceControlCompat surfaceControl, Matrix matrix) {
+        mTransaction.setMatrix(surfaceControl.mSurfaceControl, matrix, mTmpValues);
+        return this;
+    }
+
+    public TransactionCompat setWindowCrop(SurfaceControlCompat surfaceControl, Rect crop) {
+        mTransaction.setWindowCrop(surfaceControl.mSurfaceControl, crop);
+        return this;
+    }
+
+    public TransactionCompat setFinalCrop(SurfaceControlCompat surfaceControl, Rect crop) {
+        mTransaction.setFinalCrop(surfaceControl.mSurfaceControl, crop);
+        return this;
+    }
+
+    public TransactionCompat deferTransactionUntil(SurfaceControlCompat surfaceControl,
+            IBinder handle, long frameNumber) {
+        mTransaction.deferTransactionUntil(surfaceControl.mSurfaceControl, handle, frameNumber);
+        return this;
+    }
+
+    public TransactionCompat deferTransactionUntil(SurfaceControlCompat surfaceControl,
+            Surface barrier, long frameNumber) {
+        mTransaction.deferTransactionUntilSurface(surfaceControl.mSurfaceControl, barrier,
+                frameNumber);
+        return this;
+    }
+
+    public TransactionCompat setColor(SurfaceControlCompat surfaceControl, float[] color) {
+        mTransaction.setColor(surfaceControl.mSurfaceControl, color);
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 225dbb4..68400fc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -20,9 +20,10 @@
 
 import android.graphics.Rect;
 import android.os.Handler;
-import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.RemoteAnimationAdapter;
+import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
@@ -32,6 +33,31 @@
 
     private static final String TAG = "WindowManagerWrapper";
 
+    public static final int TRANSIT_UNSET = WindowManager.TRANSIT_UNSET;
+    public static final int TRANSIT_NONE = WindowManager.TRANSIT_NONE;
+    public static final int TRANSIT_ACTIVITY_OPEN = WindowManager.TRANSIT_ACTIVITY_OPEN;
+    public static final int TRANSIT_ACTIVITY_CLOSE = WindowManager.TRANSIT_ACTIVITY_CLOSE;
+    public static final int TRANSIT_TASK_OPEN = WindowManager.TRANSIT_TASK_OPEN;
+    public static final int TRANSIT_TASK_CLOSE = WindowManager.TRANSIT_TASK_CLOSE;
+    public static final int TRANSIT_TASK_TO_FRONT = WindowManager.TRANSIT_TASK_TO_FRONT;
+    public static final int TRANSIT_TASK_TO_BACK = WindowManager.TRANSIT_TASK_TO_BACK;
+    public static final int TRANSIT_WALLPAPER_CLOSE = WindowManager.TRANSIT_WALLPAPER_CLOSE;
+    public static final int TRANSIT_WALLPAPER_OPEN = WindowManager.TRANSIT_WALLPAPER_OPEN;
+    public static final int TRANSIT_WALLPAPER_INTRA_OPEN =
+            WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
+    public static final int TRANSIT_WALLPAPER_INTRA_CLOSE =
+            WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
+    public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_TASK_OPEN_BEHIND;
+    public static final int TRANSIT_TASK_IN_PLACE = WindowManager.TRANSIT_TASK_IN_PLACE;
+    public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
+    public static final int TRANSIT_DOCK_TASK_FROM_RECENTS =
+            WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+    public static final int TRANSIT_KEYGUARD_GOING_AWAY = WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+    public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
+            WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+    public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
+    public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
     private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
 
     public static WindowManagerWrapper getInstance() {
@@ -65,4 +91,14 @@
             Log.w(TAG, "Failed to override pending app transition (multi-thumbnail future): ", e);
         }
     }
+
+    public void overridePendingAppTransitionRemote(
+            RemoteAnimationAdapterCompat remoteAnimationAdapter) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().overridePendingAppTransitionRemote(
+                    remoteAnimationAdapter.getWrapped());
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to override pending app transition (remote): ", e);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index a7d1f0d..0be522b 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -51,7 +51,8 @@
  */
 public class OverviewProxyService implements CallbackController<OverviewProxyListener>, Dumpable {
 
-    private static final String TAG = "OverviewProxyService";
+    public static final String TAG_OPS = "OverviewProxyService";
+    public static final boolean DEBUG_OVERVIEW_PROXY = false;
     private static final long BACKOFF_MILLIS = 5000;
 
     private final Context mContext;
@@ -96,12 +97,12 @@
                 try {
                     service.linkToDeath(mOverviewServiceDeathRcpt, 0);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Lost connection to launcher service", e);
+                    Log.e(TAG_OPS, "Lost connection to launcher service", e);
                 }
                 try {
                     mOverviewProxy.onBind(mSysUiProxy);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to call onBind()", e);
+                    Log.e(TAG_OPS, "Failed to call onBind()", e);
                 }
                 notifyConnectionChanged();
             }
@@ -211,7 +212,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(TAG + " state:");
+        pw.println(TAG_OPS + " state:");
         pw.print("  mConnectionBackoffAttempts="); pw.println(mConnectionBackoffAttempts);
         pw.print("  isCurrentUserSetup="); pw.println(mDeviceProvisionedController
                 .isCurrentUserSetup());
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 653e500..8501519 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -707,6 +707,10 @@
                     && !mLockPatternUtils.isLockScreenDisabled(
                             KeyguardUpdateMonitor.getCurrentUser()),
                     mSecondaryDisplayShowing, true /* forceCallbacks */);
+        } else {
+            // The system's keyguard is disabled or missing.
+            setShowingLocked(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()),
+                    mSecondaryDisplayShowing, true);
         }
 
         mStatusBarKeyguardViewManager =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 9ee40cc..d9583af 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -41,6 +41,7 @@
     private ImageView mOut;
 
     private int mWideOverlayIconStartPadding;
+    private int mSignalIndicatorToIconFrameSpacing;
 
     public SignalTileView(Context context) {
         super(context);
@@ -48,8 +49,13 @@
         mIn = addTrafficView(R.drawable.ic_qs_signal_in);
         mOut = addTrafficView(R.drawable.ic_qs_signal_out);
 
+        setClipChildren(false);
+        setClipToPadding(false);
+
         mWideOverlayIconStartPadding = context.getResources().getDimensionPixelSize(
                 R.dimen.wide_type_icon_start_padding_qs);
+        mSignalIndicatorToIconFrameSpacing = context.getResources().getDimensionPixelSize(
+                R.dimen.signal_indicator_to_icon_frame_spacing);
     }
 
     private ImageView addTrafficView(int icon) {
@@ -99,10 +105,10 @@
         boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
         int left, right;
         if (isRtl) {
-            right = mIconFrame.getLeft();
+            right = getLeft() - mSignalIndicatorToIconFrameSpacing;
             left = right - indicator.getMeasuredWidth();
         } else {
-            left = mIconFrame.getRight();
+            left = getRight() + mSignalIndicatorToIconFrameSpacing;
             right = left + indicator.getMeasuredWidth();
         }
         indicator.layout(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index acd327b..b4cfda6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -85,6 +85,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
         params.setMargins(0, padding, 0, padding);
         mIconFrame.addView(mIcon, params);
+        mIconFrame.setClipChildren(false);
+        mIconFrame.setClipToPadding(false);
 
         mTileBackground = newTileBackground();
         if (mTileBackground instanceof RippleDrawable) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 263dac0..9eb9906 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -18,6 +18,7 @@
 import android.content.res.Configuration;
 import android.service.quicksettings.Tile;
 import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -36,8 +37,10 @@
 /** View that represents a standard quick settings tile. **/
 public class QSTileView extends QSTileBaseView {
 
+    private static final boolean DUAL_TARGET_ALLOWED = false;
     private View mDivider;
     protected TextView mLabel;
+    private TextView mSecondLine;
     private ImageView mPadLock;
     private int mState;
     private ViewGroup mLabelContainer;
@@ -86,6 +89,8 @@
         mDivider = mLabelContainer.findViewById(R.id.underline);
         mExpandIndicator = mLabelContainer.findViewById(R.id.expand_indicator);
         mExpandSpace = mLabelContainer.findViewById(R.id.expand_space);
+        mSecondLine = mLabelContainer.findViewById(R.id.app_label);
+        mSecondLine.setAlpha(.6f);
 
         addView(mLabelContainer);
     }
@@ -103,14 +108,20 @@
             mState = state.state;
             mLabel.setText(state.label);
         }
-        mExpandIndicator.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE);
-        mExpandSpace.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE);
-        mLabelContainer.setContentDescription(state.dualTarget ? state.dualLabelContentDescription
+        if (!Objects.equal(mSecondLine.getText(), state.secondaryLabel)) {
+            mSecondLine.setText(state.secondaryLabel);
+            mSecondLine.setVisibility(TextUtils.isEmpty(state.secondaryLabel) ? View.GONE
+                    : View.VISIBLE);
+        }
+        boolean dualTarget = DUAL_TARGET_ALLOWED && state.dualTarget;
+        mExpandIndicator.setVisibility(dualTarget ? View.VISIBLE : View.GONE);
+        mExpandSpace.setVisibility(dualTarget ? View.VISIBLE : View.GONE);
+        mLabelContainer.setContentDescription(dualTarget ? state.dualLabelContentDescription
                 : null);
-        if (state.dualTarget != mLabelContainer.isClickable()) {
-            mLabelContainer.setClickable(state.dualTarget);
-            mLabelContainer.setLongClickable(state.dualTarget);
-            mLabelContainer.setBackground(state.dualTarget ? newTileBackground() : null);
+        if (dualTarget != mLabelContainer.isClickable()) {
+            mLabelContainer.setClickable(dualTarget);
+            mLabelContainer.setLongClickable(dualTarget);
+            mLabelContainer.setBackground(dualTarget ? newTileBackground() : null);
         }
         mLabel.setEnabled(!state.disabledByPolicy);
         mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE);
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 0e4a9fe..fff9f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -125,11 +125,11 @@
             state.slash = new SlashState();
         }
         state.slash.isSlashed = !enabled;
+        state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
         if (enabled) {
-            state.label = null;
             if (connected) {
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
-                state.label = mController.getLastDeviceName();
+                state.secondaryLabel = mController.getLastDeviceName();
                 CachedBluetoothDevice lastDevice = mController.getLastDevice();
                 if (lastDevice != null) {
                     int batteryLevel = lastDevice.getBatteryLevel();
@@ -140,25 +140,20 @@
                     }
                 }
                 state.contentDescription = mContext.getString(
-                        R.string.accessibility_bluetooth_name, state.label);
+                        R.string.accessibility_bluetooth_name, state.secondaryLabel);
             } else if (state.isTransient) {
                 state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_connecting);
-                state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             } else {
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_on) + ","
                         + mContext.getString(R.string.accessibility_not_connected);
             }
-            if (TextUtils.isEmpty(state.label)) {
-                state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
-            }
             state.state = Tile.STATE_ACTIVE;
         } else {
             state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on);
-            state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_bluetooth_off);
             state.state = Tile.STATE_INACTIVE;
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 763ffc6..99a9be3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Intent;
 import android.provider.Settings;
@@ -29,9 +30,17 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
+import java.time.format.DateTimeFormatter;
+
 public class NightDisplayTile extends QSTileImpl<BooleanState>
         implements ColorDisplayController.Callback {
 
+    /**
+     * 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 ColorDisplayController mController;
     private boolean mIsListening;
 
@@ -74,13 +83,49 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        final boolean isActivated = mController.isActivated();
-        state.value = isActivated;
+        state.value = mController.isActivated();
         state.label = state.contentDescription =
                 mContext.getString(R.string.quick_settings_night_display_label);
         state.icon = ResourceIcon.get(R.drawable.ic_qs_night_display_on);
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+        state.secondaryLabel = getSecondaryLabel(state.value);
+    }
+
+    /**
+     * Returns a {@link String} for the secondary label that reflects when the light will be turned
+     * on or off based on the current auto mode and night light activated status.
+     */
+    @Nullable
+    private String getSecondaryLabel(boolean isNightLightActivated) {
+        switch(mController.getAutoMode()) {
+            case ColorDisplayController.AUTO_MODE_TWILIGHT:
+                // Auto mode related to sunrise & sunset. If the light is on, it's guaranteed to be
+                // turned off at sunrise. If it's off, it's guaranteed to be turned on at sunset.
+                return isNightLightActivated
+                        ? mContext.getString(
+                                R.string.quick_settings_night_secondary_label_until_sunrise)
+                        : mContext.getString(
+                                R.string.quick_settings_night_secondary_label_on_at_sunset);
+
+            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)));
+
+            default:
+                // No secondary label when auto mode is disabled.
+                return null;
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 1e00894..60422ee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -36,20 +36,8 @@
 
 /** Quick settings tile: Rotation **/
 public class RotationLockTile extends QSTileImpl<BooleanState> {
-    private final AnimationIcon mPortraitToAuto
-            = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation,
-            R.drawable.ic_portrait_from_auto_rotate);
-    private final AnimationIcon mAutoToPortrait
-            = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation,
-            R.drawable.ic_portrait_to_auto_rotate);
 
-    private final AnimationIcon mLandscapeToAuto
-            = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation,
-            R.drawable.ic_landscape_from_auto_rotate);
-    private final AnimationIcon mAutoToLandscape
-            = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation,
-            R.drawable.ic_landscape_to_auto_rotate);
-
+    private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_auto_rotate);
     private final RotationLockController mController;
 
     public RotationLockTile(QSHost host) {
@@ -93,19 +81,10 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         if (mController == null) return;
         final boolean rotationLocked = mController.isRotationLocked();
-        // TODO: Handle accessibility rotation lock and whatnot.
 
         state.value = !rotationLocked;
-        final boolean portrait = isCurrentOrientationLockPortrait(mController, mContext);
-        if (rotationLocked) {
-            final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label
-                    : R.string.quick_settings_rotation_locked_landscape_label;
-            state.label = mContext.getString(label);
-            state.icon = portrait ? mAutoToPortrait : mAutoToLandscape;
-        } else {
-            state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
-            state.icon = portrait ? mPortraitToAuto : mLandscapeToAuto;
-        }
+        state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
+        state.icon = mIcon;
         state.contentDescription = getAccessibilityString(rotationLocked);
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
@@ -134,18 +113,7 @@
      * @param locked Whether or not rotation is locked.
      */
     private String getAccessibilityString(boolean locked) {
-        if (locked) {
-            return mContext.getString(R.string.accessibility_quick_settings_rotation_value,
-                    isCurrentOrientationLockPortrait(mController, mContext)
-                            ? mContext.getString(
-                                    R.string.quick_settings_rotation_locked_portrait_label)
-                            : mContext.getString(
-                                    R.string.quick_settings_rotation_locked_landscape_label))
-                    + "," + mContext.getString(R.string.accessibility_quick_settings_rotation);
-
-        } else {
-            return mContext.getString(R.string.accessibility_quick_settings_rotation);
-        }
+        return mContext.getString(R.string.accessibility_quick_settings_rotation);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index d1e6dcc..5f4854a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -33,6 +33,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
@@ -173,6 +174,7 @@
     private FalsingManager mFalsingManager;
     private AboveShelfChangedListener mAboveShelfChangedListener;
     private HeadsUpManager mHeadsUpManager;
+    private View mHelperButton;
 
     private boolean mJustClicked;
     private boolean mIconAnimationRunning;
@@ -387,6 +389,9 @@
         updateLimits();
         updateIconVisibilities();
         updateShelfIconColor();
+
+        showBlockingHelper(mEntry.userSentiment ==
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
     }
 
     @VisibleForTesting
@@ -1318,6 +1323,10 @@
         requestLayout();
     }
 
+    public void showBlockingHelper(boolean show) {
+        mHelperButton.setVisibility(show ? View.VISIBLE : View.GONE);
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
@@ -1325,6 +1334,12 @@
         mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
         mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
 
+        final NotificationGutsManager gutsMan = Dependency.get(NotificationGutsManager.class);
+        mHelperButton = findViewById(R.id.helper);
+        mHelperButton.setOnClickListener(view -> {
+            doLongClickCallback();
+        });
+
         for (NotificationContentView l : mLayouts) {
             l.setExpandClickListener(mExpandClickListener);
             l.setContainingNotification(this);
@@ -2362,7 +2377,9 @@
             NotificationContentView contentView = (NotificationContentView) child;
             if (isClippingNeeded()) {
                 return true;
-            } else if (!hasNoRounding() && contentView.shouldClipToRounding()) {
+            } else if (!hasNoRounding()
+                    && contentView.shouldClipToRounding(getCurrentTopRoundness() != 0.0f,
+                    getCurrentBottomRoundness() != 0.0f)) {
                 return true;
             }
         } else if (child == mChildrenContainer) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index c73e548..64df92c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -1489,19 +1489,21 @@
         return false;
     }
 
-    public boolean shouldClipToRounding() {
-        boolean needsPaddings = shouldClipToRounding(getVisibleType());
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        boolean needsPaddings = shouldClipToRounding(getVisibleType(), topRounded, bottomRounded);
         if (mUserExpanding) {
-             needsPaddings |= shouldClipToRounding(mTransformationStartVisibleType);
+             needsPaddings |= shouldClipToRounding(mTransformationStartVisibleType, topRounded,
+                     bottomRounded);
         }
         return needsPaddings;
     }
 
-    private boolean shouldClipToRounding(int visibleType) {
+    private boolean shouldClipToRounding(int visibleType, boolean topRounded,
+            boolean bottomRounded) {
         NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
         if (visibleWrapper == null) {
             return false;
         }
-        return visibleWrapper.shouldClipToRounding();
+        return visibleWrapper.shouldClipToRounding(topRounded, bottomRounded);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index d0417b5..127f3f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -67,6 +67,7 @@
 
     public static final class Entry {
         private static final long LAUNCH_COOLDOWN = 2000;
+        private static final long REMOTE_INPUT_COOLDOWN = 500;
         private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
         private static final int COLOR_INVALID = 1;
         public String key;
@@ -86,10 +87,14 @@
         public RemoteViews cachedAmbientContentView;
         public CharSequence remoteInputText;
         public List<SnoozeCriterion> snoozeCriteria;
+        public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL;
+
         private int mCachedContrastColor = COLOR_INVALID;
         private int mCachedContrastColorIsFor = COLOR_INVALID;
         private InflationTask mRunningTask = null;
         private Throwable mDebugThrowable;
+        public CharSequence remoteInputTextWhenReset;
+        public long lastRemoteInputSent = NOT_LAUNCHED_YET;
 
         public Entry(StatusBarNotification n) {
             this.key = n.getKey();
@@ -130,6 +135,10 @@
             return SystemClock.elapsedRealtime() < lastFullScreenIntentLaunchTime + LAUNCH_COOLDOWN;
         }
 
+        public boolean hasJustSentRemoteInput() {
+            return SystemClock.elapsedRealtime() < lastRemoteInputSent + REMOTE_INPUT_COOLDOWN;
+        }
+
         /**
          * Create the icons for a notification
          * @param context the context to create the icons with
@@ -263,6 +272,11 @@
         public Throwable getDebugThrowable() {
             return mDebugThrowable;
         }
+
+        public void onRemoteInputInserted() {
+            lastRemoteInputSent = NOT_LAUNCHED_YET;
+            remoteInputTextWhenReset = null;
+        }
     }
 
     private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
@@ -463,6 +477,7 @@
                     }
                     entry.channel = getChannel(entry.key);
                     entry.snoozeCriteria = getSnoozeCriteria(entry.key);
+                    entry.userSentiment = mTmpRanking.getUserSentiment();
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
index 6bbd09f..5b06874 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
@@ -35,6 +35,7 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.Log;
@@ -462,7 +463,8 @@
         mMediaManager.onNotificationRemoved(key);
 
         NotificationData.Entry entry = mNotificationData.get(key);
-        if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputManager.getController().isSpinning(key)
+        if (FORCE_REMOTE_INPUT_HISTORY
+                && shouldKeepForRemoteInput(entry)
                 && entry.row != null && !entry.row.isDismissed()) {
             StatusBarNotification sbn = entry.notification;
 
@@ -477,7 +479,11 @@
                 newHistory = new CharSequence[oldHistory.length + 1];
                 System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
             }
-            newHistory[0] = String.valueOf(entry.remoteInputText);
+            CharSequence remoteInputText = entry.remoteInputText;
+            if (TextUtils.isEmpty(remoteInputText)) {
+                remoteInputText = entry.remoteInputTextWhenReset;
+            }
+            newHistory[0] = String.valueOf(remoteInputText);
             b.setRemoteInputHistory(newHistory);
 
             Notification newNotification = b.build();
@@ -492,6 +498,7 @@
                     sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
                     newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
             boolean updated = false;
+            entry.onRemoteInputInserted();
             try {
                 updateNotificationInternal(newSbn, null);
                 updated = true;
@@ -539,6 +546,19 @@
         mCallback.onNotificationRemoved(key, old);
     }
 
+    private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
+        if (entry == null) {
+            return false;
+        }
+        if (mRemoteInputManager.getController().isSpinning(entry.key)) {
+            return true;
+        }
+        if (entry.hasJustSentRemoteInput()) {
+            return true;
+        }
+        return false;
+    }
+
     private StatusBarNotification removeNotificationViews(String key,
             NotificationListenerService.RankingMap ranking) {
         NotificationData.Entry entry = mNotificationData.remove(key, ranking);
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 6cbbd6c..e5a311d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -17,11 +17,15 @@
 package com.android.systemui.statusbar.car;
 
 import android.content.Context;
+import android.graphics.Canvas;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.LinearLayout;
 
 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;
 
 /**
@@ -72,4 +76,68 @@
         // 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() {
+        }
+    }
 }
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 27defca..113118a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -26,9 +26,7 @@
 import com.android.internal.widget.MessagingLinearLayout;
 import com.android.internal.widget.MessagingMessage;
 import com.android.internal.widget.MessagingPropertyAnimator;
-import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -157,8 +155,8 @@
             setClippingDeactivated(child, true);
         }
         appear(ownGroup.getAvatar(), transformationAmount);
-        appear(ownGroup.getSender(), transformationAmount);
-        setClippingDeactivated(ownGroup.getSender(), true);
+        appear(ownGroup.getSenderView(), transformationAmount);
+        setClippingDeactivated(ownGroup.getSenderView(), true);
         setClippingDeactivated(ownGroup.getAvatar(), true);
     }
 
@@ -170,7 +168,7 @@
         } else {
             relativeOffset = (1.0f - transformationAmount) * mRelativeTranslationOffset;
         }
-        if (ownGroup.getSender().getVisibility() != View.GONE) {
+        if (ownGroup.getSenderView().getVisibility() != View.GONE) {
             relativeOffset *= 0.5f;
         }
         ownGroup.getMessageContainer().setTranslationY(relativeOffset);
@@ -188,8 +186,8 @@
             setClippingDeactivated(child, true);
         }
         disappear(ownGroup.getAvatar(), transformationAmount);
-        disappear(ownGroup.getSender(), transformationAmount);
-        setClippingDeactivated(ownGroup.getSender(), true);
+        disappear(ownGroup.getSenderView(), transformationAmount);
+        setClippingDeactivated(ownGroup.getSenderView(), true);
         setClippingDeactivated(ownGroup.getAvatar(), true);
     }
 
@@ -226,7 +224,7 @@
 
     private void transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
             float transformationAmount, boolean to) {
-        transformView(transformationAmount, to, ownGroup.getSender(), otherGroup.getSender(),
+        transformView(transformationAmount, to, ownGroup.getSenderView(), otherGroup.getSenderView(),
                 true /* sameAsAny */);
         transformView(transformationAmount, to, ownGroup.getAvatar(), otherGroup.getAvatar(),
                 true /* sameAsAny */);
@@ -345,7 +343,7 @@
                     setVisible(child, visible, force);
                 }
                 setVisible(ownGroup.getAvatar(), visible, force);
-                setVisible(ownGroup.getSender(), visible, force);
+                setVisible(ownGroup.getSenderView(), visible, force);
             }
         }
     }
@@ -376,9 +374,9 @@
                     setClippingDeactivated(child, false);
                 }
                 resetTransformedView(ownGroup.getAvatar());
-                resetTransformedView(ownGroup.getSender());
+                resetTransformedView(ownGroup.getSenderView());
                 setClippingDeactivated(ownGroup.getAvatar(), false);
-                setClippingDeactivated(ownGroup.getSender(), false);
+                setClippingDeactivated(ownGroup.getSenderView(), false);
                 ownGroup.setTranslationY(0);
                 ownGroup.getMessageContainer().setTranslationY(0);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 0d22095..adc0914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
-import android.os.Build;
 import android.view.View;
 
 import com.android.systemui.R;
@@ -118,7 +117,7 @@
     }
 
     @Override
-    public boolean shouldClipToRounding() {
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
         return true;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index d7c08cc..548f006 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public boolean shouldClipToRounding() {
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
         return true;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index fd085d9..d463eae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -265,6 +265,15 @@
         updateActionOffset();
     }
 
+    @Override
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
+        if (super.shouldClipToRounding(topRounded, bottomRounded)) {
+            return true;
+        }
+        return bottomRounded && mActionsContainer != null
+                && mActionsContainer.getVisibility() != View.GONE;
+    }
+
     private void updateActionOffset() {
         if (mActionsContainer != null) {
             // We should never push the actions higher than they are in the headsup view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index c71d604..17eb4c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -195,7 +195,7 @@
         return 0;
     }
 
-    public boolean shouldClipToRounding() {
+    public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
         return false;
     }
 }
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 4faa84a..ff923e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -43,6 +43,8 @@
 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.
@@ -118,6 +120,9 @@
             event.transform(mTransformGlobalMatrix);
             try {
                 overviewProxy.onMotionEvent(event);
+                if (DEBUG_OVERVIEW_PROXY) {
+                    Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
+                }
                 return true;
             } catch (RemoteException e) {
                 Log.e(TAG, "Callback failed", e);
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 f41cb29..6857337 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -39,7 +39,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.graphics.drawable.Icon;
 import android.media.AudioManager;
 import android.net.Uri;
@@ -66,7 +65,6 @@
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
 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.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -146,7 +144,6 @@
     private boolean mDockedStackExists;
 
     private boolean mManagedProfileIconVisible = false;
-    private boolean mManagedProfileInQuietMode = false;
 
     private BluetoothController mBluetooth;
 
@@ -474,17 +471,6 @@
         }
     }
 
-    private void updateQuietState() {
-        mManagedProfileInQuietMode = false;
-        int currentUserId = ActivityManager.getCurrentUser();
-        for (UserInfo ui : mUserManager.getEnabledProfiles(currentUserId)) {
-            if (ui.isManagedProfile() && ui.isQuietModeEnabled()) {
-                mManagedProfileInQuietMode = true;
-                return;
-            }
-        }
-    }
-
     private void updateManagedProfile() {
         // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
         // some cases. Since it doesn't really matter here whether it's updated in this frame
@@ -502,11 +488,6 @@
                         mIconController.setIcon(mSlotManagedProfile,
                                 R.drawable.stat_sys_managed_profile_status,
                                 mContext.getString(R.string.accessibility_managed_profile));
-                    } else if (mManagedProfileInQuietMode) {
-                        showIcon = true;
-                        mIconController.setIcon(mSlotManagedProfile,
-                                R.drawable.stat_sys_managed_profile_status_off,
-                                mContext.getString(R.string.accessibility_managed_profile));
                     } else {
                         showIcon = false;
                     }
@@ -676,7 +657,6 @@
                 public void onUserSwitchComplete(int newUserId) throws RemoteException {
                     mHandler.post(() -> {
                         updateAlarm();
-                        updateQuietState();
                         updateManagedProfile();
                         updateForegroundInstantApps();
                     });
@@ -724,7 +704,6 @@
         if (mCurrentUserSetup == userSetup) return;
         mCurrentUserSetup = userSetup;
         updateAlarm();
-        updateQuietState();
     }
 
     @Override
@@ -793,7 +772,6 @@
             } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) ||
                     action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) ||
                     action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)) {
-                updateQuietState();
                 updateManagedProfile();
             } else if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
                 updateHeadsetPlug(intent);
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 9f8a7ef..6fc5bbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -49,6 +49,8 @@
 
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
 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;
 
 /**
  * Class to detect gestures on the navigation bar and implement quick scrub and switch.
@@ -144,6 +146,9 @@
                     try {
                         final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
                         overviewProxy.onQuickSwitch();
+                        if (DEBUG_OVERVIEW_PROXY) {
+                            Log.d(TAG_OPS, "Quick Switch");
+                        }
                     } catch (RemoteException e) {
                         Log.e(TAG, "Failed to send start of quick switch.", e);
                     }
@@ -207,21 +212,31 @@
                     int y = (int) event.getY();
                     int xDiff = Math.abs(x - mTouchDownX);
                     int yDiff = Math.abs(y - mTouchDownY);
-                    boolean exceededTouchSlop;
+                    boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
+                    boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
+                    boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
                     int pos, touchDown, offset, trackSize;
+
                     if (mIsVertical) {
-                        exceededTouchSlop = yDiff > mScrollTouchSlop && yDiff > xDiff;
+                        exceededTouchSlop = exceededTouchSlopY;
+                        exceededPerpendicularTouchSlop = exceededTouchSlopX;
                         pos = y;
                         touchDown = mTouchDownY;
                         offset = pos - mTrackRect.top;
                         trackSize = mTrackRect.height();
                     } else {
-                        exceededTouchSlop = xDiff > mScrollTouchSlop && xDiff > yDiff;
+                        exceededTouchSlop = exceededTouchSlopX;
+                        exceededPerpendicularTouchSlop = exceededTouchSlopY;
                         pos = x;
                         touchDown = mTouchDownX;
                         offset = pos - mTrackRect.left;
                         trackSize = mTrackRect.width();
                     }
+                    // Do not start scrubbing when dragging in the perpendicular direction
+                    if (!mDraggingActive && exceededPerpendicularTouchSlop) {
+                        mHandler.removeCallbacksAndMessages(null);
+                        return false;
+                    }
                     if (!mDragPositive) {
                         offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
                     }
@@ -246,6 +261,9 @@
                         if (mQuickScrubActive) {
                             try {
                                 overviewProxy.onQuickScrubProgress(scrubFraction);
+                                if (DEBUG_OVERVIEW_PROXY) {
+                                    Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
+                                }
                             } catch (RemoteException e) {
                                 Log.e(TAG, "Failed to send progress of quick scrub.", e);
                             }
@@ -294,12 +312,14 @@
 
         // Get the touch rect of the home button location
         View homeView = mNavigationBarView.getHomeButton().getCurrentView();
-        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());
+        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
@@ -343,6 +363,9 @@
             mTrackAnimator.start();
             try {
                 mOverviewEventSender.getProxy().onQuickScrubStart();
+                if (DEBUG_OVERVIEW_PROXY) {
+                    Log.d(TAG_OPS, "Quick Scrub Start");
+                }
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to send start of quick scrub.", e);
             }
@@ -357,6 +380,9 @@
             mQuickScrubEndAnimator.start();
             try {
                 mOverviewEventSender.getProxy().onQuickScrubEnd();
+                if (DEBUG_OVERVIEW_PROXY) {
+                    Log.d(TAG_OPS, "Quick Scrub End");
+                }
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to send end of quick scrub.", e);
             }
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 af65a86..5e08ec3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4931,18 +4931,11 @@
                     // system process is dead if we're here.
                 }
                 if (parentToCancelFinal != null) {
-                    // We have to post it to the UI thread for synchronization
-                    mHandler.post(() -> {
-                        Runnable removeRunnable =
-                                () -> mEntryManager.performRemoveNotification(parentToCancelFinal);
-                        if (isCollapsing()) {
-                            // To avoid lags we're only performing the remove
-                            // after the shade was collapsed
-                            addPostCollapseAction(removeRunnable);
-                        } else {
-                            removeRunnable.run();
-                        }
-                    });
+                    removeNotification(parentToCancelFinal);
+                }
+                if (shouldAutoCancel(sbn)) {
+                    // Automatically remove all notifications that we may have kept around longer
+                    removeNotification(sbn);
                 }
             };
 
@@ -4966,6 +4959,21 @@
         }, afterKeyguardGone);
     }
 
+    private void removeNotification(StatusBarNotification notification) {
+        // We have to post it to the UI thread for synchronization
+        mHandler.post(() -> {
+            Runnable removeRunnable =
+                    () -> mEntryManager.performRemoveNotification(notification);
+            if (isCollapsing()) {
+                // To avoid lags we're only performing the remove
+                // after the shade was collapsed
+                addPostCollapseAction(removeRunnable);
+            } else {
+                removeRunnable.run();
+            }
+        });
+    }
+
     protected NotificationListener mNotificationListener;
 
     protected void notifyUserAboutHiddenNotifications() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
index 2951943..2ede327 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -74,17 +74,9 @@
         }
     }
 
-    private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
-        public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
-        }
-
-        @Override
-        public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
-        }
-
-        @Override
-        public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
+        public void onRestrictBackgroundChanged(final boolean isDataSaving) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -92,10 +84,6 @@
                 }
             });
         }
-
-        @Override
-        public void onUidPoliciesChanged(int uid, int uidPolicies) throws RemoteException {
-        }
     };
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 4fc50442..c377feb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -27,7 +27,9 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.SystemClock;
 import android.text.Editable;
+import android.text.SpannedString;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -140,6 +142,7 @@
         mSendButton.setVisibility(INVISIBLE);
         mProgressBar.setVisibility(VISIBLE);
         mEntry.remoteInputText = mEditText.getText();
+        mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
         mController.addSpinning(mEntry.key, mToken);
         mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
@@ -298,6 +301,7 @@
 
     private void reset() {
         mResetting = true;
+        mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText());
 
         mEditText.getText().clear();
         mEditText.setEnabled(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
new file mode 100644
index 0000000..1dcdf63
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -0,0 +1,63 @@
+package com.android.systemui.statusbar.policy;
+
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+
+/** View which displays smart reply buttons in notifications. */
+public class SmartReplyView extends LinearLayout {
+
+    private static final String TAG = "SmartReplyView";
+
+    public SmartReplyView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setRepliesFromRemoteInput(RemoteInput remoteInput, PendingIntent pendingIntent) {
+        removeAllViews();
+        if (remoteInput != null && pendingIntent != null) {
+            CharSequence[] choices = remoteInput.getChoices();
+            if (choices != null) {
+                for (CharSequence choice : choices) {
+                    Button replyButton = inflateReplyButton(
+                            getContext(), this, choice, remoteInput, pendingIntent);
+                    addView(replyButton);
+                }
+            }
+        }
+    }
+
+    public static SmartReplyView inflate(Context context, ViewGroup root) {
+        return (SmartReplyView)
+                LayoutInflater.from(context).inflate(R.layout.smart_reply_view, root, false);
+    }
+
+    private 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);
+        b.setText(choice);
+        b.setOnClickListener(view -> {
+            Bundle results = new Bundle();
+            results.putString(remoteInput.getResultKey(), choice.toString());
+            Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            RemoteInput.addResultsToIntent(new RemoteInput[]{remoteInput}, intent, results);
+            try {
+                pendingIntent.send(context, 0, intent);
+            } catch (PendingIntent.CanceledException e) {
+                Log.w(TAG, "Unable to send smart reply", e);
+            }
+        });
+        return b;
+    }
+}
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 4d8da44..ebf4cda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.stack;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.view.View;
 
@@ -236,6 +237,7 @@
         mShelf = shelf;
     }
 
+    @Nullable
     public NotificationShelf getShelf() {
         return mShelf;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 7374f11..2ce6df2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -122,7 +122,9 @@
     }
     private void updateShelfState(StackScrollState resultState, AmbientState ambientState) {
         NotificationShelf shelf = ambientState.getShelf();
-        shelf.updateState(resultState, ambientState);
+        if (shelf != null) {
+            shelf.updateState(resultState, ambientState);
+        }
     }
 
     private void updateClipping(StackScrollState resultState,
@@ -495,6 +497,10 @@
      */
     private void clampPositionToShelf(ExpandableViewState childViewState,
             AmbientState ambientState) {
+        if (ambientState.getShelf() == null) {
+            return;
+        }
+
         int shelfStart = ambientState.getInnerHeight()
                 - ambientState.getShelf().getIntrinsicHeight();
         childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
@@ -556,7 +562,8 @@
         } else if (i == 0 && ambientState.isAboveShelf(child)) {
             // In case this is a new view that has never been measured before, we don't want to
             // elevate if we are currently expanded more then the notification
-            int shelfHeight = ambientState.getShelf().getIntrinsicHeight();
+            int shelfHeight = ambientState.getShelf() == null ? 0 :
+                    ambientState.getShelf().getIntrinsicHeight();
             float shelfStart = ambientState.getInnerHeight()
                     - shelfHeight + ambientState.getTopPadding()
                     + ambientState.getStackTranslation();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index bc98140f..efa8386 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -52,7 +52,7 @@
     public static final String VOLUME_UP_SILENT = "sysui_volume_up_silent";
     public static final String VOLUME_SILENT_DO_NOT_DISTURB = "sysui_do_not_disturb";
 
-    public static final boolean DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT = true;
+    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;
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7b91f14..9041d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -20,6 +20,7 @@
 import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC;
 
 import static com.android.systemui.volume.Events.DISMISS_REASON_OUTPUT_CHOOSER;
+import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
 import static com.android.systemui.volume.Events.DISMISS_REASON_TOUCH_OUTSIDE;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
@@ -30,14 +31,13 @@
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
-import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.os.Debug;
@@ -45,9 +45,8 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.provider.Settings.Global;
-import android.transition.AutoTransition;
-import android.transition.TransitionManager;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
@@ -72,7 +71,6 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.plugins.VolumeDialog;
 import com.android.systemui.plugins.VolumeDialogController;
@@ -104,7 +102,6 @@
     private CustomDialog mDialog;
     private ViewGroup mDialogView;
     private ViewGroup mDialogRowsView;
-    private ImageButton mExpandButton;
     private ImageButton mRingerIcon;
     private ImageButton mOutputChooser;
     private TextView mRingerStatus;
@@ -120,8 +117,6 @@
     private final ColorStateList mInactiveSliderTint;
 
     private boolean mShowing;
-    private boolean mExpanded;
-    private boolean mExpandButtonAnimationRunning;
     private boolean mShowA11yStream;
 
     private int mActiveStream;
@@ -182,11 +177,11 @@
 
         mDialog.setContentView(R.layout.volume_dialog);
         mDialog.setOnShowListener(dialog -> {
-            mDialogView.setTranslationY(-mDialogView.getHeight());
+            mDialogView.setTranslationX(mDialogView.getWidth() / 2);
             mDialogView.setAlpha(0);
             mDialogView.animate()
                     .alpha(1)
-                    .translationY(0)
+                    .translationX(0)
                     .setDuration(300)
                     .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
                     .withEndAction(() -> {
@@ -205,20 +200,10 @@
         VolumeUiLayout hardwareLayout = VolumeUiLayout.get(mDialogView);
         hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
 
-        ViewGroup dialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
-        mDialogRowsView = dialogContentView.findViewById(R.id.volume_dialog_rows);
+        mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
         mRingerIcon = mDialog.findViewById(R.id.ringer_icon);
         mRingerStatus = mDialog.findViewById(R.id.ringer_status);
 
-        mExpanded = false;
-        mExpandButton = mDialogView.findViewById(R.id.volume_expand_button);
-        mExpandButton.setOnClickListener(mClickExpand);
-        mExpandButton.setVisibility(
-                AudioSystem.isSingleVolume(mContext) ? View.GONE : View.VISIBLE);
-
-        mOutputChooser = mDialogView.findViewById(R.id.output_chooser);
-        mOutputChooser.setOnClickListener(mClickOutputChooser);
-
         if (mRows.isEmpty()) {
             addRow(AudioManager.STREAM_MUSIC,
                     R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true);
@@ -239,6 +224,10 @@
         } else {
             addExistingRows();
         }
+
+        mOutputChooser = mDialogView.findViewById(R.id.output_chooser);
+        mOutputChooser.setOnClickListener(mClickOutputChooser);
+
         updateRowsH(getActiveRow());
         initRingerH();
     }
@@ -273,11 +262,9 @@
         VolumeRow row = new VolumeRow();
         initRow(row, stream, iconRes, iconMuteRes, important, defaultStream);
         int rowSize;
-        int viewSize;
-        if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1
-                && (viewSize = mDialogRowsView.getChildCount()) > 1) {
-            // A11y Stream should be the last in the list
-            mDialogRowsView.addView(row.view, viewSize - 2);
+        if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1) {
+            // A11y Stream should be the first in the list, so it's shown to start of other rows
+            mDialogRowsView.addView(row.view, 0);
             mRows.add(rowSize - 2, row);
         } else {
             mDialogRowsView.addView(row.view);
@@ -315,7 +302,6 @@
     public void dump(PrintWriter writer) {
         writer.println(VolumeDialogImpl.class.getSimpleName() + " state:");
         writer.print("  mShowing: "); writer.println(mShowing);
-        writer.print("  mExpanded: "); writer.println(mExpanded);
         writer.print("  mActiveStream: "); writer.println(mActiveStream);
         writer.print("  mDynamic: "); writer.println(mDynamic);
         writer.print("  mAutomute: "); writer.println(mAutomute);
@@ -382,16 +368,16 @@
                 mController.setActiveStream(row.stream);
                 if (row.stream == AudioManager.STREAM_RING) {
                     final boolean hasVibrator = mController.hasVibrator();
-                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                    if (mState.ringerModeExternal == AudioManager.RINGER_MODE_NORMAL) {
                         if (hasVibrator) {
-                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, true);
                         } else {
                             final boolean wasZero = row.ss.level == 0;
                             mController.setStreamVolume(stream,
                                     wasZero ? row.lastAudibleLevel : 0);
                         }
                     } else {
-                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, true);
                         if (row.ss.level == 0) {
                             mController.setStreamVolume(stream, 1);
                         }
@@ -417,21 +403,28 @@
                 return;
             }
             final boolean hasVibrator = mController.hasVibrator();
-            if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+            if (mState.ringerModeExternal == AudioManager.RINGER_MODE_NORMAL) {
                 if (hasVibrator) {
-                    mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                    mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, true);
                 } else {
                     final boolean wasZero = ss.level == 0;
                     mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
                 }
             } else {
-                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, true);
                 if (ss.level == 0) {
                     mController.setStreamVolume(AudioManager.STREAM_RING, 1);
                 }
             }
             updateRingerH();
         });
+        mRingerIcon.setOnLongClickListener(v -> {
+            Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            dismissH(DISMISS_REASON_SETTINGS_CLICKED);
+            mContext.startActivity(intent);
+            return true;
+        });
         updateRingerH();
     }
 
@@ -468,7 +461,6 @@
     private int computeTimeoutH() {
         if (mAccessibility.mFeedbackEnabled) return 20000;
         if (mHovering) return 16000;
-        if (mExpanded) return 5000;
         if (mSafetyWarning != null) return 5000;
         return 3000;
     }
@@ -480,13 +472,11 @@
         mDialogView.animate().cancel();
         mShowing = false;
 
-        updateExpandedH(false /* expanding */, true /* dismissing */);
-
-        mDialogView.setTranslationY(0);
+        mDialogView.setTranslationX(0);
         mDialogView.setAlpha(1);
         mDialogView.animate()
                 .alpha(0)
-                .translationY(-mDialogView.getHeight())
+                .translationX(mDialogView.getWidth() / 2)
                 .setDuration(250)
                 .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator())
                 .withEndAction(() -> mHandler.postDelayed(() -> {
@@ -514,67 +504,6 @@
         }
     }
 
-    private void updateExpandedH(final boolean expanded, final boolean dismissing) {
-        if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded);
-
-        if (mExpanded == expanded) return;
-        mExpanded = expanded;
-        mExpandButtonAnimationRunning = isAttached();
-        updateExpandButtonH();
-        TransitionManager.endTransitions(mDialogView);
-        final VolumeRow activeRow = getActiveRow();
-        if (!dismissing) {
-            mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
-            TransitionManager.beginDelayedTransition(mDialogView, getTransition());
-        }
-        updateRowsH(activeRow);
-        rescheduleTimeoutH();
-    }
-
-    private AutoTransition getTransition() {
-        AutoTransition transition = new AutoTransition();
-        transition.setDuration(300);
-        transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-        return transition;
-    }
-
-    private void updateExpandButtonH() {
-        if (D.BUG) Log.d(TAG, "updateExpandButtonH");
-
-        mExpandButton.setClickable(!mExpandButtonAnimationRunning);
-        if (!(mExpandButtonAnimationRunning && isAttached())) {
-            final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
-                    : R.drawable.ic_volume_expand_animation;
-            if (hasTouchFeature()) {
-                mExpandButton.setImageResource(res);
-            } else {
-                // if there is no touch feature, show the volume ringer instead
-                mExpandButton.setImageResource(R.drawable.ic_volume_ringer);
-                mExpandButton.setBackgroundResource(0);  // remove gray background emphasis
-            }
-            mExpandButton.setContentDescription(mContext.getString(mExpanded ?
-                    R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand));
-        }
-        if (mExpandButtonAnimationRunning) {
-            final Drawable d = mExpandButton.getDrawable();
-            if (d instanceof AnimatedVectorDrawable) {
-                // workaround to reset drawable
-                final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d.getConstantState()
-                        .newDrawable();
-                mExpandButton.setImageDrawable(avd);
-                avd.start();
-                mHandler.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        mExpandButtonAnimationRunning = false;
-                        updateExpandButtonH();
-                        rescheduleTimeoutH();
-                    }
-                }, 300);
-            }
-        }
-    }
-
     private boolean isAttached() {
         return mDialogView != null && mDialogView.isAttachedToWindow();
     }
@@ -597,7 +526,7 @@
             return true;
         }
 
-        return row.defaultStream || isActive || (mExpanded && row.important);
+        return row.defaultStream || isActive;
     }
 
     private void updateRowsH(final VolumeRow activeRow) {
@@ -623,7 +552,7 @@
             if (ss == null) {
                 return;
             }
-            switch (mState.ringerModeInternal) {
+            switch (mState.ringerModeExternal) {
                 case AudioManager.RINGER_MODE_VIBRATE:
                     mRingerStatus.setText(R.string.volume_ringer_status_vibrate);
                     mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
@@ -724,9 +653,9 @@
         final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
         final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC;
         final boolean isRingVibrate = isRingStream
-                && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
+                && mState.ringerModeExternal == AudioManager.RINGER_MODE_VIBRATE;
         final boolean isRingSilent = isRingStream
-                && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
+                && mState.ringerModeExternal == AudioManager.RINGER_MODE_SILENT;
         final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
         final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
@@ -954,16 +883,6 @@
         }
     }
 
-    private final OnClickListener mClickExpand = new OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            mExpandButton.animate().cancel();
-            final boolean newExpand = !mExpanded;
-            Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
-            updateExpandedH(newExpand, false /* dismissing */);
-        }
-    };
-
     private final OnClickListener mClickOutputChooser = new OnClickListener() {
         @Override
         public void onClick(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
index 49ac9b6..1c9cbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
@@ -14,15 +14,37 @@
 
 package com.android.systemui.volume;
 
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
 
 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;
     public VolumeUiLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -40,11 +62,245 @@
     }
 
     @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        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
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateRotation();
+    }
+
+    private void updateRotation() {
+        int rotation = RotationUtils.getRotation(getContext());
+        if (rotation != mRotation) {
+            rotate(mRotation, rotation);
+            mRotation = rotation;
+        }
+    }
+
+    private void rotate(View view, int from, int to, boolean swapDimens) {
+        if (from != ROTATION_NONE && to != ROTATION_NONE) {
+            // Rather than handling this confusing case, just do 2 rotations.
+            rotate(view, from, ROTATION_NONE, swapDimens);
+            rotate(view, ROTATION_NONE, to, swapDimens);
+            return;
+        }
+        if (from == ROTATION_LANDSCAPE || to == ROTATION_SEASCAPE) {
+            rotateRight(view);
+        } else {
+            rotateLeft(view);
+        }
+        if (to != ROTATION_NONE) {
+            if (swapDimens && view instanceof LinearLayout) {
+                LinearLayout linearLayout = (LinearLayout) view;
+                linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+                swapDimens(view);
+            }
+        } else {
+            if (swapDimens && view instanceof LinearLayout) {
+                LinearLayout linearLayout = (LinearLayout) view;
+                linearLayout.setOrientation(LinearLayout.VERTICAL);
+                swapDimens(view);
+            }
+        }
+    }
+
+    private void rotate(int from, int to) {
+        View footer = mChild.findViewById(R.id.footer);
+        rotate(footer, from, to, false);
+        rotate(this, from, to, true);
+        rotate(mChild, from, to, true);
+        ViewGroup rows = mChild.findViewById(R.id.volume_dialog_rows);
+        rotate(rows, from, to, true);
+        int rowCount = rows.getChildCount();
+        for (int i = 0; i < rowCount; i++) {
+            View child = rows.getChildAt(i);
+            if (to == ROTATION_SEASCAPE) {
+                rotateSeekBars(to, 0);
+            } else if (to == ROTATION_LANDSCAPE) {
+                rotateSeekBars(to, 180);
+            } else {
+                rotateSeekBars(to, 270);
+            }
+            rotate(child, from, to, true);
+        }
+    }
+
+    private void swapDimens(View v) {
+        if (v == null) {
+            return;
+        }
+        ViewGroup.LayoutParams params = v.getLayoutParams();
+        int h = params.width;
+        params.width = params.height;
+        params.height = h;
+        v.setLayoutParams(params);
+    }
+
+    private void rotateSeekBars(int to, int rotation) {
+        SeekBar seekbar = mChild.findViewById(R.id.volume_row_slider);
+        if (seekbar != null) {
+            seekbar.setRotation((float) rotation);
+        }
+
+        View parent = mChild.findViewById(R.id.volume_row_slider_frame);
+        swapDimens(parent);
+        ViewGroup.LayoutParams params = seekbar.getLayoutParams();
+        ViewGroup.LayoutParams parentParams = parent.getLayoutParams();
+        if (to != ROTATION_NONE) {
+            params.height = parentParams.height;
+            params.width = parentParams.width;
+        } else {
+            params.height = parentParams.width;
+            params.width = parentParams.height;
+        }
+        seekbar.setLayoutParams(params);
+    }
+
+    private int rotateGravityRight(int gravity) {
+        int retGravity = 0;
+        int layoutDirection = getLayoutDirection();
+        final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
+        final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.CENTER_HORIZONTAL:
+                retGravity |= Gravity.CENTER_VERTICAL;
+                break;
+            case Gravity.RIGHT:
+                retGravity |= Gravity.BOTTOM;
+                break;
+            case Gravity.LEFT:
+            default:
+                retGravity |= Gravity.TOP;
+                break;
+        }
+
+        switch (verticalGravity) {
+            case Gravity.CENTER_VERTICAL:
+                retGravity |= Gravity.CENTER_HORIZONTAL;
+                break;
+            case Gravity.BOTTOM:
+                retGravity |= Gravity.LEFT;
+                break;
+            case Gravity.TOP:
+            default:
+                retGravity |= Gravity.RIGHT;
+                break;
+        }
+        return retGravity;
+    }
+
+    private int rotateGravityLeft(int gravity) {
+        if (gravity == -1) {
+            gravity = Gravity.TOP | Gravity.START;
+        }
+        int retGravity = 0;
+        int layoutDirection = getLayoutDirection();
+        final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
+        final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.CENTER_HORIZONTAL:
+                retGravity |= Gravity.CENTER_VERTICAL;
+                break;
+            case Gravity.RIGHT:
+                retGravity |= Gravity.TOP;
+                break;
+            case Gravity.LEFT:
+            default:
+                retGravity |= Gravity.BOTTOM;
+                break;
+        }
+
+        switch (verticalGravity) {
+            case Gravity.CENTER_VERTICAL:
+                retGravity |= Gravity.CENTER_HORIZONTAL;
+                break;
+            case Gravity.BOTTOM:
+                retGravity |= Gravity.RIGHT;
+                break;
+            case Gravity.TOP:
+            default:
+                retGravity |= Gravity.LEFT;
+                break;
+        }
+        return retGravity;
+    }
+
+    private void rotateLeft(View v) {
+        if (v.getParent() instanceof FrameLayout) {
+            LayoutParams p = (LayoutParams) v.getLayoutParams();
+            p.gravity = rotateGravityLeft(p.gravity);
+        }
+
+        v.setPadding(v.getPaddingTop(), v.getPaddingRight(), v.getPaddingBottom(),
+                v.getPaddingLeft());
+        MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
+        params.setMargins(params.topMargin, params.rightMargin, params.bottomMargin,
+                params.leftMargin);
+        v.setLayoutParams(params);
+    }
+
+    private void rotateRight(View v) {
+        if (v.getParent() instanceof FrameLayout) {
+            LayoutParams p = (LayoutParams) v.getLayoutParams();
+            p.gravity = rotateGravityRight(p.gravity);
+        }
+
+        v.setPadding(v.getPaddingBottom(), v.getPaddingLeft(), v.getPaddingTop(),
+                v.getPaddingRight());
+        MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
+        params.setMargins(params.bottomMargin, params.leftMargin, params.topMargin,
+                params.rightMargin);
+        v.setLayoutParams(params);
+    }
+
+    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);
@@ -60,7 +316,14 @@
     }
 
     private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
+        if (mHasOutsideTouch || (mChild == null)) {
+            inoutInfo.setTouchableInsets(
+                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
+            return;
+        }
         inoutInfo.setTouchableInsets(
-                ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
+                ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT);
+        inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(),
+                0, getBottom() - mChild.getBottom());
     };
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
index 0a68389..f9ec3f92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
@@ -32,11 +32,14 @@
 
 import android.app.ActivityManager;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationRankingUpdate;
 import android.service.notification.StatusBarNotification;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -120,6 +123,23 @@
         }
     }
 
+    private void setUserSentiment(String key, int sentiment) {
+        doAnswer(invocationOnMock -> {
+            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+                    invocationOnMock.getArguments()[1];
+            ranking.populate(
+                    key,
+                    0,
+                    false,
+                    0,
+                    0,
+                    NotificationManager.IMPORTANCE_DEFAULT,
+                    null, null,
+                    null, null, null, true, sentiment);
+            return true;
+        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -158,6 +178,8 @@
 
         mEntryManager = new TestableNotificationEntryManager(mContext, mBarService);
         mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mCallback, mHeadsUpManager);
+
+        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
@@ -196,6 +218,8 @@
 
         assertEquals(mEntryManager.getNotificationData().get(mSbn.getKey()), entry);
         assertNotNull(entry.row);
+        assertEquals(mEntry.userSentiment,
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
@@ -204,6 +228,8 @@
 
         mEntryManager.getNotificationData().add(mEntry);
 
+        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+
         mHandler.post(() -> {
             mEntryManager.updateNotification(mSbn, mRankingMap);
         });
@@ -219,6 +245,8 @@
         verify(mForegroundServiceController).updateNotification(eq(mSbn), anyInt());
         verify(mCallback).onNotificationUpdated(mSbn);
         assertNotNull(mEntry.row);
+        assertEquals(mEntry.userSentiment,
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
     }
 
     @Test
diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml
index 7091ce7..fc4fdcd 100644
--- a/packages/VpnDialogs/res/values-hi/strings.xml
+++ b/packages/VpnDialogs/res/values-hi/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"कनेक्शन अनुरोध"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्‍शन सेट करना चाहता है जो उसे नेटवर्क ट्रैफ़िक मॉनीटर करने देता है. केवल तभी स्‍वीकार करें, जबकि आप स्रोत पर भरोसा करते हों. VPN सक्रिय होने पर आपकी स्‍क्रीन पर ऊपर &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; दिखाई देता है."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्‍शन सेट करना चाहता है जिससे वह नेटवर्क ट्रैफ़िक पर नज़र रख पाएगा. इसकी मंज़ूरी तभी दें जब आपको आप इसपर भरोसा हो. VPN चालू होने पर आपकी स्क्रीन के सबसे ऊपर &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; दिखाई देता है."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्‍ट है"</string>
     <string name="session" msgid="6470628549473641030">"सत्र:"</string>
     <string name="duration" msgid="3584782459928719435">"अवधि:"</string>
diff --git a/packages/VpnDialogs/res/values-nb/strings.xml b/packages/VpnDialogs/res/values-nb/strings.xml
index b45d3b9..be572d4 100644
--- a/packages/VpnDialogs/res/values-nb/strings.xml
+++ b/packages/VpnDialogs/res/values-nb/strings.xml
@@ -32,5 +32,5 @@
     <string name="configure" msgid="4905518375574791375">"Konfigurer"</string>
     <string name="disconnect" msgid="971412338304200056">"Koble fra"</string>
     <string name="open_app" msgid="3717639178595958667">"Åpne appen"</string>
-    <string name="dismiss" msgid="6192859333764711227">"Avvis"</string>
+    <string name="dismiss" msgid="6192859333764711227">"Lukk"</string>
 </resources>
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index cac7fed..6d845f9 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -44,6 +44,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
@@ -51,6 +52,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.service.autofill.AutofillFieldClassificationService.Scores;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.UserData;
 import android.util.LocalLog;
@@ -78,6 +80,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -443,6 +446,18 @@
         }
     }
 
+    // Called by Shell command.
+    public void getScore(@Nullable String algorithmName, @NonNull String value1,
+            @NonNull String value2, @NonNull RemoteCallback callback) {
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+        final FieldClassificationStrategy strategy =
+                new FieldClassificationStrategy(mContext, UserHandle.USER_CURRENT);
+
+        strategy.getScores(callback, algorithmName, null,
+                Arrays.asList(AutofillValue.forText(value1)), new String[] { value2 });
+    }
+
     private void setDebugLocked(boolean debug) {
         com.android.server.autofill.Helper.sDebug = debug;
         android.view.autofill.Helper.sDebug = debug;
@@ -518,6 +533,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.removeClientLocked(client);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "removeClient(): no service for " + userId);
                 }
             }
         }
@@ -574,6 +591,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getFillEventHistory(getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
                 }
             }
 
@@ -588,6 +607,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getUserData(getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "getUserData(): no service for " + userId);
                 }
             }
 
@@ -602,6 +623,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.setUserData(getCallingUid(), userData);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "setUserData(): no service for " + userId);
                 }
             }
         }
@@ -614,6 +637,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.isFieldClassificationEnabled(getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
                 }
             }
 
@@ -621,31 +646,39 @@
         }
 
         @Override
-        public String getDefaultFieldClassificationAlgorithm() throws RemoteException {
+        public void getDefaultFieldClassificationAlgorithm(RemoteCallback callback)
+                throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getDefaultFieldClassificationAlgorithm(getCallingUid());
+                    service.getDefaultFieldClassificationAlgorithm(getCallingUid(), callback);
+                } else {
+                    if (sVerbose) {
+                        Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
+                    }
+                    callback.sendResult(null);
                 }
             }
-
-            return null;
         }
 
         @Override
-        public List<String> getAvailableFieldClassificationAlgorithms() throws RemoteException {
+        public void getAvailableFieldClassificationAlgorithms(RemoteCallback callback)
+                throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.getAvailableFieldClassificationAlgorithms(getCallingUid());
+                    service.getAvailableFieldClassificationAlgorithms(getCallingUid(), callback);
+                } else {
+                    if (sVerbose) {
+                        Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
+                    }
+                    callback.sendResult(null);
                 }
             }
-
-            return null;
         }
 
         @Override
@@ -656,6 +689,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getServiceComponentName();
+                } else if (sVerbose) {
+                    Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
                 }
             }
 
@@ -665,15 +700,17 @@
         @Override
         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
                 throws RemoteException {
+            final int userId = UserHandle.getCallingUserId();
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
 
             synchronized (mLock) {
-                final AutofillManagerServiceImpl service = mServicesCache.get(
-                        UserHandle.getCallingUserId());
+                final AutofillManagerServiceImpl service = mServicesCache.get(userId);
                 if (service != null) {
                     return service.restoreSession(sessionId, getCallingUid(), activityToken,
                             appCallback);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "restoreSession(): no service for " + userId);
                 }
             }
 
@@ -688,6 +725,8 @@
                 if (service != null) {
                     service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
                             value, action, flags);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "updateSession(): no service for " + userId);
                 }
             }
         }
@@ -703,6 +742,8 @@
                 if (service != null) {
                     restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId,
                             bounds, value, action, flags);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "updateOrRestartSession(): no service for " + userId);
                 }
             }
             if (restart) {
@@ -720,6 +761,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.finishSessionLocked(sessionId, getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "finishSession(): no service for " + userId);
                 }
             }
         }
@@ -730,6 +773,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.cancelSessionLocked(sessionId, getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "cancelSession(): no service for " + userId);
                 }
             }
         }
@@ -740,6 +785,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "cancelSession(): no service for " + userId);
                 }
             }
         }
@@ -755,8 +802,12 @@
         public boolean isServiceEnabled(int userId, String packageName) {
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
-                if (service == null) return false;
-                return Objects.equals(packageName, service.getServicePackageName());
+                if (service != null) {
+                    return Objects.equals(packageName, service.getServicePackageName());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "isServiceEnabled(): no service for " + userId);
+                }
+                return false;
             }
         }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index da74dba..a5bd59a9 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -43,20 +43,15 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.RemoteCallback;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.Parcelable.Creator;
-import android.os.RemoteCallback;
 import android.provider.Settings;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
-import android.service.autofill.Dataset;
-import android.service.autofill.EditDistanceScorer;
 import android.service.autofill.FieldClassification;
 import android.service.autofill.FieldClassification.Match;
 import android.service.autofill.FillEventHistory;
@@ -69,8 +64,6 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.LocalLog;
-import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -89,7 +82,6 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Random;
 
@@ -124,137 +116,7 @@
 
     private final LocalLog mRequestsHistory;
     private final LocalLog mUiLatencyHistory;
-
-    // TODO(b/70939974): temporary, will be moved to ExtServices
-    static final class FieldClassificationAlgorithmService {
-
-        static final String EXTRA_SCORES = "scores";
-
-        /**
-         * Gets the name of all available algorithms.
-         */
-        @NonNull
-        public List<String> getAvailableAlgorithms() {
-            return Arrays.asList(EditDistanceScorer.NAME);
-        }
-
-        /**
-         * Gets the default algorithm that's used when an algorithm is not specified or is invalid.
-         */
-        @NonNull
-        public String getDefaultAlgorithm() {
-            return EditDistanceScorer.NAME;
-        }
-
-        /**
-         * Gets the field classification scores.
-         *
-         * @param algorithmName algorithm to be used. If invalid, the default algorithm will be used
-         * instead.
-         * @param algorithmArgs optional arguments to be passed to the algorithm.
-         * @param currentValues values entered by the user.
-         * @param userValues values from the user data.
-         * @param callback returns a nullable bundle with the parcelable results on
-         * {@link #EXTRA_SCORES}.
-         */
-        @Nullable
-        void getScores(@NonNull String algorithmName, @Nullable Bundle algorithmArgs,
-                List<AutofillValue> currentValues, @NonNull String[] userValues,
-                @NonNull RemoteCallback callback) {
-            if (currentValues == null || userValues == null) {
-                // TODO(b/70939974): use preconditions / add unit test
-                throw new IllegalArgumentException("values cannot be null");
-            }
-            if (currentValues.isEmpty() || userValues.length == 0) {
-                Slog.w(TAG, "getScores(): empty currentvalues (" + currentValues
-                        + ") or userValues (" + Arrays.toString(userValues) + ")");
-                // TODO(b/70939974): add unit test
-                callback.sendResult(null);
-            }
-            String actualAlgorithName = algorithmName;
-            if (!EditDistanceScorer.NAME.equals(algorithmName)) {
-                Slog.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
-                        + EditDistanceScorer.NAME + " instead");
-                actualAlgorithName = EditDistanceScorer.NAME;
-            }
-            final int currentValuesSize = currentValues.size();
-            if (sDebug) {
-                Log.d(TAG, "getScores() will return a " + currentValuesSize + "x"
-                        + userValues.length + " matrix for " + actualAlgorithName);
-            }
-            final FieldClassificationScores scores = new FieldClassificationScores(
-                    actualAlgorithName, currentValuesSize, userValues.length);
-            final EditDistanceScorer algorithm = EditDistanceScorer.getInstance();
-            for (int i = 0; i < currentValuesSize; i++) {
-                for (int j = 0; j < userValues.length; j++) {
-                    final float score = algorithm.getScore(currentValues.get(i), userValues[j]);
-                    scores.scores[i][j] = score;
-                }
-            }
-            final Bundle result = new Bundle();
-            result.putParcelable(EXTRA_SCORES, scores);
-            callback.sendResult(result);
-        }
-    }
-
-    // TODO(b/70939974): temporary, will be moved to ExtServices
-    public static final class FieldClassificationScores implements Parcelable {
-        public final String algorithmName;
-        public final float[][] scores;
-
-        public FieldClassificationScores(String algorithmName, int size1, int size2) {
-            this.algorithmName = algorithmName;
-            scores = new float[size1][size2];
-        }
-
-        public FieldClassificationScores(Parcel parcel) {
-            algorithmName = parcel.readString();
-            final int size1 = parcel.readInt();
-            final int size2 = parcel.readInt();
-            scores = new float[size1][size2];
-            for (int i = 0; i < size1; i++) {
-                for (int j = 0; j < size2; j++) {
-                    scores[i][j] = parcel.readFloat();
-                }
-            }
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel parcel, int flags) {
-            parcel.writeString(algorithmName);
-            int size1 = scores.length;
-            int size2 = scores[0].length;
-            parcel.writeInt(size1);
-            parcel.writeInt(size2);
-            for (int i = 0; i < size1; i++) {
-                for (int j = 0; j < size2; j++) {
-                    parcel.writeFloat(scores[i][j]);
-                }
-            }
-        }
-
-        public static final Creator<FieldClassificationScores> CREATOR = new Creator<FieldClassificationScores>() {
-
-            @Override
-            public FieldClassificationScores createFromParcel(Parcel parcel) {
-                return new FieldClassificationScores(parcel);
-            }
-
-            @Override
-            public FieldClassificationScores[] newArray(int size) {
-                return new FieldClassificationScores[size];
-            }
-
-        };
-    }
-
-    private final FieldClassificationAlgorithmService mFcService =
-            new FieldClassificationAlgorithmService();
+    private final FieldClassificationStrategy mFieldClassificationStrategy;
 
     /**
      * Apps disabled by the service; key is package name, value is when they will be enabled again.
@@ -324,6 +186,7 @@
         mUiLatencyHistory = uiLatencyHistory;
         mUserId = userId;
         mUi = ui;
+        mFieldClassificationStrategy = new FieldClassificationStrategy(context, userId);
         updateLocked(disabled);
     }
 
@@ -1089,10 +952,8 @@
             mUserData.dump(prefix2, pw);
         }
 
-        pw.print(prefix); pw.print("Available Field Classification algorithms: ");
-        pw.println(mFcService.getAvailableAlgorithms());
-        pw.print(prefix); pw.print("Default Field Classification algorithm: ");
-        pw.println(mFcService.getDefaultAlgorithm());
+        pw.print(prefix); pw.println("Field Classification strategy: ");
+        mFieldClassificationStrategy.dump(prefix2, pw);
     }
 
     void destroySessionsLocked() {
@@ -1288,26 +1149,26 @@
                 mUserId) == 1;
     }
 
-    FieldClassificationAlgorithmService getFieldClassificationService() {
-        return mFcService;
+    FieldClassificationStrategy getFieldClassificationStrategy() {
+        return mFieldClassificationStrategy;
     }
 
-    List<String> getAvailableFieldClassificationAlgorithms(int callingUid) {
+    void getAvailableFieldClassificationAlgorithms(int callingUid, RemoteCallback callback) {
         synchronized (mLock) {
             if (!isCalledByServiceLocked("getFCAlgorithms()", callingUid)) {
-                return null;
+                return;
             }
         }
-        return mFcService.getAvailableAlgorithms();
+        mFieldClassificationStrategy.getAvailableAlgorithms(callback);
     }
 
-    String getDefaultFieldClassificationAlgorithm(int callingUid) {
+    void getDefaultFieldClassificationAlgorithm(int callingUid, RemoteCallback callback) {
         synchronized (mLock) {
             if (!isCalledByServiceLocked("getDefaultFCAlgorithm()", callingUid)) {
-                return null;
+                return;
             }
         }
-        return mFcService.getDefaultAlgorithm();
+        mFieldClassificationStrategy.getDefaultAlgorithm(callback);
     }
 
     @Override
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index f3de557..4456087 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -16,11 +16,15 @@
 
 package com.android.server.autofill;
 
+import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
+
 import static com.android.server.autofill.AutofillManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
 
 import android.os.Bundle;
+import android.os.RemoteCallback;
 import android.os.ShellCommand;
 import android.os.UserHandle;
+import android.service.autofill.AutofillFieldClassificationService.Scores;
 import android.view.autofill.AutofillManager;
 
 import com.android.internal.os.IResultReceiver;
@@ -80,13 +84,16 @@
             pw.println("    Sets the maximum number of partitions per session.");
             pw.println("");
             pw.println("  list sessions [--user USER_ID]");
-            pw.println("    List all pending sessions.");
+            pw.println("    Lists all pending sessions.");
             pw.println("");
             pw.println("  destroy sessions [--user USER_ID]");
-            pw.println("    Destroy all pending sessions.");
+            pw.println("    Destroys all pending sessions.");
             pw.println("");
             pw.println("  reset");
-            pw.println("    Reset all pending sessions and cached service connections.");
+            pw.println("    Resets all pending sessions and cached service connections.");
+            pw.println("");
+            pw.println("  get fc_score [--algorithm ALGORITHM] value1 value2");
+            pw.println("    Gets the field classification score for 2 fields.");
             pw.println("");
         }
     }
@@ -98,6 +105,8 @@
                 return getLogLevel(pw);
             case "max_partitions":
                 return getMaxPartitions(pw);
+            case "fc_score":
+                return getFieldClassificationScore(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -164,6 +173,35 @@
         return 0;
     }
 
+    private int getFieldClassificationScore(PrintWriter pw) {
+        final String nextArg = getNextArgRequired();
+        final String algorithm, value1;
+        if ("--algorithm".equals(nextArg)) {
+            algorithm = getNextArgRequired();
+            value1 = getNextArgRequired();
+        } else {
+            algorithm = null;
+            value1 = nextArg;
+        }
+        final String value2 = getNextArgRequired();
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        mService.getScore(algorithm, value1, value2, new RemoteCallback((result) -> {
+            final Scores scores = result.getParcelable(EXTRA_SCORES);
+            if (scores == null) {
+                pw.println("no score");
+            } else {
+                pw.print("algorithm: ");
+                pw.print(scores.getAlgorithm());
+                pw.print(" score: ");
+                pw.println(scores.getScores()[0][0]);
+            }
+            latch.countDown();
+        }));
+
+        return waitForLatch(pw, latch);
+    }
+
     private int requestDestroy(PrintWriter pw) {
         if (!isNextArgSessions(pw)) {
             return -1;
@@ -210,19 +248,13 @@
         return true;
     }
 
-    private boolean isNextArgLogLevel(PrintWriter pw, String cmd) {
-        final String type = getNextArgRequired();
-        if (!type.equals("log_level")) {
-            pw.println("Error: invalid " + cmd + " type: " + type);
-            return false;
-        }
-        return true;
-    }
-
     private int requestSessionCommon(PrintWriter pw, CountDownLatch latch,
             Runnable command) {
         command.run();
+        return waitForLatch(pw, latch);
+    }
 
+    private int waitForLatch(PrintWriter pw, CountDownLatch latch) {
         try {
             final boolean received = latch.await(5, TimeUnit.SECONDS);
             if (!received) {
diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
new file mode 100644
index 0000000..7228f1d
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
@@ -0,0 +1,279 @@
+/*
+ * 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.autofill;
+
+import static android.view.autofill.AutofillManager.EXTRA_AVAILABLE_ALGORITHMS;
+import static android.view.autofill.AutofillManager.EXTRA_DEFAULT_ALGORITHM;
+import static android.view.autofill.AutofillManager.FC_SERVICE_TIMEOUT;
+
+import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
+
+import android.Manifest;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.autofill.AutofillFieldClassificationService;
+import android.service.autofill.IAutofillFieldClassificationService;
+import android.util.Log;
+import android.util.Slog;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Strategy used to bridge the field classification algorithms provided by a service in an external
+ * package.
+ */
+//TODO(b/70291841): add unit tests ?
+final class FieldClassificationStrategy {
+
+    private static final String TAG = "FieldClassificationStrategy";
+
+    private final Context mContext;
+    private final Object mLock = new Object();
+    private final int mUserId;
+
+    @GuardedBy("mLock")
+    private ServiceConnection mServiceConnection;
+
+    @GuardedBy("mLock")
+    private IAutofillFieldClassificationService mRemoteService;
+
+    @GuardedBy("mLock")
+    private ArrayList<Command> mQueuedCommands;
+
+    public FieldClassificationStrategy(Context context, int userId) {
+        mContext = context;
+        mUserId = userId;
+    }
+
+    private ComponentName getServiceComponentName() {
+        final String packageName =
+                mContext.getPackageManager().getServicesSystemSharedLibraryPackageName();
+        if (packageName == null) {
+            Slog.w(TAG, "no external services package!");
+            return null;
+        }
+
+        final Intent intent = new Intent(AutofillFieldClassificationService.SERVICE_INTERFACE);
+        intent.setPackage(packageName);
+        final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
+            Slog.w(TAG, "No valid components found.");
+            return null;
+        }
+        final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+        final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
+
+        if (!Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE
+                .equals(serviceInfo.permission)) {
+            Slog.w(TAG, name.flattenToShortString() + " does not require permission "
+                    + Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE);
+            return null;
+        }
+
+        if (sVerbose) Slog.v(TAG, "getServiceComponentName(): " + name);
+        return name;
+    }
+
+    /**
+     * Run a command, starting the service connection if necessary.
+     */
+    private void connectAndRun(@NonNull Command command) {
+        synchronized (mLock) {
+            if (mRemoteService != null) {
+                try {
+                    if (sVerbose) Slog.v(TAG, "running command right away");
+                    command.run(mRemoteService);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "exception calling service: " + e);
+                }
+                return;
+            } else {
+                if (sDebug) Slog.d(TAG, "service is null; queuing command");
+                if (mQueuedCommands == null) {
+                    mQueuedCommands = new ArrayList<>(1);
+                }
+                mQueuedCommands.add(command);
+                // If we're already connected, don't create a new connection, just leave - the
+                // command will be run when the service connects
+                if (mServiceConnection != null) return;
+            }
+
+            if (sVerbose) Slog.v(TAG, "creating connection");
+
+            // Create the connection
+            mServiceConnection = new ServiceConnection() {
+                @Override
+                public void onServiceConnected(ComponentName name, IBinder service) {
+                    if (sVerbose) Slog.v(TAG, "onServiceConnected(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = IAutofillFieldClassificationService.Stub
+                                .asInterface(service);
+                        if (mQueuedCommands != null) {
+                            final int size = mQueuedCommands.size();
+                            if (sDebug) Slog.d(TAG, "running " + size + " queued commands");
+                            for (int i = 0; i < size; i++) {
+                                final Command queuedCommand = mQueuedCommands.get(i);
+                                try {
+                                    if (sVerbose) Slog.v(TAG, "running queued command #" + i);
+                                    queuedCommand.run(mRemoteService);
+                                } catch (RemoteException e) {
+                                    Slog.w(TAG, "exception calling " + name + ": " + e);
+                                }
+                            }
+                            mQueuedCommands = null;
+                        } else if (sDebug) Slog.d(TAG, "no queued commands");
+                    }
+                }
+
+                @Override
+                @MainThread
+                public void onServiceDisconnected(ComponentName name) {
+                    if (sVerbose) Slog.v(TAG, "onServiceDisconnected(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = null;
+                    }
+                }
+
+                @Override
+                public void onBindingDied(ComponentName name) {
+                    if (sVerbose) Slog.v(TAG, "onBindingDied(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = null;
+                    }
+                }
+
+                @Override
+                public void onNullBinding(ComponentName name) {
+                    if (sVerbose) Slog.v(TAG, "onNullBinding(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = null;
+                    }
+                }
+            };
+
+            final ComponentName component = getServiceComponentName();
+            if (sVerbose) Slog.v(TAG, "binding to: " + component);
+            if (component != null) {
+                final Intent intent = new Intent();
+                intent.setComponent(component);
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mContext.bindServiceAsUser(intent, mServiceConnection, Context.BIND_AUTO_CREATE,
+                            UserHandle.of(mUserId));
+                    if (sVerbose) Slog.v(TAG, "bound");
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        }
+    }
+
+    void getAvailableAlgorithms(RemoteCallback callback) {
+        connectAndRun((service) -> service.getAvailableAlgorithms(callback));
+    }
+
+    void getDefaultAlgorithm(RemoteCallback callback) {
+        connectAndRun((service) -> service.getDefaultAlgorithm(callback));
+    }
+
+    //TODO(b/70291841): rename this method (and all others in the chain) to something like
+    // calculateScores() ?
+    void getScores(RemoteCallback callback, @Nullable String algorithmName,
+            @Nullable Bundle algorithmArgs, @NonNull List<AutofillValue> actualValues,
+            @NonNull String[] userDataValues) {
+        connectAndRun((service) -> service.getScores(callback, algorithmName,
+                algorithmArgs, actualValues, userDataValues));
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        final ComponentName impl = getServiceComponentName();
+        pw.print(prefix); pw.print("User ID: "); pw.println(mUserId);
+        pw.print(prefix); pw.print("Queued commands: ");
+        if (mQueuedCommands == null) {
+            pw.println("N/A");
+        } else {
+            pw.println(mQueuedCommands.size());
+        }
+        pw.print(prefix); pw.print("Implementation: ");
+        if (impl == null) {
+            pw.println("N/A");
+            return;
+        }
+        pw.println(impl.flattenToShortString());
+
+        final CountDownLatch latch = new CountDownLatch(2);
+
+        // Lock used to make sure lines don't overlap
+        final Object lock = latch;
+
+        connectAndRun((service) -> service.getAvailableAlgorithms(new RemoteCallback((bundle) -> {
+            synchronized (lock) {
+                pw.print(prefix); pw.print("Available algorithms: ");
+                pw.println(bundle.getStringArrayList(EXTRA_AVAILABLE_ALGORITHMS));
+            }
+            latch.countDown();
+        })));
+
+        connectAndRun((service) -> service.getDefaultAlgorithm(new RemoteCallback((bundle) -> {
+            synchronized (lock) {
+                pw.print(prefix); pw.print("Default algorithm: ");
+                pw.println(bundle.getString(EXTRA_DEFAULT_ALGORITHM));
+            }
+            latch.countDown();
+        })));
+
+        try {
+            if (!latch.await(FC_SERVICE_TIMEOUT, TimeUnit.MILLISECONDS)) {
+                synchronized (lock) {
+                    pw.print(prefix); pw.print("timeout ("); pw.print(FC_SERVICE_TIMEOUT);
+                    pw.println("ms) waiting for service");
+                }
+            }
+        } catch (InterruptedException e) {
+            synchronized (lock) {
+                pw.print(prefix); pw.println("interrupted while waiting for service");
+            }
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    private interface Command {
+        void run(IAutofillFieldClassificationService service) throws RemoteException;
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index f5d1336..a0e23a1 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static android.app.ActivityManagerInternal.ASSIST_KEY_STRUCTURE;
+import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
 import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
@@ -25,7 +26,6 @@
 import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
 
-import static com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationAlgorithmService.EXTRA_SCORES;
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
@@ -54,11 +54,11 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.service.autofill.AutofillFieldClassificationService.Scores;
 import android.service.autofill.AutofillService;
 import android.service.autofill.Dataset;
 import android.service.autofill.FieldClassification;
 import android.service.autofill.FieldClassification.Match;
-import android.service.carrier.CarrierMessagingService.ResultCallback;
 import android.service.autofill.FillContext;
 import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
@@ -86,8 +86,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationAlgorithmService;
-import com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationScores;
 import com.android.server.autofill.ui.AutoFillUI;
 import com.android.server.autofill.ui.PendingUi;
 
@@ -99,7 +97,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * A session for a given activity.
@@ -1101,10 +1098,9 @@
         }
 
         // Sets field classification scores
-        final FieldClassificationAlgorithmService fcService =
-                mService.getFieldClassificationService();
-        if (userData != null && fcService != null) {
-            logFieldClassificationScoreLocked(fcService, ignoredDatasets, changedFieldIds,
+        final FieldClassificationStrategy fcStrategy = mService.getFieldClassificationStrategy();
+        if (userData != null && fcStrategy != null) {
+            logFieldClassificationScoreLocked(fcStrategy, ignoredDatasets, changedFieldIds,
                     changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds,
                     manuallyFilledIds, userData,
                     mViewStates.values());
@@ -1121,7 +1117,7 @@
      * {@code fieldId} based on its {@code currentValue} and {@code userData}.
      */
     private void logFieldClassificationScoreLocked(
-            @NonNull AutofillManagerServiceImpl.FieldClassificationAlgorithmService fcService,
+            @NonNull FieldClassificationStrategy fcStrategy,
             @NonNull ArraySet<String> ignoredDatasets,
             @NonNull ArrayList<AutofillId> changedFieldIds,
             @NonNull ArrayList<String> changedDatasetIds,
@@ -1161,6 +1157,7 @@
             fieldIds[k++] = viewState.id;
         }
 
+        // Then use the results, asynchronously
         final RemoteCallback callback = new RemoteCallback((result) -> {
             if (result == null) {
                 if (sDebug) Slog.d(TAG, "setFieldClassificationScore(): no results");
@@ -1170,35 +1167,46 @@
                         mComponentName.getPackageName());
                 return;
             }
-            final FieldClassificationScores matrix = result.getParcelable(EXTRA_SCORES);
+            final Scores scores = result.getParcelable(EXTRA_SCORES);
+            if (scores == null) {
+                Slog.w(TAG, "No field classification score on " + result);
+                return;
+            }
+            final float[][] scoresMatrix = scores.getScores();
 
-            // Then use the results.
-            for (int i = 0; i < viewsSize; i++) {
-                final AutofillId fieldId = fieldIds[i];
+            int i = 0, j = 0;
+            try {
+                for (i = 0; i < viewsSize; i++) {
+                    final AutofillId fieldId = fieldIds[i];
 
-                ArrayList<Match> matches = null;
-                for (int j = 0; j < userValues.length; j++) {
-                    String remoteId = remoteIds[j];
-                    final String actualAlgorithm = matrix.algorithmName;
-                    final float score = matrix.scores[i][j];
-                    if (score > 0) {
-                        if (sVerbose) {
-                            Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
-                                    + fieldId);
+                    ArrayList<Match> matches = null;
+                    for (j = 0; j < userValues.length; j++) {
+                        String remoteId = remoteIds[j];
+                        final String actualAlgorithm = scores.getAlgorithm();
+                        final float score = scoresMatrix[i][j];
+                        if (score > 0) {
+                            if (sVerbose) {
+                                Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
+                                        + fieldId);
+                            }
+                            if (matches == null) {
+                                matches = new ArrayList<>(userValues.length);
+                            }
+                            matches.add(new Match(remoteId, score, actualAlgorithm));
                         }
-                        if (matches == null) {
-                            matches = new ArrayList<>(userValues.length);
+                        else if (sVerbose) {
+                            Slog.v(TAG, "skipping score 0 at index " + j + " and id " + fieldId);
                         }
-                        matches.add(new Match(remoteId, score, actualAlgorithm));
                     }
-                    else if (sVerbose) {
-                        Slog.v(TAG, "skipping score 0 at index " + j + " and id " + fieldId);
+                    if (matches != null) {
+                        detectedFieldIds.add(fieldId);
+                        detectedFieldClassifications.add(new FieldClassification(matches));
                     }
                 }
-                if (matches != null) {
-                    detectedFieldIds.add(fieldId);
-                    detectedFieldClassifications.add(new FieldClassification(matches));
-                }
+            } catch (ArrayIndexOutOfBoundsException e) {
+                Slog.wtf(TAG, "Error accessing FC score at " + i + " x " + j + ": "
+                        + Arrays.toString(scoresMatrix), e);
+                return;
             }
 
             mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
@@ -1207,7 +1215,7 @@
                     mComponentName.getPackageName());
         });
 
-        fcService.getScores(algorithm, algorithmArgs, currentValues, userValues, callback);
+        fcStrategy.getScores(callback, algorithm, algorithmArgs, currentValues, userValues);
     }
 
     /**
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 307f74d..f96fa7c2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -231,8 +231,7 @@
 
         final Window window = mDialog.getWindow();
         window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
-        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+        window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
         window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS);
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index f33ec55..5188910 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -3140,6 +3140,7 @@
                 mCurrentToken = 0;
                 Slog.w(TAG, "Transport " + newTransportName + " not available: current token = 0");
             }
+            mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
         } else {
             Slog.w(TAG, "Transport " + newTransportName + " not registered: current token = 0");
             // The named transport isn't registered, so we can't know what its current dataset token
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index a628c9d..540f5a1 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -177,12 +177,15 @@
         }
     }
 
+    // IBackupManager binder API
+
     /**
      * Querying activity state of backup service. Calling this method before initialize yields
      * undefined result.
      * @param userHandle The user in which the activity state of backup service is queried.
      * @return true if the service is active.
      */
+    @Override
     public boolean isBackupServiceActive(final int userHandle) {
         // TODO: http://b/22388012
         if (userHandle == UserHandle.USER_SYSTEM) {
@@ -193,7 +196,6 @@
         return false;
     }
 
-    // IBackupManager binder API
     @Override
     public void dataChanged(String packageName) throws RemoteException {
         BackupManagerServiceInterface svc = mService;
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 09456b68..5b901ee 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -29,14 +29,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
-import android.util.EventLog;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.util.Preconditions;
-import com.android.server.EventLogTags;
 import com.android.server.backup.transport.OnTransportRegisteredListener;
 import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.transport.TransportClientManager;
@@ -64,9 +62,17 @@
     private final PackageManager mPackageManager;
     private final Set<ComponentName> mTransportWhitelist;
     private final TransportClientManager mTransportClientManager;
-    private final Object mTransportLock = new Object();
     private OnTransportRegisteredListener mOnTransportRegisteredListener = (c, n) -> {};
 
+    /**
+     * Lock for registered transports and currently selected transport.
+     *
+     * <p><b>Warning:</b> No calls to {@link IBackupTransport} or calls that result in transport
+     * code being executed such as {@link TransportClient#connect(String)}} and its variants should
+     * be made with this lock held, risk of deadlock.
+     */
+    private final Object mTransportLock = new Object();
+
     /** @see #getRegisteredTransportNames() */
     @GuardedBy("mTransportLock")
     private final Map<ComponentName, TransportDescription> mRegisteredTransportsDescriptionMap =
@@ -111,15 +117,16 @@
 
     @WorkerThread
     void onPackageChanged(String packageName, String... components) {
+        // Unfortunately this can't be atomic because we risk a deadlock if
+        // registerTransportsFromPackage() is put inside the synchronized block
+        Set<ComponentName> transportComponents =
+                Stream.of(components)
+                        .map(component -> new ComponentName(packageName, component))
+                        .collect(Collectors.toSet());
         synchronized (mTransportLock) {
-            Set<ComponentName> transportComponents =
-                    Stream.of(components)
-                            .map(component -> new ComponentName(packageName, component))
-                            .collect(Collectors.toSet());
-
             mRegisteredTransportsDescriptionMap.keySet().removeIf(transportComponents::contains);
-            registerTransportsFromPackage(packageName, transportComponents::contains);
         }
+        registerTransportsFromPackage(packageName, transportComponents::contains);
     }
 
     /**
@@ -265,6 +272,9 @@
      * This is called with an internal lock held, ensuring that the transport will remain registered
      * while {@code transportConsumer} is being executed. Don't do heavy operations in {@code
      * transportConsumer}.
+     *
+     * <p><b>Warning:</b> Do NOT make any calls to {@link IBackupTransport} or call any variants of
+     * {@link TransportClient#connect(String)} here, otherwise you risk deadlock.
      */
     public void forEachRegisteredTransport(Consumer<String> transportConsumer) {
         synchronized (mTransportLock) {
@@ -467,20 +477,27 @@
      */
     @WorkerThread
     public int registerAndSelectTransport(ComponentName transportComponent) {
+        // If it's already registered we select and return
         synchronized (mTransportLock) {
-            if (!mRegisteredTransportsDescriptionMap.containsKey(transportComponent)) {
-                int result = registerTransport(transportComponent);
-                if (result != BackupManager.SUCCESS) {
-                    return result;
-                }
-            }
-
             try {
                 selectTransport(getTransportName(transportComponent));
                 return BackupManager.SUCCESS;
             } catch (TransportNotRegisteredException e) {
-                // Shouldn't happen because we are holding the lock
-                Slog.wtf(TAG, "Transport unexpectedly not registered");
+                // Fall through and release lock
+            }
+        }
+
+        // We can't call registerTransport() with the transport lock held
+        int result = registerTransport(transportComponent);
+        if (result != BackupManager.SUCCESS) {
+            return result;
+        }
+        synchronized (mTransportLock) {
+            try {
+                selectTransport(getTransportName(transportComponent));
+                return BackupManager.SUCCESS;
+            } catch (TransportNotRegisteredException e) {
+                Slog.wtf(TAG, "Transport got unregistered");
                 return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
             }
         }
@@ -514,13 +531,11 @@
         if (hosts == null) {
             return;
         }
-        synchronized (mTransportLock) {
-            for (ResolveInfo host : hosts) {
-                ComponentName transportComponent = host.serviceInfo.getComponentName();
-                if (transportComponentFilter.test(transportComponent)
-                        && isTransportTrusted(transportComponent)) {
-                    registerTransport(transportComponent);
-                }
+        for (ResolveInfo host : hosts) {
+            ComponentName transportComponent = host.serviceInfo.getComponentName();
+            if (transportComponentFilter.test(transportComponent)
+                    && isTransportTrusted(transportComponent)) {
+                registerTransport(transportComponent);
             }
         }
     }
@@ -549,22 +564,24 @@
     /**
      * Tries to register transport represented by {@code transportComponent}.
      *
+     * <p><b>Warning:</b> Don't call this with the transport lock held.
+     *
      * @param transportComponent Host of the transport that we want to register.
      * @return One of {@link BackupManager#SUCCESS}, {@link BackupManager#ERROR_TRANSPORT_INVALID}
      *     or {@link BackupManager#ERROR_TRANSPORT_UNAVAILABLE}.
      */
     @WorkerThread
     private int registerTransport(ComponentName transportComponent) {
+        checkCanUseTransport();
+
         if (!isTransportTrusted(transportComponent)) {
             return BackupManager.ERROR_TRANSPORT_INVALID;
         }
 
         String transportString = transportComponent.flattenToShortString();
-
         String callerLogString = "TransportManager.registerTransport()";
         TransportClient transportClient =
                 mTransportClientManager.getTransportClient(transportComponent, callerLogString);
-
         final IBackupTransport transport;
         try {
             transport = transportClient.connectOrThrow(callerLogString);
@@ -574,8 +591,6 @@
             return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
         }
 
-        EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 1);
-
         int result;
         try {
             String transportName = transport.name();
@@ -587,7 +602,6 @@
             result = BackupManager.SUCCESS;
         } catch (RemoteException e) {
             Slog.e(TAG, "Transport " + transportString + " died while registering");
-            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 0);
             result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
         }
 
@@ -598,20 +612,26 @@
     /** If {@link RemoteException} is thrown the transport is guaranteed to not be registered. */
     private void registerTransport(ComponentName transportComponent, IBackupTransport transport)
             throws RemoteException {
+        checkCanUseTransport();
+
+        TransportDescription description =
+                new TransportDescription(
+                        transport.name(),
+                        transport.transportDirName(),
+                        transport.configurationIntent(),
+                        transport.currentDestinationString(),
+                        transport.dataManagementIntent(),
+                        transport.dataManagementLabel());
         synchronized (mTransportLock) {
-            String name = transport.name();
-            TransportDescription description =
-                    new TransportDescription(
-                            name,
-                            transport.transportDirName(),
-                            transport.configurationIntent(),
-                            transport.currentDestinationString(),
-                            transport.dataManagementIntent(),
-                            transport.dataManagementLabel());
             mRegisteredTransportsDescriptionMap.put(transportComponent, description);
         }
     }
 
+    private void checkCanUseTransport() {
+        Preconditions.checkState(
+                !Thread.holdsLock(mTransportLock), "Can't call transport with transport lock held");
+    }
+
     private static Predicate<ComponentName> fromPackageFilter(String packageName) {
         return transportComponent -> packageName.equals(transportComponent.getPackageName());
     }
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java
index bd4a0bb..399f338 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java
@@ -29,12 +29,14 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.EventLog;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.util.Preconditions;
+import com.android.server.EventLogTags;
 import com.android.server.backup.TransportManager;
 
 import java.lang.annotation.Retention;
@@ -419,10 +421,45 @@
     @GuardedBy("mStateLock")
     private void setStateLocked(@State int state, @Nullable IBackupTransport transport) {
         log(Log.VERBOSE, "State: " + stateToString(mState) + " => " + stateToString(state));
+        onStateTransition(mState, state);
         mState = state;
         mTransport = transport;
     }
 
+    private void onStateTransition(int oldState, int newState) {
+        String transport = mTransportComponent.flattenToShortString();
+        int bound = transitionThroughState(oldState, newState, State.BOUND_AND_CONNECTING);
+        int connected = transitionThroughState(oldState, newState, State.CONNECTED);
+        if (bound != Transition.NO_TRANSITION) {
+            int value = (bound == Transition.UP) ? 1 : 0; // 1 is bound, 0 is not bound
+            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transport, value);
+        }
+        if (connected != Transition.NO_TRANSITION) {
+            int value = (connected == Transition.UP) ? 1 : 0; // 1 is connected, 0 is not connected
+            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_CONNECTION, transport, value);
+        }
+    }
+
+    /**
+     * Returns:
+     *
+     * <ul>
+     *   <li>{@link Transition#UP}, if oldState < stateReference <= newState
+     *   <li>{@link Transition#DOWN}, if oldState >= stateReference > newState
+     *   <li>{@link Transition#NO_TRANSITION}, otherwise
+     */
+    @Transition
+    private int transitionThroughState(
+            @State int oldState, @State int newState, @State int stateReference) {
+        if (oldState < stateReference && stateReference <= newState) {
+            return Transition.UP;
+        }
+        if (oldState >= stateReference && stateReference > newState) {
+            return Transition.DOWN;
+        }
+        return Transition.NO_TRANSITION;
+    }
+
     @GuardedBy("mStateLock")
     private void checkStateIntegrityLocked() {
         switch (mState) {
@@ -481,6 +518,14 @@
         // CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
     }
 
+    @IntDef({Transition.DOWN, Transition.NO_TRANSITION, Transition.UP})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface Transition {
+        int DOWN = -1;
+        int NO_TRANSITION = 0;
+        int UP = 1;
+    }
+
     @IntDef({State.UNUSABLE, State.IDLE, State.BOUND_AND_CONNECTING, State.CONNECTED})
     @Retention(RetentionPolicy.SOURCE)
     private @interface State {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 04d292f..dc5f5a2 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -383,16 +383,16 @@
         }
     }
 
-    private void update(HealthInfo info) {
+    private void update(android.hardware.health.V2_0.HealthInfo info) {
         traceBegin("HealthInfoUpdate");
         synchronized (mLock) {
             if (!mUpdatesStopped) {
-                mHealthInfo = info;
+                mHealthInfo = info.legacy;
                 // Process the new values.
                 processValuesLocked(false);
                 mLock.notifyAll(); // for any waiters on new info
             } else {
-                copy(mLastHealthInfo, info);
+                copy(mLastHealthInfo, info.legacy);
             }
         }
         traceEnd();
@@ -1010,7 +1010,7 @@
 
     private final class HealthHalCallback extends IHealthInfoCallback.Stub
             implements HealthServiceWrapper.Callback {
-        @Override public void healthInfoChanged(HealthInfo props) {
+        @Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
             BatteryService.this.update(props);
         }
         // on new service registered
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index d9713a5..2077790 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -60,6 +60,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Slog;
 
+import com.android.internal.R;
 import com.android.internal.util.DumpUtils;
 import com.android.server.pm.UserRestrictionsUtils;
 
@@ -415,9 +416,14 @@
 
         int systemUiUid = -1;
         try {
-            systemUiUid = mContext.getPackageManager()
-                    .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY,
-                            UserHandle.USER_SYSTEM);
+            // Check if device is configured with no home screen, which implies no SystemUI.
+            boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
+            if (!noHome) {
+                systemUiUid = mContext.getPackageManager()
+                        .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY,
+                                UserHandle.USER_SYSTEM);
+            }
+            Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
         } catch (PackageManager.NameNotFoundException e) {
             // Some platforms, such as wearables do not have a system ui.
             Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
@@ -433,10 +439,17 @@
                 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
     }
 
+    private boolean supportBluetoothPersistedState() {
+        return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
+    }
+
     /**
      *  Returns true if the Bluetooth saved state is "on"
      */
     private boolean isBluetoothPersistedStateOn() {
+        if (!supportBluetoothPersistedState()) {
+            return false;
+        }
         int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
         if (DBG) {
             Slog.d(TAG, "Bluetooth persisted state: " + state);
@@ -448,6 +461,9 @@
      *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
      */
     private boolean isBluetoothPersistedStateOnBluetooth() {
+        if (!supportBluetoothPersistedState()) {
+            return false;
+        }
         return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
                 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
     }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 77521df..4097707 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -63,6 +63,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
+import android.net.NetworkPolicyManager;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
@@ -131,6 +132,7 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.DataConnectionStats;
 import com.android.server.connectivity.DnsManager;
+import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
 import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.KeepaliveTracker;
 import com.android.server.connectivity.LingerMonitor;
@@ -400,6 +402,9 @@
      */
     private static final int EVENT_REVALIDATE_NETWORK = 36;
 
+    // Handle changes in Private DNS settings.
+    private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
+
     private static String eventName(int what) {
         return sMagicDecoderRing.get(what, Integer.toString(what));
     }
@@ -886,6 +891,7 @@
         mMultinetworkPolicyTracker.start();
 
         mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
+        registerPrivateDnsSettingsCallbacks();
     }
 
     private Tethering makeTethering() {
@@ -946,6 +952,12 @@
                 EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
     }
 
+    private void registerPrivateDnsSettingsCallbacks() {
+        for (Uri u : DnsManager.getPrivateDnsSettingsUris()) {
+            mSettingsObserver.observe(u, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
+        }
+    }
+
     private synchronized int nextNetworkRequestId() {
         return mNextNetworkRequestId++;
     }
@@ -1490,15 +1502,12 @@
         return true;
     }
 
-    private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
         public void onUidRulesChanged(int uid, int uidRules) {
             // TODO: notify UID when it has requested targeted updates
         }
         @Override
-        public void onMeteredIfacesChanged(String[] meteredIfaces) {
-        }
-        @Override
         public void onRestrictBackgroundChanged(boolean restrictBackground) {
             // TODO: relocate this specific callback in Tethering.
             if (restrictBackground) {
@@ -1506,9 +1515,6 @@
                 mTethering.untetherAll();
             }
         }
-        @Override
-        public void onUidPoliciesChanged(int uid, int uidPolicies) {
-        }
     };
 
     /**
@@ -2114,36 +2120,59 @@
                     synchronized (mNetworkForNetId) {
                         nai = mNetworkForNetId.get(msg.arg2);
                     }
-                    if (nai != null) {
-                        final boolean valid =
-                                (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
-                        final boolean wasValidated = nai.lastValidated;
-                        final boolean wasDefault = isDefaultNetwork(nai);
-                        if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") +
-                                (msg.obj == null ? "" : " with redirect to " + (String)msg.obj));
-                        if (valid != nai.lastValidated) {
-                            if (wasDefault) {
-                                metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
-                                        SystemClock.elapsedRealtime(), valid);
-                            }
-                            final int oldScore = nai.getCurrentScore();
-                            nai.lastValidated = valid;
-                            nai.everValidated |= valid;
-                            updateCapabilities(oldScore, nai, nai.networkCapabilities);
-                            // If score has changed, rebroadcast to NetworkFactories. b/17726566
-                            if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
+                    if (nai == null) break;
+
+                    final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
+                    final boolean wasValidated = nai.lastValidated;
+                    final boolean wasDefault = isDefaultNetwork(nai);
+
+                    final PrivateDnsConfig privateDnsCfg = (msg.obj instanceof PrivateDnsConfig)
+                            ? (PrivateDnsConfig) msg.obj : null;
+                    final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
+
+                    final boolean reevaluationRequired;
+                    final String logMsg;
+                    if (valid) {
+                        reevaluationRequired = updatePrivateDns(nai, privateDnsCfg);
+                        logMsg = (DBG && (privateDnsCfg != null))
+                                 ? " with " + privateDnsCfg.toString() : "";
+                    } else {
+                        reevaluationRequired = false;
+                        logMsg = (DBG && !TextUtils.isEmpty(redirectUrl))
+                                 ? " with redirect to " + redirectUrl : "";
+                    }
+                    if (DBG) {
+                        log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
+                    }
+                    // If there is a change in Private DNS configuration,
+                    // trigger reevaluation of the network to test it.
+                    if (reevaluationRequired) {
+                        nai.networkMonitor.sendMessage(
+                                NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
+                        break;
+                    }
+                    if (valid != nai.lastValidated) {
+                        if (wasDefault) {
+                            metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
+                                    SystemClock.elapsedRealtime(), valid);
                         }
-                        updateInetCondition(nai);
-                        // Let the NetworkAgent know the state of its network
-                        Bundle redirectUrlBundle = new Bundle();
-                        redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, (String)msg.obj);
-                        nai.asyncChannel.sendMessage(
-                                NetworkAgent.CMD_REPORT_NETWORK_STATUS,
-                                (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
-                                0, redirectUrlBundle);
-                         if (wasValidated && !nai.lastValidated) {
-                             handleNetworkUnvalidated(nai);
-                         }
+                        final int oldScore = nai.getCurrentScore();
+                        nai.lastValidated = valid;
+                        nai.everValidated |= valid;
+                        updateCapabilities(oldScore, nai, nai.networkCapabilities);
+                        // If score has changed, rebroadcast to NetworkFactories. b/17726566
+                        if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
+                    }
+                    updateInetCondition(nai);
+                    // Let the NetworkAgent know the state of its network
+                    Bundle redirectUrlBundle = new Bundle();
+                    redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
+                    nai.asyncChannel.sendMessage(
+                            NetworkAgent.CMD_REPORT_NETWORK_STATUS,
+                            (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
+                            0, redirectUrlBundle);
+                    if (wasValidated && !nai.lastValidated) {
+                        handleNetworkUnvalidated(nai);
                     }
                     break;
                 }
@@ -2183,6 +2212,21 @@
                     }
                     break;
                 }
+                case NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
+                    final NetworkAgentInfo nai;
+                    synchronized (mNetworkForNetId) {
+                        nai = mNetworkForNetId.get(msg.arg2);
+                    }
+                    if (nai == null) break;
+
+                    final PrivateDnsConfig cfg = (PrivateDnsConfig) msg.obj;
+                    final boolean reevaluationRequired = updatePrivateDns(nai, cfg);
+                    if (nai.lastValidated && reevaluationRequired) {
+                        nai.networkMonitor.sendMessage(
+                                NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
+                    }
+                    break;
+                }
             }
             return true;
         }
@@ -2218,6 +2262,63 @@
         }
     }
 
+    private void handlePrivateDnsSettingsChanged() {
+        final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
+
+        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+            // Private DNS only ever applies to networks that might provide
+            // Internet access and therefore also require validation.
+            if (!NetworkMonitor.isValidationRequired(
+                    mDefaultRequest.networkCapabilities, nai.networkCapabilities)) {
+                continue;
+            }
+
+            // Notify the NetworkMonitor thread in case it needs to cancel or
+            // schedule DNS resolutions. If a DNS resolution is required the
+            // result will be sent back to us.
+            nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
+
+            if (!cfg.inStrictMode()) {
+                // No strict mode hostname DNS resolution needed, so just update
+                // DNS settings directly. In opportunistic and "off" modes this
+                // just reprograms netd with the network-supplied DNS servers
+                // (and of course the boolean of whether or not to attempt TLS).
+                //
+                // TODO: Consider code flow parity with strict mode, i.e. having
+                // NetworkMonitor relay the PrivateDnsConfig back to us and then
+                // performing this call at that time.
+                updatePrivateDns(nai, cfg);
+            }
+        }
+    }
+
+    private boolean updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
+        final boolean reevaluationRequired = true;
+        final boolean dontReevaluate = false;
+
+        final PrivateDnsConfig oldCfg = mDnsManager.updatePrivateDns(nai.network, newCfg);
+        updateDnses(nai.linkProperties, null, nai.network.netId);
+
+        if (newCfg == null) {
+            if (oldCfg == null) return dontReevaluate;
+            return oldCfg.useTls ? reevaluationRequired : dontReevaluate;
+        }
+
+        if (oldCfg == null) {
+            return newCfg.useTls ? reevaluationRequired : dontReevaluate;
+        }
+
+        if (oldCfg.useTls != newCfg.useTls) {
+            return reevaluationRequired;
+        }
+
+        if (newCfg.inStrictMode() && !Objects.equals(oldCfg.hostname, newCfg.hostname)) {
+            return reevaluationRequired;
+        }
+
+        return dontReevaluate;
+    }
+
     private void updateLingerState(NetworkAgentInfo nai, long now) {
         // 1. Update the linger timer. If it's changed, reschedule or cancel the alarm.
         // 2. If the network was lingering and there are now requests, unlinger it.
@@ -2352,6 +2453,7 @@
                 } catch (Exception e) {
                     loge("Exception removing network: " + e);
                 }
+                mDnsManager.removeNetwork(nai.network);
             }
             synchronized (mNetworkForNetId) {
                 mNetIdInUse.delete(nai.network.netId);
@@ -2898,6 +3000,9 @@
                     handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
                     break;
                 }
+                case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
+                    handlePrivateDnsSettingsChanged();
+                    break;
             }
         }
     }
@@ -4587,11 +4692,12 @@
         final NetworkAgentInfo defaultNai = getDefaultNetwork();
         final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
 
-        Collection<InetAddress> dnses = newLp.getDnsServers();
-        if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
+        if (DBG) {
+            final Collection<InetAddress> dnses = newLp.getDnsServers();
+            log("Setting DNS servers for network " + netId + " to " + dnses);
+        }
         try {
-            mDnsManager.setDnsConfigurationForNetwork(
-                    netId, dnses, newLp.getDomains(), isDefaultNetwork);
+            mDnsManager.setDnsConfigurationForNetwork(netId, newLp, isDefaultNetwork);
         } catch (Exception e) {
             loge("Exception in setDnsConfigurationForNetwork: " + e);
         }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 985f16d..a12c85a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1591,6 +1591,8 @@
                     mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
                             mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
                             mPowerSaveWhitelistExceptIdleAppIds);
+
+                    passWhiteListToForceAppStandbyTrackerLocked();
                 }
                 return true;
             } catch (PackageManager.NameNotFoundException e) {
@@ -1608,6 +1610,8 @@
                         mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
                         mPowerSaveWhitelistExceptIdleAppIds);
                 mPowerSaveWhitelistUserAppsExceptIdle.clear();
+
+                passWhiteListToForceAppStandbyTrackerLocked();
             }
         }
     }
@@ -2572,7 +2576,7 @@
 
     private void passWhiteListToForceAppStandbyTrackerLocked() {
         ForceAppStandbyTracker.getInstance(getContext()).setPowerSaveWhitelistAppIds(
-                mPowerSaveWhitelistAllAppIdArray,
+                mPowerSaveWhitelistExceptIdleAppIdArray,
                 mTempWhitelistAppIdArray);
     }
 
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 2d2c6b0..e884de0 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -19,6 +19,10 @@
 import android.content.Context;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.IBinder;
+import android.os.IStoraged;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.StatFs;
 import android.os.SystemClock;
 import android.os.storage.StorageManager;
@@ -109,6 +113,12 @@
             }
         }
 
+        if (protoFormat) {
+            reportDiskWriteSpeedProto(proto);
+        } else {
+            reportDiskWriteSpeed(pw);
+        }
+
         reportFreeSpace(Environment.getDataDirectory(), "Data", pw, proto,
                 DiskStatsFreeSpaceProto.FOLDER_DATA);
         reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw, proto,
@@ -285,4 +295,41 @@
             Log.w(TAG, "exception reading diskstats cache file", e);
         }
     }
+
+    private int getRecentPerf() throws RemoteException, IllegalStateException {
+        IBinder binder = ServiceManager.getService("storaged");
+        if (binder == null) throw new IllegalStateException("storaged not found");
+        IStoraged storaged = IStoraged.Stub.asInterface(binder);
+        return storaged.getRecentPerf();
+    }
+
+    // Keep reportDiskWriteSpeed and reportDiskWriteSpeedProto in sync
+    private void reportDiskWriteSpeed(PrintWriter pw) {
+        try {
+            long perf = getRecentPerf();
+            if (perf != 0) {
+                pw.print("Recent Disk Write Speed (kB/s) = ");
+                pw.println(perf);
+            } else {
+                pw.println("Recent Disk Write Speed data unavailable");
+                Log.w(TAG, "Recent Disk Write Speed data unavailable!");
+            }
+        } catch (RemoteException | IllegalStateException e) {
+            pw.println(e.toString());
+            Log.e(TAG, e.toString());
+        }
+    }
+
+    private void reportDiskWriteSpeedProto(ProtoOutputStream proto) {
+        try {
+            long perf = getRecentPerf();
+            if (perf != 0) {
+                proto.write(DiskStatsServiceDumpProto.BENCHMARKED_WRITE_SPEED_KBPS, perf);
+            } else {
+                Log.w(TAG, "Recent Disk Write Speed data unavailable!");
+            }
+        } catch (RemoteException | IllegalStateException e) {
+            Log.e(TAG, e.toString());
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 8361132..732ac66 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -133,6 +133,7 @@
 2846 full_backup_cancelled (Package|3),(Message|3)
 
 2850 backup_transport_lifecycle (Transport|3),(Bound|1|1)
+2851 backup_transport_connection (Transport|3),(Connected|1|1)
 
 
 # ---------------------------
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
index 8776f3a..a75a367 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -98,6 +98,9 @@
     @GuardedBy("mLock")
     final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
 
+    /**
+     * System except-idle + user whitelist in the device idle controller.
+     */
     @GuardedBy("mLock")
     private int[] mPowerWhitelistedAllAppIds = new int[0];
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 55046959..21137ad 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -51,6 +51,7 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.Manifest;
+import android.annotation.AnyThread;
 import android.annotation.BinderThread;
 import android.annotation.ColorInt;
 import android.annotation.IntDef;
@@ -110,6 +111,7 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -256,6 +258,44 @@
     private static final String ACTION_SHOW_INPUT_METHOD_PICKER =
             "com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER";
 
+    /**
+     * Debug flag for overriding runtime {@link SystemProperties}.
+     */
+    @AnyThread
+    private static final class DebugFlag {
+        private static final Object LOCK = new Object();
+        private final String mKey;
+        @GuardedBy("LOCK")
+        private boolean mValue;
+
+        public DebugFlag(String key) {
+            mKey = key;
+            refresh();
+        }
+
+        void refresh() {
+            synchronized (LOCK) {
+                mValue = SystemProperties.getBoolean(mKey, true);
+            }
+        }
+
+        boolean value() {
+            synchronized (LOCK) {
+                return mValue;
+            }
+        }
+    }
+
+    /**
+     * Debug flags that can be overridden using "adb shell setprop <key>"
+     * Note: These flags are cached. To refresh, run "adb shell ime refresh_debug_properties".
+     */
+    private static final class DebugFlags {
+        static final DebugFlag FLAG_OPTIMIZE_START_INPUT =
+                new DebugFlag("debug.optimize_startinput");
+    }
+
+
     final Context mContext;
     final Resources mRes;
     final Handler mHandler;
@@ -2930,8 +2970,12 @@
                 }
 
                 if (!didStart && attribute != null) {
-                    res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
-                            controlFlags, startInputReason);
+                    if (!DebugFlags.FLAG_OPTIMIZE_START_INPUT.value()
+                            || (controlFlags
+                                    & InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0) {
+                        res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
+                                controlFlags, startInputReason);
+                    }
                 }
             }
         } finally {
@@ -4703,6 +4747,8 @@
                         return mService.handleShellCommandSetInputMethod(this);
                     case "reset":
                         return mService.handleShellCommandResetInputMethod(this);
+                    case "refresh_debug_properties":
+                        return refreshDebugProperties();
                     default:
                         getOutPrintWriter().println("Unknown command: " + imeCommand);
                         return ShellCommandResult.FAILURE;
@@ -4713,6 +4759,13 @@
         }
 
         @BinderThread
+        @ShellCommandResult
+        private int refreshDebugProperties() {
+            DebugFlags.FLAG_OPTIMIZE_START_INPUT.refresh();
+            return ShellCommandResult.SUCCESS;
+        }
+
+        @BinderThread
         @Override
         public void onHelp() {
             try (PrintWriter pw = getOutPrintWriter()) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 9d228c3..46a35ec 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1235,8 +1235,8 @@
      * reserved for future improved input validation.
      */
     @Override
-    public synchronized void removeTransportModeTransforms(
-            ParcelFileDescriptor socket, int resourceId) throws RemoteException {
+    public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
+            throws RemoteException {
         try {
             mSrvConfig
                     .getNetdInstance()
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index ea748db..6c63f43 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -232,10 +232,9 @@
 
     private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
 
-    private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
-            new ArrayMap<>();
+    private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
 
-    private final ArrayMap<IGnssNavigationMessageListener, Identity>
+    private final ArrayMap<IBinder, Identity>
             mGnssNavigationMessageListeners = new ArrayMap<>();
 
     // current active user on the device - other users are denied location data
@@ -438,23 +437,23 @@
                 applyRequirementsLocked(provider);
             }
 
-            for (Entry<IGnssMeasurementsListener, Identity> entry
-                    : mGnssMeasurementsListeners.entrySet()) {
+            for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
                 if (entry.getValue().mUid == uid) {
                     if (D) {
                         Log.d(TAG, "gnss measurements listener from uid " + uid
                                 + " is now " + (foreground ? "foreground" : "background)"));
                     }
                     if (foreground || isThrottlingExemptLocked(entry.getValue())) {
-                        mGnssMeasurementsProvider.addListener(entry.getKey());
+                        mGnssMeasurementsProvider.addListener(
+                                IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
                     } else {
-                        mGnssMeasurementsProvider.removeListener(entry.getKey());
+                        mGnssMeasurementsProvider.removeListener(
+                                IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
                     }
                 }
             }
 
-            for (Entry<IGnssNavigationMessageListener, Identity> entry
-                    : mGnssNavigationMessageListeners.entrySet()) {
+            for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
                 if (entry.getValue().mUid == uid) {
                     if (D) {
                         Log.d(TAG, "gnss navigation message listener from uid "
@@ -462,9 +461,11 @@
                                 + (foreground ? "foreground" : "background)"));
                     }
                     if (foreground || isThrottlingExemptLocked(entry.getValue())) {
-                        mGnssNavigationMessageProvider.addListener(entry.getKey());
+                        mGnssNavigationMessageProvider.addListener(
+                                IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
                     } else {
-                        mGnssNavigationMessageProvider.removeListener(entry.getKey());
+                        mGnssNavigationMessageProvider.removeListener(
+                                IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
                     }
                 }
             }
@@ -2401,7 +2402,7 @@
         synchronized (mLock) {
             Identity callerIdentity
                     = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
-            mGnssMeasurementsListeners.put(listener, callerIdentity);
+            mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
             long identity = Binder.clearCallingIdentity();
             try {
                 if (isThrottlingExemptLocked(callerIdentity)
@@ -2421,7 +2422,7 @@
     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
         if (mGnssMeasurementsProvider != null) {
             synchronized (mLock) {
-                mGnssMeasurementsListeners.remove(listener);
+                mGnssMeasurementsListeners.remove(listener.asBinder());
                 mGnssMeasurementsProvider.removeListener(listener);
             }
         }
@@ -2438,7 +2439,7 @@
         synchronized (mLock) {
             Identity callerIdentity
                     = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
-            mGnssNavigationMessageListeners.put(listener, callerIdentity);
+            mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
             long identity = Binder.clearCallingIdentity();
             try {
                 if (isThrottlingExemptLocked(callerIdentity)
@@ -2458,7 +2459,7 @@
     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
         if (mGnssNavigationMessageProvider != null) {
             synchronized (mLock) {
-                mGnssNavigationMessageListeners.remove(listener);
+                mGnssNavigationMessageListeners.remove(listener.asBinder());
                 mGnssNavigationMessageProvider.removeListener(listener);
             }
         }
@@ -3180,6 +3181,16 @@
                     pw.println("      " + record);
                 }
             }
+            pw.println("  Active GnssMeasurement Listeners:");
+            for (Identity identity : mGnssMeasurementsListeners.values()) {
+                pw.println("    " + identity.mPid + " " + identity.mUid + " "
+                        + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
+            }
+            pw.println("  Active GnssNavigationMessage Listeners:");
+            for (Identity identity : mGnssNavigationMessageListeners.values()) {
+                pw.println("    " + identity.mPid + " " + identity.mUid + " "
+                        + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
+            }
             pw.println("  Overlay Provider Packages:");
             for (LocationProviderInterface provider : mProviders) {
                 if (provider instanceof LocationProviderProxy) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8f646e7..88ae224 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -21,9 +21,6 @@
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.Manifest.permission.NETWORK_STACK;
 import static android.Manifest.permission.SHUTDOWN;
-import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
@@ -1957,15 +1954,6 @@
         }
     }
 
-    private static boolean shouldUseTls(ContentResolver cr) {
-        String privateDns = Settings.Global.getString(cr, Settings.Global.PRIVATE_DNS_MODE);
-        if (TextUtils.isEmpty(privateDns)) {
-            privateDns = PRIVATE_DNS_DEFAULT_MODE;
-        }
-        return privateDns.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
-               privateDns.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
-    }
-
     @Override
     public void addVpnUidRanges(int netId, UidRange[] ranges) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 35f83e4..30432df4 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -84,6 +84,7 @@
         "/system/bin/sdcard",
         "/system/bin/surfaceflinger",
         "media.extractor", // system/bin/mediaextractor
+        "media.metrics", // system/bin/mediametrics
         "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
         "com.android.bluetooth",  // Bluetooth service
     };
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dfe89e0..29d33ce 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.BIND_VOICE_INTERACTION;
 import static android.Manifest.permission.CHANGE_CONFIGURATION;
 import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
+import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
@@ -192,11 +193,11 @@
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
-import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_NONE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -293,6 +294,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManagerInternal;
 import android.location.LocationManager;
 import android.media.audiofx.AudioEffect;
 import android.metrics.LogMaker;
@@ -370,6 +372,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.RemoteAnimationDefinition;
 import android.view.View;
 import android.view.WindowManager;
 
@@ -472,6 +475,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -13674,7 +13678,8 @@
      * not.
      */
     private void enforceSystemHasVrFeature() {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
+        if (!mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE)) {
             throw new UnsupportedOperationException("VR mode not supported on this device!");
         }
     }
@@ -13733,9 +13738,7 @@
 
     @Override
     public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
-            throw new UnsupportedOperationException("VR mode not supported on this device!");
-        }
+        enforceSystemHasVrFeature();
 
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
 
@@ -13767,9 +13770,7 @@
 
     @Override
     public boolean isVrModePackageEnabled(ComponentName packageName) {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
-            throw new UnsupportedOperationException("VR mode not supported on this device!");
-        }
+        enforceSystemHasVrFeature();
 
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
 
@@ -25133,6 +25134,21 @@
         public boolean canStartMoreUsers() {
             return mUserController.canStartMoreUsers();
         }
+
+        @Override
+        public void setSwitchingFromSystemUserMessage(String switchingFromSystemUserMessage) {
+            mUserController.setSwitchingFromSystemUserMessage(switchingFromSystemUserMessage);
+        }
+
+        @Override
+        public void setSwitchingToSystemUserMessage(String switchingToSystemUserMessage) {
+            mUserController.setSwitchingToSystemUserMessage(switchingToSystemUserMessage);
+        }
+
+        @Override
+        public int getMaxRunningUsers() {
+            return mUserController.mMaxRunningUsers;
+        }
     }
 
     /**
@@ -25343,9 +25359,18 @@
                 }
             }
         }
-        if (updateFrameworkRes && mWindowManager != null) {
-            ActivityThread.currentActivityThread().getExecutor().execute(
-                    mWindowManager::onOverlayChanged);
+        if (updateFrameworkRes) {
+            // Update system server components that need to know about changed overlays. Because the
+            // overlay is applied in ActivityThread, we need to serialize through its thread too.
+            final Executor executor = ActivityThread.currentActivityThread().getExecutor();
+            final DisplayManagerInternal display =
+                    LocalServices.getService(DisplayManagerInternal.class);
+            if (display != null) {
+                executor.execute(display::onOverlayChanged);
+            }
+            if (mWindowManager != null) {
+                executor.execute(mWindowManager::onOverlayChanged);
+            }
         }
     }
 
@@ -25437,4 +25462,23 @@
             }
         }
     }
+
+    @Override
+    public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition)
+            throws RemoteException {
+        enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+                "registerRemoteAnimations");
+        synchronized (this) {
+            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            if (r == null) {
+                return;
+            }
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                r.registerRemoteAnimations(definition);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index b5fbee6..3bef877 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -21,6 +21,7 @@
 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
 import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
 import static android.app.ActivityOptions.ANIM_SCALE_UP;
 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
@@ -170,6 +171,7 @@
 import android.view.AppTransitionAnimationSpec;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IApplicationToken;
+import android.view.RemoteAnimationDefinition;
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.R;
@@ -372,6 +374,10 @@
         }
     }
 
+    String getLifecycleDescription(String reason) {
+        return "packageName=" + packageName + ", state=" + state + ", reason=" + reason;
+    }
+
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
@@ -1481,6 +1487,10 @@
                 case ANIM_OPEN_CROSS_PROFILE_APPS:
                     service.mWindowManager.overridePendingAppTransitionStartCrossProfileApps();
                     break;
+                case ANIM_REMOTE_ANIMATION:
+                    service.mWindowManager.overridePendingAppTransitionRemote(
+                            pendingOptions.getRemoteAnimationAdapter());
+                    break;
                 default:
                     Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
                     break;
@@ -1611,12 +1621,16 @@
 
             // If the activity is stopped or stopping, cycle to the paused state.
             if (state == STOPPED || state == STOPPING) {
+                // Capture reason before state change
+                final String reason = getLifecycleDescription("makeVisibleIfNeeded");
+
                 // An activity must be in the {@link PAUSING} state for the system to validate
                 // the move to {@link PAUSED}.
                 state = PAUSING;
                 service.mLifecycleManager.scheduleTransaction(app.thread, appToken,
                         PauseActivityItem.obtain(finishing, false /* userLeaving */,
-                                configChangeFlags, false /* dontReport */));
+                                configChangeFlags, false /* dontReport */)
+                                .setDescription(reason));
             }
         } catch (Exception e) {
             // Just skip on any failure; we'll make it visible when it next restarts.
@@ -2777,6 +2791,10 @@
         return mStackSupervisor.topRunningActivityLocked() == this;
     }
 
+    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
+        mWindowContainerController.registerRemoteAnimations(definition);
+    }
+
     @Override
     public String toString() {
         if (stringName != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a343965..f496a67 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -84,14 +84,14 @@
 import static com.android.server.am.proto.ActivityStackProto.ID;
 import static com.android.server.am.proto.ActivityStackProto.RESUMED_ACTIVITY;
 import static com.android.server.am.proto.ActivityStackProto.TASKS;
-import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
-import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_NONE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN_BEHIND;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
 
 import static java.lang.Integer.MAX_VALUE;
 
@@ -1817,7 +1817,8 @@
             boolean behindFullscreenActivity = !stackShouldBeVisible;
             boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
                     && (isInStackLocked(starting) == null);
-            final boolean isTopNotPinnedStack = getDisplay().isTopNotPinnedStack(this);
+            final boolean isTopNotPinnedStack =
+                    isAttached() && getDisplay().isTopNotPinnedStack(this);
             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                 final TaskRecord task = mTaskHistory.get(taskNdx);
                 final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -2639,7 +2640,9 @@
                     next.clearOptionsLocked();
                     mService.mLifecycleManager.scheduleTransaction(next.app.thread, next.appToken,
                             ResumeActivityItem.obtain(next.app.repProcState,
-                                    mService.isNextTransitionForward()));
+                                    mService.isNextTransitionForward())
+                                    .setDescription(next.getLifecycleDescription(
+                                            "resumeTopActivityInnerLocked")));
 
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                             + next);
@@ -3419,7 +3422,8 @@
                 EventLogTags.writeAmStopActivity(
                         r.userId, System.identityHashCode(r), r.shortComponentName);
                 mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
-                        StopActivityItem.obtain(r.visible, r.configChangeFlags));
+                        StopActivityItem.obtain(r.visible, r.configChangeFlags)
+                                .setDescription(r.getLifecycleDescription("stopActivityLocked")));
                 if (shouldSleepOrShutDownActivities()) {
                     r.setSleeping(true);
                 }
@@ -4225,7 +4229,8 @@
             try {
                 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
                 mService.mLifecycleManager.scheduleTransaction(r.app.thread, r.appToken,
-                        DestroyActivityItem.obtain(r.finishing, r.configChangeFlags));
+                        DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)
+                            .setDescription(r.getLifecycleDescription("destroyActivityLocked")));
             } catch (Exception e) {
                 // We can just ignore exceptions here...  if the process
                 // has crashed, our death notification will clean things
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b567303..8168cba 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.ACTIVITY_EMBEDDING;
+import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.START_ANY_ACTIVITY;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
@@ -93,7 +94,7 @@
 import static com.android.server.am.proto.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
 import static com.android.server.am.proto.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
 import static com.android.server.am.proto.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
-import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 
 import static java.lang.Integer.MAX_VALUE;
 
@@ -162,6 +163,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
+import android.view.RemoteAnimationAdapter;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.ReferrerIntent;
@@ -1422,7 +1424,8 @@
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
                 if (andResume) {
-                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
+                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward())
+                            .setDescription(r.getLifecycleDescription("realStartActivityLocked"));
                 } else {
                     lifecycleItem = PauseActivityItem.obtain();
                 }
@@ -1680,6 +1683,18 @@
                 Slog.w(TAG, msg);
                 throw new SecurityException(msg);
             }
+
+            // Check permission for remote animations
+            final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
+            if (adapter != null && mService.checkPermission(
+                    CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
+                            != PERMISSION_GRANTED) {
+                final String msg = "Permission Denial: starting " + intent.toString()
+                        + " from " + callerApp + " (pid=" + callingPid
+                        + ", uid=" + callingUid + ") with remoteAnimationAdapter";
+                Slog.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
         }
 
         return true;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 35465a7..8910274 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -738,9 +738,18 @@
                 }
                 return;
             }
+            final boolean showFirstCrash = Settings.Global.getInt(
+                    mContext.getContentResolver(),
+                    Settings.Global.SHOW_FIRST_CRASH_DIALOG, 0) != 0;
+            final boolean showFirstCrashDevOption = Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
+                    0,
+                    UserHandle.USER_CURRENT) != 0;
             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
                     mAppsNotReportingCrashes.contains(proc.info.packageName);
-            if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced) {
+            if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced
+                    && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
                 proc.crashDialog = new AppErrorDialog(mContext, mService, data);
             } else {
                 // The device is asleep, so just pretend that the user
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 4d7bc1e..79f3fe3 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -27,13 +27,13 @@
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.proto.KeyguardControllerProto.KEYGUARD_OCCLUDED;
 import static com.android.server.am.proto.KeyguardControllerProto.KEYGUARD_SHOWING;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_OCCLUDE;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_UNSET;
 
 import android.app.ActivityManagerInternal.SleepToken;
 import android.os.IBinder;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a327a01..1a47aa5 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -217,6 +217,18 @@
     private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks;
 
     /**
+     * Messages for for switching from {@link android.os.UserHandle#SYSTEM}.
+     */
+    @GuardedBy("mLock")
+    private String mSwitchingFromSystemUserMessage;
+
+    /**
+     * Messages for for switching to {@link android.os.UserHandle#SYSTEM}.
+     */
+    @GuardedBy("mLock")
+    private String mSwitchingToSystemUserMessage;
+
+    /**
      * Callbacks that are still active after {@link #USER_SWITCH_TIMEOUT_MS}
      */
     @GuardedBy("mLock")
@@ -783,11 +795,13 @@
      */
     private void stopGuestOrEphemeralUserIfBackground(int oldUserId) {
         if (DEBUG_MU) Slog.i(TAG, "Stop guest or ephemeral user if background: " + oldUserId);
-        UserState oldUss = mStartedUsers.get(oldUserId);
-        if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
-                || oldUss.state == UserState.STATE_STOPPING
-                || oldUss.state == UserState.STATE_SHUTDOWN) {
-            return;
+        synchronized(mLock) {
+            UserState oldUss = mStartedUsers.get(oldUserId);
+            if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId || oldUss == null
+                    || oldUss.state == UserState.STATE_STOPPING
+                    || oldUss.state == UserState.STATE_SHUTDOWN) {
+                return;
+            }
         }
 
         UserInfo userInfo = getUserInfo(oldUserId);
@@ -1189,7 +1203,8 @@
 
     private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) {
         // The dialog will show and then initiate the user switch by calling startUserInForeground
-        mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second);
+        mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second,
+                getSwitchingFromSystemUserMessage(), getSwitchingToSystemUserMessage());
     }
 
     private void dispatchForegroundProfileChanged(int userId) {
@@ -1799,6 +1814,30 @@
         return mLockPatternUtils.isLockScreenDisabled(userId);
     }
 
+    void setSwitchingFromSystemUserMessage(String switchingFromSystemUserMessage) {
+        synchronized (mLock) {
+            mSwitchingFromSystemUserMessage = switchingFromSystemUserMessage;
+        }
+    }
+
+    void setSwitchingToSystemUserMessage(String switchingToSystemUserMessage) {
+        synchronized (mLock) {
+            mSwitchingToSystemUserMessage = switchingToSystemUserMessage;
+        }
+    }
+
+    private String getSwitchingFromSystemUserMessage() {
+        synchronized (mLock) {
+            return mSwitchingFromSystemUserMessage;
+        }
+    }
+
+    private String getSwitchingToSystemUserMessage() {
+        synchronized (mLock) {
+            return mSwitchingToSystemUserMessage;
+        }
+    }
+
     void dump(PrintWriter pw, boolean dumpAll) {
         synchronized (mLock) {
             pw.println("  mStartedUsers:");
@@ -2079,9 +2118,11 @@
             mService.installEncryptionUnawareProviders(userId);
         }
 
-        void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser) {
+        void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
+                String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
             Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
-                    true /* above system */);
+                    true /* above system */, switchingFromSystemUserMessage,
+                    switchingToSystemUserMessage);
             d.show();
         }
 
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 3e6934f..afcba3b 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -53,7 +53,8 @@
     private boolean mStartedUser;
 
     public UserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
-            UserInfo newUser, boolean aboveSystem) {
+            UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
+            String switchingToSystemUserMessage) {
         super(context);
 
         mService = service;
@@ -65,7 +66,7 @@
         // Custom view due to alignment and font size requirements
         View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog, null);
 
-        String viewMessage;
+        String viewMessage = null;
         if (UserManager.isSplitSystemUser() && newUser.id == UserHandle.USER_SYSTEM) {
             viewMessage = res.getString(R.string.user_logging_out_message, oldUser.name);
         } else if (UserManager.isDeviceInDemoMode(context)) {
@@ -75,7 +76,17 @@
                 viewMessage = res.getString(R.string.demo_starting_message);
             }
         } else {
-            viewMessage = res.getString(R.string.user_switching_message, newUser.name);
+            if (oldUser.id == UserHandle.USER_SYSTEM) {
+                viewMessage = switchingFromSystemUserMessage;
+            } else if (newUser.id == UserHandle.USER_SYSTEM) {
+                viewMessage = switchingToSystemUserMessage;
+            }
+
+            // If switchingFromSystemUserMessage or switchingToSystemUserMessage is null, fallback
+            // to system message.
+            if (viewMessage == null) {
+                viewMessage = res.getString(R.string.user_switching_message, newUser.name);
+            }
         }
         ((TextView) view.findViewById(R.id.message)).setText(viewMessage);
         setView(view);
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index a4170ce..a1c54bd 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -17,6 +17,7 @@
 package com.android.server.connectivity;
 
 import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
 import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
@@ -29,19 +30,32 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkUtils;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.INetworkManagementService;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.system.GaiException;
+import android.system.OsConstants;
+import android.system.StructAddrinfo;
 import android.text.TextUtils;
 import android.util.Slog;
 
 import com.android.server.connectivity.MockableSystemProperties;
 
+import libcore.io.Libcore;
+
 import java.net.InetAddress;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.StringJoiner;
 
 
 /**
@@ -61,10 +75,86 @@
     private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
     private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
 
+    public static class PrivateDnsConfig {
+        public final boolean useTls;
+        public final String hostname;
+        public final InetAddress[] ips;
+
+        public PrivateDnsConfig() {
+            this(false);
+        }
+
+        public PrivateDnsConfig(boolean useTls) {
+            this.useTls = useTls;
+            this.hostname = "";
+            this.ips = new InetAddress[0];
+        }
+
+        public PrivateDnsConfig(String hostname, InetAddress[] ips) {
+            this.useTls = !TextUtils.isEmpty(hostname);
+            this.hostname = useTls ? hostname : "";
+            this.ips = (ips != null) ? ips : new InetAddress[0];
+        }
+
+        public PrivateDnsConfig(PrivateDnsConfig cfg) {
+            useTls = cfg.useTls;
+            hostname = cfg.hostname;
+            ips = cfg.ips;
+        }
+
+        public boolean inStrictMode() {
+            return useTls && !TextUtils.isEmpty(hostname);
+        }
+
+        public String toString() {
+            return PrivateDnsConfig.class.getSimpleName() +
+                    "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}";
+        }
+    }
+
+    public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) {
+        final String mode = getPrivateDnsMode(cr);
+
+        final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode);
+
+        if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) {
+            final String specifier = getStringSetting(cr, PRIVATE_DNS_SPECIFIER);
+            return new PrivateDnsConfig(specifier, null);
+        }
+
+        return new PrivateDnsConfig(useTls);
+    }
+
+    public static PrivateDnsConfig tryBlockingResolveOf(Network network, String name) {
+        final StructAddrinfo hints = new StructAddrinfo();
+        // Unnecessary, but expressly no AI_ADDRCONFIG.
+        hints.ai_flags = 0;
+        // Fetch all IP addresses at once to minimize re-resolution.
+        hints.ai_family = OsConstants.AF_UNSPEC;
+        hints.ai_socktype = OsConstants.SOCK_DGRAM;
+
+        try {
+            final InetAddress[] ips = Libcore.os.android_getaddrinfo(name, hints, network.netId);
+            if (ips != null && ips.length > 0) {
+                return new PrivateDnsConfig(name, ips);
+            }
+        } catch (GaiException ignored) {}
+
+        return null;
+    }
+
+    public static Uri[] getPrivateDnsSettingsUris() {
+        final Uri[] uris = new Uri[2];
+        uris[0] = Settings.Global.getUriFor(PRIVATE_DNS_MODE);
+        uris[1] = Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER);
+        return uris;
+    }
+
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private final INetworkManagementService mNMS;
     private final MockableSystemProperties mSystemProperties;
+    private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap;
 
     private int mNumDnsEntries;
     private int mSampleValidity;
@@ -79,44 +169,55 @@
         mContentResolver = mContext.getContentResolver();
         mNMS = nms;
         mSystemProperties = sp;
+        mPrivateDnsMap = new HashMap<>();
 
         // TODO: Create and register ContentObservers to track every setting
         // used herein, posting messages to respond to changes.
     }
 
-    public boolean isPrivateDnsInStrictMode() {
-        return !TextUtils.isEmpty(mPrivateDnsMode) &&
-               mPrivateDnsMode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) &&
-               !TextUtils.isEmpty(mPrivateDnsSpecifier);
+    public PrivateDnsConfig getPrivateDnsConfig() {
+        return getPrivateDnsConfig(mContentResolver);
+    }
+
+    public void removeNetwork(Network network) {
+        mPrivateDnsMap.remove(network.netId);
+    }
+
+    public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
+        Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
+        return (cfg != null)
+                ? mPrivateDnsMap.put(network.netId, cfg)
+                : mPrivateDnsMap.remove(network);
     }
 
     public void setDnsConfigurationForNetwork(
-            int netId, Collection<InetAddress> servers, String domains, boolean isDefaultNetwork) {
-        updateParametersSettings();
-        updatePrivateDnsSettings();
+            int netId, LinkProperties lp, boolean isDefaultNetwork) {
+        // We only use the PrivateDnsConfig data pushed to this class instance
+        // from ConnectivityService because it works in coordination with
+        // NetworkMonitor to decide which networks need validation and runs the
+        // blocking calls to resolve Private DNS strict mode hostnames.
+        //
+        // At this time we do attempt to enable Private DNS on non-Internet
+        // networks like IMS.
+        final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.get(netId);
 
-        final String[] serverStrs = NetworkUtils.makeStrings(servers);
-        final String[] domainStrs = (domains == null) ? new String[0] : domains.split(" ");
+        final boolean useTls = (privateDnsCfg != null) && privateDnsCfg.useTls;
+        final boolean strictMode = (privateDnsCfg != null) && privateDnsCfg.inStrictMode();
+        final String tlsHostname = strictMode ? privateDnsCfg.hostname : "";
+
+        final String[] serverStrs = NetworkUtils.makeStrings(
+                strictMode ? Arrays.stream(privateDnsCfg.ips)
+                                   .filter((ip) -> lp.isReachable(ip))
+                                   .collect(Collectors.toList())
+                           : lp.getDnsServers());
+        final String[] domainStrs = getDomainStrings(lp.getDomains());
+
+        updateParametersSettings();
         final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
-        final boolean useTls = shouldUseTls(mPrivateDnsMode);
-        // TODO: Populate tlsHostname once it's decided how the hostname's IP
-        // addresses will be resolved:
-        //
-        //     [1] network-provided DNS servers are included here with the
-        //         hostname and netd will use the network-provided servers to
-        //         resolve the hostname and fix up its internal structures, or
-        //
-        //     [2] network-provided DNS servers are included here without the
-        //         hostname, the ConnectivityService layer resolves the given
-        //         hostname, and then reconfigures netd with this information.
-        //
-        // In practice, there will always be a need for ConnectivityService or
-        // the captive portal app to use the network-provided services to make
-        // some queries. This argues in favor of [1], in concert with another
-        // mechanism, perhaps setting a high bit in the netid, to indicate
-        // via existing DNS APIs which set of servers (network-provided or
-        // non-network-provided private DNS) should be queried.
-        final String tlsHostname = "";
+
+        Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %s, %s, %s)",
+                netId, Arrays.toString(serverStrs), Arrays.toString(domainStrs),
+                Arrays.toString(params), useTls, tlsHostname));
         try {
             mNMS.setDnsConfigurationForNetwork(
                     netId, serverStrs, domainStrs, params, useTls, tlsHostname);
@@ -129,7 +230,7 @@
         // default network, and we should just set net.dns1 to ::1, not least
         // because applications attempting to use net.dns resolvers will bypass
         // the privacy protections of things like DNS-over-TLS.
-        if (isDefaultNetwork) setDefaultDnsSystemProperties(servers);
+        if (isDefaultNetwork) setDefaultDnsSystemProperties(lp.getDnsServers());
         flushVmDnsCache();
     }
 
@@ -163,11 +264,6 @@
         }
     }
 
-    private void updatePrivateDnsSettings() {
-        mPrivateDnsMode = getStringSetting(PRIVATE_DNS_MODE);
-        mPrivateDnsSpecifier = getStringSetting(PRIVATE_DNS_SPECIFIER);
-    }
-
     private void updateParametersSettings() {
         mSampleValidity = getIntSetting(
                 DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
@@ -198,10 +294,6 @@
         }
     }
 
-    private String getStringSetting(String which) {
-        return Settings.Global.getString(mContentResolver, which);
-    }
-
     private int getIntSetting(String which, int dflt) {
         return Settings.Global.getInt(mContentResolver, which, dflt);
     }
@@ -216,11 +308,16 @@
         }
     }
 
-    private static boolean shouldUseTls(String mode) {
-        if (TextUtils.isEmpty(mode)) {
-            mode = PRIVATE_DNS_DEFAULT_MODE;
-        }
-        return mode.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
-               mode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+    private static String getPrivateDnsMode(ContentResolver cr) {
+        final String mode = getStringSetting(cr, PRIVATE_DNS_MODE);
+        return !TextUtils.isEmpty(mode) ? mode : PRIVATE_DNS_DEFAULT_MODE;
+    }
+
+    private static String getStringSetting(ContentResolver cr, String which) {
+        return Settings.Global.getString(cr, which);
+    }
+
+    private static String[] getDomainStrings(String domains) {
+        return (TextUtils.isEmpty(domains)) ? new String[0] : domains.split(" ");
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 7684030..ed268581b 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -29,6 +29,7 @@
 import android.net.ConnectivityManager;
 import android.net.ICaptivePortal;
 import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.ProxyInfo;
 import android.net.TrafficStats;
@@ -215,6 +216,15 @@
      */
     private static final int CMD_CAPTIVE_PORTAL_RECHECK = BASE + 12;
 
+    /**
+     * ConnectivityService notifies NetworkMonitor of settings changes to
+     * Private DNS. If a DNS resolution is required, e.g. for DNS-over-TLS in
+     * strict mode, then an event is sent back to ConnectivityService with the
+     * result of the resolution attempt.
+     */
+    private static final int CMD_PRIVATE_DNS_SETTINGS_CHANGED = BASE + 13;
+    public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = BASE + 14;
+
     // Start mReevaluateDelayMs at this value and double.
     private static final int INITIAL_REEVALUATE_DELAY_MS = 1000;
     private static final int MAX_REEVALUATE_DELAY_MS = 10*60*1000;
@@ -230,6 +240,12 @@
 
     private static final int NUM_VALIDATION_LOG_LINES = 20;
 
+    public static boolean isValidationRequired(
+            NetworkCapabilities dfltNetCap, NetworkCapabilities nc) {
+        // TODO: Consider requiring validation for DUN networks.
+        return dfltNetCap.satisfiedByNetworkCapabilities(nc);
+    }
+
     private final Context mContext;
     private final Handler mConnectivityServiceHandler;
     private final NetworkAgentInfo mNetworkAgentInfo;
@@ -261,6 +277,8 @@
 
     public boolean systemReady = false;
 
+    private DnsManager.PrivateDnsConfig mPrivateDnsCfg = null;
+
     private final State mDefaultState = new DefaultState();
     private final State mValidatedState = new ValidatedState();
     private final State mMaybeNotifyState = new MaybeNotifyState();
@@ -342,6 +360,11 @@
         return 0 == mValidations ? ValidationStage.FIRST_VALIDATION : ValidationStage.REVALIDATION;
     }
 
+    private boolean isValidationRequired() {
+        return isValidationRequired(
+                mDefaultRequest.networkCapabilities, mNetworkAgentInfo.networkCapabilities);
+    }
+
     // DefaultState is the parent of all States.  It exists only to handle CMD_* messages but
     // does not entail any real state (hence no enter() or exit() routines).
     private class DefaultState extends State {
@@ -405,6 +428,18 @@
                             break;
                     }
                     return HANDLED;
+                case CMD_PRIVATE_DNS_SETTINGS_CHANGED:
+                    if (isValidationRequired()) {
+                        // This performs a blocking DNS resolution of the
+                        // strict mode hostname, if required.
+                        resolvePrivateDnsConfig((DnsManager.PrivateDnsConfig) message.obj);
+                        if ((mPrivateDnsCfg != null) && mPrivateDnsCfg.inStrictMode()) {
+                            mConnectivityServiceHandler.sendMessage(obtainMessage(
+                                    EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, mNetId,
+                                    new DnsManager.PrivateDnsConfig(mPrivateDnsCfg)));
+                        }
+                    }
+                    return HANDLED;
                 default:
                     return HANDLED;
             }
@@ -421,7 +456,7 @@
             maybeLogEvaluationResult(
                     networkEventType(validationStage(), EvaluationResult.VALIDATED));
             mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
-                    NETWORK_TEST_RESULT_VALID, mNetId, null));
+                    NETWORK_TEST_RESULT_VALID, mNetId, mPrivateDnsCfg));
             mValidations++;
         }
 
@@ -567,9 +602,9 @@
                     //    the network so don't bother validating here.  Furthermore sending HTTP
                     //    packets over the network may be undesirable, for example an extremely
                     //    expensive metered network, or unwanted leaking of the User Agent string.
-                    if (!mDefaultRequest.networkCapabilities.satisfiedByNetworkCapabilities(
-                            mNetworkAgentInfo.networkCapabilities)) {
+                    if (!isValidationRequired()) {
                         validationLog("Network would not satisfy default request, not validating");
+                        mPrivateDnsCfg = null;
                         transitionTo(mValidatedState);
                         return HANDLED;
                     }
@@ -582,6 +617,7 @@
                     // if this is found to cause problems.
                     CaptivePortalProbeResult probeResult = isCaptivePortal();
                     if (probeResult.isSuccessful()) {
+                        resolvePrivateDnsConfig();
                         transitionTo(mValidatedState);
                     } else if (probeResult.isPortal()) {
                         mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
@@ -1045,6 +1081,44 @@
         return null;
     }
 
+    public void notifyPrivateDnsSettingsChanged(DnsManager.PrivateDnsConfig newCfg) {
+        // Cancel any outstanding resolutions.
+        removeMessages(CMD_PRIVATE_DNS_SETTINGS_CHANGED);
+        // Send the update to the proper thread.
+        sendMessage(CMD_PRIVATE_DNS_SETTINGS_CHANGED, newCfg);
+    }
+
+    private void resolvePrivateDnsConfig() {
+        resolvePrivateDnsConfig(DnsManager.getPrivateDnsConfig(mContext.getContentResolver()));
+    }
+
+    private void resolvePrivateDnsConfig(DnsManager.PrivateDnsConfig cfg) {
+        // Nothing to do.
+        if (cfg == null) {
+            mPrivateDnsCfg = null;
+            return;
+        }
+
+        // No DNS resolution required.
+        if (!cfg.inStrictMode()) {
+            mPrivateDnsCfg = cfg;
+            return;
+        }
+
+        if ((mPrivateDnsCfg != null) && mPrivateDnsCfg.inStrictMode() &&
+                (mPrivateDnsCfg.ips.length > 0) && mPrivateDnsCfg.hostname.equals(cfg.hostname)) {
+            // We have already resolved this strict mode hostname. Assume that
+            // Private DNS services won't be changing serving IP addresses very
+            // frequently and save ourselves one re-resolve.
+            return;
+        }
+
+        mPrivateDnsCfg = cfg;
+        final DnsManager.PrivateDnsConfig resolvedCfg = DnsManager.tryBlockingResolveOf(
+                mNetwork, mPrivateDnsCfg.hostname);
+        if (resolvedCfg != null) mPrivateDnsCfg = resolvedCfg;
+    }
+
     /**
      * @param responseReceived - whether or not we received a valid HTTP response to our request.
      * If false, isCaptivePortal and responseTimestampMs are ignored
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 3c2d724..aa174e3 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.BIND_VPN_SERVICE;
 import static android.net.ConnectivityManager.NETID_UNSET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.RouteInfo.RTN_THROW;
@@ -298,11 +299,13 @@
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         boolean metered = false;
         boolean roaming = false;
+        boolean congested = false;
 
         if (ArrayUtils.isEmpty(underlyingNetworks)) {
             // No idea what the underlying networks are; assume sane defaults
             metered = true;
             roaming = false;
+            congested = false;
         } else {
             for (Network underlying : underlyingNetworks) {
                 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
@@ -319,22 +322,16 @@
                         underlyingCaps.getLinkUpstreamBandwidthKbps());
                 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
                 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+                congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
             }
         }
 
         caps.setTransportTypes(transportTypes);
         caps.setLinkDownstreamBandwidthKbps(downKbps);
         caps.setLinkUpstreamBandwidthKbps(upKbps);
-        if (metered) {
-            caps.removeCapability(NET_CAPABILITY_NOT_METERED);
-        } else {
-            caps.addCapability(NET_CAPABILITY_NOT_METERED);
-        }
-        if (roaming) {
-            caps.removeCapability(NET_CAPABILITY_NOT_ROAMING);
-        } else {
-            caps.addCapability(NET_CAPABILITY_NOT_ROAMING);
-        }
+        caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
+        caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
+        caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 1e94e00..bcf8bfe 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -521,6 +521,7 @@
     public void dump(PrintWriter pw) {
         pw.println("BrightnessTracker state:");
         synchronized (mDataCollectionLock) {
+            pw.println("  mStarted=" + mStarted);
             pw.println("  mLastSensorReadings.size=" + mLastSensorReadings.size());
             if (!mLastSensorReadings.isEmpty()) {
                 pw.println("  mLastSensorReadings time span "
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 839ab4d..3a8e291 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -143,6 +143,9 @@
     public void requestDisplayModesInTransactionLocked(int colorMode, int modeId) {
     }
 
+    public void onOverlayChangedLocked() {
+    }
+
     /**
      * Sets the display layer stack while in a transaction.
      */
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 02e4fe0..b97de65 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -29,6 +29,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -1005,11 +1006,13 @@
     }
 
     private void setBrightnessConfigurationForUserInternal(
-            @NonNull BrightnessConfiguration c, @UserIdInt int userId) {
+            @NonNull BrightnessConfiguration c, @UserIdInt int userId,
+            @Nullable String packageName) {
         final int userSerial = getUserManager().getUserSerialNumber(userId);
         synchronized (mSyncRoot) {
             try {
-                mPersistentDataStore.setBrightnessConfigurationForUser(c, userSerial);
+                mPersistentDataStore.setBrightnessConfigurationForUser(c, userSerial,
+                        packageName);
             } finally {
                 mPersistentDataStore.saveIfNeeded();
             }
@@ -1833,7 +1836,7 @@
 
         @Override // Binder call
         public void setBrightnessConfigurationForUser(
-                BrightnessConfiguration c, @UserIdInt int userId) {
+                BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
                     "Permission required to change the display's brightness configuration");
@@ -1843,10 +1846,13 @@
                         "Permission required to change the display brightness"
                         + " configuration of another user");
             }
+            if (packageName != null && !validatePackageName(getCallingUid(), packageName)) {
+                packageName = null;
+            }
             Preconditions.checkNotNull(c);
             final long token = Binder.clearCallingIdentity();
             try {
-                setBrightnessConfigurationForUserInternal(c, userId);
+                setBrightnessConfigurationForUserInternal(c, userId, packageName);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -2009,5 +2015,14 @@
                 mDisplayPowerController.persistBrightnessSliderEvents();
             }
         }
+
+        @Override
+        public void onOverlayChanged() {
+            synchronized (mSyncRoot) {
+                for (int i = 0; i < mDisplayDevices.size(); i++) {
+                    mDisplayDevices.get(i).onOverlayChangedLocked();
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 23e4c9b..fc3c1f7 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -600,6 +600,11 @@
             }
         }
 
+        @Override
+        public void onOverlayChangedLocked() {
+            updateDeviceInfoLocked();
+        }
+
         public boolean requestModeInTransactionLocked(int modeId) {
             if (modeId == 0) {
                 modeId = mDefaultModeId;
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 49b4465..f1ce5c5 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -23,6 +23,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.Nullable;
 import android.graphics.Point;
 import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.WifiDisplay;
@@ -30,6 +31,8 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Pair;
+import android.util.SparseLongArray;
+import android.util.TimeUtils;
 import android.util.Xml;
 import android.view.Display;
 
@@ -73,8 +76,8 @@
  *      &lt;stable-display-width>1080&lt;/stable-display-width>
  *  &lt;/stable-device-values>
  *  &lt;brightness-configurations>
- *      &lt;brightness-configuration user-id="0">
- *          &lt;brightness-curve>
+ *      &lt;brightness-configuration user-serial="0" package-name="com.example" timestamp="1234">
+ *          &lt;brightness-curve description="some text">
  *              &lt;brightness-point lux="0" nits="13.25"/>
  *              &lt;brightness-point lux="20" nits="35.94"/>
  *          &lt;/brightness-curve>
@@ -110,8 +113,11 @@
     private static final String TAG_BRIGHTNESS_CURVE = "brightness-curve";
     private static final String TAG_BRIGHTNESS_POINT = "brightness-point";
     private static final String ATTR_USER_SERIAL = "user-serial";
+    private static final String ATTR_PACKAGE_NAME = "package-name";
+    private static final String ATTR_TIME_STAMP = "timestamp";
     private static final String ATTR_LUX = "lux";
     private static final String ATTR_NITS = "nits";
+    private static final String ATTR_DESCRIPTION = "description";
 
     // Remembered Wifi display devices.
     private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
@@ -273,9 +279,11 @@
 		}
 	}
 
-    public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userSerial) {
+    public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userSerial,
+            @Nullable String packageName) {
         loadIfNeeded();
-        if (mBrightnessConfigurations.setBrightnessConfigurationForUser(c, userSerial)) {
+        if (mBrightnessConfigurations.setBrightnessConfigurationForUser(c, userSerial,
+                packageName)) {
             setDirty();
         }
     }
@@ -576,15 +584,27 @@
     private static final class BrightnessConfigurations {
         // Maps from a user ID to the users' given brightness configuration
         private SparseArray<BrightnessConfiguration> mConfigurations;
+        // Timestamp of time the configuration was set.
+        private SparseLongArray mTimeStamps;
+        // Package that set the configuration.
+        private SparseArray<String> mPackageNames;
 
         public BrightnessConfigurations() {
             mConfigurations = new SparseArray<>();
+            mTimeStamps = new SparseLongArray();
+            mPackageNames = new SparseArray<>();
         }
 
         private boolean setBrightnessConfigurationForUser(BrightnessConfiguration c,
-                int userSerial) {
+                int userSerial, String packageName) {
             BrightnessConfiguration currentConfig = mConfigurations.get(userSerial);
             if (currentConfig == null || !currentConfig.equals(c)) {
+                if (packageName == null) {
+                    mPackageNames.remove(userSerial);
+                } else {
+                    mPackageNames.put(userSerial, packageName);
+                }
+                mTimeStamps.put(userSerial, System.currentTimeMillis());
                 mConfigurations.put(userSerial, c);
                 return true;
             }
@@ -604,14 +624,31 @@
                         userSerial = Integer.parseInt(
                                 parser.getAttributeValue(null, ATTR_USER_SERIAL));
                     } catch (NumberFormatException nfe) {
-                        userSerial= -1;
+                        userSerial = -1;
                         Slog.e(TAG, "Failed to read in brightness configuration", nfe);
                     }
 
+                    String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
+                    String timeStampString = parser.getAttributeValue(null, ATTR_TIME_STAMP);
+                    long timeStamp = -1;
+                    if (timeStampString != null) {
+                        try {
+                            timeStamp = Long.parseLong(timeStampString);
+                        } catch (NumberFormatException nfe) {
+                            // Ignore we will just not restore the timestamp.
+                        }
+                    }
+
                     try {
                         BrightnessConfiguration config = loadConfigurationFromXml(parser);
-                        if (userSerial>= 0 && config != null) {
+                        if (userSerial >= 0 && config != null) {
                             mConfigurations.put(userSerial, config);
+                            if (timeStamp != -1) {
+                                mTimeStamps.put(userSerial, timeStamp);
+                            }
+                            if (packageName != null) {
+                                mPackageNames.put(userSerial, packageName);
+                            }
                         }
                     } catch (IllegalArgumentException iae) {
                         Slog.e(TAG, "Failed to load brightness configuration!", iae);
@@ -623,18 +660,24 @@
         private static BrightnessConfiguration loadConfigurationFromXml(XmlPullParser parser)
                 throws IOException, XmlPullParserException {
             final int outerDepth = parser.getDepth();
-            final BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
+            String description = null;
+            Pair<float[], float[]> curve = null;
             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                 if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) {
-                    Pair<float[], float[]> curve = loadCurveFromXml(parser, builder);
-                    builder.setCurve(curve.first /*lux*/, curve.second /*nits*/);
+                    description = parser.getAttributeValue(null, ATTR_DESCRIPTION);
+                    curve = loadCurveFromXml(parser);
                 }
             }
+            if (curve == null) {
+                return null;
+            }
+            final BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                    curve.first, curve.second);
+            builder.setDescription(description);
             return builder.build();
         }
 
-        private static Pair<float[], float[]> loadCurveFromXml(XmlPullParser parser,
-                BrightnessConfiguration.Builder builder)
+        private static Pair<float[], float[]> loadCurveFromXml(XmlPullParser parser)
                 throws IOException, XmlPullParserException {
             final int outerDepth = parser.getDepth();
             List<Float> luxLevels = new ArrayList<>();
@@ -666,11 +709,19 @@
 
         public void saveToXml(XmlSerializer serializer) throws IOException {
             for (int i = 0; i < mConfigurations.size(); i++) {
-                final int userSerial= mConfigurations.keyAt(i);
+                final int userSerial = mConfigurations.keyAt(i);
                 final BrightnessConfiguration config = mConfigurations.valueAt(i);
 
                 serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATION);
                 serializer.attribute(null, ATTR_USER_SERIAL, Integer.toString(userSerial));
+                String packageName = mPackageNames.get(userSerial);
+                if (packageName != null) {
+                    serializer.attribute(null, ATTR_PACKAGE_NAME, packageName);
+                }
+                long timestamp = mTimeStamps.get(userSerial, -1);
+                if (timestamp != -1) {
+                    serializer.attribute(null, ATTR_TIME_STAMP, Long.toString(timestamp));
+                }
                 saveConfigurationToXml(serializer, config);
                 serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATION);
             }
@@ -679,6 +730,9 @@
         private static void saveConfigurationToXml(XmlSerializer serializer,
                 BrightnessConfiguration config) throws IOException {
             serializer.startTag(null, TAG_BRIGHTNESS_CURVE);
+            if (config.getDescription() != null) {
+                serializer.attribute(null, ATTR_DESCRIPTION, config.getDescription());
+            }
             final Pair<float[], float[]> curve = config.getCurve();
             for (int i = 0; i < curve.first.length; i++) {
                 serializer.startTag(null, TAG_BRIGHTNESS_POINT);
@@ -691,8 +745,16 @@
 
         public void dump(final PrintWriter pw, final String prefix) {
             for (int i = 0; i < mConfigurations.size(); i++) {
-                final int userSerial= mConfigurations.keyAt(i);
+                final int userSerial = mConfigurations.keyAt(i);
+                long time = mTimeStamps.get(userSerial, -1);
+                String packageName = mPackageNames.get(userSerial);
                 pw.println(prefix + "User " + userSerial + ":");
+                if (time != -1) {
+                    pw.println(prefix + "  set at: " + TimeUtils.formatForLogging(time));
+                }
+                if (packageName != null) {
+                    pw.println(prefix + "  set by: " + packageName);
+                }
                 pw.println(prefix + "  " + mConfigurations.valueAt(i));
             }
         }
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
old mode 100644
new mode 100755
index 97a6e85..db8dedb
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -228,12 +228,20 @@
                 if (cmd.getOpcode() == Constants.MESSAGE_SET_OSD_NAME) {
                     handleSetOsdName(cmd);
                     return true;
+                } else if ((cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) &&
+                        ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_GIVE_OSD_NAME)) {
+                    handleSetOsdName(cmd);
+                    return true;
                 }
                 return false;
             case STATE_WAITING_FOR_VENDOR_ID:
                 if (cmd.getOpcode() == Constants.MESSAGE_DEVICE_VENDOR_ID) {
                     handleVendorId(cmd);
                     return true;
+                } else if ((cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) &&
+                        ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID)) {
+                    handleVendorId(cmd);
+                    return true;
                 }
                 return false;
             case STATE_WAITING_FOR_DEVICE_POLLING:
@@ -281,7 +289,11 @@
 
         String displayName = null;
         try {
-            displayName = new String(cmd.getParams(), "US-ASCII");
+            if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) {
+                displayName = HdmiUtils.getDefaultDeviceName(current.mLogicalAddress);
+            } else {
+                displayName = new String(cmd.getParams(), "US-ASCII");
+            }
         } catch (UnsupportedEncodingException e) {
             Slog.w(TAG, "Failed to decode display name: " + cmd.toString());
             // If failed to get display name, use the default name of device.
@@ -302,9 +314,12 @@
             return;
         }
 
-        byte[] params = cmd.getParams();
-        int vendorId = HdmiUtils.threeBytesToInt(params);
-        current.mVendorId = vendorId;
+        if (cmd.getOpcode() != Constants.MESSAGE_FEATURE_ABORT) {
+            byte[] params = cmd.getParams();
+            int vendorId = HdmiUtils.threeBytesToInt(params);
+            current.mVendorId = vendorId;
+        }
+
         increaseProcessedDeviceCount();
         checkAndProceedStage();
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 81bccdc..1e09383 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -698,10 +698,9 @@
     protected boolean handleReportAudioStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
 
-        byte params[] = message.getParams();
-        int mute = params[0] & 0x80;
-        int volume = params[0] & 0x7F;
-        setAudioStatus(mute == 0x80, volume);
+        boolean mute = HdmiUtils.isAudioStatusMute(message);
+        int volume = HdmiUtils.getAudioStatusVolume(message);
+        setAudioStatus(mute, volume);
         return true;
     }
 
@@ -1004,6 +1003,9 @@
     }
 
     void setAudioStatus(boolean mute, int volume) {
+        if (!isSystemAudioActivated()) {
+            return;
+        }
         synchronized (mLock) {
             mSystemAudioMute = mute;
             mSystemAudioVolume = volume;
@@ -1019,6 +1021,10 @@
     @ServiceThreadOnly
     void changeVolume(int curVolume, int delta, int maxVolume) {
         assertRunOnServiceThread();
+        if (getAvrDeviceInfo() == null) {
+            // On initialization process, getAvrDeviceInfo() may return null and cause exception
+            return;
+        }
         if (delta == 0 || !isSystemAudioActivated()) {
             return;
         }
@@ -1048,6 +1054,10 @@
     @ServiceThreadOnly
     void changeMute(boolean mute) {
         assertRunOnServiceThread();
+        if (getAvrDeviceInfo() == null) {
+            // On initialization process, getAvrDeviceInfo() may return null and cause exception
+            return;
+        }
         HdmiLogger.debug("[A]:Change mute:%b", mute);
         synchronized (mLock) {
             if (mSystemAudioMute == mute) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 807b1b1..3d079cc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -989,8 +989,12 @@
             }
             // FLAG_HDMI_SYSTEM_AUDIO_VOLUME prevents audio manager from announcing
             // volume change notification back to hdmi control service.
-            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume,
-                    AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME);
+            int flag = AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME;
+            if (0 <= volume && volume <= 100) {
+                Slog.i(TAG, "volume: " + volume);
+                flag |= AudioManager.FLAG_SHOW_UI;
+                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, flag);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 8b16411..4ac3bba 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -152,6 +152,32 @@
     }
 
     /**
+     * Parse the <Report Audio Status> message and check if it is mute
+     *
+     * @param cmd the CEC message to parse
+     * @return true if the given parameter has [MUTE]
+     */
+    static boolean isAudioStatusMute(HdmiCecMessage cmd) {
+        byte params[] = cmd.getParams();
+        return (params[0] & 0x80) == 0x80;
+    }
+
+    /**
+     * Parse the <Report Audio Status> message and extract the volume
+     *
+     * @param cmd the CEC message to parse
+     * @return device's volume. Constants.UNKNOWN_VOLUME in case it is out of range
+     */
+    static int getAudioStatusVolume(HdmiCecMessage cmd) {
+        byte params[] = cmd.getParams();
+        int volume = params[0] & 0x7F;
+        if (volume < 0x00 || 0x64 < volume) {
+            volume = Constants.UNKNOWN_VOLUME;
+        }
+        return volume;
+    }
+
+    /**
      * Convert integer array to list of {@link Integer}.
      *
      * <p>The result is immutable.
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
index cab8439..d41a36c 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
@@ -92,8 +92,8 @@
 
     private void handleReportAudioStatus(HdmiCecMessage cmd) {
         byte[] params = cmd.getParams();
-        boolean mute = (params[0] & 0x80) == 0x80;
-        int volume = params[0] & 0x7F;
+        boolean mute = HdmiUtils.isAudioStatusMute(cmd);
+        int volume = HdmiUtils.getAudioStatusVolume(cmd);
         tv().setAudioStatus(mute, volume);
 
         if (!(tv().isSystemAudioActivated() ^ mute)) {
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index cd38b1f..0011387 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -139,8 +139,8 @@
 
     private boolean handleReportAudioStatus(HdmiCecMessage cmd) {
         byte params[] = cmd.getParams();
-        boolean mute = (params[0] & 0x80) == 0x80;
-        int volume = params[0] & 0x7F;
+        boolean mute = HdmiUtils.isAudioStatusMute(cmd);
+        int volume = HdmiUtils.getAudioStatusVolume(cmd);
         mLastAvrVolume = volume;
         mLastAvrMute = mute;
         if (shouldUpdateAudioVolume(mute)) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java
index c97eeaf..945726d 100644
--- a/services/core/java/com/android/server/job/JobSchedulerInternal.java
+++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -16,6 +16,7 @@
 
 package com.android.server.job;
 
+import android.annotation.UserIdInt;
 import android.app.job.JobInfo;
 
 import java.util.List;
@@ -39,6 +40,14 @@
     long nextHeartbeatForBucket(int bucket);
 
     /**
+     * Heartbeat ordinal for the given app.  This is typically the heartbeat at which
+     * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run
+     * jobs in a long time is immediately runnable even if the app is bucketed into
+     * an infrequent time allocation.
+     */
+    public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, int appBucket);
+
+    /**
      * Returns a list of pending jobs scheduled by the system service.
      */
     List<JobInfo> getSystemScheduledPendingJobs();
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index bd1dbf9..91227c1 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 
+import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
@@ -38,6 +39,7 @@
 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;
@@ -2020,6 +2022,29 @@
         }
 
         /**
+         * Heartbeat ordinal for the given app.  This is typically the heartbeat at which
+         * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run
+         * jobs in a long time is immediately runnable even if the app is bucketed into
+         * an infrequent time allocation.
+         */
+        public long baseHeartbeatForApp(String packageName, @UserIdInt int userId,
+                final int appStandbyBucket) {
+            if (appStandbyBucket == 0) {
+                // Active => everything can be run right away
+                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);
+        }
+
+        /**
          * Returns a list of all pending jobs. A running job is not considered pending. Periodic
          * jobs are always considered pending.
          */
@@ -2094,10 +2119,14 @@
             mUsageStats = usageStats;
         }
 
+        public long getTimeSinceLastJobRun(String packageName, final @UserIdInt int userId) {
+            return mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+        }
+
         // AppIdleStateChangeListener interface for live updates
 
         @Override
-        public void onAppIdleStateChanged(final String packageName, final int userId,
+        public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
                 boolean idle, int bucket) {
             final int uid = mLocalPM.getPackageUid(packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
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 5f95f1a..1d053a5 100644
--- a/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -17,14 +17,11 @@
 package com.android.server.job.controllers;
 
 import android.content.Context;
-import android.os.IDeviceIdleController;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.util.ArrayUtils;
 import com.android.server.ForceAppStandbyTracker;
 import com.android.server.ForceAppStandbyTracker.Listener;
 import com.android.server.job.JobSchedulerService;
@@ -44,7 +41,6 @@
     private static volatile BackgroundJobsController sController;
 
     private final JobSchedulerService mJobSchedulerService;
-    private final IDeviceIdleController mDeviceIdleController;
 
     private final ForceAppStandbyTracker mForceAppStandbyTracker;
 
@@ -62,8 +58,6 @@
     private BackgroundJobsController(JobSchedulerService service, Context context, Object lock) {
         super(service, context, lock);
         mJobSchedulerService = service;
-        mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
-                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
 
         mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
 
@@ -235,17 +229,23 @@
     private final Listener mForceAppStandbyListener = new Listener() {
         @Override
         public void updateAllJobs() {
-            updateAllJobRestrictionsLocked();
+            synchronized (mLock) {
+                updateAllJobRestrictionsLocked();
+            }
         }
 
         @Override
         public void updateJobsForUid(int uid) {
-            updateJobRestrictionsForUidLocked(uid);
+            synchronized (mLock) {
+                updateJobRestrictionsForUidLocked(uid);
+            }
         }
 
         @Override
         public void updateJobsForUidPackage(int uid, String packageName) {
-            updateJobRestrictionsForUidLocked(uid);
+            synchronized (mLock) {
+                updateJobRestrictionsForUidLocked(uid);
+            }
         }
     };
 }
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 03fd7b3..5a30eb4 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -244,7 +244,7 @@
         }
     };
 
-    private final INetworkPolicyListener mNetPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
         public void onUidRulesChanged(int uid, int uidRules) {
             if (DEBUG) {
@@ -254,11 +254,6 @@
         }
 
         @Override
-        public void onMeteredIfacesChanged(String[] meteredIfaces) {
-            // We track this via our NetworkCallback
-        }
-
-        @Override
         public void onRestrictBackgroundChanged(boolean restrictBackground) {
             if (DEBUG) {
                 Slog.v(TAG, "Background restriction change to " + restrictBackground);
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 8f68713..1add1ca 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -391,7 +391,9 @@
         int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage,
                 sourceUserId, elapsedNow);
         JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
-        long currentHeartbeat = js != null ? js.currentHeartbeat() : 0;
+        long currentHeartbeat = js != null
+                ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket)
+                : 0;
         return new JobStatus(job, callingUid, sourcePkg, sourceUserId,
                 standbyBucket, currentHeartbeat, tag, 0,
                 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 60b5b1f..a61842b 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -113,9 +113,7 @@
         NanoAppMessage clientMessage = ContextHubServiceUtil.createNanoAppMessage(message);
 
         if (DEBUG_LOG_ENABLED) {
-            String targetAudience = clientMessage.isBroadcastMessage() ? "broadcast" : "unicast";
-            Log.v(TAG, "Received a " + targetAudience + " message from nanoapp 0x"
-                    + Long.toHexString(clientMessage.getNanoAppId()));
+            Log.v(TAG, "Received " + clientMessage);
         }
 
         if (clientMessage.isBroadcastMessage()) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e158819..6dc5403 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -2628,6 +2628,10 @@
         s.append("  mStarted=").append(mStarted).append('\n');
         s.append("  mFixInterval=").append(mFixInterval).append('\n');
         s.append("  mLowPowerMode=").append(mLowPowerMode).append('\n');
+        s.append("  mGnssMeasurementsProvider.isRegistered()=")
+                .append(mGnssMeasurementsProvider.isRegistered()).append('\n');
+        s.append("  mGnssNavigationMessageProvider.isRegistered()=")
+                .append(mGnssNavigationMessageProvider.isRegistered()).append('\n');
         s.append("  mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
         s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
         s.append(" ( ");
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 58a9516..fcdb9d1 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -46,7 +46,8 @@
 
     private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
 
-    private boolean mIsRegistered;  // must access only on handler thread
+    private volatile boolean mIsRegistered;  // must access only on handler thread, or read-only
+
     private boolean mHasIsSupported;
     private boolean mIsSupported;
 
@@ -58,6 +59,11 @@
         mTag = name;
     }
 
+    // read-only access for a dump() thread assured via volatile
+    public boolean isRegistered() {
+        return mIsRegistered;
+    }
+
     public boolean addListener(@NonNull TListener listener) {
         Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
         IBinder binder = listener.asBinder();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ee08c38..07ea51b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -63,7 +63,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
 import android.os.ShellCallback;
 import android.os.StrictMode;
 import android.os.SystemProperties;
@@ -78,11 +77,10 @@
 import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.security.keystore.KeychainProtectionParams;
 import android.security.keystore.UserNotAuthenticatedException;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
-import android.security.keystore.RecoveryManagerException;
+import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.KeychainSnapshot;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
@@ -90,6 +88,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -1874,6 +1873,7 @@
         mSpManager.removeUser(userId);
         mStorage.removeUser(userId);
         mStrongAuth.removeUser(userId);
+        cleanSpCache();
 
         final KeyStore ks = KeyStore.getInstance();
         ks.onUserRemoved(userId);
@@ -1968,7 +1968,7 @@
     }
 
     @Override
-    public RecoveryData getRecoveryData(@NonNull byte[] account) throws RemoteException {
+    public KeychainSnapshot getRecoveryData(@NonNull byte[] account) throws RemoteException {
         return mRecoverableKeyStoreManager.getRecoveryData(account);
     }
 
@@ -1997,7 +1997,7 @@
     }
 
     @Override
-    public void setRecoverySecretTypes(@NonNull @RecoveryMetadata.UserSecretType
+    public void setRecoverySecretTypes(@NonNull @KeychainProtectionParams.UserSecretType
             int[] secretTypes) throws RemoteException {
         mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
     }
@@ -2014,7 +2014,7 @@
     }
 
     @Override
-    public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
+    public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
             throws RemoteException {
         mRecoverableKeyStoreManager.recoverySecretAvailable(recoverySecret);
     }
@@ -2022,15 +2022,19 @@
     @Override
     public byte[] startRecoverySession(@NonNull String sessionId,
             @NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams,
-            @NonNull byte[] vaultChallenge, @NonNull List<RecoveryMetadata> secrets)
+            @NonNull byte[] vaultChallenge, @NonNull List<KeychainProtectionParams> secrets)
             throws RemoteException {
         return mRecoverableKeyStoreManager.startRecoverySession(sessionId, verifierPublicKey,
                 vaultParams, vaultChallenge, secrets);
     }
 
+    public void closeSession(@NonNull String sessionId) throws RemoteException {
+        mRecoverableKeyStoreManager.closeSession(sessionId);
+    }
+
     @Override
     public Map<String, byte[]> recoverKeys(@NonNull String sessionId,
-            @NonNull byte[] recoveryKeyBlob, @NonNull List<EntryRecoveryData> applicationKeys)
+            @NonNull byte[] recoveryKeyBlob, @NonNull List<WrappedApplicationKey> applicationKeys)
             throws RemoteException {
         return mRecoverableKeyStoreManager.recoverKeys(
                 sessionId, recoveryKeyBlob, applicationKeys);
@@ -2112,6 +2116,63 @@
     }
 
     /**
+     * A user's synthetic password does not change so it must be cached in certain circumstances to
+     * enable untrusted credential reset.
+     *
+     * Untrusted credential reset will be removed in a future version (b/68036371) at which point
+     * this cache is no longer needed as the SP will always be known when changing the user's
+     * credential.
+     */
+    @GuardedBy("mSpManager")
+    private SparseArray<AuthenticationToken> mSpCache = new SparseArray();
+
+    private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
+        // Update the SP cache, removing the entry when allowed
+        synchronized (mSpManager) {
+            if (shouldCacheSpForUser(userId)) {
+                Slog.i(TAG, "Caching SP for user " + userId);
+                mSpCache.put(userId, auth);
+            } else {
+                Slog.i(TAG, "Not caching SP for user " + userId);
+                mSpCache.delete(userId);
+            }
+        }
+    }
+
+    /** Clean up the SP cache by removing unneeded entries. */
+    private void cleanSpCache() {
+        synchronized (mSpManager) {
+            // Preserve indicies after removal by iterating backwards
+            for (int i = mSpCache.size() - 1; i >= 0; --i) {
+                final int userId = mSpCache.keyAt(i);
+                if (!shouldCacheSpForUser(userId)) {
+                    Slog.i(TAG, "Uncaching SP for user " + userId);
+                    mSpCache.removeAt(i);
+                }
+            }
+        }
+    }
+
+    private boolean shouldCacheSpForUser(@UserIdInt int userId) {
+        // Before the user setup has completed, an admin could be installed that requires the SP to
+        // be cached (see below).
+        if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.USER_SETUP_COMPLETE, 0, userId) == 0) {
+            return true;
+        }
+
+        // If the user has an admin which can perform an untrusted credential reset, the SP needs to
+        // be cached. If there isn't a DevicePolicyManager then there can't be an admin in the first
+        // place so caching is not necessary.
+        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
+                DevicePolicyManagerInternal.class);
+        if (dpmi == null) {
+            return false;
+        }
+        return dpmi.canUserHaveUntrustedCredentialReset(userId);
+    }
+
+    /**
      * Precondition: vold and keystore unlocked.
      *
      * Create new synthetic password, set up synthetic password blob protected by the supplied
@@ -2126,9 +2187,7 @@
      * 3. Once a user is migrated to have synthetic password, its value will never change, no matter
      *     whether the user changes his lockscreen PIN or clear/reset it. When the user clears its
      *     lockscreen PIN, we still maintain the existing synthetic password in a password blob
-     *     protected by a default PIN. The only exception is when the DPC performs an untrusted
-     *     credential change, in which case we have no way to derive the existing synthetic password
-     *     and has to create a new one.
+     *     protected by a default PIN.
      * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user
      *     clears/re-creates his lockscreen PIN.
      *
@@ -2148,13 +2207,23 @@
      *     This is the untrusted credential reset, OR the user sets a new lockscreen password
      *     FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
      */
+    @GuardedBy("mSpManager")
     @VisibleForTesting
     protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
             String credential, int credentialType, int requestedQuality,
             int userId) throws RemoteException {
         Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
-        AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(getGateKeeperService(),
-                credentialHash, credential, 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);
+        }
+        onAuthTokenKnownForUser(userId, auth);
         if (auth == null) {
             Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token");
             return null;
@@ -2269,6 +2338,8 @@
                 trustManager.setDeviceLockedForUser(userId, false);
             }
             mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
+
+            onAuthTokenKnownForUser(userId, authResult.authToken);
         } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
             if (response.getTimeout() > 0) {
                 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
@@ -2287,6 +2358,7 @@
      * SID is gone. We also clear password from (software-based) keystore and vold, which will be
      * added back when new password is set in future.
      */
+    @GuardedBy("mSpManager")
     private long setLockCredentialWithAuthTokenLocked(String credential, int credentialType,
             AuthenticationToken auth, int requestedQuality, int userId) throws RemoteException {
         if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
@@ -2334,6 +2406,7 @@
         return newHandle;
     }
 
+    @GuardedBy("mSpManager")
     private void spBasedSetLockCredentialInternalLocked(String credential, int credentialType,
             String savedCredential, int requestedQuality, int userId) throws RemoteException {
         if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
@@ -2369,13 +2442,19 @@
             setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality,
                     userId);
             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
+            onAuthTokenKnownForUser(userId, auth);
         } else if (response != null
-                && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR){
+                && 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.
-
             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);
@@ -2486,8 +2565,9 @@
 
     private boolean setLockCredentialWithTokenInternal(String credential, int type,
             long tokenHandle, byte[] token, int requestedQuality, int userId) throws RemoteException {
+        final AuthenticationResult result;
         synchronized (mSpManager) {
-            AuthenticationResult result = mSpManager.unwrapTokenBasedSyntheticPassword(
+            result = mSpManager.unwrapTokenBasedSyntheticPassword(
                     getGateKeeperService(), tokenHandle, token, userId);
             if (result.authToken == null) {
                 Slog.w(TAG, "Invalid escrow token supplied");
@@ -2508,8 +2588,9 @@
             setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
                     requestedQuality, userId);
             mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
-            return true;
         }
+        onAuthTokenKnownForUser(userId, result.authToken);
+        return true;
     }
 
     @Override
@@ -2529,6 +2610,7 @@
             }
         }
         unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
+        onAuthTokenKnownForUser(userId, authResult.authToken);
     }
 
     @Override
@@ -2610,6 +2692,8 @@
     private class DeviceProvisionedObserver extends ContentObserver {
         private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
                 Settings.Global.DEVICE_PROVISIONED);
+        private final Uri mUserSetupCompleteUri = Settings.Secure.getUriFor(
+                Settings.Secure.USER_SETUP_COMPLETE);
 
         private boolean mRegistered;
 
@@ -2627,6 +2711,8 @@
                     reportDeviceSetupComplete();
                     clearFrpCredentialIfOwnerNotSecure();
                 }
+            } else if (mUserSetupCompleteUri.equals(uri)) {
+                cleanSpCache();
             }
         }
 
@@ -2678,6 +2764,8 @@
             if (register) {
                 mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri,
                         false, this);
+                mContext.getContentResolver().registerContentObserver(mUserSetupCompleteUri,
+                        false, this, UserHandle.USER_ALL);
             } else {
                 mContext.getContentResolver().unregisterContentObserver(this);
             }
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 5fe11b11..724073a 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -16,15 +16,14 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.KeychainProtectionParams;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.WrappedApplicationKey;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -175,8 +174,8 @@
             return;
         }
 
-        byte[] deviceId = mRecoverableKeyStoreDb.getServerParams(mUserId, recoveryAgentUid);
-        if (deviceId == null) {
+        byte[] vaultHandle = mRecoverableKeyStoreDb.getServerParams(mUserId, recoveryAgentUid);
+        if (vaultHandle == null) {
             Log.w(TAG, "No device ID set for user " + mUserId);
             return;
         }
@@ -229,11 +228,15 @@
                 counterId = generateAndStoreCounterId(recoveryAgentUid);
             }
         }
+
+        // TODO: make sure the same counter id is used during recovery and remove temporary fix.
+        counterId = 1L;
+
         byte[] vaultParams = KeySyncUtils.packVaultParams(
                 publicKey,
                 counterId,
-                deviceId,
-                TRUSTED_HARDWARE_MAX_ATTEMPTS);
+                TRUSTED_HARDWARE_MAX_ATTEMPTS,
+                vaultHandle);
 
         byte[] encryptedRecoveryKey;
         try {
@@ -251,12 +254,12 @@
         }
         // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
         // TODO: use Builder.
-        RecoveryMetadata metadata = new RecoveryMetadata(
+        KeychainProtectionParams metadata = new KeychainProtectionParams(
                 /*userSecretType=*/ TYPE_LOCKSCREEN,
                 /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
                 /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt),
                 /*secret=*/ new byte[0]);
-        ArrayList<RecoveryMetadata> metadataList = new ArrayList<>();
+        ArrayList<KeychainProtectionParams> metadataList = new ArrayList<>();
         metadataList.add(metadata);
 
         int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
@@ -264,12 +267,16 @@
         // If application keys are not updated, snapshot will not be created on next unlock.
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
 
-        // TODO: use Builder.
-        mRecoverySnapshotStorage.put(recoveryAgentUid, new RecoveryData(
-                snapshotVersion,
-                /*recoveryMetadata=*/ metadataList,
-                /*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
-                /*encryptedRecoveryKeyblob=*/ encryptedRecoveryKey));
+        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot.Builder()
+                .setSnapshotVersion(snapshotVersion)
+                .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
+                .setCounterId(counterId)
+                .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
+                .setServerParams(vaultHandle)
+                .setKeychainProtectionParams(metadataList)
+                .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys))
+                .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
+                .build());
 
         mSnapshotListenersStorage.recoverySnapshotAvailable(recoveryAgentUid);
     }
@@ -308,7 +315,7 @@
      */
     private boolean shoudCreateSnapshot(int recoveryAgentUid) {
         int[] types = mRecoverableKeyStoreDb.getRecoverySecretTypes(mUserId, recoveryAgentUid);
-        if (!ArrayUtils.contains(types, RecoveryMetadata.TYPE_LOCKSCREEN)) {
+        if (!ArrayUtils.contains(types, KeychainProtectionParams.TYPE_LOCKSCREEN)) {
             // Only lockscreen type is supported.
             // We will need to pass extra argument to KeySyncTask to support custom pass phrase.
             return false;
@@ -331,14 +338,14 @@
      * @return The format - either pattern, pin, or password.
      */
     @VisibleForTesting
-    @RecoveryMetadata.LockScreenUiFormat static int getUiFormat(
+    @KeychainProtectionParams.LockScreenUiFormat static int getUiFormat(
             int credentialType, String credential) {
         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
-            return RecoveryMetadata.TYPE_PATTERN;
+            return KeychainProtectionParams.TYPE_PATTERN;
         } else if (isPin(credential)) {
-            return RecoveryMetadata.TYPE_PIN;
+            return KeychainProtectionParams.TYPE_PIN;
         } else {
-            return RecoveryMetadata.TYPE_PASSWORD;
+            return KeychainProtectionParams.TYPE_PASSWORD;
         }
     }
 
@@ -401,12 +408,12 @@
         return keyGenerator.generateKey();
     }
 
-    private static List<EntryRecoveryData> createApplicationKeyEntries(
+    private static List<WrappedApplicationKey> createApplicationKeyEntries(
             Map<String, byte[]> encryptedApplicationKeys) {
-        ArrayList<EntryRecoveryData> keyEntries = new ArrayList<>();
+        ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>();
         for (String alias : encryptedApplicationKeys.keySet()) {
             keyEntries.add(
-                    new EntryRecoveryData(
+                    new WrappedApplicationKey(
                             alias,
                             encryptedApplicationKeys.get(alias)));
         }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java
index b4bef17..89e2deb 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java
@@ -61,7 +61,8 @@
     private static final byte[] THM_KF_HASH_PREFIX = "THM_KF_hash".getBytes(StandardCharsets.UTF_8);
 
     private static final int KEY_CLAIMANT_LENGTH_BYTES = 16;
-    private static final int VAULT_PARAMS_LENGTH_BYTES = 85;
+    private static final int VAULT_PARAMS_LENGTH_BYTES = 94;
+    private static final int VAULT_HANDLE_LENGTH_BYTES = 17;
 
     /**
      * Encrypts the recovery key using both the lock screen hash and the remote storage's public
@@ -287,18 +288,19 @@
      *
      * @param thmPublicKey Public key of the trusted hardware module.
      * @param counterId ID referring to the specific counter in the hardware module.
-     * @param deviceId ID of the device.
      * @param maxAttempts Maximum allowed guesses before trusted hardware wipes key.
+     * @param vaultHandle Handle of the Vault.
      * @return The binary vault params, ready for sync.
      */
     public static byte[] packVaultParams(
-            PublicKey thmPublicKey, long counterId, byte[] deviceId, int maxAttempts) {
+            PublicKey thmPublicKey, long counterId, int maxAttempts, byte[] vaultHandle) {
+        // TODO: Check if vaultHandle has exactly the length of VAULT_HANDLE_LENGTH_BYTES somewhere
         return ByteBuffer.allocate(VAULT_PARAMS_LENGTH_BYTES)
                 .order(ByteOrder.LITTLE_ENDIAN)
                 .put(SecureBox.encodePublicKey(thmPublicKey))
                 .putLong(counterId)
-                .putLong(0L) // TODO: replace with device Id.
                 .putInt(maxAttempts)
+                .put(vaultHandle)
                 .array();
     }
 
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 7658178..76508d5 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -16,13 +16,12 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryManagerException.ERROR_BAD_X509_CERTIFICATE;
-import static android.security.keystore.RecoveryManagerException.ERROR_DATABASE_ERROR;
-import static android.security.keystore.RecoveryManagerException.ERROR_DECRYPTION_FAILED;
-import static android.security.keystore.RecoveryManagerException.ERROR_INSECURE_USER;
-import static android.security.keystore.RecoveryManagerException.ERROR_KEYSTORE_INTERNAL_ERROR;
-import static android.security.keystore.RecoveryManagerException.ERROR_UNEXPECTED_MISSING_ALGORITHM;
-import static android.security.keystore.RecoveryManagerException.ERROR_NO_SNAPSHOT_PENDING;
+import static android.security.keystore.RecoveryController.ERROR_BAD_CERTIFICATE_FORMAT;
+import static android.security.keystore.RecoveryController.ERROR_DECRYPTION_FAILED;
+import static android.security.keystore.RecoveryController.ERROR_INSECURE_USER;
+import static android.security.keystore.RecoveryController.ERROR_NO_SNAPSHOT_PENDING;
+import static android.security.keystore.RecoveryController.ERROR_SERVICE_INTERNAL_ERROR;
+import static android.security.keystore.RecoveryController.ERROR_SESSION_EXPIRED;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,10 +33,10 @@
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
-import android.security.keystore.RecoveryManager;
+import android.security.keystore.KeychainProtectionParams;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.RecoveryController;
+import android.security.keystore.WrappedApplicationKey;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -45,7 +44,6 @@
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
 
-import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
 import java.security.KeyStoreException;
 import java.security.KeyFactory;
@@ -65,7 +63,7 @@
 import javax.crypto.AEADBadTagException;
 
 /**
- * Class with {@link RecoveryManager} API implementation and internal methods to interact
+ * Class with {@link RecoveryController} API implementation and internal methods to interact
  * with {@code LockSettingsService}.
  *
  * @hide
@@ -99,7 +97,7 @@
                 // Impossible: all algorithms must be supported by AOSP
                 throw new RuntimeException(e);
             } catch (KeyStoreException e) {
-                throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR, e.getMessage());
+                throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
             }
 
             mInstance = new RecoverableKeyStoreManager(
@@ -135,7 +133,7 @@
             mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase);
         } catch (NoSuchAlgorithmException e) {
             Log.wtf(TAG, "AES keygen algorithm not available. AOSP must support this.", e);
-            throw new ServiceSpecificException(ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         }
     }
 
@@ -154,10 +152,10 @@
             publicKey = kf.generatePublic(pkSpec);
         } catch (NoSuchAlgorithmException e) {
             Log.wtf(TAG, "EC algorithm not available. AOSP must support this.", e);
-            throw new ServiceSpecificException(ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         } catch (InvalidKeySpecException e) {
             throw new ServiceSpecificException(
-                    ERROR_BAD_X509_CERTIFICATE, "Not a valid X509 certificate.");
+                    ERROR_BAD_CERTIFICATE_FORMAT, "Not a valid X509 certificate.");
         }
         long updatedRows = mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey);
         if (updatedRows > 0) {
@@ -171,11 +169,12 @@
      * @return recovery data
      * @hide
      */
-    public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
+    public @NonNull
+    KeychainSnapshot getRecoveryData(@NonNull byte[] account)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
-        RecoveryData snapshot = mSnapshotStorage.get(uid);
+        KeychainSnapshot snapshot = mSnapshotStorage.get(uid);
         if (snapshot == null) {
             throw new ServiceSpecificException(ERROR_NO_SNAPSHOT_PENDING);
         }
@@ -257,7 +256,7 @@
      * @hide
      */
     public void setRecoverySecretTypes(
-            @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
+            @NonNull @KeychainProtectionParams.UserSecretType int[] secretTypes)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int userId = UserHandle.getCallingUserId();
@@ -292,9 +291,9 @@
     }
 
     public void recoverySecretAvailable(
-            @NonNull RecoveryMetadata recoverySecret) throws RemoteException {
+            @NonNull KeychainProtectionParams recoverySecret) throws RemoteException {
         int uid = Binder.getCallingUid();
-        if (recoverySecret.getLockScreenUiFormat() == RecoveryMetadata.TYPE_LOCKSCREEN) {
+        if (recoverySecret.getLockScreenUiFormat() == KeychainProtectionParams.TYPE_LOCKSCREEN) {
             throw new SecurityException(
                     "Caller " + uid + " is not allowed to set lock screen secret");
         }
@@ -320,13 +319,14 @@
             @NonNull byte[] verifierPublicKey,
             @NonNull byte[] vaultParams,
             @NonNull byte[] vaultChallenge,
-            @NonNull List<RecoveryMetadata> secrets)
+            @NonNull List<KeychainProtectionParams> secrets)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
 
         if (secrets.size() != 1) {
-            throw new UnsupportedOperationException("Only a single RecoveryMetadata is supported");
+            throw new UnsupportedOperationException(
+                    "Only a single KeychainProtectionParams is supported");
         }
 
         PublicKey publicKey;
@@ -336,13 +336,13 @@
             // Should never happen
             throw new RuntimeException(e);
         } catch (InvalidKeySpecException e) {
-            throw new ServiceSpecificException(ERROR_BAD_X509_CERTIFICATE, "Not a valid X509 key");
+            throw new ServiceSpecificException(ERROR_BAD_CERTIFICATE_FORMAT, "Not a valid X509 key");
         }
         // The raw public key bytes contained in vaultParams must match the ones given in
         // verifierPublicKey; otherwise, the user secret may be decrypted by a key that is not owned
         // by the original recovery service.
         if (!publicKeysMatch(publicKey, vaultParams)) {
-            throw new ServiceSpecificException(ERROR_BAD_X509_CERTIFICATE,
+            throw new ServiceSpecificException(ERROR_BAD_CERTIFICATE_FORMAT,
                     "The public keys given in verifierPublicKey and vaultParams do not match.");
         }
 
@@ -362,9 +362,9 @@
                     keyClaimant);
         } catch (NoSuchAlgorithmException e) {
             Log.wtf(TAG, "SecureBox algorithm missing. AOSP must support this.", e);
-            throw new ServiceSpecificException(ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         } catch (InvalidKeyException e) {
-            throw new ServiceSpecificException(ERROR_BAD_X509_CERTIFICATE, e.getMessage());
+            throw new ServiceSpecificException(ERROR_BAD_CERTIFICATE_FORMAT, e.getMessage());
         }
     }
 
@@ -384,13 +384,13 @@
     public Map<String, byte[]> recoverKeys(
             @NonNull String sessionId,
             @NonNull byte[] encryptedRecoveryKey,
-            @NonNull List<EntryRecoveryData> applicationKeys)
+            @NonNull List<WrappedApplicationKey> applicationKeys)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
         RecoverySessionStorage.Entry sessionEntry = mRecoverySessionStorage.get(uid, sessionId);
         if (sessionEntry == null) {
-            throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR,
+            throw new ServiceSpecificException(ERROR_SESSION_EXPIRED,
                     String.format(Locale.US,
                     "Application uid=%d does not have pending session '%s'", uid, sessionId));
         }
@@ -423,20 +423,25 @@
             // Impossible: all algorithms must be supported by AOSP
             throw new RuntimeException(e);
         } catch (KeyStoreException | UnrecoverableKeyException e) {
-            throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR, e.getMessage());
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         } catch (InsecureUserException e) {
             throw new ServiceSpecificException(ERROR_INSECURE_USER, e.getMessage());
         }
 
         try {
             return mRecoverableKeyGenerator.generateAndStoreKey(encryptionKey, userId, uid, alias);
-        } catch (KeyStoreException | InvalidKeyException e) {
-            throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR, e.getMessage());
-        } catch (RecoverableKeyStorageException e) {
-            throw new ServiceSpecificException(ERROR_DATABASE_ERROR, e.getMessage());
+        } catch (KeyStoreException | InvalidKeyException | RecoverableKeyStorageException e) {
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         }
     }
 
+    /**
+     * Destroys the session with the given {@code sessionId}.
+     */
+    public void closeSession(@NonNull String sessionId) throws RemoteException {
+        mRecoverySessionStorage.remove(Binder.getCallingUid(), sessionId);
+    }
+
     public void removeKey(@NonNull String alias) throws RemoteException {
         int uid = Binder.getCallingUid();
         int userId = UserHandle.getCallingUserId();
@@ -457,12 +462,12 @@
                     encryptedClaimResponse);
             return KeySyncUtils.decryptRecoveryKey(sessionEntry.getLskfHash(), locallyEncryptedKey);
         } catch (InvalidKeyException | AEADBadTagException e) {
-            throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR,
+            throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
                     "Failed to decrypt recovery key " + e.getMessage());
 
         } catch (NoSuchAlgorithmException e) {
             // Should never happen: all the algorithms used are required by AOSP implementations
-            throw new ServiceSpecificException(ERROR_KEYSTORE_INTERNAL_ERROR, e.getMessage());
+            throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         }
     }
 
@@ -474,9 +479,9 @@
      */
     private Map<String, byte[]> recoverApplicationKeys(
             @NonNull byte[] recoveryKey,
-            @NonNull List<EntryRecoveryData> applicationKeys) throws RemoteException {
+            @NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException {
         HashMap<String, byte[]> keyMaterialByAlias = new HashMap<>();
-        for (EntryRecoveryData applicationKey : applicationKeys) {
+        for (WrappedApplicationKey applicationKey : applicationKeys) {
             String alias = applicationKey.getAlias();
             byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial();
 
@@ -487,7 +492,7 @@
             } catch (NoSuchAlgorithmException e) {
                 Log.wtf(TAG, "Missing SecureBox algorithm. AOSP required to support this.", e);
                 throw new ServiceSpecificException(
-                        ERROR_UNEXPECTED_MISSING_ALGORITHM, e.getMessage());
+                        ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
             } catch (InvalidKeyException | AEADBadTagException e) {
                 throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
                         "Failed to recover key with alias '" + alias + "': " + e.getMessage());
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java
index 0042e10..c33c9de 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java
@@ -16,8 +16,8 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
+import android.security.keystore.RecoveryController;
 import android.util.Log;
-import android.security.keystore.RecoveryManager;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
@@ -97,7 +97,7 @@
                 /*nonce=*/ cipher.getIV(),
                 /*keyMaterial=*/ encryptedKeyMaterial,
                 /*platformKeyGenerationId=*/ wrappingKey.getGenerationId(),
-                RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+                RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS);
     }
 
     /**
@@ -107,14 +107,14 @@
      * @param keyMaterial The encrypted bytes of the key material.
      * @param platformKeyGenerationId The generation ID of the key used to wrap this key.
      *
-     * @see RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS
+     * @see RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS
      * @hide
      */
     public WrappedKey(byte[] nonce, byte[] keyMaterial, int platformKeyGenerationId) {
         mNonce = nonce;
         mKeyMaterial = keyMaterial;
         mPlatformKeyGenerationId = platformKeyGenerationId;
-        mRecoveryStatus = RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS;
+        mRecoveryStatus = RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS;
     }
 
     /**
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 eb2da80..2b1416e 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
@@ -404,7 +404,7 @@
     /**
      * Updates the list of user secret types used for end-to-end encryption.
      * If no secret types are set, recovery snapshot will not be created.
-     * See {@code RecoveryMetadata}
+     * See {@code KeychainProtectionParams}
      *
      * @param userId The userId of the profile the application is running under.
      * @param uid The uid of the application.
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorage.java
index f7633e4..0e66746 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorage.java
@@ -73,6 +73,16 @@
     }
 
     /**
+     * Deletes the session with {@code sessionId} created by app with {@code uid}.
+     */
+    public void remove(int uid, String sessionId) {
+        if (mSessionsByUid.get(uid) == null) {
+            return;
+        }
+        mSessionsByUid.get(uid).removeIf(session -> session.mSessionId.equals(sessionId));
+    }
+
+    /**
      * Removes all sessions associated with the given recovery agent uid.
      *
      * @param uid The uid of the recovery agent whose sessions to remove.
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
index 158b1e3..62bb41e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
@@ -17,7 +17,7 @@
 package com.android.server.locksettings.recoverablekeystore.storage;
 
 import android.annotation.Nullable;
-import android.security.keystore.RecoveryData;
+import android.security.keystore.KeychainSnapshot;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -34,12 +34,12 @@
  */
 public class RecoverySnapshotStorage {
     @GuardedBy("this")
-    private final SparseArray<RecoveryData> mSnapshotByUid = new SparseArray<>();
+    private final SparseArray<KeychainSnapshot> mSnapshotByUid = new SparseArray<>();
 
     /**
      * Sets the latest {@code snapshot} for the recovery agent {@code uid}.
      */
-    public synchronized void put(int uid, RecoveryData snapshot) {
+    public synchronized void put(int uid, KeychainSnapshot snapshot) {
         mSnapshotByUid.put(uid, snapshot);
     }
 
@@ -47,7 +47,7 @@
      * Returns the latest snapshot for the recovery agent {@code uid}, or null if none exists.
      */
     @Nullable
-    public synchronized RecoveryData get(int uid) {
+    public synchronized KeychainSnapshot get(int uid) {
         return mSnapshotByUid.get(uid);
     }
 
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 37e6ae9..42093e8 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -71,6 +71,7 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -98,6 +99,9 @@
     static final String ATT_APPROVED_LIST = "approved";
     static final String ATT_USER_ID = "user";
     static final String ATT_IS_PRIMARY = "primary";
+    static final String ATT_VERSION = "version";
+
+    static final int DB_VERSION = 1;
 
     static final int APPROVAL_BY_PACKAGE = 0;
     static final int APPROVAL_BY_COMPONENT = 1;
@@ -295,6 +299,8 @@
     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
         out.startTag(null, getConfig().xmlTag);
 
+        out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION));
+
         if (forBackup) {
             trimApprovedListsAccordingToInstalledServices();
         }
@@ -336,6 +342,14 @@
 
     public void readXml(XmlPullParser parser)
             throws XmlPullParserException, IOException {
+        // upgrade xml
+        int xmlVersion = XmlUtils.readIntAttribute(parser, ATT_VERSION, 0);
+        final List<UserInfo> activeUsers = mUm.getUsers(true);
+        for (UserInfo userInfo : activeUsers) {
+            upgradeXml(xmlVersion, userInfo.getUserHandle().getIdentifier());
+        }
+
+        // read grants
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
             String tag = parser.getName();
@@ -346,6 +360,7 @@
             if (type == XmlPullParser.START_TAG) {
                 if (TAG_MANAGED_SERVICES.equals(tag)) {
                     Slog.i(TAG, "Read " + mConfig.caption + " permissions from xml");
+
                     final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST);
                     final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
                     final boolean isPrimary =
@@ -360,6 +375,8 @@
         rebindServices(false);
     }
 
+    protected void upgradeXml(final int xmlVersion, final int userId) {}
+
     private void loadAllowedComponentsFromSettings() {
 
         UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -379,7 +396,7 @@
         Slog.d(TAG, "Done loading approved values from settings");
     }
 
-    private void addApprovedList(String approved, int userId, boolean isPrimary) {
+    protected void addApprovedList(String approved, int userId, boolean isPrimary) {
         if (TextUtils.isEmpty(approved)) {
             approved = "";
         }
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 4c00921..2584187 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -160,7 +160,7 @@
     }
 
     private boolean isCall(NotificationRecord record) {
-        return record.getNotification().category == Notification.CATEGORY_CALL
+        return record.isCategory(Notification.CATEGORY_CALL)
                 && isDefaultPhoneApp(record.sbn.getPackageName());
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 16b9257..2f6618f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -434,6 +434,7 @@
                 }
             }
         }
+
         String defaultDndAccess = getContext().getResources().getString(
                 com.android.internal.R.string.config_defaultDndAccessPackages);
         if (defaultListenerAccess != null) {
@@ -446,6 +447,29 @@
                 }
             }
         }
+
+        readDefaultAssistant(userId);
+    }
+
+    protected void readDefaultAssistant(int userId) {
+        String defaultAssistantAccess = getContext().getResources().getString(
+                com.android.internal.R.string.config_defaultAssistantAccessPackage);
+        if (defaultAssistantAccess != null) {
+            // Gather all notification assistant components for candidate pkg. There should
+            // only be one
+            Set<ComponentName> approvedAssistants =
+                    mAssistants.queryPackageForServices(defaultAssistantAccess,
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+            for (ComponentName cn : approvedAssistants) {
+                try {
+                    getBinderService().setNotificationAssistantAccessGrantedForUser(cn,
+                            userId, true);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
     }
 
     void readPolicyXml(InputStream stream, boolean forRestore)
@@ -1155,6 +1179,7 @@
         }
     }
 
+    @VisibleForTesting
     void clearNotifications() {
         mEnqueuedNotifications.clear();
         mNotificationList.clear();
@@ -1374,7 +1399,8 @@
                 AppGlobals.getPackageManager(), getContext().getPackageManager(),
                 getLocalService(LightsManager.class),
                 new NotificationListeners(AppGlobals.getPackageManager()),
-                new NotificationAssistants(AppGlobals.getPackageManager()),
+                new NotificationAssistants(getContext(), mNotificationLock, mUserProfiles,
+                        AppGlobals.getPackageManager()),
                 new ConditionProviders(getContext(), mUserProfiles, AppGlobals.getPackageManager()),
                 null, snoozeHelper, new NotificationUsageStats(getContext()),
                 new AtomicFile(new File(systemDir, "notification_policy.xml")),
@@ -5553,8 +5579,9 @@
     public class NotificationAssistants extends ManagedServices {
         static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
 
-        public NotificationAssistants(IPackageManager pm) {
-            super(getContext(), mNotificationLock, mUserProfiles, pm);
+        public NotificationAssistants(Context context, Object lock, UserProfiles up,
+                IPackageManager pm) {
+            super(context, lock, up, pm);
         }
 
         @Override
@@ -5659,6 +5686,14 @@
         public boolean isEnabled() {
             return !getServices().isEmpty();
         }
+
+        protected void upgradeXml(final int xmlVersion, final int userId) {
+            if (xmlVersion == 0) {
+                // one time approval of the OOB assistant
+                Slog.d(TAG, "Approving default notification assistant for user " + userId);
+                readDefaultAssistant(userId);
+            }
+        }
     }
 
     public class NotificationListeners extends ManagedServices {
@@ -6072,7 +6107,7 @@
         public static final String USAGE = "help\n"
                 + "allow_listener COMPONENT [user_id]\n"
                 + "disallow_listener COMPONENT [user_id]\n"
-                + "set_assistant COMPONENT\n"
+                + "allow_assistant COMPONENT\n"
                 + "remove_assistant COMPONENT\n"
                 + "allow_dnd PACKAGE\n"
                 + "disallow_dnd PACKAGE";
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index b5d2844..8f672b5 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1002,7 +1002,7 @@
                     if (isChange && policy.doNotDisturbWhenSilent) {
                         if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS
                                 && mZenMode != Global.ZEN_MODE_ALARMS) {
-                            newZen = Global.ZEN_MODE_ALARMS;
+                            newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
                         }
                         setPreviousRingerModeSetting(ringerModeOld);
                     }
@@ -1042,7 +1042,7 @@
                 case AudioManager.RINGER_MODE_SILENT:
                     if (isChange) {
                         if (mZenMode == Global.ZEN_MODE_OFF) {
-                            newZen = Global.ZEN_MODE_ALARMS;
+                            newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
                         }
                         ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
                                 : AudioManager.RINGER_MODE_SILENT;
diff --git a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsService.java b/services/core/java/com/android/server/pm/CrossProfileAppsService.java
similarity index 95%
rename from services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsService.java
rename to services/core/java/com/android/server/pm/CrossProfileAppsService.java
index 0913269..027a302 100644
--- a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsService.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsService.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.crossprofile;
+package com.android.server.pm;
 
 import android.content.Context;
 
diff --git a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
similarity index 98%
rename from services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
rename to services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index a517d6d..2007a0e 100644
--- a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.crossprofile;
+package com.android.server.pm;
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
@@ -25,14 +25,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ICrossProfileApps;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
-import android.content.pm.crossprofile.ICrossProfileApps;
-import android.graphics.Rect;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index be66fe2..4b3758d 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -281,13 +281,14 @@
     public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
             int dexoptNeeded, @Nullable String outputPath, int dexFlags,
             String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries,
-            @Nullable String seInfo, boolean downgrade)
+            @Nullable String seInfo, boolean downgrade, int targetSdkVersion)
             throws InstallerException {
         assertValidInstructionSet(instructionSet);
         if (!checkBeforeRemote()) return;
         try {
             mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
-                    dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade);
+                    dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade,
+                    targetSdkVersion);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 03f662a..0395011 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -260,12 +260,13 @@
             public void dexopt(String apkPath, int uid, @Nullable String pkgName,
                     String instructionSet, int dexoptNeeded, @Nullable String outputPath,
                     int dexFlags, String compilerFilter, @Nullable String volumeUuid,
-                    @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade)
+                    @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade,
+                    int targetSdkVersion)
                     throws InstallerException {
                 final StringBuilder builder = new StringBuilder();
 
-                // The version. Right now it's 3.
-                builder.append("3 ");
+                // The version. Right now it's 4.
+                builder.append("4 ");
 
                 builder.append("dexopt");
 
@@ -281,6 +282,7 @@
                 encodeParameter(builder, sharedLibraries);
                 encodeParameter(builder, seInfo);
                 encodeParameter(builder, downgrade);
+                encodeParameter(builder, targetSdkVersion);
 
                 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 730a9fd..91df87b 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -274,7 +274,7 @@
             // primary dex files.
             mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,
                     compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo,
-                    false /* downgrade*/);
+                    false /* downgrade*/, pkg.applicationInfo.targetSdkVersion);
 
             if (packageStats != null) {
                 long endTime = System.currentTimeMillis();
@@ -395,7 +395,7 @@
                 mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0,
                         /*oatDir*/ null, dexoptFlags,
                         compilerFilter, info.volumeUuid, classLoaderContext, info.seInfoUser,
-                        options.isDowngrade());
+                        options.isDowngrade(), info.targetSdkVersion);
             }
 
             return DEX_OPT_PERFORMED;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index a43818a..cc448da 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,10 +17,12 @@
 package com.android.server.pm;
 
 import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
+import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
 import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
+import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
@@ -96,6 +98,7 @@
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
+import android.content.pm.dex.DexMetadataHelper;
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -259,6 +262,7 @@
             // entries like "lost+found".
             if (file.isDirectory()) return false;
             if (file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+            if (DexMetadataHelper.isDexMetadataFile(file)) return false;
             return true;
         }
     };
@@ -939,6 +943,15 @@
                 mInstallerPackageName, mInstallerUid, user, mSigningDetails);
     }
 
+    private static void maybeRenameFile(File from, File to) throws PackageManagerException {
+        if (!from.equals(to)) {
+            if (!from.renameTo(to)) {
+                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+                        "Could not rename file " + from + " to " + to);
+            }
+        }
+    }
+
     /**
      * Validate install by confirming that all application packages are have
      * consistent package name, version code, and signing certificates.
@@ -983,6 +996,7 @@
         if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
         }
+
         // Verify that all staged packages are internally consistent
         final ArraySet<String> stagedSplits = new ArraySet<>();
         for (File addedFile : addedFiles) {
@@ -1013,9 +1027,9 @@
             // Take this opportunity to enforce uniform naming
             final String targetName;
             if (apk.splitName == null) {
-                targetName = "base.apk";
+                targetName = "base" + APK_FILE_EXTENSION;
             } else {
-                targetName = "split_" + apk.splitName + ".apk";
+                targetName = "split_" + apk.splitName + APK_FILE_EXTENSION;
             }
             if (!FileUtils.isValidExtFilename(targetName)) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
@@ -1023,9 +1037,7 @@
             }
 
             final File targetFile = new File(mResolvedStageDir, targetName);
-            if (!addedFile.equals(targetFile)) {
-                addedFile.renameTo(targetFile);
-            }
+            maybeRenameFile(addedFile, targetFile);
 
             // Base is coming from session
             if (apk.splitName == null) {
@@ -1033,6 +1045,18 @@
             }
 
             mResolvedStagedFiles.add(targetFile);
+
+            final File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(addedFile);
+            if (dexMetadataFile != null) {
+                if (!FileUtils.isValidExtFilename(dexMetadataFile.getName())) {
+                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                            "Invalid filename: " + dexMetadataFile);
+                }
+                final File targetDexMetadataFile = new File(mResolvedStageDir,
+                        DexMetadataHelper.buildDexMetadataPathForApk(targetName));
+                mResolvedStagedFiles.add(targetDexMetadataFile);
+                maybeRenameFile(dexMetadataFile, targetDexMetadataFile);
+            }
         }
 
         if (removeSplitList.size() > 0) {
@@ -1097,6 +1121,12 @@
             if (mResolvedBaseFile == null) {
                 mResolvedBaseFile = new File(appInfo.getBaseCodePath());
                 mResolvedInheritedFiles.add(mResolvedBaseFile);
+                // Inherit the dex metadata if present.
+                final File baseDexMetadataFile =
+                        DexMetadataHelper.findDexMetadataForFile(mResolvedBaseFile);
+                if (baseDexMetadataFile != null) {
+                    mResolvedInheritedFiles.add(baseDexMetadataFile);
+                }
             }
 
             // Inherit splits if not overridden
@@ -1107,6 +1137,12 @@
                     final boolean splitRemoved = removeSplitList.contains(splitName);
                     if (!stagedSplits.contains(splitName) && !splitRemoved) {
                         mResolvedInheritedFiles.add(splitFile);
+                        // Inherit the dex metadata if present.
+                        final File splitDexMetadataFile =
+                                DexMetadataHelper.findDexMetadataForFile(splitFile);
+                        if (splitDexMetadataFile != null) {
+                            mResolvedInheritedFiles.add(splitDexMetadataFile);
+                        }
                     }
                 }
             }
@@ -1163,43 +1199,6 @@
     }
 
     /**
-     * Calculate the final install footprint size, combining both staged and
-     * existing APKs together and including unpacked native code from both.
-     */
-    private long calculateInstalledSize() throws PackageManagerException {
-        Preconditions.checkNotNull(mResolvedBaseFile);
-
-        final ApkLite baseApk;
-        try {
-            baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0);
-        } catch (PackageParserException e) {
-            throw PackageManagerException.from(e);
-        }
-
-        final List<String> splitPaths = new ArrayList<>();
-        for (File file : mResolvedStagedFiles) {
-            if (mResolvedBaseFile.equals(file)) continue;
-            splitPaths.add(file.getAbsolutePath());
-        }
-        for (File file : mResolvedInheritedFiles) {
-            if (mResolvedBaseFile.equals(file)) continue;
-            splitPaths.add(file.getAbsolutePath());
-        }
-
-        // This is kind of hacky; we're creating a half-parsed package that is
-        // straddled between the inherited and staged APKs.
-        final PackageLite pkg = new PackageLite(null, baseApk, null, null, null, null,
-                splitPaths.toArray(new String[splitPaths.size()]), null);
-
-        try {
-            return PackageHelper.calculateInstalledSize(pkg, params.abiOverride);
-        } catch (IOException e) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
-                    "Failed to calculate install size", e);
-        }
-    }
-
-    /**
      * Determine if creating hard links between source and destination is
      * possible. That is, do they all live on the same underlying device.
      */
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6e94523..dd374fe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -191,6 +191,7 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
 import android.content.pm.VersionedPackage;
+import android.content.pm.dex.DexMetadataHelper;
 import android.content.pm.dex.IArtManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -10764,6 +10765,26 @@
                     }
                 }
             }
+
+            // Verify that packages sharing a user with a privileged app are marked as privileged.
+            if (!pkg.isPrivileged() && (pkg.mSharedUserId != null)) {
+                SharedUserSetting sharedUserSetting = null;
+                try {
+                    sharedUserSetting = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, false);
+                } catch (PackageManagerException ignore) {}
+                if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
+                    // Exempt SharedUsers signed with the platform key.
+                    PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
+                    if ((platformPkgSetting.signatures.mSignatures != null) &&
+                            (compareSignatures(platformPkgSetting.signatures.mSignatures,
+                                pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) {
+                        throw new PackageManagerException("Apps that share a user with a " +
+                                "privileged app must themselves be marked as privileged. " +
+                                pkg.packageName + " shares privileged user " +
+                                pkg.mSharedUserId + ".");
+                    }
+                }
+            }
         }
     }
 
@@ -16466,6 +16487,7 @@
         final PackageParser.Package pkg;
         try {
             pkg = pp.parsePackage(tmpPackageFile, parseFlags);
+            DexMetadataHelper.validatePackageDexMetadata(pkg);
         } catch (PackageParserException e) {
             res.setError("Failed parse during installPackageLI", e);
             return;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index bd1cd33..a33f071 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -18,6 +18,7 @@
 
 import android.accounts.IAccountManager;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentReceiver;
@@ -46,6 +47,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VersionedPackage;
+import android.content.pm.dex.DexMetadataHelper;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -72,13 +74,13 @@
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.SizedInputStream;
+import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 
 import dalvik.system.DexFile;
 
 import libcore.io.IoUtils;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -222,6 +224,8 @@
                     return runSetUserRestriction();
                 case "get-max-users":
                     return runGetMaxUsers();
+                case "get-max-running-users":
+                    return runGetMaxRunningUsers();
                 case "set-home-activity":
                     return runSetHomeActivity();
                 case "set-installer":
@@ -1883,6 +1887,14 @@
         return 0;
     }
 
+    public int runGetMaxRunningUsers() {
+        ActivityManagerInternal activityManagerInternal =
+                LocalServices.getService(ActivityManagerInternal.class);
+        getOutPrintWriter().println("Maximum supported running users: "
+                + activityManagerInternal.getMaxRunningUsers());
+        return 0;
+    }
+
     private static class InstallParams {
         SessionParams sessionParams;
         String installerPackageName;
@@ -2246,6 +2258,14 @@
             session = new PackageInstaller.Session(
                     mInterface.getPackageInstaller().openSession(sessionId));
 
+            // Sanity check that all .dm files match an apk.
+            // (The installer does not support standalone .dm files and will not process them.)
+            try {
+                DexMetadataHelper.validateDexPaths(session.getNames());
+            } catch (IllegalStateException | IOException e) {
+                pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
+            }
+
             final LocalIntentReceiver receiver = new LocalIntentReceiver();
             session.commit(receiver.getIntentSender());
 
@@ -2607,6 +2627,8 @@
         pw.println("");
         pw.println("  get-max-users");
         pw.println("");
+        pw.println("  get-max-running-users");
+        pw.println("");
         pw.println("  compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]");
         pw.println("          [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
         pw.println("    Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".  Options are:");
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 877da14..2446131 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
 import android.service.pm.PackageServiceDumpProto;
 import android.util.ArraySet;
@@ -102,4 +103,8 @@
         }
         return pkgList;
     }
+
+    public boolean isPrivileged() {
+        return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+    }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a453c33..88e4270 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5655,11 +5655,7 @@
 
     @Override
     public boolean allowAppAnimationsLw() {
-        if (mShowingDream) {
-            // If keyguard or dreams is currently visible, no reason to animate behind it.
-            return false;
-        }
-        return true;
+        return !mShowingDream;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 60dae53..c05dd2a 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1206,13 +1206,12 @@
 
     /**
      * Return true if it is okay to perform animations for an app transition
-     * that is about to occur.  You may return false for this if, for example,
-     * the lock screen is currently displayed so the switch should happen
+     * that is about to occur. You may return false for this if, for example,
+     * the dream window is currently displayed so the switch should happen
      * immediately.
      */
     public boolean allowAppAnimationsLw();
 
-
     /**
      * A new window has been focused.
      */
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index de723c6..d84fbc5 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -185,6 +185,14 @@
             ComponentName component = null;
             synchronized (mLock) {
                 component = ((mCurrentVrService == null) ? null : mCurrentVrService.getComponent());
+
+                // If the VrCore main service was disconnected or the binding died we'll rebind
+                // automatically. Call focusedActivityChanged() once we rebind.
+                if (component != null && component.equals(event.component) &&
+                        (event.event == LogEvent.EVENT_DISCONNECTED ||
+                         event.event == LogEvent.EVENT_BINDING_DIED)) {
+                    callFocusedActivityChangedLocked();
+                }
             }
 
             // If not on an AIO device and we permanently stopped trying to connect to the
@@ -980,16 +988,7 @@
                     oldVrServicePackage, oldUserId);
 
             if (mCurrentVrService != null && sendUpdatedCaller) {
-                final ComponentName c = mCurrentVrModeComponent;
-                final boolean b = running2dInVr;
-                final int pid = processId;
-                mCurrentVrService.sendEvent(new PendingEvent() {
-                    @Override
-                    public void runEvent(IInterface service) throws RemoteException {
-                        IVrListener l = (IVrListener) service;
-                        l.focusedActivityChanged(c, b, pid);
-                    }
-                });
+                callFocusedActivityChangedLocked();
             }
 
             if (!nothingChanged) {
@@ -1002,6 +1001,23 @@
         }
     }
 
+    private void callFocusedActivityChangedLocked() {
+        final ComponentName c = mCurrentVrModeComponent;
+        final boolean b = mRunning2dInVr;
+        final int pid = mVrAppProcessId;
+        mCurrentVrService.sendEvent(new PendingEvent() {
+            @Override
+            public void runEvent(IInterface service) throws RemoteException {
+                // Under specific (and unlikely) timing scenarios, when VrCore
+                // crashes and is rebound, focusedActivityChanged() may be
+                // called a 2nd time with the same arguments. IVrListeners
+                // should make sure to handle that scenario gracefully.
+                IVrListener l = (IVrListener) service;
+                l.focusedActivityChanged(c, b, pid);
+            }
+        });
+    }
+
     private boolean isDefaultAllowed(String packageName) {
         PackageManager pm = mContext.getPackageManager();
 
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 163b160..659253f 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -346,12 +346,12 @@
             final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
             if (magnifying) {
                 switch (transition) {
-                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
-                    case AppTransition.TRANSIT_TASK_OPEN:
-                    case AppTransition.TRANSIT_TASK_TO_FRONT:
-                    case AppTransition.TRANSIT_WALLPAPER_OPEN:
-                    case AppTransition.TRANSIT_WALLPAPER_CLOSE:
-                    case AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN: {
+                    case WindowManager.TRANSIT_ACTIVITY_OPEN:
+                    case WindowManager.TRANSIT_TASK_OPEN:
+                    case WindowManager.TRANSIT_TASK_TO_FRONT:
+                    case WindowManager.TRANSIT_WALLPAPER_OPEN:
+                    case WindowManager.TRANSIT_WALLPAPER_CLOSE:
+                    case WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN: {
                         mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED);
                     }
                 }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d4b437a..fc7ad09 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -16,6 +16,28 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.LayoutParams;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
@@ -75,9 +97,11 @@
 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;
+import android.view.WindowManager.TransitionFlags;
+import android.view.WindowManager.TransitionType;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.view.animation.AnimationSet;
@@ -109,63 +133,6 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppTransition" : TAG_WM;
     private static final int CLIP_REVEAL_TRANSLATION_Y_DP = 8;
 
-    /** Not set up for a transition. */
-    public static final int TRANSIT_UNSET = -1;
-    /** No animation for transition. */
-    public static final int TRANSIT_NONE = 0;
-    /** A window in a new activity is being opened on top of an existing one in the same task. */
-    public static final int TRANSIT_ACTIVITY_OPEN = 6;
-    /** The window in the top-most activity is being closed to reveal the
-     * previous activity in the same task. */
-    public static final int TRANSIT_ACTIVITY_CLOSE = 7;
-    /** A window in a new task is being opened on top of an existing one
-     * in another activity's task. */
-    public static final int TRANSIT_TASK_OPEN = 8;
-    /** A window in the top-most activity is being closed to reveal the
-     * previous activity in a different task. */
-    public static final int TRANSIT_TASK_CLOSE = 9;
-    /** A window in an existing task is being displayed on top of an existing one
-     * in another activity's task. */
-    public static final int TRANSIT_TASK_TO_FRONT = 10;
-    /** A window in an existing task is being put below all other tasks. */
-    public static final int TRANSIT_TASK_TO_BACK = 11;
-    /** A window in a new activity that doesn't have a wallpaper is being opened on top of one that
-     * does, effectively closing the wallpaper. */
-    public static final int TRANSIT_WALLPAPER_CLOSE = 12;
-    /** A window in a new activity that does have a wallpaper is being opened on one that didn't,
-     * effectively opening the wallpaper. */
-    public static final int TRANSIT_WALLPAPER_OPEN = 13;
-    /** A window in a new activity is being opened on top of an existing one, and both are on top
-     * of the wallpaper. */
-    public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14;
-    /** The window in the top-most activity is being closed to reveal the previous activity, and
-     * both are on top of the wallpaper. */
-    public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
-    /** A window in a new task is being opened behind an existing one in another activity's task.
-     * The new window will show briefly and then be gone. */
-    public static final int TRANSIT_TASK_OPEN_BEHIND = 16;
-    /** A window in a task is being animated in-place. */
-    public static final int TRANSIT_TASK_IN_PLACE = 17;
-    /** An activity is being relaunched (e.g. due to configuration change). */
-    public static final int TRANSIT_ACTIVITY_RELAUNCH = 18;
-    /** A task is being docked from recents. */
-    public static final int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
-    /** Keyguard is going away */
-    public static final int TRANSIT_KEYGUARD_GOING_AWAY = 20;
-    /** Keyguard is going away with showing an activity behind that requests wallpaper */
-    public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
-    /** Keyguard is being occluded */
-    public static final int TRANSIT_KEYGUARD_OCCLUDE = 22;
-    /** Keyguard is being unoccluded */
-    public static final int TRANSIT_KEYGUARD_UNOCCLUDE = 23;
-
-    /** Transition flag: Keyguard is going away, but keeping the notification shade open */
-    public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE = 0x1;
-    /** Transition flag: Keyguard is going away, but doesn't want an animation for it */
-    public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION = 0x2;
-    /** Transition flag: Keyguard is going away while it was showing the system wallpaper. */
-    public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER = 0x4;
-
     /** Fraction of animation at which the recents thumbnail stays completely transparent */
     private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.5f;
     /** Fraction of animation at which the recents thumbnail becomes completely transparent */
@@ -191,8 +158,8 @@
     private final Context mContext;
     private final WindowManagerService mService;
 
-    private int mNextAppTransition = TRANSIT_UNSET;
-    private int mNextAppTransitionFlags = 0;
+    private @TransitionType int mNextAppTransition = TRANSIT_UNSET;
+    private @TransitionFlags int mNextAppTransitionFlags = 0;
     private int mLastUsedAppTransition = TRANSIT_UNSET;
     private String mLastOpeningApp;
     private String mLastClosingApp;
@@ -213,6 +180,8 @@
      * }.
      */
     private static final int NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS = 9;
+    private static final int NEXT_TRANSIT_TYPE_REMOTE = 10;
+
     private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
 
     // These are the possible states for the enter/exit activities during a thumbnail transition
@@ -275,6 +244,8 @@
     private final boolean mGridLayoutRecentsEnabled;
     private final boolean mLowRamRecentsEnabled;
 
+    private RemoteAnimationController mRemoteAnimationController;
+
     AppTransition(Context context, WindowManagerService service) {
         mContext = context;
         mService = service;
@@ -321,11 +292,11 @@
         return mNextAppTransition != TRANSIT_UNSET;
     }
 
-    boolean isTransitionEqual(int transit) {
+    boolean isTransitionEqual(@TransitionType int transit) {
         return mNextAppTransition == transit;
     }
 
-    int getAppTransition() {
+    @TransitionType int getAppTransition() {
         return mNextAppTransition;
      }
 
@@ -454,6 +425,9 @@
                 app.startDelayingAnimationStart();
             }
         }
+        if (mRemoteAnimationController != null) {
+            mRemoteAnimationController.goodToGo();
+        }
         return redoLayout;
     }
 
@@ -468,6 +442,7 @@
         mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
         mNextAppTransitionPackage = null;
         mNextAppTransitionAnimationsSpecs.clear();
+        mRemoteAnimationController = null;
         mNextAppTransitionAnimationsSpecsFuture = null;
         mDefaultNextAppTransitionAnimationSpec = null;
         mAnimationFinishedCallback = null;
@@ -476,7 +451,7 @@
 
     void freeze() {
         final int transit = mNextAppTransition;
-        setAppTransition(AppTransition.TRANSIT_UNSET, 0 /* flags */);
+        setAppTransition(TRANSIT_UNSET, 0 /* flags */);
         clear();
         setReady();
         notifyAppTransitionCancelledLocked(transit);
@@ -531,7 +506,7 @@
         return redoLayout;
     }
 
-    private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
+    private AttributeCache.Entry getCachedAnimations(LayoutParams lp) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
                 + (lp != null ? lp.packageName : null)
                 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
@@ -567,7 +542,7 @@
         return null;
     }
 
-    Animation loadAnimationAttr(WindowManager.LayoutParams lp, int animAttr) {
+    Animation loadAnimationAttr(LayoutParams lp, int animAttr) {
         int anim = 0;
         Context context = mContext;
         if (animAttr >= 0) {
@@ -583,7 +558,7 @@
         return null;
     }
 
-    Animation loadAnimationRes(WindowManager.LayoutParams lp, int resId) {
+    Animation loadAnimationRes(LayoutParams lp, int resId) {
         Context context = mContext;
         if (resId >= 0) {
             AttributeCache.Entry ent = getCachedAnimations(lp);
@@ -1551,6 +1526,10 @@
                 && mNextAppTransition != TRANSIT_KEYGUARD_GOING_AWAY;
     }
 
+    RemoteAnimationController getRemoteAnimationController() {
+        return mRemoteAnimationController;
+    }
+
     /**
      *
      * @param frame These are the bounds of the window when it finishes the animation. This is where
@@ -1572,7 +1551,7 @@
      *                      to the recents thumbnail and hence need to account for the surface being
      *                      bigger.
      */
-    Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int uiMode,
+    Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode,
             int orientation, Rect frame, Rect displayFrame, Rect insets,
             @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,
             boolean freeform, int taskId) {
@@ -1788,7 +1767,7 @@
 
     void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
             IRemoteCallback startedCallback) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
             mNextAppTransitionPackage = packageName;
@@ -1796,14 +1775,12 @@
             mNextAppTransitionExit = exitAnim;
             postAnimationCallback();
             mNextAppTransitionCallback = startedCallback;
-        } else {
-            postAnimationCallback();
         }
     }
 
     void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
             int startHeight) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
             putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
@@ -1813,7 +1790,7 @@
 
     void overridePendingAppTransitionClipReveal(int startX, int startY,
                                                 int startWidth, int startHeight) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
             putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
@@ -1823,7 +1800,7 @@
 
     void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY,
                                            IRemoteCallback startedCallback, boolean scaleUp) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
@@ -1831,14 +1808,12 @@
             putDefaultNextAppTransitionCoordinates(startX, startY, 0, 0, srcThumb);
             postAnimationCallback();
             mNextAppTransitionCallback = startedCallback;
-        } else {
-            postAnimationCallback();
         }
     }
 
     void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY,
             int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
@@ -1847,15 +1822,13 @@
                     srcThumb);
             postAnimationCallback();
             mNextAppTransitionCallback = startedCallback;
-        } else {
-            postAnimationCallback();
         }
     }
 
-    public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+    void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
             IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
             boolean scaleUp) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
@@ -1878,15 +1851,13 @@
             postAnimationCallback();
             mNextAppTransitionCallback = onAnimationStartedCallback;
             mAnimationFinishedCallback = onAnimationFinishedCallback;
-        } else {
-            postAnimationCallback();
         }
     }
 
     void overridePendingAppTransitionMultiThumbFuture(
             IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
             boolean scaleUp) {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
                     : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
@@ -1896,14 +1867,21 @@
         }
     }
 
-    void overrideInPlaceAppTransition(String packageName, int anim) {
+    void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter) {
         if (isTransitionSet()) {
             clear();
+            mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE;
+            mRemoteAnimationController = new RemoteAnimationController(mService,
+                    remoteAnimationAdapter, mService.mH);
+        }
+    }
+
+    void overrideInPlaceAppTransition(String packageName, int anim) {
+        if (canOverridePendingAppTransition()) {
+            clear();
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE;
             mNextAppTransitionPackage = packageName;
             mNextAppTransitionInPlace = anim;
-        } else {
-            postAnimationCallback();
         }
     }
 
@@ -1911,13 +1889,18 @@
      * @see {@link #NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS}
      */
     void overridePendingAppTransitionStartCrossProfileApps() {
-        if (isTransitionSet()) {
+        if (canOverridePendingAppTransition()) {
             clear();
             mNextAppTransitionType = NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS;
             postAnimationCallback();
         }
     }
 
+    private boolean canOverridePendingAppTransition() {
+        // Remote animations always take precedence
+        return isTransitionSet() &&  mNextAppTransitionType != NEXT_TRANSIT_TYPE_REMOTE;
+    }
+
     /**
      * If a future is set for the app transition specs, fetch it in another thread.
      */
@@ -2140,8 +2123,8 @@
      * @return true if transition is not running and should not be skipped, false if transition is
      *         already running
      */
-    boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent, int flags,
-            boolean forceOverride) {
+    boolean prepareAppTransitionLocked(@TransitionType int transit, boolean alwaysKeepCurrent,
+            @TransitionFlags int flags, boolean forceOverride) {
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:"
                 + " transit=" + appTransitionToString(transit)
                 + " " + this
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index ae9f28b..e9efd4e 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -19,8 +19,8 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 
-import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
-import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static android.view.WindowManager.TRANSIT_UNSET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -32,7 +32,6 @@
 import android.app.ActivityManager.TaskSnapshot;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
-import android.graphics.Rect;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
@@ -40,6 +39,8 @@
 import android.os.Message;
 import android.util.Slog;
 import android.view.IApplicationToken;
+import android.view.RemoteAnimationDefinition;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.AttributeCache;
@@ -393,7 +394,7 @@
                     wtoken.mEnteringAnimation = false;
                 }
                 if (mService.mAppTransition.getAppTransition()
-                        == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
+                        == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
                     // We're launchingBehind, add the launching activity to mOpeningApps.
                     final WindowState win =
                             mService.getDefaultDisplayContentLocked().findFocusedWindow();
@@ -695,6 +696,17 @@
         }
     }
 
+    public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
+                        + " token: " + mToken);
+                return;
+            }
+            mContainer.registerRemoteAnimations(definition);
+        }
+    }
+
     void reportStartingWindowDrawn() {
         mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_STARTING_WINDOW_DRAWN));
     }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a254ba2..b474c62 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -34,7 +34,7 @@
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_UNSET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
@@ -91,6 +91,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
 import android.view.IApplicationToken;
+import android.view.RemoteAnimationDefinition;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowManager;
@@ -106,7 +107,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.LinkedList;
 
 class AppTokenList extends ArrayList<AppWindowToken> {
 }
@@ -250,6 +250,7 @@
 
     private final Point mTmpPoint = new Point();
     private final Rect mTmpRect = new Rect();
+    private RemoteAnimationDefinition mRemoteAnimationDefinition;
 
     AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
             DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
@@ -378,7 +379,6 @@
         // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
         // been set by the app now.
         mHiddenSetFromTransferredStartingWindow = false;
-        setClientHidden(!visible);
 
         // Allow for state changes and animation to be applied if:
         // * token is transitioning visibility state
@@ -394,7 +394,7 @@
 
             boolean runningAppAnimation = false;
 
-            if (transit != AppTransition.TRANSIT_UNSET) {
+            if (transit != WindowManager.TRANSIT_UNSET) {
                 if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
                     delayed = runningAppAnimation = true;
                 }
@@ -463,6 +463,12 @@
                 mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
             }
 
+            // Update the client visibility if we are not running an animation. Otherwise, we'll
+            // update client visibility state in onAnimationFinished.
+            if (!visible && !delayed) {
+                setClientHidden(true);
+            }
+
             // If we are hidden but there is no delay needed we immediately
             // apply the Surface transaction so that the ActivityManager
             // can have some guarantee on the Surface state following
@@ -511,15 +517,25 @@
     }
 
     WindowState findMainWindow() {
+        return findMainWindow(true);
+    }
+
+    /**
+     * Finds the main window that either has type base application or application starting if
+     * requested.
+     *
+     * @param includeStartingApp Allow to search application-starting windows to also be returned.
+     * @return The main window of type base application or application starting if requested.
+     */
+    WindowState findMainWindow(boolean includeStartingApp) {
         WindowState candidate = null;
-        int j = mChildren.size();
-        while (j > 0) {
-            j--;
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
             final WindowState win = mChildren.get(j);
             final int type = win.mAttrs.type;
             // No need to loop through child window as base application and starting types can't be
             // child windows.
-            if (type == TYPE_BASE_APPLICATION || type == TYPE_APPLICATION_STARTING) {
+            if (type == TYPE_BASE_APPLICATION
+                    || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
                 // In cases where there are multiple windows, we prefer the non-exiting window. This
                 // happens for example when replacing windows during an activity relaunch. When
                 // constructing the animation, we want the new window, not the exiting one.
@@ -1367,8 +1383,11 @@
 
         if (mLastTransactionSequence != mService.mTransactionSequence) {
             mLastTransactionSequence = mService.mTransactionSequence;
-            mNumInterestingWindows = mNumDrawnWindows = 0;
+            mNumDrawnWindows = 0;
             startingDisplayed = false;
+
+            // There is the main base application window, even if it is exiting, wait for it
+            mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
         }
 
         final WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -1390,7 +1409,10 @@
 
             if (w != startingWindow) {
                 if (w.isInteresting()) {
-                    mNumInterestingWindows++;
+                    // Add non-main window as interesting since the main app has already been added
+                    if (findMainWindow(false /* includeStartingApp */) != w) {
+                        mNumInterestingWindows++;
+                    }
                     if (w.isDrawnLw()) {
                         mNumDrawnWindows++;
 
@@ -1611,27 +1633,37 @@
         // different animation is running.
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
         if (okToAnimate()) {
-            final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
-            if (a != null) {
-                final TaskStack stack = getStack();
-                mTmpPoint.set(0, 0);
-                mTmpRect.setEmpty();
-                if (stack != null) {
-                    stack.getRelativePosition(mTmpPoint);
-                    stack.getBounds(mTmpRect);
-                    mTmpRect.offsetTo(0, 0);
+            final AnimationAdapter adapter;
+            final TaskStack stack = getStack();
+            mTmpPoint.set(0, 0);
+            mTmpRect.setEmpty();
+            if (stack != null) {
+                stack.getRelativePosition(mTmpPoint);
+                stack.getBounds(mTmpRect);
+                mTmpRect.offsetTo(0, 0);
+            }
+            if (mService.mAppTransition.getRemoteAnimationController() != null) {
+                adapter = mService.mAppTransition.getRemoteAnimationController()
+                        .createAnimationAdapter(this, mTmpPoint, mTmpRect);
+            } else {
+                final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
+                if (a != null) {
+                    adapter = new LocalAnimationAdapter(
+                            new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
+                                    mService.mAppTransition.canSkipFirstFrame(),
+                                    mService.mAppTransition.getAppStackClipMode()),
+                            mService.mSurfaceAnimationRunner);
+                    if (a.getZAdjustment() == Animation.ZORDER_TOP) {
+                        mNeedsZBoost = true;
+                    }
+                    mTransit = transit;
+                    mTransitFlags = mService.mAppTransition.getTransitFlags();
+                } else {
+                    adapter = null;
                 }
-                final AnimationAdapter adapter = new LocalAnimationAdapter(
-                        new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
-                                mService.mAppTransition.canSkipFirstFrame(),
-                                mService.mAppTransition.getAppStackClipMode()),
-                        mService.mSurfaceAnimationRunner);
-                if (a.getZAdjustment() == Animation.ZORDER_TOP) {
-                    mNeedsZBoost = true;
-                }
+            }
+            if (adapter != null) {
                 startAnimation(getPendingTransaction(), adapter, !isVisible());
-                mTransit = transit;
-                mTransitFlags = mService.mAppTransition.getTransitFlags();
             }
         } else {
             cancelAnimation();
@@ -1754,6 +1786,7 @@
                 "AppWindowToken");
 
         clearThumbnail();
+        setClientHidden(isHidden());
 
         if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
             getDisplayContent().computeImeTarget(true /* updateImeTarget */);
@@ -1884,6 +1917,14 @@
         mThumbnail = null;
     }
 
+    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
+        mRemoteAnimationDefinition = definition;
+    }
+
+    RemoteAnimationDefinition getRemoteAnimationDefinition() {
+        return mRemoteAnimationDefinition;
+    }
+
     @Override
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         super.dump(pw, prefix, dumpAll);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a8e00dd..fba404e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -63,7 +63,7 @@
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -134,6 +134,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.MutableBoolean;
 import android.util.Slog;
@@ -330,6 +331,8 @@
     final PinnedStackController mPinnedStackControllerLocked;
 
     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
+    /** A collection of windows that provide tap exclude regions inside of them. */
+    final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
 
     private boolean mHaveBootMsg = false;
     private boolean mHaveApp = false;
@@ -1866,10 +1869,14 @@
             }
         }
         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mTapExcludedWindows.get(i);
+            final WindowState win = mTapExcludedWindows.get(i);
             win.getTouchableRegion(mTmpRegion);
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
+        for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
+            final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
+            win.amendTapExcludeRegion(mTouchExcludeRegion);
+        }
         // TODO(multi-display): Support docked stacks on secondary displays.
         if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
             mDividerControllerLocked.getTouchRegion(mTmpRect);
@@ -3690,6 +3697,13 @@
             .setParent(mOverlayLayer);
     }
 
+    /**
+     * Reparents the given surface to mOverlayLayer.
+     */
+    void reparentToOverlay(Transaction transaction, SurfaceControl surface) {
+        transaction.reparent(surface, mOverlayLayer.getHandle());
+    }
+
     void applyMagnificationSpec(MagnificationSpec spec) {
         applyMagnificationSpec(getPendingTransaction(), spec);
         getPendingTransaction().apply();
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 03c0768..36e5d10 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -29,7 +29,7 @@
 import static android.view.WindowManager.DOCKED_TOP;
 import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
 import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.server.wm.AppTransition.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_NONE;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED;
@@ -454,8 +454,11 @@
                 inputMethodManagerInternal.hideCurrentInputMethod();
                 mImeHideRequested = true;
             }
+
+            // If a primary stack was just created, it will not have access to display content at
+            // this point so pass it from here to get a valid dock side.
             final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
-            mOriginalDockedSide = stack.getDockSide();
+            mOriginalDockedSide = stack.getDockSideForDisplay(mDisplayContent);
             return;
         }
         mOriginalDockedSide = DOCKED_INVALID;
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 0171b56..d55a649 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -18,12 +18,10 @@
 
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.NonNull;
 import android.content.ClipData;
-import android.graphics.PixelFormat;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -32,8 +30,8 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.IWindow;
-import android.view.Surface;
 import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
 import android.view.View;
 
@@ -50,10 +48,9 @@
     private static final long DRAG_TIMEOUT_MS = 5000;
 
     // Messages for Handler.
-    private static final int MSG_DRAG_START_TIMEOUT = 0;
-    static final int MSG_DRAG_END_TIMEOUT = 1;
-    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 2;
-    static final int MSG_ANIMATION_END = 3;
+    static final int MSG_DRAG_END_TIMEOUT = 0;
+    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 1;
+    static final int MSG_ANIMATION_END = 2;
 
     /**
      * Drag state per operation.
@@ -95,87 +92,35 @@
         mDragState.sendDragStartedIfNeededLocked(window);
     }
 
-    IBinder prepareDrag(SurfaceSession session, int callerPid,
-            int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) {
+    IBinder performDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window,
+            int flags, SurfaceControl surface, int touchSource, float touchX, float touchY,
+            float thumbCenterX, float thumbCenterY, ClipData data) {
         if (DEBUG_DRAG) {
-            Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
-                    + " flags=" + Integer.toHexString(flags) + " win=" + window
-                    + " asbinder=" + window.asBinder());
+            Slog.d(TAG_WM, "perform drag: win=" + window + " surface=" + surface + " flags=" +
+                            Integer.toHexString(flags) + " data=" + data);
         }
 
-        if (width <= 0 || height <= 0) {
-            Slog.w(TAG_WM, "width and height of drag shadow must be positive");
-            return null;
-        }
-
-        synchronized (mService.mWindowMap) {
-            if (dragDropActiveLocked()) {
-                Slog.w(TAG_WM, "Drag already in progress");
-                return null;
-            }
-
-            // TODO(multi-display): support other displays
-            final DisplayContent displayContent =
-                    mService.getDefaultDisplayContentLocked();
-            final Display display = displayContent.getDisplay();
-
-            final SurfaceControl surface = new SurfaceControl.Builder(session)
-                    .setName("drag surface")
-                    .setSize(width, height)
-                    .setFormat(PixelFormat.TRANSLUCENT)
-                    .build();
-            surface.setLayerStack(display.getLayerStack());
-            float alpha = 1;
-            if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
-                alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
-            }
-            surface.setAlpha(alpha);
-
-            if (SHOW_TRANSACTIONS)
-                Slog.i(TAG_WM, "  DRAG " + surface + ": CREATE");
-            outSurface.copyFrom(surface);
-            final IBinder winBinder = window.asBinder();
-            IBinder token = new Binder();
-            mDragState = new DragState(mService, this, token, surface, flags, winBinder);
-            mDragState.mPid = callerPid;
-            mDragState.mUid = callerUid;
-            mDragState.mOriginalAlpha = alpha;
-            token = mDragState.mToken = new Binder();
-
-            // 5 second timeout for this window to actually begin the drag
-            sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder);
-            return token;
-        }
-    }
-
-    boolean performDrag(IWindow window, IBinder dragToken,
-            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
-            ClipData data) {
-        if (DEBUG_DRAG) {
-            Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
-        }
-
+        final IBinder dragToken = new Binder();
         final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken,
                 touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
         try {
             synchronized (mService.mWindowMap) {
-                mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder());
                 try {
                     if (!callbackResult) {
-                        return false;
+                        Slog.w(TAG_WM, "IDragDropCallback rejects the performDrag request");
+                        return null;
                     }
 
-                    Preconditions.checkState(
-                            mDragState != null, "performDrag() without prepareDrag()");
-                    Preconditions.checkState(
-                            mDragState.mToken == dragToken,
-                            "performDrag() does not match prepareDrag()");
+                    if (dragDropActiveLocked()) {
+                        Slog.w(TAG_WM, "Drag already in progress");
+                        return null;
+                    }
 
                     final WindowState callingWin = mService.windowForClientLocked(
                             null, window, false);
                     if (callingWin == null) {
                         Slog.w(TAG_WM, "Bad requesting window " + window);
-                        return false;  // !!! TODO: throw here?
+                        return null;  // !!! TODO: throw here?
                     }
 
                     // !!! TODO: if input is not still focused on the initiating window, fail
@@ -188,18 +133,31 @@
                     // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as
                     // the actual drag event dispatch stuff in the dragstate
 
+                    // !!! TODO(multi-display): support other displays
+
                     final DisplayContent displayContent = callingWin.getDisplayContent();
                     if (displayContent == null) {
                         Slog.w(TAG_WM, "display content is null");
-                        return false;
+                        return null;
                     }
 
+                    final float alpha = (flags & View.DRAG_FLAG_OPAQUE) == 0 ?
+                            DRAG_SHADOW_ALPHA_TRANSPARENT : 1;
+                    final IBinder winBinder = window.asBinder();
+                    IBinder token = new Binder();
+                    mDragState = new DragState(mService, this, token, surface, flags, winBinder);
+                    surface = null;
+                    mDragState.mPid = callerPid;
+                    mDragState.mUid = callerUid;
+                    mDragState.mOriginalAlpha = alpha;
+                    mDragState.mToken = dragToken;
+
                     final Display display = displayContent.getDisplay();
                     mDragState.register(display);
                     if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                             mDragState.getInputChannel())) {
                         Slog.e(TAG_WM, "Unable to transfer touch focus");
-                        return false;
+                        return null;
                     }
 
                     mDragState.mDisplayContent = displayContent;
@@ -213,28 +171,31 @@
                     // Make the surface visible at the proper location
                     final SurfaceControl surfaceControl = mDragState.mSurfaceControl;
                     if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag");
-                    mService.openSurfaceTransaction();
-                    try {
-                        surfaceControl.setPosition(touchX - thumbCenterX,
-                                touchY - thumbCenterY);
-                        surfaceControl.setLayer(mDragState.getDragLayerLocked());
-                        surfaceControl.setLayerStack(display.getLayerStack());
-                        surfaceControl.show();
-                    } finally {
-                        mService.closeSurfaceTransaction("performDrag");
-                        if (SHOW_LIGHT_TRANSACTIONS) {
-                            Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
-                        }
+
+                    final SurfaceControl.Transaction transaction =
+                            callingWin.getPendingTransaction();
+                    transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha);
+                    transaction.setPosition(
+                            surfaceControl, touchX - thumbCenterX, touchY - thumbCenterY);
+                    transaction.show(surfaceControl);
+                    displayContent.reparentToOverlay(transaction, surfaceControl);
+                    callingWin.scheduleAnimation();
+
+                    if (SHOW_LIGHT_TRANSACTIONS) {
+                        Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
                     }
 
                     mDragState.notifyLocationLocked(touchX, touchY);
                 } finally {
+                    if (surface != null) {
+                        surface.release();
+                    }
                     if (mDragState != null && !mDragState.isInProgress()) {
                         mDragState.closeLocked();
                     }
                 }
             }
-            return true;    // success!
+            return dragToken;    // success!
         } finally {
             mCallback.get().postPerformDrag();
         }
@@ -385,21 +346,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_DRAG_START_TIMEOUT: {
-                    IBinder win = (IBinder) msg.obj;
-                    if (DEBUG_DRAG) {
-                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
-                    }
-
-                    synchronized (mService.mWindowMap) {
-                        // !!! TODO: ANR the app that has failed to start the drag in time
-                        if (mDragState != null) {
-                            mDragState.closeLocked();
-                        }
-                    }
-                    break;
-                }
-
                 case MSG_DRAG_END_TIMEOUT: {
                     final IBinder win = (IBinder) msg.obj;
                     if (DEBUG_DRAG) {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
new file mode 100644
index 0000000..688b4ff
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -0,0 +1,206 @@
+/*
+ * 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.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationFinishedCallback.Stub;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+import java.util.ArrayList;
+
+/**
+ * Helper class to run app animations in a remote process.
+ */
+class RemoteAnimationController {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "RemoteAnimationController" : TAG_WM;
+    private static final long TIMEOUT_MS = 2000;
+
+    private final WindowManagerService mService;
+    private final RemoteAnimationAdapter mRemoteAnimationAdapter;
+    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 final Runnable mTimeoutRunnable = () -> {
+        onAnimationFinished();
+        invokeAnimationCancelled();
+    };
+
+    RemoteAnimationController(WindowManagerService service,
+            RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) {
+        mService = service;
+        mRemoteAnimationAdapter = remoteAnimationAdapter;
+        mHandler = handler;
+    }
+
+    /**
+     * Creates an animation for each individual {@link AppWindowToken}.
+     *
+     * @param appWindowToken The app to animate.
+     * @param position The position app bounds, in screen coordinates.
+     * @param stackBounds The stack bounds of the app.
+     * @return The adapter to be run on the app.
+     */
+    AnimationAdapter createAnimationAdapter(AppWindowToken appWindowToken, Point position,
+            Rect stackBounds) {
+        final RemoteAnimationAdapterWrapper adapter = new RemoteAnimationAdapterWrapper(
+                appWindowToken, position, stackBounds);
+        mPendingAnimations.add(adapter);
+        return adapter;
+    }
+
+    /**
+     * Called when the transition is ready to be started, and all leashes have been set up.
+     */
+    void goodToGo() {
+        mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS);
+        try {
+            mRemoteAnimationAdapter.getRunner().onAnimationStart(createAnimations(),
+                    mFinishedCallback);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to start remote animation", e);
+            onAnimationFinished();
+        }
+    }
+
+    private RemoteAnimationTarget[] createAnimations() {
+        final RemoteAnimationTarget[] result = new RemoteAnimationTarget[mPendingAnimations.size()];
+        for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+            result[i] = mPendingAnimations.get(i).createRemoteAppAnimation();
+        }
+        return result;
+    }
+
+    private void onAnimationFinished() {
+        mHandler.removeCallbacks(mTimeoutRunnable);
+        synchronized (mService.mWindowMap) {
+            mService.openSurfaceTransaction();
+            try {
+                for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+                    final RemoteAnimationAdapterWrapper adapter = mPendingAnimations.get(i);
+                    adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
+                }
+            } finally {
+                mService.closeSurfaceTransaction("RemoteAnimationController#finished");
+            }
+        }
+    }
+
+    private void invokeAnimationCancelled() {
+        try {
+            mRemoteAnimationAdapter.getRunner().onAnimationCancelled();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to notify cancel", e);
+        }
+    }
+
+    private class RemoteAnimationAdapterWrapper implements AnimationAdapter {
+
+        private final AppWindowToken mAppWindowToken;
+        private SurfaceControl mCapturedLeash;
+        private OnAnimationFinishedCallback mCapturedFinishCallback;
+        private final Point mPosition = new Point();
+        private final Rect mStackBounds = new Rect();
+
+        RemoteAnimationAdapterWrapper(AppWindowToken appWindowToken, Point position,
+                Rect stackBounds) {
+            mAppWindowToken = appWindowToken;
+            mPosition.set(position.x, position.y);
+            mStackBounds.set(stackBounds);
+        }
+
+        RemoteAnimationTarget createRemoteAppAnimation() {
+            return new RemoteAnimationTarget(mAppWindowToken.getTask().mTaskId, getMode(),
+                    mCapturedLeash, !mAppWindowToken.fillsParent(),
+                    mAppWindowToken.findMainWindow().mWinAnimator.mLastClipRect,
+                    mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds);
+        }
+
+        private int getMode() {
+            if (mService.mOpeningApps.contains(mAppWindowToken)) {
+                return RemoteAnimationTarget.MODE_OPENING;
+            } else {
+                return RemoteAnimationTarget.MODE_CLOSING;
+            }
+        }
+
+        @Override
+        public boolean getDetachWallpaper() {
+            return false;
+        }
+
+        @Override
+        public int getBackgroundColor() {
+            return 0;
+        }
+
+        @Override
+        public void startAnimation(SurfaceControl animationLeash, Transaction t,
+                OnAnimationFinishedCallback finishCallback) {
+
+            // Restore z-layering, position and stack crop until client has a chance to modify it.
+            t.setLayer(animationLeash, mAppWindowToken.getPrefixOrderIndex());
+            t.setPosition(animationLeash, mPosition.x, mPosition.y);
+            mTmpRect.set(mStackBounds);
+            mTmpRect.offsetTo(0, 0);
+            t.setWindowCrop(animationLeash, mTmpRect);
+            mCapturedLeash = animationLeash;
+            mCapturedFinishCallback = finishCallback;
+        }
+
+        @Override
+        public void onAnimationCancelled(SurfaceControl animationLeash) {
+            mPendingAnimations.remove(this);
+            if (mPendingAnimations.isEmpty()) {
+                mHandler.removeCallbacks(mTimeoutRunnable);
+                invokeAnimationCancelled();
+            }
+        }
+
+        @Override
+        public long getDurationHint() {
+            return mRemoteAnimationAdapter.getDuration();
+        }
+
+        @Override
+        public long getStatusBarTransitionsStartTime() {
+            return SystemClock.uptimeMillis()
+                    + mRemoteAnimationAdapter.getStatusBarTransitionDelay();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 192d6c8..04ae38e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -51,6 +51,7 @@
 import android.view.IWindowSessionCallback;
 import android.view.InputChannel;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 
@@ -308,30 +309,22 @@
     }
 
     /* Drag/drop */
+
     @Override
-    public IBinder prepareDrag(IWindow window, int flags, int width, int height,
-            Surface outSurface) {
+    public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource,
+            float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
         final int callerPid = Binder.getCallingPid();
         final int callerUid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         try {
-            return mDragDropController.prepareDrag(
-                    mSurfaceSession, callerPid, callerUid, window, flags, width, height,
-                    outSurface);
+            return mDragDropController.performDrag(mSurfaceSession, callerPid, callerUid, window,
+                    flags, surface, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
     }
 
     @Override
-    public boolean performDrag(IWindow window, IBinder dragToken,
-            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
-            ClipData data) {
-        return mDragDropController.performDrag(window, dragToken, touchSource,
-                touchX, touchY, thumbCenterX, thumbCenterY, data);
-    }
-
-    @Override
     public void reportDropResult(IWindow window, boolean consumed) {
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -467,6 +460,17 @@
         }
     }
 
+    @Override
+    public void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
+            int height) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mService.updateTapExcludeRegion(window, regionId, left, top, width, height);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     void windowAddedLocked(String packageName) {
         mPackageName = packageName;
         mRelayoutTag = "relayoutWindow: " + mPackageName;
diff --git a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
new file mode 100644
index 0000000..cbc936f
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.server.wm;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.SparseArray;
+
+/**
+ * A holder that contains a collection of rectangular areas identified by int id. Each individual
+ * region can be updated separately.
+ */
+class TapExcludeRegionHolder {
+    private SparseArray<Rect> mTapExcludeRects = new SparseArray<>();
+
+    /** Update the specified region with provided position and size. */
+    void updateRegion(int regionId, int left, int top, int width, int height) {
+        if (width <= 0 || height <= 0) {
+            // A region became empty - remove it.
+            mTapExcludeRects.remove(regionId);
+            return;
+        }
+
+        Rect region = mTapExcludeRects.get(regionId);
+        if (region == null) {
+            region = new Rect();
+        }
+        region.set(left, top, left + width, top + height);
+        mTapExcludeRects.put(regionId, region);
+    }
+
+    /**
+     * Union the provided region with current region formed by this container.
+     */
+    void amendRegion(Region region, Rect boundingRegion) {
+        for (int i = mTapExcludeRects.size() - 1; i>= 0 ; --i) {
+            final Rect rect = mTapExcludeRects.valueAt(i);
+            rect.intersect(boundingRegion);
+            region.union(rect);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index fa7ea2f..26c87b7 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -59,6 +59,8 @@
     private static final String TAG_LOCAL = "TaskPositioner";
     private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
 
+    private static Factory sFactory;
+
     // The margin the pointer position has to be within the side of the screen to be
     // considered at the side of the screen.
     static final int SIDE_MARGIN_DIP = 100;
@@ -214,6 +216,7 @@
         }
     }
 
+    /** Use {@link #create(WindowManagerService)} instead **/
     TaskPositioner(WindowManagerService service) {
         mService = service;
     }
@@ -622,4 +625,22 @@
     public String toShortString() {
         return TAG;
     }
+
+    static void setFactory(Factory factory) {
+        sFactory = factory;
+    }
+
+    static TaskPositioner create(WindowManagerService service) {
+        if (sFactory == null) {
+            sFactory = new Factory() {};
+        }
+
+        return sFactory.create(service);
+    }
+
+    interface Factory {
+        default TaskPositioner create(WindowManagerService service) {
+            return new TaskPositioner(service);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 4dfe290..a3f4ee8 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -126,7 +126,7 @@
         }
 
         Display display = displayContent.getDisplay();
-        mTaskPositioner = new TaskPositioner(mService);
+        mTaskPositioner = TaskPositioner.create(mService);
         mTaskPositioner.register(displayContent);
         mInputMonitor.updateInputWindowsLw(true /*force*/);
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 8a36226..bc0f9ad 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1397,15 +1397,23 @@
         return getDockSide(getRawBounds());
     }
 
+    int getDockSideForDisplay(DisplayContent dc) {
+        return getDockSide(dc, getRawBounds());
+    }
+
     private int getDockSide(Rect bounds) {
-        if (!inSplitScreenWindowingMode()) {
-            return DOCKED_INVALID;
-        }
         if (mDisplayContent == null) {
             return DOCKED_INVALID;
         }
-        mDisplayContent.getBounds(mTmpRect);
-        final int orientation = mDisplayContent.getConfiguration().orientation;
+        return getDockSide(mDisplayContent, bounds);
+    }
+
+    private int getDockSide(DisplayContent dc, Rect bounds) {
+        if (!inSplitScreenWindowingMode()) {
+            return DOCKED_INVALID;
+        }
+        dc.getBounds(mTmpRect);
+        final int orientation = dc.getConfiguration().orientation;
         return getDockSideUnchecked(bounds, mTmpRect, orientation);
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index ac0919d..1218d3b 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -25,7 +25,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d2ab9df..53086f7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
@@ -87,7 +88,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
@@ -210,17 +210,18 @@
 import android.view.MagnificationSpec;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
+import android.view.RemoteAnimationAdapter;
 import android.view.Surface;
 import android.view.SurfaceControl;
-import android.view.SurfaceControl.Builder;
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowContentFrameStats;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.WindowManager.TransitionFlags;
+import android.view.WindowManager.TransitionType;
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
-import android.view.animation.Animation;
 import android.view.inputmethod.InputMethodManagerInternal;
 
 import com.android.internal.R;
@@ -1540,7 +1541,7 @@
         // We treat this as if this activity was opening, so we can trigger the app transition
         // animation and piggy-back on existing transition animation infrastructure.
         mOpeningApps.add(atoken);
-        prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
+        prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT);
         mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
                 frame.width(), frame.height());
         executeAppTransition();
@@ -1554,7 +1555,7 @@
         // we don't set up the transition anymore and just let it go.
         if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
             mOpeningApps.add(atoken);
-            prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
+            prepareAppTransition(WindowManager.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
             executeAppTransition();
         }
     }
@@ -2509,7 +2510,7 @@
     }
 
     @Override
-    public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
+    public void prepareAppTransition(@TransitionType int transit, boolean alwaysKeepCurrent) {
         prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
     }
 
@@ -2522,8 +2523,8 @@
      *              AppTransition.TRANSIT_FLAG_*.
      * @param forceOverride Always override the transit, not matter what was set previously.
      */
-    public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags,
-            boolean forceOverride) {
+    public void prepareAppTransition(@TransitionType int transit, boolean alwaysKeepCurrent,
+            @TransitionFlags int flags, boolean forceOverride) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
@@ -2539,7 +2540,7 @@
     }
 
     @Override
-    public int getPendingAppTransition() {
+    public @TransitionType int getPendingAppTransition() {
         return mAppTransition.getAppTransition();
     }
 
@@ -2624,6 +2625,18 @@
     }
 
     @Override
+    public void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter) {
+        if (!checkCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+                "overridePendingAppTransitionRemote()")) {
+            throw new SecurityException(
+                    "Requires CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS permission");
+        }
+        synchronized (mWindowMap) {
+            mAppTransition.overridePendingAppTransitionRemote(remoteAnimationAdapter);
+        }
+    }
+
+    @Override
     public void endProlongedAnimations() {
         synchronized (mWindowMap) {
             for (final WindowState win : mWindowMap.values()) {
@@ -6600,6 +6613,7 @@
     public void onOverlayChanged() {
         synchronized (mWindowMap) {
             mPolicy.onOverlayChangedLw();
+            getDefaultDisplayContentLocked().updateDisplayInfo();
             requestTraversal();
         }
     }
@@ -6908,6 +6922,23 @@
         }
     }
 
+    /**
+     * Update a tap exclude region with a rectangular area in the window identified by the provided
+     * id. Touches on this region will not switch focus to this window. Passing an empty rect will
+     * remove the area from the exclude region of this window.
+     */
+    void updateTapExcludeRegion(IWindow client, int regionId, int left, int top, int width,
+            int height) {
+        synchronized (mWindowMap) {
+            final WindowState callingWin = windowForClientLocked(null, client, false);
+            if (callingWin == null) {
+                Slog.w(TAG_WM, "Bad requesting window " + client);
+                return;
+            }
+            callingWin.updateTapExcludeRegion(regionId, left, top, width, height);
+        }
+    }
+
     @Override
     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
             throws RemoteException {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d068c49..477dd2b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -193,6 +193,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.server.input.InputWindowHandle;
 import com.android.server.policy.WindowManagerPolicy;
@@ -629,6 +630,11 @@
     private final Point mSurfacePosition = new Point();
 
     /**
+     * A region inside of this window to be excluded from touch-related focus switches.
+     */
+    private TapExcludeRegionHolder mTapExcludeRegionHolder;
+
+    /**
      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
      */
@@ -1869,6 +1875,11 @@
         if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) {
             dc.mTapExcludedWindows.remove(this);
         }
+        if (mTapExcludeRegionHolder != null) {
+            // If a tap exclude region container was initialized for this window, then it should've
+            // also been registered in display.
+            dc.mTapExcludeProvidingWindows.remove(this);
+        }
         mPolicy.removeWindowLw(this);
 
         disposeInputChannel();
@@ -3952,6 +3963,22 @@
         return null;
     }
 
+    /**
+     * @return True if we our one of our ancestors has {@link #mAnimatingExit} set to true, false
+     *         otherwise.
+     */
+    @VisibleForTesting
+    boolean isSelfOrAncestorWindowAnimatingExit() {
+        WindowState window = this;
+        do {
+            if (window.mAnimatingExit) {
+                return true;
+            }
+            window = window.getParentWindow();
+        } while (window != null);
+        return false;
+    }
+
     void onExitAnimationDone() {
         if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
                 + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
@@ -3987,7 +4014,7 @@
             mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
         }
 
-        if (!mAnimatingExit) {
+        if (!isSelfOrAncestorWindowAnimatingExit()) {
             return;
         }
 
@@ -4603,6 +4630,37 @@
         }
     }
 
+    /**
+     * Update a tap exclude region with a rectangular area identified by provided id. The requested
+     * area will be clipped to the window bounds.
+     */
+    void updateTapExcludeRegion(int regionId, int left, int top, int width, int height) {
+        final DisplayContent currentDisplay = getDisplayContent();
+        if (currentDisplay == null) {
+            throw new IllegalStateException("Trying to update window not attached to any display.");
+        }
+
+        if (mTapExcludeRegionHolder == null) {
+            mTapExcludeRegionHolder = new TapExcludeRegionHolder();
+
+            // Make sure that this window is registered as one that provides a tap exclude region
+            // for its containing display.
+            currentDisplay.mTapExcludeProvidingWindows.add(this);
+        }
+
+        mTapExcludeRegionHolder.updateRegion(regionId, left, top, width, height);
+        // Trigger touch exclude region update on current display.
+        final boolean isAppFocusedOnDisplay = mService.mFocusedApp != null
+                && mService.mFocusedApp.getDisplayContent() == currentDisplay;
+        currentDisplay.setTouchExcludeRegion(isAppFocusedOnDisplay ? mService.mFocusedApp.getTask()
+                : null);
+    }
+
+    /** Union the region with current tap exclude region that this window provides. */
+    void amendTapExcludeRegion(Region region) {
+        mTapExcludeRegionHolder.amendRegion(region, getBounds());
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 017b325..7364e87 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -23,23 +23,23 @@
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
-import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
-import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
-import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_NONE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
-import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
-import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_CLOSE;
-import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
-import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_OPEN;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
@@ -57,14 +57,19 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.view.Display;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationDefinition;
 import android.view.SurfaceControl;
+import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.WindowManager.TransitionType;
 import android.view.animation.Animation;
 
 import com.android.server.wm.WindowManagerService.H;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.function.Predicate;
 
 /**
  * Positions windows and their surfaces.
@@ -247,7 +252,7 @@
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
         int transit = mService.mAppTransition.getAppTransition();
         if (mService.mSkipAppTransitionAnimation && !isKeyguardGoingAwayTransit(transit)) {
-            transit = AppTransition.TRANSIT_UNSET;
+            transit = WindowManager.TRANSIT_UNSET;
         }
         mService.mSkipAppTransitionAnimation = false;
         mService.mNoAnimationNotifyOnTransitionFinished.clear();
@@ -255,17 +260,9 @@
         mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
 
         final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
-        // TODO: Don't believe this is really needed...
-        //mService.mWindowsChanged = true;
 
         mService.mRoot.mWallpaperMayChange = false;
 
-        // The top-most window will supply the layout params, and we will determine it below.
-        LayoutParams animLp = null;
-        int bestAnimLayer = -1;
-        boolean fullscreenAnim = false;
-        boolean voiceInteraction = false;
-
         int i;
         for (i = 0; i < appsCount; i++) {
             final AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
@@ -274,7 +271,6 @@
             // visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the
             // transition selection depends on wallpaper target visibility.
             wtoken.clearAnimatingFlags();
-
         }
 
         // Adjust wallpaper before we pull the lower/upper target, since pending changes
@@ -283,62 +279,30 @@
         mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(displayContent,
                 mService.mOpeningApps);
 
-        final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
-        boolean openingAppHasWallpaper = false;
-        boolean closingAppHasWallpaper = false;
-
-        // Do a first pass through the tokens for two things:
-        // (1) Determine if both the closing and opening app token sets are wallpaper targets, in
-        // which case special animations are needed (since the wallpaper needs to stay static behind
-        // them).
-        // (2) Find the layout params of the top-most application window in the tokens, which is
-        // what will control the animation theme.
-        final int closingAppsCount = mService.mClosingApps.size();
-        appsCount = closingAppsCount + mService.mOpeningApps.size();
-        for (i = 0; i < appsCount; i++) {
-            final AppWindowToken wtoken;
-            if (i < closingAppsCount) {
-                wtoken = mService.mClosingApps.valueAt(i);
-                if (wallpaperTarget != null && wtoken.windowsCanBeWallpaperTarget()) {
-                    closingAppHasWallpaper = true;
-                }
-            } else {
-                wtoken = mService.mOpeningApps.valueAt(i - closingAppsCount);
-                if (wallpaperTarget != null && wtoken.windowsCanBeWallpaperTarget()) {
-                    openingAppHasWallpaper = true;
-                }
-            }
-
-            voiceInteraction |= wtoken.mVoiceInteraction;
-
-            if (wtoken.fillsParent()) {
-                final WindowState ws = wtoken.findMainWindow();
-                if (ws != null) {
-                    animLp = ws.mAttrs;
-                    bestAnimLayer = ws.mLayer;
-                    fullscreenAnim = true;
-                }
-            } else if (!fullscreenAnim) {
-                final WindowState ws = wtoken.findMainWindow();
-                if (ws != null) {
-                    if (ws.mLayer > bestAnimLayer) {
-                        animLp = ws.mAttrs;
-                        bestAnimLayer = ws.mLayer;
-                    }
-                }
-            }
-        }
+        // Determine if closing and opening app token sets are wallpaper targets, in which case
+        // special animations are needed.
+        final boolean hasWallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget() != null;
+        final boolean openingAppHasWallpaper = canBeWallpaperTarget(mService.mOpeningApps)
+                && hasWallpaperTarget;
+        final boolean closingAppHasWallpaper = canBeWallpaperTarget(mService.mClosingApps)
+                && hasWallpaperTarget;
 
         transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
                 closingAppHasWallpaper);
 
-        // If all closing windows are obscured, then there is no need to do an animation. This is
-        // the case, for example, when this transition is being done behind the lock screen.
-        if (!mService.mPolicy.allowAppAnimationsLw()) {
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                    "Animations disallowed by keyguard or dream.");
-            animLp = null;
-        }
+        // Find the layout params of the top-most application window in the tokens, which is
+        // what will control the animation theme. If all closing windows are obscured, then there is
+        // no need to do an animation. This is the case, for example, when this transition is being
+        // done behind a dream window.
+        final AppWindowToken animLpToken = mService.mPolicy.allowAppAnimationsLw()
+                ? findAnimLayoutParamsToken(transit)
+                : null;
+
+        final LayoutParams animLp = getAnimLp(animLpToken);
+        overrideWithRemoteAnimationIfSet(animLpToken, transit);
+
+        final boolean voiceInteraction = containsVoiceInteraction(mService.mOpeningApps)
+                || containsVoiceInteraction(mService.mOpeningApps);
 
         final int layoutRedo;
         mService.mSurfaceAnimationRunner.deferStartingAnimations();
@@ -388,6 +352,81 @@
         return layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
     }
 
+    private static LayoutParams getAnimLp(AppWindowToken wtoken) {
+        final WindowState mainWindow = wtoken != null ? wtoken.findMainWindow() : null;
+        return mainWindow != null ? mainWindow.mAttrs : null;
+    }
+
+    /**
+     * Overrides the pending transition with the remote animation defined for the transition in the
+     * set of defined remote animations in the app window token.
+     */
+    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit) {
+        if (animLpToken == null) {
+            return;
+        }
+        final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
+        if (definition != null) {
+            final RemoteAnimationAdapter adapter = definition.getAdapter(transit);
+            if (adapter != null) {
+                mService.mAppTransition.overridePendingAppTransitionRemote(adapter);
+            }
+        }
+    }
+
+    /**
+     * @return The window token that determines the animation theme.
+     */
+    private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit) {
+        AppWindowToken result;
+
+        // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
+        result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
+                w -> w.getRemoteAnimationDefinition() != null
+                        && w.getRemoteAnimationDefinition().hasTransition(transit));
+        if (result != null) {
+            return result;
+        }
+        result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
+                w -> w.fillsParent() && w.findMainWindow() != null);
+        if (result != null) {
+            return result;
+        }
+        return lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
+                w -> w.findMainWindow() != null);
+    }
+
+    private AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
+            ArraySet<AppWindowToken> array2, Predicate<AppWindowToken> filter) {
+        final int array1count = array1.size();
+        final int count = array1count + array2.size();
+        int bestPrefixOrderIndex = Integer.MIN_VALUE;
+        AppWindowToken bestToken = null;
+        for (int i = 0; i < count; i++) {
+            final AppWindowToken wtoken;
+            if (i < array1count) {
+                wtoken = array1.valueAt(i);
+            } else {
+                wtoken = array2.valueAt(i - array1count);
+            }
+            final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
+            if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) {
+                bestPrefixOrderIndex = prefixOrderIndex;
+                bestToken = wtoken;
+            }
+        }
+        return bestToken;
+    }
+
+    private boolean containsVoiceInteraction(ArraySet<AppWindowToken> apps) {
+        for (int i = apps.size() - 1; i >= 0; i--) {
+            if (apps.valueAt(i).mVoiceInteraction) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private AppWindowToken handleOpeningApps(int transit, LayoutParams animLp,
             boolean voiceInteraction) {
         AppWindowToken topOpeningApp = null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 36de3d1..384b416 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -109,4 +109,21 @@
     public boolean startUserInBackground(ComponentName who, UserHandle userHandle) {
         return false;
     }
+
+    @Override
+    public void setStartUserSessionMessage(
+            ComponentName admin, CharSequence startUserSessionMessage) {}
+
+    @Override
+    public void setEndUserSessionMessage(ComponentName admin, CharSequence endUserSessionMessage) {}
+
+    @Override
+    public String getStartUserSessionMessage(ComponentName admin) {
+        return null;
+    }
+
+    @Override
+    public String getEndUserSessionMessage(ComponentName admin) {
+        return null;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 62a97f8..cb4f5c1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -200,6 +200,7 @@
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 import com.android.server.pm.UserRestrictionsUtils;
+
 import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -792,6 +793,8 @@
         private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
         private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
         private static final String TAG_MANDATORY_BACKUP_TRANSPORT = "mandatory_backup_transport";
+        private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
+        private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
 
         DeviceAdminInfo info;
 
@@ -912,6 +915,10 @@
         // or null if backups are not mandatory.
         ComponentName mandatoryBackupTransport = null;
 
+        // Message for user switcher
+        String startUserSessionMessage = null;
+        String endUserSessionMessage = null;
+
         ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
             info = _info;
             isParent = parent;
@@ -1180,6 +1187,16 @@
                 out.attribute(null, ATTR_VALUE, mandatoryBackupTransport.flattenToString());
                 out.endTag(null, TAG_MANDATORY_BACKUP_TRANSPORT);
             }
+            if (startUserSessionMessage != null) {
+                out.startTag(null, TAG_START_USER_SESSION_MESSAGE);
+                out.text(startUserSessionMessage);
+                out.endTag(null, TAG_START_USER_SESSION_MESSAGE);
+            }
+            if (endUserSessionMessage != null) {
+                out.startTag(null, TAG_END_USER_SESSION_MESSAGE);
+                out.text(endUserSessionMessage);
+                out.endTag(null, TAG_END_USER_SESSION_MESSAGE);
+            }
         }
 
         void writePackageListToXml(XmlSerializer out, String outerTag,
@@ -1361,6 +1378,20 @@
                 } else if (TAG_MANDATORY_BACKUP_TRANSPORT.equals(tag)) {
                     mandatoryBackupTransport = ComponentName.unflattenFromString(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        startUserSessionMessage = parser.getText();
+                    } else {
+                        Log.w(LOG_TAG, "Missing text when loading start session message");
+                    }
+                } else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        endUserSessionMessage = parser.getText();
+                    } else {
+                        Log.w(LOG_TAG, "Missing text when loading end session message");
+                    }
                 } else {
                     Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -3215,10 +3246,18 @@
         }
 
         synchronized (this) {
-            // push the force-ephemeral-users policy to the user manager.
             ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
             if (deviceOwner != null) {
+                // Push the force-ephemeral-users policy to the user manager.
                 mUserManagerInternal.setForceEphemeralUsers(deviceOwner.forceEphemeralUsers);
+
+                // Update user switcher message to activity manager.
+                ActivityManagerInternal activityManagerInternal =
+                        mInjector.getActivityManagerInternal();
+                activityManagerInternal.setSwitchingFromSystemUserMessage(
+                        deviceOwner.startUserSessionMessage);
+                activityManagerInternal.setSwitchingToSystemUserMessage(
+                        deviceOwner.endUserSessionMessage);
             }
         }
     }
@@ -4517,6 +4556,28 @@
         }
     }
 
+    private boolean canPOorDOCallResetPassword(ActiveAdmin admin, @UserIdInt int userId) {
+        // Only if the admins targets a pre-O SDK
+        return getTargetSdk(admin.info.getPackageName(), userId) < Build.VERSION_CODES.O;
+    }
+
+    /* PO or DO could do an untrusted reset in certain conditions. */
+    private boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
+        synchronized (this) {
+            // An active DO or PO might be able to fo an untrusted credential reset
+            for (final ActiveAdmin admin : getUserData(userId).mAdminList) {
+                if (!isActiveAdminWithPolicyForUserLocked(admin,
+                          DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, userId)) {
+                    continue;
+                }
+                if (canPOorDOCallResetPassword(admin, userId)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     @Override
     public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException {
         final int callingUid = mInjector.binderGetCallingUid();
@@ -4535,12 +4596,12 @@
                     null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
             final boolean preN;
             if (admin != null) {
-                final int targetSdk = getTargetSdk(admin.info.getPackageName(), userHandle);
-                if (targetSdk >= Build.VERSION_CODES.O) {
+                if (!canPOorDOCallResetPassword(admin, userHandle)) {
                     throw new SecurityException("resetPassword() is deprecated for DPC targeting O"
                             + " or later");
                 }
-                preN = targetSdk <= android.os.Build.VERSION_CODES.M;
+                preN = getTargetSdk(admin.info.getPackageName(),
+                        userHandle) <= android.os.Build.VERSION_CODES.M;
             } else {
                 // Otherwise, make sure the caller has any active admin with the right policy.
                 admin = getActiveAdminForCallerLocked(null,
@@ -10111,6 +10172,11 @@
                 updateMaximumTimeToLockLocked(userId);
             }
         }
+
+        @Override
+        public boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
+            return DevicePolicyManagerService.this.canUserHaveUntrustedCredentialReset(userId);
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
@@ -12007,15 +12073,18 @@
             return;
         }
         Preconditions.checkNotNull(admin);
-        getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
 
-        if (enabled == isLogoutEnabledInternalLocked()) {
-            // already in the requested state
-            return;
+        synchronized (this) {
+            ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+            if (deviceOwner.isLogoutEnabled == enabled) {
+                // already in the requested state
+                return;
+            }
+            deviceOwner.isLogoutEnabled = enabled;
+            saveSettingsLocked(mInjector.userHandleGetCallingUserId());
         }
-        ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
-        deviceOwner.isLogoutEnabled = enabled;
-        saveSettingsLocked(mInjector.userHandleGetCallingUserId());
     }
 
     @Override
@@ -12024,15 +12093,11 @@
             return false;
         }
         synchronized (this) {
-            return isLogoutEnabledInternalLocked();
+            ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+            return (deviceOwner != null) && deviceOwner.isLogoutEnabled;
         }
     }
 
-    private boolean isLogoutEnabledInternalLocked() {
-        ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
-        return (deviceOwner != null) && deviceOwner.isLogoutEnabled;
-    }
-
     @Override
     public List<String> getDisallowedSystemApps(ComponentName admin, int userId,
             String provisioningAction) throws RemoteException {
@@ -12069,6 +12134,11 @@
         final DeviceAdminInfo incomingDeviceInfo = findAdmin(target, callingUserId,
                 /* throwForMissingPermission= */ true);
         checkActiveAdminPrecondition(target, incomingDeviceInfo, policy);
+        if (!incomingDeviceInfo.getActivityInfo().metaData
+                .getBoolean(DeviceAdminReceiver.SUPPORT_TRANSFER_OWNERSHIP_META_DATA, false)) {
+            throw new IllegalArgumentException("Provided target does not support "
+                    + "ownership transfer.");
+        }
 
         final long id = mInjector.binderClearCallingIdentity();
         try {
@@ -12125,4 +12195,83 @@
         }
         return extras;
     }
+
+    @Override
+    public void setStartUserSessionMessage(
+            ComponentName admin, CharSequence startUserSessionMessage) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(admin);
+
+        final String startUserSessionMessageString =
+                startUserSessionMessage != null ? startUserSessionMessage.toString() : null;
+
+        synchronized (this) {
+            final ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+            if (TextUtils.equals(deviceOwner.startUserSessionMessage, startUserSessionMessage)) {
+                return;
+            }
+            deviceOwner.startUserSessionMessage = startUserSessionMessageString;
+            saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+        }
+
+        mInjector.getActivityManagerInternal()
+                .setSwitchingFromSystemUserMessage(startUserSessionMessageString);
+    }
+
+    @Override
+    public void setEndUserSessionMessage(ComponentName admin, CharSequence endUserSessionMessage) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(admin);
+
+        final String endUserSessionMessageString =
+                endUserSessionMessage != null ? endUserSessionMessage.toString() : null;
+
+        synchronized (this) {
+            final ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+            if (TextUtils.equals(deviceOwner.endUserSessionMessage, endUserSessionMessage)) {
+                return;
+            }
+            deviceOwner.endUserSessionMessage = endUserSessionMessageString;
+            saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+        }
+
+        mInjector.getActivityManagerInternal()
+                .setSwitchingToSystemUserMessage(endUserSessionMessageString);
+    }
+
+    @Override
+    public String getStartUserSessionMessage(ComponentName admin) {
+        if (!mHasFeature) {
+            return null;
+        }
+        Preconditions.checkNotNull(admin);
+
+        synchronized (this) {
+            final ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            return deviceOwner.startUserSessionMessage;
+        }
+    }
+
+    @Override
+    public String getEndUserSessionMessage(ComponentName admin) {
+        if (!mHasFeature) {
+            return null;
+        }
+        Preconditions.checkNotNull(admin);
+
+        synchronized (this) {
+            final ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            return deviceOwner.endUserSessionMessage;
+        }
+    }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3199bfa..e660c50 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -46,10 +46,10 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.IStorageManager;
-import android.util.TimingsTraceLog;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Slog;
+import android.util.TimingsTraceLog;
 import android.view.WindowManager;
 
 import com.android.internal.R;
@@ -57,20 +57,21 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BinderInternal;
-import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
 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;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
-import com.android.server.display.DisplayManagerService;
 import com.android.server.display.ColorDisplayService;
+import com.android.server.display.DisplayManagerService;
 import com.android.server.dreams.DreamManagerService;
 import com.android.server.emergency.EmergencyAffordanceService;
 import com.android.server.fingerprint.FingerprintService;
@@ -92,17 +93,16 @@
 import com.android.server.os.DeviceIdentifiersPolicyService;
 import com.android.server.os.SchedulingPolicyService;
 import com.android.server.pm.BackgroundDexOptService;
+import com.android.server.pm.CrossProfileAppsService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.LauncherAppsService;
 import com.android.server.pm.OtaDexoptService;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
-import com.android.server.pm.crossprofile.CrossProfileAppsService;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
-import com.android.server.broadcastradio.BroadcastRadioService;
 import com.android.server.restrictions.RestrictionsManagerService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 71ba685..cd4e8f9 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -57,7 +57,9 @@
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.print.DualDumpOutputStream;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 
@@ -670,37 +672,29 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 if (dumpAsProto) {
-                    dump(new ProtoOutputStream(fd), userStatesToDump);
+                    dump(new DualDumpOutputStream(new ProtoOutputStream(fd), null),
+                            userStatesToDump);
                 } else {
-                    dump(fd, pw, userStatesToDump);
+                    pw.println("PRINT MANAGER STATE (dumpsys print)");
+
+                    dump(new DualDumpOutputStream(null, new IndentingPrintWriter(pw, "  ")),
+                            userStatesToDump);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
         }
 
-        private void dump(@NonNull ProtoOutputStream proto,
+        private void dump(@NonNull DualDumpOutputStream dumpStream,
                 @NonNull ArrayList<UserState> userStatesToDump) {
             final int userStateCount = userStatesToDump.size();
             for (int i = 0; i < userStateCount; i++) {
-                long token = proto.start(PrintServiceDumpProto.USER_STATES);
-                userStatesToDump.get(i).dump(proto);
-                proto.end(token);
+                long token = dumpStream.start("user_states", PrintServiceDumpProto.USER_STATES);
+                userStatesToDump.get(i).dump(dumpStream);
+                dumpStream.end(token);
             }
 
-            proto.flush();
-        }
-
-        private void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
-                @NonNull ArrayList<UserState> userStatesToDump) {
-            pw = Preconditions.checkNotNull(pw);
-
-            pw.println("PRINT MANAGER STATE (dumpsys print)");
-            final int userStateCount = userStatesToDump.size();
-            for (int i = 0; i < userStateCount; i++) {
-                userStatesToDump.get(i).dump(fd, pw, "");
-                pw.println();
-            }
+            dumpStream.flush();
         }
 
         private void registerContentObservers() {
diff --git a/services/print/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java
index 13462cd..80b97cf 100644
--- a/services/print/java/com/android/server/print/RemotePrintService.java
+++ b/services/print/java/com/android/server/print/RemotePrintService.java
@@ -47,11 +47,10 @@
 import android.printservice.IPrintServiceClient;
 import android.service.print.ActivePrintServiceProto;
 import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.print.DualDumpOutputStream;
 
-import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -532,49 +531,30 @@
         }
     }
 
-    public void dump(@NonNull ProtoOutputStream proto) {
-        writeComponentName(proto, ActivePrintServiceProto.COMPONENT_NAME, mComponentName);
+    public void dump(@NonNull DualDumpOutputStream proto) {
+        writeComponentName(proto, "component_name", ActivePrintServiceProto.COMPONENT_NAME,
+                mComponentName);
 
-        proto.write(ActivePrintServiceProto.IS_DESTROYED, mDestroyed);
-        proto.write(ActivePrintServiceProto.IS_BOUND, isBound());
-        proto.write(ActivePrintServiceProto.HAS_DISCOVERY_SESSION, mHasPrinterDiscoverySession);
-        proto.write(ActivePrintServiceProto.HAS_ACTIVE_PRINT_JOBS, mHasActivePrintJobs);
-        proto.write(ActivePrintServiceProto.IS_DISCOVERING_PRINTERS,
+        proto.write("is_destroyed", ActivePrintServiceProto.IS_DESTROYED, mDestroyed);
+        proto.write("is_bound", ActivePrintServiceProto.IS_BOUND, isBound());
+        proto.write("has_discovery_session", ActivePrintServiceProto.HAS_DISCOVERY_SESSION,
+                mHasPrinterDiscoverySession);
+        proto.write("has_active_print_jobs", ActivePrintServiceProto.HAS_ACTIVE_PRINT_JOBS,
+                mHasActivePrintJobs);
+        proto.write("is_discovering_printers", ActivePrintServiceProto.IS_DISCOVERING_PRINTERS,
                 mDiscoveryPriorityList != null);
 
         synchronized (mLock) {
             if (mTrackedPrinterList != null) {
                 int numTrackedPrinters = mTrackedPrinterList.size();
                 for (int i = 0; i < numTrackedPrinters; i++) {
-                    writePrinterId(proto, ActivePrintServiceProto.TRACKED_PRINTERS,
-                            mTrackedPrinterList.get(i));
+                    writePrinterId(proto, "tracked_printers",
+                            ActivePrintServiceProto.TRACKED_PRINTERS, mTrackedPrinterList.get(i));
                 }
             }
         }
     }
 
-    public void dump(PrintWriter pw, String prefix) {
-        String tab = "  ";
-        pw.append(prefix).append("service:").println();
-        pw.append(prefix).append(tab).append("componentName=")
-                .append(mComponentName.flattenToString()).println();
-        pw.append(prefix).append(tab).append("destroyed=")
-                .append(String.valueOf(mDestroyed)).println();
-        pw.append(prefix).append(tab).append("bound=")
-                .append(String.valueOf(isBound())).println();
-        pw.append(prefix).append(tab).append("hasDicoverySession=")
-                .append(String.valueOf(mHasPrinterDiscoverySession)).println();
-        pw.append(prefix).append(tab).append("hasActivePrintJobs=")
-                .append(String.valueOf(mHasActivePrintJobs)).println();
-        pw.append(prefix).append(tab).append("isDiscoveringPrinters=")
-                .append(String.valueOf(mDiscoveryPriorityList != null)).println();
-
-        synchronized (mLock) {
-            pw.append(prefix).append(tab).append("trackedPrinters=").append(
-                    (mTrackedPrinterList != null) ? mTrackedPrinterList.toString() : "null");
-        }
-    }
-
     private boolean isBound() {
         return mPrintService != null;
     }
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index f654fcb..a69baa1 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -43,16 +43,14 @@
 import android.service.print.PrintSpoolerStateProto;
 import android.util.Slog;
 import android.util.TimedRemoteCaller;
-import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.print.DualDumpOutputStream;
 
 import libcore.io.IoUtils;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
@@ -558,37 +556,25 @@
         }
     }
 
-    public void dump(@NonNull ProtoOutputStream proto) {
+    public void dump(@NonNull DualDumpOutputStream dumpStream) {
         synchronized (mLock) {
-            proto.write(PrintSpoolerStateProto.IS_DESTROYED, mDestroyed);
-            proto.write(PrintSpoolerStateProto.IS_BOUND, mRemoteInstance != null);
+            dumpStream.write("is_destroyed", PrintSpoolerStateProto.IS_DESTROYED, mDestroyed);
+            dumpStream.write("is_bound", PrintSpoolerStateProto.IS_BOUND, mRemoteInstance != null);
         }
 
         try {
-            proto.write(PrintSpoolerStateProto.INTERNAL_STATE,
-                    TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), "--proto"));
+            if (dumpStream.isProto()) {
+                dumpStream.write(null, PrintSpoolerStateProto.INTERNAL_STATE,
+                        TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), "--proto"));
+            } else {
+                dumpStream.writeNested("internal_state", TransferPipe.dumpAsync(
+                        getRemoteInstanceLazy().asBinder()));
+            }
         } catch (IOException | TimeoutException | RemoteException | InterruptedException e) {
             Slog.e(LOG_TAG, "Failed to dump remote instance", e);
         }
     }
 
-    public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
-        synchronized (mLock) {
-            pw.append(prefix).append("destroyed=")
-                    .append(String.valueOf(mDestroyed)).println();
-            pw.append(prefix).append("bound=")
-                    .append((mRemoteInstance != null) ? "true" : "false").println();
-
-            pw.flush();
-            try {
-                TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd,
-                        new String[] { prefix });
-            } catch (IOException | TimeoutException | RemoteException | InterruptedException e) {
-                pw.println("Failed to dump remote instance: " + e);
-            }
-        }
-    }
-
     private void onAllPrintJobsHandled() {
         synchronized (mLock) {
             throwIfDestroyedLocked();
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 364bbc0..e2808e8 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -76,19 +76,17 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.print.DualDumpOutputStream;
 import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
 import com.android.server.print.RemotePrintServiceRecommendationService
         .RemotePrintServiceRecommendationServiceCallbacks;
 import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -817,112 +815,63 @@
         mDestroyed = true;
     }
 
-    public void dump(@NonNull ProtoOutputStream proto) {
+    public void dump(@NonNull DualDumpOutputStream dumpStream) {
         synchronized (mLock) {
-            proto.write(PrintUserStateProto.USER_ID, mUserId);
+            dumpStream.write("user_id", PrintUserStateProto.USER_ID, mUserId);
 
             final int installedServiceCount = mInstalledServices.size();
             for (int i = 0; i < installedServiceCount; i++) {
-                long token = proto.start(PrintUserStateProto.INSTALLED_SERVICES);
+                long token = dumpStream.start("installed_services",
+                        PrintUserStateProto.INSTALLED_SERVICES);
                 PrintServiceInfo installedService = mInstalledServices.get(i);
 
                 ResolveInfo resolveInfo = installedService.getResolveInfo();
-                writeComponentName(proto, InstalledPrintServiceProto.COMPONENT_NAME,
+                writeComponentName(dumpStream, "component_name",
+                        InstalledPrintServiceProto.COMPONENT_NAME,
                         new ComponentName(resolveInfo.serviceInfo.packageName,
                                 resolveInfo.serviceInfo.name));
 
-                writeStringIfNotNull(proto, InstalledPrintServiceProto.SETTINGS_ACTIVITY,
+                writeStringIfNotNull(dumpStream, "settings_activity",
+                        InstalledPrintServiceProto.SETTINGS_ACTIVITY,
                         installedService.getSettingsActivityName());
-                writeStringIfNotNull(proto, InstalledPrintServiceProto.ADD_PRINTERS_ACTIVITY,
+                writeStringIfNotNull(dumpStream, "add_printers_activity",
+                        InstalledPrintServiceProto.ADD_PRINTERS_ACTIVITY,
                         installedService.getAddPrintersActivityName());
-                writeStringIfNotNull(proto, InstalledPrintServiceProto.ADVANCED_OPTIONS_ACTIVITY,
+                writeStringIfNotNull(dumpStream, "advanced_options_activity",
+                        InstalledPrintServiceProto.ADVANCED_OPTIONS_ACTIVITY,
                         installedService.getAdvancedOptionsActivityName());
 
-                proto.end(token);
+                dumpStream.end(token);
             }
 
             for (ComponentName disabledService : mDisabledServices) {
-                writeComponentName(proto, PrintUserStateProto.DISABLED_SERVICES, disabledService);
+                writeComponentName(dumpStream, "disabled_services",
+                        PrintUserStateProto.DISABLED_SERVICES, disabledService);
             }
 
             final int activeServiceCount = mActiveServices.size();
             for (int i = 0; i < activeServiceCount; i++) {
-                long token = proto.start(PrintUserStateProto.ACTIVE_SERVICES);
-                mActiveServices.valueAt(i).dump(proto);
-                proto.end(token);
+                long token = dumpStream.start("actives_services",
+                        PrintUserStateProto.ACTIVE_SERVICES);
+                mActiveServices.valueAt(i).dump(dumpStream);
+                dumpStream.end(token);
             }
 
-            mPrintJobForAppCache.dumpLocked(proto);
+            mPrintJobForAppCache.dumpLocked(dumpStream);
 
             if (mPrinterDiscoverySession != null) {
-                long token = proto.start(PrintUserStateProto.DISCOVERY_SESSIONS);
-                mPrinterDiscoverySession.dumpLocked(proto);
-                proto.end(token);
+                long token = dumpStream.start("discovery_service",
+                        PrintUserStateProto.DISCOVERY_SESSIONS);
+                mPrinterDiscoverySession.dumpLocked(dumpStream);
+                dumpStream.end(token);
             }
 
         }
 
-        long token = proto.start(PrintUserStateProto.PRINT_SPOOLER_STATE);
-        mSpooler.dump(proto);
-        proto.end(token);
-    }
-
-    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String prefix) {
-        pw.append(prefix).append("user state ").append(String.valueOf(mUserId)).append(":");
-        pw.println();
-
-        String tab = "  ";
-
-        synchronized (mLock) {
-            pw.append(prefix).append(tab).append("installed services:").println();
-            final int installedServiceCount = mInstalledServices.size();
-            for (int i = 0; i < installedServiceCount; i++) {
-                PrintServiceInfo installedService = mInstalledServices.get(i);
-                String installedServicePrefix = prefix + tab + tab;
-                pw.append(installedServicePrefix).append("service:").println();
-                ResolveInfo resolveInfo = installedService.getResolveInfo();
-                ComponentName componentName = new ComponentName(
-                        resolveInfo.serviceInfo.packageName,
-                        resolveInfo.serviceInfo.name);
-                pw.append(installedServicePrefix).append(tab).append("componentName=")
-                        .append(componentName.flattenToString()).println();
-                pw.append(installedServicePrefix).append(tab).append("settingsActivity=")
-                        .append(installedService.getSettingsActivityName()).println();
-                pw.append(installedServicePrefix).append(tab).append("addPrintersActivity=")
-                        .append(installedService.getAddPrintersActivityName()).println();
-                pw.append(installedServicePrefix).append(tab).append("avancedOptionsActivity=")
-                        .append(installedService.getAdvancedOptionsActivityName()).println();
-            }
-
-            pw.append(prefix).append(tab).append("disabled services:").println();
-            for (ComponentName disabledService : mDisabledServices) {
-                String disabledServicePrefix = prefix + tab + tab;
-                pw.append(disabledServicePrefix).append("service:").println();
-                pw.append(disabledServicePrefix).append(tab).append("componentName=")
-                        .append(disabledService.flattenToString());
-                pw.println();
-            }
-
-            pw.append(prefix).append(tab).append("active services:").println();
-            final int activeServiceCount = mActiveServices.size();
-            for (int i = 0; i < activeServiceCount; i++) {
-                RemotePrintService activeService = mActiveServices.valueAt(i);
-                activeService.dump(pw, prefix + tab + tab);
-                pw.println();
-            }
-
-            pw.append(prefix).append(tab).append("cached print jobs:").println();
-            mPrintJobForAppCache.dumpLocked(pw, prefix + tab + tab);
-
-            pw.append(prefix).append(tab).append("discovery mediator:").println();
-            if (mPrinterDiscoverySession != null) {
-                mPrinterDiscoverySession.dumpLocked(pw, prefix + tab + tab);
-            }
-        }
-
-        pw.append(prefix).append(tab).append("print spooler:").println();
-        mSpooler.dump(fd, pw, prefix + tab + tab);
-        pw.println();
+        long token = dumpStream.start("print_spooler_state",
+                PrintUserStateProto.PRINT_SPOOLER_STATE);
+        mSpooler.dump(dumpStream);
+        dumpStream.end(token);
     }
 
     private void readConfigurationLocked() {
@@ -1650,15 +1599,17 @@
             }
         }
 
-        public void dumpLocked(@NonNull ProtoOutputStream proto) {
-            proto.write(PrinterDiscoverySessionProto.IS_DESTROYED, mDestroyed);
-            proto.write(PrinterDiscoverySessionProto.IS_PRINTER_DISCOVERY_IN_PROGRESS,
+        public void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
+            dumpStream.write("is_destroyed", PrinterDiscoverySessionProto.IS_DESTROYED, mDestroyed);
+            dumpStream.write("is_printer_discovery_in_progress",
+                    PrinterDiscoverySessionProto.IS_PRINTER_DISCOVERY_IN_PROGRESS,
                     !mStartedPrinterDiscoveryTokens.isEmpty());
 
             final int observerCount = mDiscoveryObservers.beginBroadcast();
             for (int i = 0; i < observerCount; i++) {
                 IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
-                proto.write(PrinterDiscoverySessionProto.PRINTER_DISCOVERY_OBSERVERS,
+                dumpStream.write("printer_discovery_observers",
+                        PrinterDiscoverySessionProto.PRINTER_DISCOVERY_OBSERVERS,
                         observer.toString());
             }
             mDiscoveryObservers.finishBroadcast();
@@ -1666,61 +1617,22 @@
             final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
             for (int i = 0; i < tokenCount; i++) {
                 IBinder token = mStartedPrinterDiscoveryTokens.get(i);
-                proto.write(PrinterDiscoverySessionProto.DISCOVERY_REQUESTS, token.toString());
+                dumpStream.write("discovery_requests",
+                        PrinterDiscoverySessionProto.DISCOVERY_REQUESTS, token.toString());
             }
 
             final int trackedPrinters = mStateTrackedPrinters.size();
             for (int i = 0; i < trackedPrinters; i++) {
                 PrinterId printer = mStateTrackedPrinters.get(i);
-                writePrinterId(proto, PrinterDiscoverySessionProto.TRACKED_PRINTER_REQUESTS,
-                        printer);
+                writePrinterId(dumpStream, "tracked_printer_requests",
+                        PrinterDiscoverySessionProto.TRACKED_PRINTER_REQUESTS, printer);
             }
 
             final int printerCount = mPrinters.size();
             for (int i = 0; i < printerCount; i++) {
                 PrinterInfo printer = mPrinters.valueAt(i);
-                writePrinterInfo(mContext, proto, PrinterDiscoverySessionProto.PRINTER, printer);
-            }
-        }
-
-        public void dumpLocked(PrintWriter pw, String prefix) {
-            pw.append(prefix).append("destroyed=")
-                    .append(String.valueOf(mDestroyed)).println();
-
-            pw.append(prefix).append("printDiscoveryInProgress=")
-                    .append(String.valueOf(!mStartedPrinterDiscoveryTokens.isEmpty())).println();
-
-            String tab = "  ";
-
-            pw.append(prefix).append(tab).append("printer discovery observers:").println();
-            final int observerCount = mDiscoveryObservers.beginBroadcast();
-            for (int i = 0; i < observerCount; i++) {
-                IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
-                pw.append(prefix).append(prefix).append(observer.toString());
-                pw.println();
-            }
-            mDiscoveryObservers.finishBroadcast();
-
-            pw.append(prefix).append(tab).append("start discovery requests:").println();
-            final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
-            for (int i = 0; i < tokenCount; i++) {
-                IBinder token = mStartedPrinterDiscoveryTokens.get(i);
-                pw.append(prefix).append(tab).append(tab).append(token.toString()).println();
-            }
-
-            pw.append(prefix).append(tab).append("tracked printer requests:").println();
-            final int trackedPrinters = mStateTrackedPrinters.size();
-            for (int i = 0; i < trackedPrinters; i++) {
-                PrinterId printer = mStateTrackedPrinters.get(i);
-                pw.append(prefix).append(tab).append(tab).append(printer.toString()).println();
-            }
-
-            pw.append(prefix).append(tab).append("printers:").println();
-            final int pritnerCount = mPrinters.size();
-            for (int i = 0; i < pritnerCount; i++) {
-                PrinterInfo printer = mPrinters.valueAt(i);
-                pw.append(prefix).append(tab).append(tab).append(
-                        printer.toString()).println();
+                writePrinterInfo(mContext, dumpStream, "printer",
+                        PrinterDiscoverySessionProto.PRINTER, printer);
             }
         }
 
@@ -1933,36 +1845,22 @@
             }
         }
 
-        public void dumpLocked(PrintWriter pw, String prefix) {
-            String tab = "  ";
-            final int bucketCount = mPrintJobsForRunningApp.size();
-            for (int i = 0; i < bucketCount; i++) {
-                final int appId = mPrintJobsForRunningApp.keyAt(i);
-                pw.append(prefix).append("appId=" + appId).append(':').println();
-                List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
-                final int printJobCount = bucket.size();
-                for (int j = 0; j < printJobCount; j++) {
-                    PrintJobInfo printJob = bucket.get(j);
-                    pw.append(prefix).append(tab).append(printJob.toString()).println();
-                }
-            }
-        }
-
-        public void dumpLocked(@NonNull ProtoOutputStream proto) {
+        public void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
             final int bucketCount = mPrintJobsForRunningApp.size();
             for (int i = 0; i < bucketCount; i++) {
                 final int appId = mPrintJobsForRunningApp.keyAt(i);
                 List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
                 final int printJobCount = bucket.size();
                 for (int j = 0; j < printJobCount; j++) {
-                    long token = proto.start(PrintUserStateProto.CACHED_PRINT_JOBS);
+                    long token = dumpStream.start("cached_print_jobs",
+                            PrintUserStateProto.CACHED_PRINT_JOBS);
 
-                    proto.write(CachedPrintJobProto.APP_ID, appId);
+                    dumpStream.write("app_id", CachedPrintJobProto.APP_ID, appId);
 
-                    writePrintJobInfo(mContext, proto, CachedPrintJobProto.PRINT_JOB,
-                            bucket.get(j));
+                    writePrintJobInfo(mContext, dumpStream, "print_job",
+                            CachedPrintJobProto.PRINT_JOB, bucket.get(j));
 
-                    proto.end(token);
+                    dumpStream.end(token);
                 }
             }
         }
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
similarity index 66%
rename from services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java
rename to services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index dc0a4e3..e072800 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -21,9 +21,7 @@
 import static com.android.server.backup.testing.TransportData.localTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;
-
 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.eq;
@@ -39,19 +37,21 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.Intent;
 import android.os.HandlerThread;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-
 import com.android.server.backup.testing.ShadowAppBackupUtils;
 import com.android.server.backup.testing.ShadowBackupPolicyEnforcer;
 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.TransportNotRegisteredException;
 import com.android.server.testing.FrameworkRobolectricTestRunner;
 import com.android.server.testing.SystemLoaderClasses;
-
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -63,13 +63,10 @@
 import org.robolectric.shadows.ShadowContextWrapper;
 import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowSettings;
 import org.robolectric.shadows.ShadowSystemClock;
 
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
     manifest = Config.NONE,
@@ -78,7 +75,7 @@
 )
 @SystemLoaderClasses({RefactoredBackupManagerService.class, TransportManager.class})
 @Presubmit
-public class BackupManagerServiceRoboTest {
+public class BackupManagerServiceTest {
     private static final String TAG = "BMSTest";
 
     @Mock private TransportManager mTransportManager;
@@ -255,17 +252,22 @@
 
     /* Tests for select transport */
 
-    private TransportData mNewTransport;
-    private TransportData mOldTransport;
     private ComponentName mNewTransportComponent;
+    private TransportData mNewTransport;
+    private TransportMock mNewTransportMock;
     private ComponentName mOldTransportComponent;
+    private TransportData mOldTransport;
+    private TransportMock mOldTransportMock;
 
     private void setUpForSelectTransport() throws Exception {
         mNewTransport = backupTransport();
         mNewTransportComponent = mNewTransport.getTransportComponent();
         mOldTransport = d2dTransport();
         mOldTransportComponent = mOldTransport.getTransportComponent();
-        setUpTransports(mTransportManager, mNewTransport, mOldTransport, localTransport());
+        List<TransportMock> transportMocks =
+                setUpTransports(mTransportManager, mNewTransport, mOldTransport, localTransport());
+        mNewTransportMock = transportMocks.get(0);
+        mOldTransportMock = transportMocks.get(1);
         when(mTransportManager.selectTransport(eq(mNewTransport.transportName)))
                 .thenReturn(mOldTransport.transportName);
     }
@@ -282,6 +284,8 @@
 
         assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
         assertThat(oldTransport).isEqualTo(mOldTransport.transportName);
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any());
     }
 
     @Test
@@ -311,6 +315,8 @@
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
         verify(callback).onSuccess(eq(mNewTransport.transportName));
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any());
     }
 
     @Test
@@ -329,11 +335,12 @@
         mShadowBackupLooper.runToEndOfTasks();
         assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
         verify(callback).onSuccess(eq(mNewTransport.transportName));
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any());
     }
 
     @Test
-    public void testSelectBackupTransportAsync_whenOtherThanMandatoryTransport()
-            throws Exception {
+    public void testSelectBackupTransportAsync_whenOtherThanMandatoryTransport() throws Exception {
         setUpForSelectTransport();
         ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mOldTransportComponent);
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
@@ -405,6 +412,220 @@
                 mContext.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
     }
 
+    /* Tests for updating transport attributes */
+
+    private static final int PACKAGE_UID = 10;
+    private ComponentName mTransportComponent;
+    private int mTransportUid;
+
+    private void setUpForUpdateTransportAttributes() throws Exception {
+        mTransportComponent = mTransport.getTransportComponent();
+        String transportPackage = mTransportComponent.getPackageName();
+
+        ShadowPackageManager shadowPackageManager = shadowOf(mContext.getPackageManager());
+        shadowPackageManager.addPackage(transportPackage);
+        shadowPackageManager.setPackagesForUid(PACKAGE_UID, transportPackage);
+
+        mTransportUid = mContext.getPackageManager().getPackageUid(transportPackage, 0);
+    }
+
+    @Test
+    public void
+            testUpdateTransportAttributes_whenTransportUidEqualsToCallingUid_callsThroughToTransportManager()
+                    throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        Intent configurationIntent = new Intent();
+        Intent dataManagementIntent = new Intent();
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        backupManagerService.updateTransportAttributes(
+                mTransportUid,
+                mTransportComponent,
+                mTransportName,
+                configurationIntent,
+                "currentDestinationString",
+                dataManagementIntent,
+                "dataManagementLabel");
+
+        verify(mTransportManager)
+                .updateTransportAttributes(
+                        eq(mTransportComponent),
+                        eq(mTransportName),
+                        eq(configurationIntent),
+                        eq("currentDestinationString"),
+                        eq(dataManagementIntent),
+                        eq("dataManagementLabel"));
+    }
+
+    @Test
+    public void testUpdateTransportAttributes_whenTransportUidNotEqualToCallingUid_throwsException()
+            throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                SecurityException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid + 1,
+                                mTransportComponent,
+                                mTransportName,
+                                new Intent(),
+                                "currentDestinationString",
+                                new Intent(),
+                                "dataManagementLabel"));
+    }
+
+    @Test
+    public void testUpdateTransportAttributes_whenTransportComponentNull_throwsException()
+            throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                RuntimeException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid,
+                                null,
+                                mTransportName,
+                                new Intent(),
+                                "currentDestinationString",
+                                new Intent(),
+                                "dataManagementLabel"));
+    }
+
+    @Test
+    public void testUpdateTransportAttributes_whenNameNull_throwsException() throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                RuntimeException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid,
+                                mTransportComponent,
+                                null,
+                                new Intent(),
+                                "currentDestinationString",
+                                new Intent(),
+                                "dataManagementLabel"));
+    }
+
+    @Test
+    public void testUpdateTransportAttributes_whenCurrentDestinationStringNull_throwsException()
+            throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                RuntimeException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid,
+                                mTransportComponent,
+                                mTransportName,
+                                new Intent(),
+                                null,
+                                new Intent(),
+                                "dataManagementLabel"));
+    }
+
+    @Test
+    public void
+            testUpdateTransportAttributes_whenDataManagementArgumentsNullityDontMatch_throwsException()
+                    throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                RuntimeException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid,
+                                mTransportComponent,
+                                mTransportName,
+                                new Intent(),
+                                "currentDestinationString",
+                                null,
+                                "dataManagementLabel"));
+
+        expectThrows(
+                RuntimeException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid,
+                                mTransportComponent,
+                                mTransportName,
+                                new Intent(),
+                                "currentDestinationString",
+                                new Intent(),
+                                null));
+    }
+
+    @Test
+    public void testUpdateTransportAttributes_whenPermissionGranted_callsThroughToTransportManager()
+            throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        Intent configurationIntent = new Intent();
+        Intent dataManagementIntent = new Intent();
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        backupManagerService.updateTransportAttributes(
+                mTransportUid,
+                mTransportComponent,
+                mTransportName,
+                configurationIntent,
+                "currentDestinationString",
+                dataManagementIntent,
+                "dataManagementLabel");
+
+        verify(mTransportManager)
+                .updateTransportAttributes(
+                        eq(mTransportComponent),
+                        eq(mTransportName),
+                        eq(configurationIntent),
+                        eq("currentDestinationString"),
+                        eq(dataManagementIntent),
+                        eq("dataManagementLabel"));
+    }
+
+    @Test
+    public void testUpdateTransportAttributes_whenPermissionDenied_throwsSecurityException()
+            throws Exception {
+        setUpForUpdateTransportAttributes();
+        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                SecurityException.class,
+                () ->
+                        backupManagerService.updateTransportAttributes(
+                                mTransportUid,
+                                mTransportComponent,
+                                mTransportName,
+                                new Intent(),
+                                "currentDestinationString",
+                                new Intent(),
+                                "dataManagementLabel"));
+    }
+
     /* Miscellaneous tests */
 
     @Test
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index cf0bc23..6753d735 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -19,9 +19,13 @@
 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.eq;
 import static org.mockito.Mockito.never;
@@ -31,23 +35,15 @@
 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;
 import android.content.Context;
 import android.content.Intent;
 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.testing.shadows.FrameworkShadowPackageManager;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.OnTransportRegisteredListener;
@@ -57,7 +53,12 @@
 import com.android.server.testing.FrameworkRobolectricTestRunner;
 import com.android.server.testing.SystemLoaderClasses;
 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;
@@ -68,12 +69,6 @@
 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,
@@ -308,6 +303,43 @@
     }
 
     @Test
+    public void testRegisterAndSelectTransport_whenTransportRegistered() throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpTransports(mTransportA1);
+        TransportManager transportManager = createTransportManager(null, mTransportA1);
+        transportManager.registerTransports();
+        ComponentName transportComponent = mTransportA1.getTransportComponent();
+
+        int result = transportManager.registerAndSelectTransport(transportComponent);
+
+        assertThat(result).isEqualTo(BackupManager.SUCCESS);
+        assertThat(transportManager.getRegisteredTransportComponents())
+                .asList()
+                .contains(transportComponent);
+        assertThat(transportManager.getCurrentTransportName())
+                .isEqualTo(mTransportA1.transportName);
+    }
+
+    @Test
+    public void testRegisterAndSelectTransport_whenTransportNotRegistered() throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpTransports(mTransportA1);
+        TransportManager transportManager = createTransportManager(null, mTransportA1);
+        ComponentName transportComponent = mTransportA1.getTransportComponent();
+
+        int result = transportManager.registerAndSelectTransport(transportComponent);
+
+        assertThat(result).isEqualTo(BackupManager.SUCCESS);
+        assertThat(transportManager.getRegisteredTransportComponents())
+                .asList()
+                .contains(transportComponent);
+        assertThat(transportManager.getTransportDirName(mTransportA1.transportName))
+                .isEqualTo(mTransportA1.transportDirName);
+        assertThat(transportManager.getCurrentTransportName())
+                .isEqualTo(mTransportA1.transportName);
+    }
+
+    @Test
     public void testGetCurrentTransportName_whenSelectTransportNotCalled_returnsDefaultTransport()
             throws Exception {
         setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index 9b4dec6..10442b7 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -35,8 +35,10 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import com.android.internal.backup.IBackupTransport;
+import com.android.server.EventLogTags;
 import com.android.server.backup.TransportManager;
 import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.ShadowEventLog;
 import com.android.server.testing.SystemLoaderClasses;
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +50,7 @@
 import org.robolectric.shadows.ShadowLooper;
 
 @RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
+@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowEventLog.class})
 @SystemLoaderClasses({TransportManager.class, TransportClient.class})
 @Presubmit
 public class TransportClientTest {
@@ -60,6 +62,7 @@
     @Mock private IBackupTransport.Stub mIBackupTransport;
     private TransportClient mTransportClient;
     private ComponentName mTransportComponent;
+    private String mTransportString;
     private Intent mBindIntent;
     private ShadowLooper mShadowLooper;
 
@@ -71,6 +74,7 @@
         mShadowLooper = shadowOf(mainLooper);
         mTransportComponent =
                 new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".transport.Transport");
+        mTransportString = mTransportComponent.flattenToShortString();
         mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
         mTransportClient =
                 new TransportClient(
@@ -161,7 +165,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesntBind_releasesConnection() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() throws Exception {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -234,6 +238,82 @@
                 .onTransportConnectionResult(isNull(), eq(mTransportClient));
     }
 
+    @Test
+    public void testConnectAsync_beforeFrameworkCall_logsBoundTransition() {
+        ShadowEventLog.clearEvents();
+
+        mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
+    }
+
+    @Test
+    public void testConnectAsync_afterOnServiceConnected_logsBoundAndConnectedTransitions() {
+        ShadowEventLog.clearEvents();
+
+        mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
+        ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
+        connection.onServiceConnected(mTransportComponent, mIBackupTransport);
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 1);
+    }
+
+    @Test
+    public void testConnectAsync_afterOnBindingDied_logsBoundAndUnboundTransitions() {
+        ShadowEventLog.clearEvents();
+
+        mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
+        ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
+        connection.onBindingDied(mTransportComponent);
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
+    }
+
+    @Test
+    public void testUnbind_whenConnected_logsDisconnectedAndUnboundTransitions() {
+        mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
+        ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
+        connection.onServiceConnected(mTransportComponent, mIBackupTransport);
+        ShadowEventLog.clearEvents();
+
+        mTransportClient.unbind("caller1");
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
+    }
+
+    @Test
+    public void testOnServiceDisconnected_whenConnected_logsDisconnectedAndUnboundTransitions() {
+        mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
+        ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
+        connection.onServiceConnected(mTransportComponent, mIBackupTransport);
+        ShadowEventLog.clearEvents();
+
+        connection.onServiceDisconnected(mTransportComponent);
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
+    }
+
+    @Test
+    public void testOnBindingDied_whenConnected_logsDisconnectedAndUnboundTransitions() {
+        mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
+        ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
+        connection.onServiceConnected(mTransportComponent, mIBackupTransport);
+        ShadowEventLog.clearEvents();
+
+        connection.onBindingDied(mTransportComponent);
+
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
+        assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
+    }
+
+    private void assertEventLogged(int tag, Object... values) {
+        assertThat(ShadowEventLog.hasEvent(tag, values)).isTrue();
+    }
+
     private ServiceConnection verifyBindServiceAsUserAndCaptureServiceConnection(Context context) {
         ArgumentCaptor<ServiceConnection> connectionCaptor =
                 ArgumentCaptor.forClass(ServiceConnection.class);
diff --git a/services/robotests/src/com/android/server/testing/ShadowEventLog.java b/services/robotests/src/com/android/server/testing/ShadowEventLog.java
new file mode 100644
index 0000000..b8059f4
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/ShadowEventLog.java
@@ -0,0 +1,71 @@
+/*
+ * 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.testing;
+
+import android.util.EventLog;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+@Implements(EventLog.class)
+public class ShadowEventLog {
+    private final static LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
+
+    @Implementation
+    public static int writeEvent(int tag, Object... values) {
+        ENTRIES.add(new Entry(tag, Arrays.asList(values)));
+        // Currently we don't care about the return value, if we do, estimate it correctly
+        return 0;
+    }
+
+    public static boolean hasEvent(int tag, Object... values) {
+        return ENTRIES.contains(new Entry(tag, Arrays.asList(values)));
+    }
+
+    public static void clearEvents() {
+        ENTRIES.clear();
+    }
+
+    public static class Entry {
+        public final int tag;
+        public final List<Object> values;
+
+        public Entry(int tag, List<Object> values) {
+            this.tag = tag;
+            this.values = values;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Entry entry = (Entry) o;
+            return tag == entry.tag && values.equals(entry.values);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = tag;
+            result = 31 * result + values.hashCode();
+            return result;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
deleted file mode 100644
index 7b4441a..0000000
--- a/services/tests/servicestests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ /dev/null
@@ -1,325 +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;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.testng.Assert.expectThrows;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.os.HandlerThread;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
-
-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 java.io.File;
-
-@SmallTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-// TODO: Migrate this to Robolectric and merge with BackupManagerServiceRoboTest (and remove 'Robo')
-public class BackupManagerServiceTest {
-    private static final String TAG = "BMSTest";
-    private static final ComponentName TRANSPORT_COMPONENT =
-            new ComponentName(
-                    "com.google.android.gms",
-                    "com.google.android.gms.backup.BackupTransportService");
-    private static final String TRANSPORT_NAME = TRANSPORT_COMPONENT.flattenToShortString();
-
-    @Mock private TransportManager mTransportManager;
-    private Context mContext;
-    private HandlerThread mBackupThread;
-    private int mPackageUid;
-    private File mBaseStateDir;
-    private File mDataDir;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        Context baseContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        mContext = spy(new ContextWrapper(baseContext));
-
-        mBackupThread = new HandlerThread("backup-test");
-        mBackupThread.setUncaughtExceptionHandler(
-                (t, e) -> Log.e(TAG, "Uncaught exception in test thread " + t.getName(), e));
-        mBackupThread.start();
-
-        File cacheDir = mContext.getCacheDir();
-        mBaseStateDir = new File(cacheDir, "base_state_dir");
-        mDataDir = new File(cacheDir, "data_dir");
-
-        mPackageUid =
-                mContext.getPackageManager().getPackageUid(TRANSPORT_COMPONENT.getPackageName(), 0);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mBackupThread.quit();
-        mBaseStateDir.delete();
-        mDataDir.delete();
-    }
-
-    @Test
-    public void testConstructor_callsTransportManagerSetTransportBoundListener() throws Exception {
-        createBackupManagerService();
-
-        verify(mTransportManager)
-                .setOnTransportRegisteredListener(any());
-    }
-
-    @Test
-    public void
-            testUpdateTransportAttributes_whenTransportUidEqualsToCallingUid_callsThroughToTransportManager()
-                    throws Exception {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-        Intent configurationIntent = new Intent();
-        Intent dataManagementIntent = new Intent();
-
-        backupManagerService.updateTransportAttributes(
-                mPackageUid,
-                TRANSPORT_COMPONENT,
-                TRANSPORT_NAME,
-                configurationIntent,
-                "currentDestinationString",
-                dataManagementIntent,
-                "dataManagementLabel");
-
-        verify(mTransportManager)
-                .updateTransportAttributes(
-                        eq(TRANSPORT_COMPONENT),
-                        eq(TRANSPORT_NAME),
-                        eq(configurationIntent),
-                        eq("currentDestinationString"),
-                        eq(dataManagementIntent),
-                        eq("dataManagementLabel"));
-    }
-
-    @Test
-    public void testUpdateTransportAttributes_whenTransportUidNotEqualToCallingUid_throwsException()
-            throws Exception {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-
-        expectThrows(
-                SecurityException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid + 1,
-                                TRANSPORT_COMPONENT,
-                                TRANSPORT_NAME,
-                                new Intent(),
-                                "currentDestinationString",
-                                new Intent(),
-                                "dataManagementLabel"));
-    }
-
-    @Test
-    public void testUpdateTransportAttributes_whenTransportComponentNull_throwsException() {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-
-        expectThrows(
-                RuntimeException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid,
-                                null,
-                                TRANSPORT_NAME,
-                                new Intent(),
-                                "currentDestinationString",
-                                new Intent(),
-                                "dataManagementLabel"));
-    }
-
-    @Test
-    public void testUpdateTransportAttributes_whenNameNull_throwsException() {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-
-        expectThrows(
-                RuntimeException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid,
-                                TRANSPORT_COMPONENT,
-                                null,
-                                new Intent(),
-                                "currentDestinationString",
-                                new Intent(),
-                                "dataManagementLabel"));
-    }
-
-    @Test
-    public void testUpdateTransportAttributes_whenCurrentDestinationStringNull_throwsException() {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-
-        expectThrows(
-                RuntimeException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid,
-                                TRANSPORT_COMPONENT,
-                                TRANSPORT_NAME,
-                                new Intent(),
-                                null,
-                                new Intent(),
-                                "dataManagementLabel"));
-    }
-
-    @Test
-    public void
-            testUpdateTransportAttributes_whenDataManagementArgumentsNullityDontMatch_throwsException() {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-
-        expectThrows(
-                RuntimeException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid,
-                                TRANSPORT_COMPONENT,
-                                TRANSPORT_NAME,
-                                new Intent(),
-                                "currentDestinationString",
-                                null,
-                                "dataManagementLabel"));
-
-        expectThrows(
-                RuntimeException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid,
-                                TRANSPORT_COMPONENT,
-                                TRANSPORT_NAME,
-                                new Intent(),
-                                "currentDestinationString",
-                                new Intent(),
-                                null));
-    }
-
-    @Test
-    public void
-            testUpdateTransportAttributes_whenDataManagementArgumentsNull_callsThroughToTransportManager() {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-        Intent configurationIntent = new Intent();
-
-        backupManagerService.updateTransportAttributes(
-                mPackageUid,
-                TRANSPORT_COMPONENT,
-                TRANSPORT_NAME,
-                configurationIntent,
-                "currentDestinationString",
-                null,
-                null);
-
-        verify(mTransportManager)
-                .updateTransportAttributes(
-                        eq(TRANSPORT_COMPONENT),
-                        eq(TRANSPORT_NAME),
-                        eq(configurationIntent),
-                        eq("currentDestinationString"),
-                        eq(null),
-                        eq(null));
-    }
-
-    @Test
-    public void
-            testUpdateTransportAttributes_whenPermissionGranted_callsThroughToTransportManager() {
-        grantBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-        Intent configurationIntent = new Intent();
-        Intent dataManagementIntent = new Intent();
-
-        backupManagerService.updateTransportAttributes(
-                mPackageUid,
-                TRANSPORT_COMPONENT,
-                TRANSPORT_NAME,
-                configurationIntent,
-                "currentDestinationString",
-                dataManagementIntent,
-                "dataManagementLabel");
-
-        verify(mTransportManager)
-                .updateTransportAttributes(
-                        eq(TRANSPORT_COMPONENT),
-                        eq(TRANSPORT_NAME),
-                        eq(configurationIntent),
-                        eq("currentDestinationString"),
-                        eq(dataManagementIntent),
-                        eq("dataManagementLabel"));
-    }
-
-    @Test
-    public void testUpdateTransportAttributes_whenPermissionDenied_throwsSecurityException() {
-        denyBackupPermission();
-        RefactoredBackupManagerService backupManagerService = createBackupManagerService();
-
-        expectThrows(
-                SecurityException.class,
-                () ->
-                        backupManagerService.updateTransportAttributes(
-                                mPackageUid,
-                                TRANSPORT_COMPONENT,
-                                TRANSPORT_NAME,
-                                new Intent(),
-                                "currentDestinationString",
-                                new Intent(),
-                                "dataManagementLabel"));
-    }
-
-    private RefactoredBackupManagerService createBackupManagerService() {
-        return new RefactoredBackupManagerService(
-                mContext,
-                new Trampoline(mContext),
-                mBackupThread,
-                mBaseStateDir,
-                mDataDir,
-                mTransportManager);
-    }
-
-    private void grantBackupPermission() {
-        doNothing().when(mContext).enforceCallingOrSelfPermission(any(), anyString());
-    }
-
-    private void denyBackupPermission() {
-        doThrow(new SecurityException())
-                .when(mContext)
-                .enforceCallingOrSelfPermission(
-                        eq(android.Manifest.permission.BACKUP), anyString());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index 0cc37b4..c5f8c90 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -58,8 +58,11 @@
         String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                 + "<display-manager-state>\n"
                 + "  <brightness-configurations>\n"
-                + "    <brightness-configuration user-serial=\"1\">\n"
-                + "      <brightness-curve>\n"
+                + "    <brightness-configuration"
+                + "         user-serial=\"1\""
+                + "         package-name=\"example.com\""
+                + "         timestamp=\"123456\">\n"
+                + "      <brightness-curve description=\"something\">\n"
                 + "        <brightness-point lux=\"0\" nits=\"13.25\"/>\n"
                 + "        <brightness-point lux=\"25\" nits=\"35.94\"/>\n"
                 + "      </brightness-curve>\n"
@@ -81,6 +84,7 @@
         float[] expectedNits = { 13.25f, 35.94f };
         assertArrayEquals(expectedLux, curve.first, "lux");
         assertArrayEquals(expectedNits, curve.second, "nits");
+        assertEquals("something", config.getDescription());
 
         config = mDataStore.getBrightnessConfiguration(3 /*userSerial*/);
         curve = config.getCurve();
@@ -88,6 +92,7 @@
         expectedNits = new float[] { 13.25f, 15f };
         assertArrayEquals(expectedLux, curve.first, "lux");
         assertArrayEquals(expectedNits, curve.second, "nits");
+        assertNull(config.getDescription());
     }
 
     @Test
@@ -144,12 +149,12 @@
     public void testStoreAndReloadOfBrightnessConfigurations() {
         final float[] lux = { 0f, 10f };
         final float[] nits = {1f, 100f };
-        final BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        final BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
+                .setDescription("a description")
                 .build();
         mDataStore.loadIfNeeded();
         assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
-        mDataStore.setBrightnessConfigurationForUser(config, 0);
+        mDataStore.setBrightnessConfigurationForUser(config, 0, "packagename");
 
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         mInjector.setWriteStream(baos);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index ccf2aaf..272b5d8 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -27,6 +27,7 @@
 import android.app.IActivityManager;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.app.trust.TrustManager;
 import android.content.ComponentName;
 import android.content.pm.UserInfo;
@@ -41,6 +42,7 @@
 
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.server.LocalServices;
 
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -75,6 +77,7 @@
     FakeStorageManager mStorageManager;
     IActivityManager mActivityManager;
     DevicePolicyManager mDevicePolicyManager;
+    DevicePolicyManagerInternal mDevicePolicyManagerInternal;
     KeyStore mKeyStore;
     MockSyntheticPasswordManager mSpManager;
 
@@ -88,6 +91,10 @@
         mStorageManager = new FakeStorageManager();
         mActivityManager = mock(IActivityManager.class);
         mDevicePolicyManager = mock(DevicePolicyManager.class);
+        mDevicePolicyManagerInternal = mock(DevicePolicyManagerInternal.class);
+
+        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+        LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal);
 
         mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
                 mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
new file mode 100644
index 0000000..4ad9f19
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
@@ -0,0 +1,116 @@
+/*
+ * 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.locksettings;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.os.RemoteException;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.VerifyCredentialResponse;
+import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
+
+/**
+ * Run the synthetic password tests with caching enabled.
+ *
+ * By default, those tests run without caching. Untrusted credential reset depends on caching so
+ * this class included those tests.
+ */
+public class CachedSyntheticPasswordTests extends SyntheticPasswordTests {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        enableSpCaching(true);
+    }
+
+    private void enableSpCaching(boolean enable) {
+        when(mDevicePolicyManagerInternal
+                .canUserHaveUntrustedCredentialReset(anyInt())).thenReturn(enable);
+    }
+
+    public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
+        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
+        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
+
+        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
+        // clear password
+        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
+                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+        assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+
+        // set a new password
+        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                    .getResponseCode());
+        assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+    }
+
+    public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
+        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
+        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
+
+        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
+        // Untrusted change password
+        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+        assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+
+        // Verify the password
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                    .getResponseCode());
+    }
+
+    public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
+        final String PASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-password";
+        final String NEWPASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword";
+
+        // Disable caching for this test
+        enableSpCaching(false);
+
+        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
+        // Untrusted change password
+        assertExpectException(IllegalStateException.class, /* messageRegex= */ null,
+                () -> mService.setLockCredential(
+                        NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+                        null, PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID));
+        assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
+
+        // Verify the new password doesn't work but the old one still does
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
+                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                        .getResponseCode());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                        .getResponseCode());
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 2e4c74f..b07d6ac 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -112,7 +112,7 @@
                 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
-    private void initializeCredentialUnderSP(String password, int userId) throws RemoteException {
+    protected void initializeCredentialUnderSP(String password, int userId) throws RemoteException {
         enableSyntheticPassword();
         int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC
                 : PASSWORD_QUALITY_UNSPECIFIED;
@@ -129,7 +129,6 @@
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
-        mGateKeeperService.clearSecureUserId(PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                 NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                         .getResponseCode());
@@ -170,44 +169,6 @@
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
-    public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
-        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
-
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
-        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        // clear password
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
-        assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
-        // set a new password
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
-        assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-    }
-
-    public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
-        final String PASSWORD = "testSyntheticPasswordClearCredential-password";
-        final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword";
-
-        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
-        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        // Untrusted change password
-        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
-        assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-        assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
-        // Verify the password
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
-    }
-
     public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
         final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd";
         disableSyntheticPassword();
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 9eb42e9..7eec4fe 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
@@ -16,11 +16,11 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_PASSWORD;
-import static android.security.keystore.RecoveryMetadata.TYPE_PATTERN;
-import static android.security.keystore.RecoveryMetadata.TYPE_PIN;
+import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD;
+import static android.security.keystore.KeychainProtectionParams.TYPE_PATTERN;
+import static android.security.keystore.KeychainProtectionParams.TYPE_PIN;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
@@ -41,8 +41,8 @@
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.WrappedApplicationKey;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -77,8 +77,8 @@
     private static final int TEST_USER_ID = 1000;
     private static final int TEST_RECOVERY_AGENT_UID = 10009;
     private static final int TEST_RECOVERY_AGENT_UID2 = 10010;
-    private static final byte[] TEST_DEVICE_ID =
-            new byte[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2};
+    private static final byte[] TEST_VAULT_HANDLE =
+            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
     private static final String TEST_APP_KEY_ALIAS = "rcleaver";
     private static final int TEST_GENERATION_ID = 2;
     private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PASSWORD;
@@ -241,7 +241,7 @@
     public void run_doesNotSendAnythingIfNoRecoveryAgentPendingIntentRegistered() throws Exception {
         SecretKey applicationKey = generateKey();
         mRecoverableKeyStoreDb.setServerParams(
-                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_DEVICE_ID);
+                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
         mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
         mRecoverableKeyStoreDb.insertKey(
                 TEST_USER_ID,
@@ -278,14 +278,18 @@
     public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception {
         mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                 TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+
+        mRecoverableKeyStoreDb.setServerParams(
+                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
         when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
         SecretKey applicationKey =
                 addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
         KeyDerivationParams KeyDerivationParams =
-                recoveryData.getRecoveryMetadata().get(0).getKeyDerivationParams();
+                keychainSnapshot.getKeychainProtectionParams().get(0).getKeyDerivationParams();
         assertThat(KeyDerivationParams.getAlgorithm()).isEqualTo(
                 KeyDerivationParams.ALGORITHM_SHA256);
         verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
@@ -293,18 +297,24 @@
                 KeyDerivationParams.getSalt(),
                 TEST_CREDENTIAL);
         Long counterId = mRecoverableKeyStoreDb.getCounterId(TEST_USER_ID, TEST_RECOVERY_AGENT_UID);
+        counterId = 1L; // TODO: use value from the database.
         assertThat(counterId).isNotNull();
         byte[] recoveryKey = decryptThmEncryptedKey(
                 lockScreenHash,
-                recoveryData.getEncryptedRecoveryKeyBlob(),
+                keychainSnapshot.getEncryptedRecoveryKeyBlob(),
                 /*vaultParams=*/ KeySyncUtils.packVaultParams(
                         mKeyPair.getPublic(),
                         counterId,
-                        TEST_DEVICE_ID,
-                        /*maxAttempts=*/ 10));
-        List<EntryRecoveryData> applicationKeys = recoveryData.getEntryRecoveryData();
+                        /*maxAttempts=*/ 10,
+                        TEST_VAULT_HANDLE));
+        List<WrappedApplicationKey> applicationKeys = keychainSnapshot.getWrappedApplicationKeys();
         assertThat(applicationKeys).hasSize(1);
-        EntryRecoveryData keyData = applicationKeys.get(0);
+        assertThat(keychainSnapshot.getCounterId()).isEqualTo(counterId);
+        assertThat(keychainSnapshot.getMaxAttempts()).isEqualTo(10);
+        assertThat(keychainSnapshot.getTrustedHardwarePublicKey())
+                .isEqualTo(SecureBox.encodePublicKey(mKeyPair.getPublic()));
+        assertThat(keychainSnapshot.getServerParams()).isEqualTo(TEST_VAULT_HANDLE);
+        WrappedApplicationKey keyData = applicationKeys.get(0);
         assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
         assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
         byte[] appKey = KeySyncUtils.decryptApplicationKey(
@@ -322,14 +332,14 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getSnapshotVersion()).isEqualTo(1); // default value;
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value;
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, true);
 
         mKeySyncTask.run();
 
-        recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getSnapshotVersion()).isEqualTo(2); // Updated
+        keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getSnapshotVersion()).isEqualTo(2); // Updated
     }
 
     @Test
@@ -352,9 +362,9 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
-        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
+        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
                 isEqualTo(TYPE_PASSWORD);
     }
 
@@ -378,10 +388,10 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
         // Password with only digits is changed to pin.
-        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
+        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
                 isEqualTo(TYPE_PIN);
     }
 
@@ -405,9 +415,9 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
-        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
+        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
                 isEqualTo(TYPE_PATTERN);
     }
 
@@ -471,7 +481,7 @@
             throws Exception{
         SecretKey applicationKey = generateKey();
         mRecoverableKeyStoreDb.setServerParams(
-                userId, recoveryAgentUid, TEST_DEVICE_ID);
+                userId, recoveryAgentUid, TEST_VAULT_HANDLE);
         mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, TEST_GENERATION_ID);
 
         // Newly added key is not synced.
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
index 3a9ff85..a251c9d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
@@ -50,8 +50,8 @@
     private static final int RECOVERY_KEY_LENGTH_BITS = 256;
     private static final int THM_KF_HASH_SIZE = 256;
     private static final int KEY_CLAIMANT_LENGTH_BYTES = 16;
-    private static final byte[] TEST_DEVICE_ID =
-            new byte[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2};
+    private static final byte[] TEST_VAULT_HANDLE =
+            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
     private static final String SHA_256_ALGORITHM = "SHA-256";
     private static final String APPLICATION_KEY_ALGORITHM = "AES";
     private static final byte[] LOCK_SCREEN_HASH_1 =
@@ -63,7 +63,8 @@
     private static final byte[] RECOVERY_RESPONSE_HEADER =
             "V1 reencrypted_recovery_key".getBytes(StandardCharsets.UTF_8);
     private static final int PUBLIC_KEY_LENGTH_BYTES = 65;
-    private static final int VAULT_PARAMS_LENGTH_BYTES = 85;
+    private static final int VAULT_PARAMS_LENGTH_BYTES = 94;
+    private static final int VAULT_HANDLE_LENGTH_BYTES = 17;
 
     @Test
     public void calculateThmKfHash_isShaOfLockScreenHashWithPrefix() throws Exception {
@@ -344,14 +345,14 @@
     }
 
     @Test
-    public void packVaultParams_returns85Bytes() throws Exception {
+    public void packVaultParams_returns94Bytes() throws Exception {
         PublicKey thmPublicKey = SecureBox.genKeyPair().getPublic();
 
         byte[] packedForm = KeySyncUtils.packVaultParams(
                 thmPublicKey,
                 /*counterId=*/ 1001L,
-                TEST_DEVICE_ID,
-                /*maxAttempts=*/ 10);
+                /*maxAttempts=*/ 10,
+                TEST_VAULT_HANDLE);
 
         assertEquals(VAULT_PARAMS_LENGTH_BYTES, packedForm.length);
     }
@@ -363,8 +364,8 @@
         byte[] packedForm = KeySyncUtils.packVaultParams(
                 thmPublicKey,
                 /*counterId=*/ 1001L,
-                TEST_DEVICE_ID,
-                /*maxAttempts=*/ 10);
+                /*maxAttempts=*/ 10,
+                TEST_VAULT_HANDLE);
 
         assertArrayEquals(
                 SecureBox.encodePublicKey(thmPublicKey),
@@ -378,8 +379,8 @@
         byte[] packedForm = KeySyncUtils.packVaultParams(
                 SecureBox.genKeyPair().getPublic(),
                 counterId,
-                TEST_DEVICE_ID,
-                /*maxAttempts=*/ 10);
+                /*maxAttempts=*/ 10,
+                TEST_VAULT_HANDLE);
 
         ByteBuffer byteBuffer = ByteBuffer.wrap(packedForm)
                 .order(ByteOrder.LITTLE_ENDIAN);
@@ -388,37 +389,36 @@
     }
 
     @Test
-    public void packVaultParams_encodesDeviceIdAsThirdParam() throws Exception {
-
-        byte[] packedForm = KeySyncUtils.packVaultParams(
-                SecureBox.genKeyPair().getPublic(),
-                /*counterId=*/ 10021L,
-                TEST_DEVICE_ID,
-                /*maxAttempts=*/ 10);
-
-        ByteBuffer byteBuffer = ByteBuffer.wrap(packedForm)
-                .order(ByteOrder.LITTLE_ENDIAN);
-        byteBuffer.position(PUBLIC_KEY_LENGTH_BYTES + Long.BYTES);
-        assertEquals(/* default value*/0, byteBuffer.getLong());
-    }
-
-    @Test
-    public void packVaultParams_encodesMaxAttemptsAsLastParam() throws Exception {
+    public void packVaultParams_encodesMaxAttemptsAsThirdParam() throws Exception {
         int maxAttempts = 10;
 
         byte[] packedForm = KeySyncUtils.packVaultParams(
                 SecureBox.genKeyPair().getPublic(),
                 /*counterId=*/ 1001L,
-                TEST_DEVICE_ID,
-                maxAttempts);
+                maxAttempts,
+                TEST_VAULT_HANDLE);
 
         ByteBuffer byteBuffer = ByteBuffer.wrap(packedForm)
                 .order(ByteOrder.LITTLE_ENDIAN);
-        // TODO: update position.
-        byteBuffer.position(PUBLIC_KEY_LENGTH_BYTES + 2 * Long.BYTES);
+        byteBuffer.position(PUBLIC_KEY_LENGTH_BYTES + Long.BYTES);
         assertEquals(maxAttempts, byteBuffer.getInt());
     }
 
+    @Test
+    public void packVaultParams_encodesVaultHandleAsLastParam() throws Exception {
+        byte[] packedForm = KeySyncUtils.packVaultParams(
+                SecureBox.genKeyPair().getPublic(),
+                /*counterId=*/ 10021L,
+                /*maxAttempts=*/ 10,
+                TEST_VAULT_HANDLE);
+
+        ByteBuffer byteBuffer = ByteBuffer.wrap(packedForm)
+                .order(ByteOrder.LITTLE_ENDIAN);
+        byteBuffer.position(PUBLIC_KEY_LENGTH_BYTES + Long.BYTES + Integer.BYTES);
+        byte[] vaultHandle = new byte[VAULT_HANDLE_LENGTH_BYTES];
+        byteBuffer.get(vaultHandle);
+        assertArrayEquals(TEST_VAULT_HANDLE, vaultHandle);
+    }
 
     private static byte[] randomBytes(int n) {
         byte[] bytes = new byte[n];
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 1bdcf47..970bc33 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
@@ -16,8 +16,8 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
-import static android.security.keystore.RecoveryMetadata.TYPE_PASSWORD;
+import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.assertArrayEquals;
@@ -43,9 +43,8 @@
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryMetadata;
-import android.security.keystore.RecoveryManager;
+import android.security.keystore.KeychainProtectionParams;
+import android.security.keystore.WrappedApplicationKey;
 import android.support.test.filters.SmallTest;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -251,7 +250,7 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new RecoveryMetadata(
+                        new KeychainProtectionParams(
                                 TYPE_LOCKSCREEN,
                                 TYPE_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -270,7 +269,7 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new RecoveryMetadata(
+                        new KeychainProtectionParams(
                                 TYPE_LOCKSCREEN,
                                 TYPE_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -284,6 +283,44 @@
     }
 
     @Test
+    public void closeSession_closesASession() throws Exception {
+        mRecoverableKeyStoreManager.startRecoverySession(
+                TEST_SESSION_ID,
+                TEST_PUBLIC_KEY,
+                TEST_VAULT_PARAMS,
+                TEST_VAULT_CHALLENGE,
+                ImmutableList.of(
+                        new KeychainProtectionParams(
+                                TYPE_LOCKSCREEN,
+                                TYPE_PASSWORD,
+                                KeyDerivationParams.createSha256Params(TEST_SALT),
+                                TEST_SECRET)));
+
+        mRecoverableKeyStoreManager.closeSession(TEST_SESSION_ID);
+
+        assertEquals(0, mRecoverySessionStorage.size());
+    }
+
+    @Test
+    public void closeSession_doesNotCloseUnrelatedSessions() throws Exception {
+        mRecoverableKeyStoreManager.startRecoverySession(
+                TEST_SESSION_ID,
+                TEST_PUBLIC_KEY,
+                TEST_VAULT_PARAMS,
+                TEST_VAULT_CHALLENGE,
+                ImmutableList.of(
+                        new KeychainProtectionParams(
+                                TYPE_LOCKSCREEN,
+                                TYPE_PASSWORD,
+                                KeyDerivationParams.createSha256Params(TEST_SALT),
+                                TEST_SECRET)));
+
+        mRecoverableKeyStoreManager.closeSession("some random session");
+
+        assertEquals(1, mRecoverySessionStorage.size());
+    }
+
+    @Test
     public void startRecoverySession_throwsIfBadNumberOfSecrets() throws Exception {
         try {
             mRecoverableKeyStoreManager.startRecoverySession(
@@ -293,9 +330,9 @@
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of());
             fail("should have thrown");
-        } catch (ServiceSpecificException e) {
+        } catch (UnsupportedOperationException e) {
             assertThat(e.getMessage()).startsWith(
-                    "Only a single RecoveryMetadata is supported");
+                    "Only a single KeychainProtectionParams is supported");
         }
     }
 
@@ -308,7 +345,7 @@
                     TEST_VAULT_PARAMS,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new RecoveryMetadata(
+                            new KeychainProtectionParams(
                                     TYPE_LOCKSCREEN,
                                     TYPE_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -330,7 +367,7 @@
                     vaultParams,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new RecoveryMetadata(
+                            new KeychainProtectionParams(
                                     TYPE_LOCKSCREEN,
                                     TYPE_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -348,7 +385,7 @@
                     TEST_SESSION_ID,
                     /*recoveryKeyBlob=*/ randomBytes(32),
                     /*applicationKeys=*/ ImmutableList.of(
-                            new EntryRecoveryData("alias", randomBytes(32))
+                            new WrappedApplicationKey("alias", randomBytes(32))
                     ));
             fail("should have thrown");
         } catch (ServiceSpecificException e) {
@@ -363,7 +400,7 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new RecoveryMetadata(
+                ImmutableList.of(new KeychainProtectionParams(
                         TYPE_LOCKSCREEN,
                         TYPE_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -387,7 +424,7 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new RecoveryMetadata(
+                ImmutableList.of(new KeychainProtectionParams(
                         TYPE_LOCKSCREEN,
                         TYPE_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -397,7 +434,7 @@
         SecretKey recoveryKey = randomRecoveryKey();
         byte[] encryptedClaimResponse = encryptClaimResponse(
                 keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
-        EntryRecoveryData badApplicationKey = new EntryRecoveryData(
+        WrappedApplicationKey badApplicationKey = new WrappedApplicationKey(
                 TEST_ALIAS,
                 randomBytes(32));
 
@@ -419,7 +456,7 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new RecoveryMetadata(
+                ImmutableList.of(new KeychainProtectionParams(
                         TYPE_LOCKSCREEN,
                         TYPE_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -430,7 +467,7 @@
         byte[] encryptedClaimResponse = encryptClaimResponse(
                 keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
         byte[] applicationKeyBytes = randomBytes(32);
-        EntryRecoveryData applicationKey = new EntryRecoveryData(
+        WrappedApplicationKey applicationKey = new WrappedApplicationKey(
                 TEST_ALIAS,
                 encryptedApplicationKey(recoveryKey, applicationKeyBytes));
 
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 5cb7b67..f0254c6 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
@@ -28,8 +28,7 @@
 import org.junit.runner.RunWith;
 
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.security.keystore.RecoveryManager;
+import android.security.keystore.RecoveryController;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -283,7 +282,7 @@
 
         Map<String, Integer> statuses = mRecoverableKeyStoreDb.getStatusForAllKeys(uid);
         assertThat(statuses).hasSize(3);
-        assertThat(statuses).containsEntry(alias, RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+        assertThat(statuses).containsEntry(alias, RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS);
         assertThat(statuses).containsEntry(alias2, status);
         assertThat(statuses).containsEntry(alias3, status);
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
index 6f93fe4..bb0474e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
@@ -19,6 +19,8 @@
 import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -88,6 +90,45 @@
     }
 
     @Test
+    public void remove_deletesSpecificSession() {
+        RecoverySessionStorage storage = new RecoverySessionStorage();
+        storage.add(TEST_USER_ID, new RecoverySessionStorage.Entry(
+                TEST_SESSION_ID,
+                lskfHashFixture(),
+                keyClaimantFixture(),
+                vaultParamsFixture()));
+        storage.add(TEST_USER_ID, new RecoverySessionStorage.Entry(
+                "some other session",
+                lskfHashFixture(),
+                keyClaimantFixture(),
+                vaultParamsFixture()));
+
+        storage.remove(TEST_USER_ID, TEST_SESSION_ID);
+
+        assertNull(storage.get(TEST_USER_ID, TEST_SESSION_ID));
+    }
+
+    @Test
+    public void remove_doesNotDeleteOtherSessions() {
+        String otherSessionId = "some other session";
+        RecoverySessionStorage storage = new RecoverySessionStorage();
+        storage.add(TEST_USER_ID, new RecoverySessionStorage.Entry(
+                TEST_SESSION_ID,
+                lskfHashFixture(),
+                keyClaimantFixture(),
+                vaultParamsFixture()));
+        storage.add(TEST_USER_ID, new RecoverySessionStorage.Entry(
+                otherSessionId,
+                lskfHashFixture(),
+                keyClaimantFixture(),
+                vaultParamsFixture()));
+
+        storage.remove(TEST_USER_ID, TEST_SESSION_ID);
+
+        assertNotNull(storage.get(TEST_USER_ID, otherSessionId));
+    }
+
+    @Test
     public void destroy_overwritesLskfHashMemory() {
         RecoverySessionStorage storage = new RecoverySessionStorage();
         RecoverySessionStorage.Entry entry = new RecoverySessionStorage.Entry(
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
index 6308f74..56b44e2 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
@@ -3,7 +3,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-import android.security.keystore.RecoveryData;
+import android.security.keystore.KeychainSnapshot;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -26,25 +26,25 @@
     @Test
     public void get_returnsSetSnapshot() {
         int userId = 1000;
-        RecoveryData recoveryData = new RecoveryData(
+        KeychainSnapshot keychainSnapshot = new KeychainSnapshot(
                 /*snapshotVersion=*/ 1,
                 new ArrayList<>(),
                 new ArrayList<>(),
                 new byte[0]);
-        mRecoverySnapshotStorage.put(userId, recoveryData);
+        mRecoverySnapshotStorage.put(userId, keychainSnapshot);
 
-        assertEquals(recoveryData, mRecoverySnapshotStorage.get(userId));
+        assertEquals(keychainSnapshot, mRecoverySnapshotStorage.get(userId));
     }
 
     @Test
     public void remove_removesSnapshots() {
         int userId = 1000;
-        RecoveryData recoveryData = new RecoveryData(
+        KeychainSnapshot keychainSnapshot = new KeychainSnapshot(
                 /*snapshotVersion=*/ 1,
                 new ArrayList<>(),
                 new ArrayList<>(),
                 new byte[0]);
-        mRecoverySnapshotStorage.put(userId, recoveryData);
+        mRecoverySnapshotStorage.put(userId, keychainSnapshot);
 
         mRecoverySnapshotStorage.remove(userId);
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java
rename to services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index ff55a2b..c69437dc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -1,9 +1,7 @@
-package com.android.server.pm.crossprofile;
+package com.android.server.pm;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static junit.framework.Assert.assertEquals;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -34,7 +32,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
@@ -44,7 +41,7 @@
 
 /**
  * Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.pm.crossprofile.CrossProfileAppsServiceImplTest
+ * atest FrameworksServicesTests:com.android.server.pm.CrossProfileAppsServiceImplTest
  */
 @Presubmit
 @RunWith(MockitoJUnitRunner.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
index 77f96ca..e7e55cd 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
@@ -16,9 +16,9 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
-import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
index ac29163..57da6a3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -20,7 +20,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
@@ -28,6 +27,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.ClipData;
+import android.graphics.PixelFormat;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -36,7 +36,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.InputChannel;
-import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
 import com.android.internal.annotations.GuardedBy;
@@ -146,14 +146,6 @@
     }
 
     @Test
-    public void testPrepareDrag_ZeroSizeSurface() throws Exception {
-        final Surface surface = new Surface();
-        mToken = mTarget.prepareDrag(
-                new SurfaceSession(), 0, 0, mWindow.mClient, 0, 0, 0, surface);
-        assertNull(mToken);
-    }
-
-    @Test
     public void testPerformDrag_NullDataWithGrantUri() throws Exception {
         dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
     }
@@ -169,16 +161,24 @@
     }
 
     private void dragFlow(int flag, ClipData data, float dropX, float dropY) {
-        final Surface surface = new Surface();
-        mToken = mTarget.prepareDrag(
-                new SurfaceSession(), 0, 0, mWindow.mClient, flag, 100, 100, surface);
-        assertNotNull(mToken);
+        final SurfaceSession appSession = new SurfaceSession();
+        try {
+            final SurfaceControl surface = new SurfaceControl.Builder(appSession)
+                    .setName("drag surface")
+                    .setSize(100, 100)
+                    .setFormat(PixelFormat.TRANSLUCENT)
+                    .build();
 
-        assertTrue(sWm.mInputManager.transferTouchFocus(null, null));
-        assertTrue(mTarget.performDrag(
-                mWindow.mClient, mToken, 0, 0, 0, 0, 0, data));
+            assertTrue(sWm.mInputManager.transferTouchFocus(null, null));
+            mToken = mTarget.performDrag(
+                    new SurfaceSession(), 0, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0,
+                    data);
+            assertNotNull(mToken);
 
-        mTarget.handleMotionEvent(false, dropX, dropY);
-        mToken = mWindow.mClient.asBinder();
+            mTarget.handleMotionEvent(false, dropX, dropY);
+            mToken = mWindow.mClient.asBinder();
+        } finally {
+            appSession.kill();
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
new file mode 100644
index 0000000..897be34
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.platform.test.annotations.Postsubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+
+import com.android.server.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * atest FrameworksServicesTests:com.android.server.wm.RemoteAnimationControllerTest
+ */
+@SmallTest
+@FlakyTest(detail = "Promote to presubmit if non-flakyness is established")
+@RunWith(AndroidJUnit4.class)
+public class RemoteAnimationControllerTest extends WindowTestsBase {
+
+    @Mock SurfaceControl mMockLeash;
+    @Mock Transaction mMockTransaction;
+    @Mock OnAnimationFinishedCallback mFinishedCallback;
+    @Mock IRemoteAnimationRunner mMockRunner;
+    private RemoteAnimationAdapter mAdapter;
+    private RemoteAnimationController mController;
+    private final OffsettableClock mClock = new OffsettableClock.Stopped();
+    private TestHandler mHandler;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mAdapter = new RemoteAnimationAdapter(mMockRunner, 100, 50);
+        sWm.mH.runWithScissors(() -> {
+            mHandler = new TestHandler(null, mClock);
+        }, 0);
+        mController = new RemoteAnimationController(sWm, mAdapter, mHandler);
+    }
+
+    @Test
+    public void testRun() throws Exception {
+        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+        sWm.mOpeningApps.add(win.mAppToken);
+        try {
+            final AnimationAdapter adapter = mController.createAnimationAdapter(win.mAppToken,
+                    new Point(50, 100), new Rect(50, 100, 150, 150));
+            adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
+            mController.goodToGo();
+
+            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
+                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
+                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
+            verify(mMockRunner).onAnimationStart(appsCaptor.capture(), finishedCaptor.capture());
+            assertEquals(1, appsCaptor.getValue().length);
+            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
+            assertEquals(new Point(50, 100), app.position);
+            assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
+            assertEquals(win.mAppToken.getPrefixOrderIndex(), app.prefixOrderIndex);
+            assertEquals(win.mAppToken.getTask().mTaskId, app.taskId);
+            assertEquals(mMockLeash, app.leash);
+            assertEquals(win.mWinAnimator.mLastClipRect, app.clipRect);
+            assertEquals(false, app.isTranslucent);
+            verify(mMockTransaction).setLayer(mMockLeash, app.prefixOrderIndex);
+            verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
+            verify(mMockTransaction).setWindowCrop(mMockLeash, new Rect(0, 0, 100, 50));
+
+            finishedCaptor.getValue().onAnimationFinished();
+            verify(mFinishedCallback).onAnimationFinished(eq(adapter));
+        } finally {
+            sWm.mOpeningApps.clear();
+        }
+    }
+
+    @Test
+    public void testCancel() throws Exception {
+        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+        final AnimationAdapter adapter = mController.createAnimationAdapter(win.mAppToken,
+                new Point(50, 100), new Rect(50, 100, 150, 150));
+        adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
+        mController.goodToGo();
+
+        adapter.onAnimationCancelled(mMockLeash);
+        verify(mMockRunner).onAnimationCancelled();
+    }
+
+    @Test
+    public void testTimeout() throws Exception {
+        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+        final AnimationAdapter adapter = mController.createAnimationAdapter(win.mAppToken,
+                new Point(50, 100), new Rect(50, 100, 150, 150));
+        adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
+        mController.goodToGo();
+
+        mClock.fastForward(2500);
+        mHandler.timeAdvance();
+
+        verify(mMockRunner).onAnimationCancelled();
+        verify(mFinishedCallback).onAnimationFinished(eq(adapter));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
index 873a01b..7bf7dd7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -33,6 +33,7 @@
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -57,6 +58,9 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
+        TaskPositioner.setFactory(null);
+
         final Display display = mDisplayContent.getDisplay();
         final DisplayMetrics dm = new DisplayMetrics();
         display.getMetrics(dm);
@@ -65,10 +69,26 @@
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
 
-        mPositioner = new TaskPositioner(sWm);
+        mPositioner = TaskPositioner.create(sWm);
         mPositioner.register(mDisplayContent);
     }
 
+    @Test
+    public void testOverrideFactory() throws Exception {
+        final boolean[] created = new boolean[1];
+        created[0] = false;
+        TaskPositioner.setFactory(new TaskPositioner.Factory() {
+            @Override
+            public TaskPositioner create(WindowManagerService service) {
+                created[0] = true;
+                return null;
+            }
+        });
+
+        assertNull(TaskPositioner.create(sWm));
+        assertTrue(created[0]);
+    }
+
     /**
      * This tests that free resizing will allow to change the orientation as well
      * as does some basic tests (e.g. dragging in Y only will keep X stable).
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 f253632..920796e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -18,7 +18,7 @@
 
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_UNSET;
 import static com.android.server.wm.TaskSnapshotController.*;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
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 7be203a..6a4710b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -223,6 +223,19 @@
         assertFalse(app.canAffectSystemUiFlags());
     }
 
+    @Test
+    public void testIsSelfOrAncestorWindowAnimating() throws Exception {
+        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
+        final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
+        final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
+        assertFalse(child2.isSelfOrAncestorWindowAnimatingExit());
+        child2.mAnimatingExit = true;
+        assertTrue(child2.isSelfOrAncestorWindowAnimatingExit());
+        child2.mAnimatingExit = false;
+        root.mAnimatingExit = true;
+        assertTrue(child2.isSelfOrAncestorWindowAnimatingExit());
+    }
+
     private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
         final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
         root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
new file mode 100644
index 0000000..689c2ce
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.notification;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+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.content.ComponentName;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.server.UiServiceTestCase;
+import com.android.server.notification.NotificationManagerService.NotificationAssistants;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class NotificationAssistantsTest extends UiServiceTestCase {
+
+    @Mock
+    private PackageManager mPm;
+    @Mock
+    private IPackageManager miPm;
+    @Mock
+    private UserManager mUm;
+    @Mock
+    NotificationManagerService mNm;
+
+    NotificationAssistants mAssistants;
+
+    @Mock
+    private ManagedServices.UserProfiles mUserProfiles;
+
+    Object mLock = new Object();
+
+    UserInfo mZero = new UserInfo(0, "zero", 0);
+    UserInfo mTen = new UserInfo(10, "ten", 0);
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        getContext().setMockPackageManager(mPm);
+        getContext().addMockSystemService(Context.USER_SERVICE, mUm);
+        mAssistants = spy(mNm.new NotificationAssistants(getContext(), mLock, mUserProfiles, miPm));
+
+        List<ResolveInfo> approved = new ArrayList<>();
+        ResolveInfo resolve = new ResolveInfo();
+        approved.add(resolve);
+        ServiceInfo info = new ServiceInfo();
+        info.packageName = "a";
+        info.name="a";
+        resolve.serviceInfo = info;
+        when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt()))
+                .thenReturn(approved);
+
+        List<UserInfo> users = new ArrayList<>();
+        users.add(mZero);
+        users.add(mTen);
+        users.add(new UserInfo(11, "11", 0));
+        users.add(new UserInfo(12, "12", 0));
+        for (UserInfo user : users) {
+            when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
+        }
+        when(mUm.getUsers()).thenReturn(users);
+        when(mUm.getUsers(anyBoolean())).thenReturn(users);
+        when(mUserProfiles.getCurrentProfileIds()).thenReturn(new int[] {0, 10, 11, 12});
+    }
+
+    @Test
+    public void testXmlUpgrade() throws Exception {
+        String xml = "<enabled_assistants/>";
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.toString().getBytes())), null);
+        parser.nextTag();
+        mAssistants.readXml(parser);
+
+        //once per user
+        verify(mNm, times(mUm.getUsers().size())).readDefaultAssistant(anyInt());
+    }
+
+    @Test
+    public void testXmlUpgradeExistingApprovedComponents() throws Exception {
+        String xml = "<enabled_assistants>"
+                + "<service_listing approved=\"b/b\" user=\"10\" primary=\"true\" />"
+                + "</enabled_assistants>";
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.toString().getBytes())), null);
+        parser.nextTag();
+        mAssistants.readXml(parser);
+
+        // once per user
+        verify(mNm, times(mUm.getUsers().size())).readDefaultAssistant(anyInt());
+        verify(mAssistants, times(1)).addApprovedList(
+                new ComponentName("b", "b").flattenToString(),10, true);
+    }
+
+    @Test
+    public void testXmlUpgradeOnce() throws Exception {
+        String xml = "<enabled_assistants/>";
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.toString().getBytes())), null);
+        parser.nextTag();
+        mAssistants.readXml(parser);
+
+        XmlSerializer serializer = new FastXmlSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        mAssistants.writeXml(serializer, true);
+        serializer.endDocument();
+        serializer.flush();
+
+        //once per user
+        verify(mNm, times(mUm.getUsers().size())).readDefaultAssistant(anyInt());
+
+        Mockito.reset(mNm);
+
+        parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mAssistants.readXml(parser);
+
+        //once per user
+        verify(mNm, never()).readDefaultAssistant(anyInt());
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
index 3dcd5b9..30fae01 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
@@ -78,6 +78,8 @@
     private NotificationRecord mRecordCheater;
     private NotificationRecord mRecordCheaterColorized;
     private NotificationRecord mNoMediaSessionMedia;
+    private NotificationRecord mRecordColorized;
+    private NotificationRecord mRecordColorizedCall;
 
     @Before
     public void setUp() {
@@ -113,7 +115,6 @@
         Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_CALL)
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
-                .setColorized(true /* colorized */)
                 .build();
         mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
                 callPkg, 1, "highcall", callUid, callUid, n2,
@@ -200,13 +201,34 @@
                 pkg2, pkg2, 1, "cheater", uid2, uid2, n12, new UserHandle(userId),
                 "", 9258), getDefaultChannel());
         mNoMediaSessionMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+
+        Notification n13 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+                .setColorized(true /* colorized */)
+                .build();
+        mRecordColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+                pkg2, 1, "colorized", uid2, uid2, n13,
+                new UserHandle(userId), "", 1999), getDefaultChannel());
+        mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+
+        Notification n14 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setCategory(Notification.CATEGORY_CALL)
+                .setColorized(true)
+                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+                .build();
+        mRecordColorizedCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
+                callPkg, 1, "colorizedCall", callUid, callUid, n14,
+                new UserHandle(userId), "", 1999), getDefaultChannel());
+        mRecordColorizedCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
     }
 
     @Test
     public void testOrdering() throws Exception {
         final List<NotificationRecord> expected = new ArrayList<>();
-        expected.add(mRecordHighCall);
+        expected.add(mRecordColorizedCall);
         expected.add(mRecordDefaultMedia);
+        expected.add(mRecordColorized);
+        expected.add(mRecordHighCall);
         expected.add(mRecordInlineReply);
         expected.add(mRecordSms);
         expected.add(mRecordStarredContact);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
index 9564ab9..36136a8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
@@ -48,7 +48,6 @@
         mScheduleCalendar = new ScheduleCalendar();
         mScheduleInfo = new ZenModeConfig.ScheduleInfo();
         mScheduleInfo.days = new int[] {1, 2, 3, 4, 5};
-        mScheduleCalendar.setSchedule(mScheduleInfo);
     }
 
     @Test
@@ -100,6 +99,7 @@
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
         mScheduleInfo.exitAtAlarm = false;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         Calendar expected = new GregorianCalendar();
         expected.setTimeInMillis(cal.getTimeInMillis());
@@ -126,6 +126,7 @@
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
         mScheduleInfo.exitAtAlarm = false;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         Calendar expected = new GregorianCalendar();
         expected.setTimeInMillis(cal.getTimeInMillis());
@@ -153,6 +154,7 @@
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
         mScheduleInfo.exitAtAlarm = false;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         Calendar expected = new GregorianCalendar();
         expected.setTimeInMillis(cal.getTimeInMillis());
@@ -171,6 +173,7 @@
     public void testShouldExitForAlarm_settingOff() {
         mScheduleInfo.exitAtAlarm = false;
         mScheduleInfo.nextAlarm = 1000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.shouldExitForAlarm(1000));
     }
@@ -179,6 +182,7 @@
     public void testShouldExitForAlarm_beforeAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 1000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.shouldExitForAlarm(999));
     }
@@ -187,6 +191,7 @@
     public void testShouldExitForAlarm_noAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 0;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.shouldExitForAlarm(999));
     }
@@ -195,6 +200,7 @@
     public void testShouldExitForAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 1000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertTrue(mScheduleCalendar.shouldExitForAlarm(1000));
     }
@@ -203,6 +209,7 @@
     public void testMaybeSetNextAlarm_settingOff() {
         mScheduleInfo.exitAtAlarm = false;
         mScheduleInfo.nextAlarm = 0;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 2000);
 
@@ -213,6 +220,7 @@
     public void testMaybeSetNextAlarm_settingOn() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 0;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 2000);
 
@@ -223,6 +231,7 @@
     public void testMaybeSetNextAlarm_alarmCanceled() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 10000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 0);
 
@@ -233,6 +242,7 @@
     public void testMaybeSetNextAlarm_earlierAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 2000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 1500);
 
@@ -242,6 +252,7 @@
     @Test
     public void testMaybeSetNextAlarm_laterAlarm() {
         mScheduleInfo.exitAtAlarm = true;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
         mScheduleInfo.nextAlarm = 2000;
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 3000);
@@ -253,6 +264,7 @@
     public void testMaybeSetNextAlarm_expiredAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 998;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 999);
 
@@ -272,6 +284,7 @@
         mScheduleInfo.endHour = 3;
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertTrue(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
@@ -289,6 +302,7 @@
         mScheduleInfo.endHour = 3;
         mScheduleInfo.startMinute = 16;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertTrue(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
@@ -306,6 +320,7 @@
         mScheduleInfo.startMinute = 16;
         mScheduleInfo.endHour = 15;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
@@ -322,6 +337,7 @@
         mScheduleInfo.endHour = 3;
         mScheduleInfo.startMinute = 16;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index e0b6f61..e633053 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2564,6 +2564,35 @@
         public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
 
         /**
+         * The {@code content://} style URL to be called from DevicePolicyManagerService,
+         * can manage DPC-owned APNs.
+         * @hide
+         */
+        public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
+
+        /**
+         * The {@code content://} style URL to be called from Telephony to query APNs.
+         * When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only
+         * non-DPC-owned APNs are returned.
+         * @hide
+         */
+        public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered");
+
+        /**
+         * The {@code content://} style URL to be called from DevicePolicyManagerService
+         * or Telephony to manage whether DPC-owned APNs are enforced.
+         * @hide
+         */
+        public static final Uri ENFORCE_MANAGED_URI = Uri.parse(
+                "content://telephony/carriers/enforce_managed");
+
+        /**
+         * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
+         * @hide
+         */
+        public static final String ENFORCE_KEY = "enforced";
+
+        /**
          * The default sort order for this table.
          */
         public static final String DEFAULT_SORT_ORDER = "name ASC";
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 2fafdf5..423dc80 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -499,7 +499,7 @@
     public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
 
     private final Context mContext;
-    private final INetworkPolicyManager mNetworkPolicy;
+    private INetworkPolicyManager mNetworkPolicy;
 
     /**
      * A listener class for monitoring changes to {@link SubscriptionInfo} records.
@@ -572,11 +572,9 @@
     }
 
     /** @hide */
-    public SubscriptionManager(Context context) throws ServiceNotFoundException {
+    public SubscriptionManager(Context context) {
         if (DBG) logd("SubscriptionManager created");
         mContext = context;
-        mNetworkPolicy = INetworkPolicyManager.Stub
-                .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_POLICY_SERVICE));
     }
 
     /**
@@ -589,6 +587,14 @@
                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
     }
 
+    private final INetworkPolicyManager getNetworkPolicy() {
+        if (mNetworkPolicy == null) {
+            mNetworkPolicy = INetworkPolicyManager.Stub
+                    .asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
+        }
+        return mNetworkPolicy;
+    }
+
     /**
      * Register for changes to the list of active {@link SubscriptionInfo} records or to the
      * individual records themselves. When a change occurs the onSubscriptionsChanged method of
@@ -1686,7 +1692,7 @@
     public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
         try {
             SubscriptionPlan[] subscriptionPlans =
-                    mNetworkPolicy.getSubscriptionPlans(subId, mContext.getOpPackageName());
+                    getNetworkPolicy().getSubscriptionPlans(subId, mContext.getOpPackageName());
             return subscriptionPlans == null
                     ? Collections.emptyList() : Arrays.asList(subscriptionPlans);
         } catch (RemoteException e) {
@@ -1715,7 +1721,7 @@
     @SystemApi
     public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
         try {
-            mNetworkPolicy.setSubscriptionPlans(subId,
+            getNetworkPolicy().setSubscriptionPlans(subId,
                     plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1725,7 +1731,7 @@
     /** @hide */
     private String getSubscriptionPlansOwner(int subId) {
         try {
-            return mNetworkPolicy.getSubscriptionPlansOwner(subId);
+            return getNetworkPolicy().getSubscriptionPlansOwner(subId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8edc8b1..de9e691 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2122,6 +2122,27 @@
      * carrier restrictions.
      */
     public static final int SIM_STATE_CARD_RESTRICTED = 9;
+    /**
+     * SIM card state: Loaded: SIM card applications have been loaded
+     * @hide
+     */
+    @SystemApi
+    public static final int SIM_STATE_LOADED = 10;
+    /**
+     * SIM card state: SIM Card is present
+     * @hide
+     */
+    @SystemApi
+    public static final int SIM_STATE_PRESENT = 11;
+
+    /**
+     * Extra included in {@link Intent.ACTION_SIM_CARD_STATE_CHANGED} and
+     * {@link Intent.ACTION_SIM_APPLICATION_STATE_CHANGED} to indicate the card/application state.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
 
     /**
      * @return true if a ICC card is present
@@ -2168,6 +2189,14 @@
      * @see #SIM_STATE_CARD_RESTRICTED
      */
     public int getSimState() {
+        int simState = getSimStateIncludingLoaded();
+        if (simState == SIM_STATE_LOADED) {
+            simState = SIM_STATE_READY;
+        }
+        return simState;
+    }
+
+    private int getSimStateIncludingLoaded() {
         int slotIndex = getSlotIndex();
         // slotIndex may be invalid due to sim being absent. In that case query all slots to get
         // sim state
@@ -2186,7 +2215,63 @@
                     "state as absent");
             return SIM_STATE_ABSENT;
         }
-        return getSimState(slotIndex);
+        return SubscriptionManager.getSimStateForSlotIndex(slotIndex);
+    }
+
+    /**
+     * Returns a constant indicating the state of the default SIM card.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_ABSENT
+     * @see #SIM_STATE_CARD_IO_ERROR
+     * @see #SIM_STATE_CARD_RESTRICTED
+     * @see #SIM_STATE_PRESENT
+     *
+     * @hide
+     */
+    @SystemApi
+    public int getSimCardState() {
+        int simCardState = getSimState();
+        switch (simCardState) {
+            case SIM_STATE_UNKNOWN:
+            case SIM_STATE_ABSENT:
+            case SIM_STATE_CARD_IO_ERROR:
+            case SIM_STATE_CARD_RESTRICTED:
+                return simCardState;
+            default:
+                return SIM_STATE_PRESENT;
+        }
+    }
+
+    /**
+     * Returns a constant indicating the state of the card applications on the default SIM card.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_PIN_REQUIRED
+     * @see #SIM_STATE_PUK_REQUIRED
+     * @see #SIM_STATE_NETWORK_LOCKED
+     * @see #SIM_STATE_NOT_READY
+     * @see #SIM_STATE_PERM_DISABLED
+     * @see #SIM_STATE_LOADED
+     *
+     * @hide
+     */
+    @SystemApi
+    public int getSimApplicationState() {
+        int simApplicationState = getSimStateIncludingLoaded();
+        switch (simApplicationState) {
+            case SIM_STATE_UNKNOWN:
+            case SIM_STATE_ABSENT:
+            case SIM_STATE_CARD_IO_ERROR:
+            case SIM_STATE_CARD_RESTRICTED:
+                return SIM_STATE_UNKNOWN;
+            case SIM_STATE_READY:
+                // Ready is not a valid state anymore. The state that is broadcast goes from
+                // NOT_READY to either LOCKED or LOADED.
+                return SIM_STATE_NOT_READY;
+            default:
+                return simApplicationState;
+        }
     }
 
     /**
@@ -2207,6 +2292,9 @@
      */
     public int getSimState(int slotIndex) {
         int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
+        if (simState == SIM_STATE_LOADED) {
+            simState = SIM_STATE_READY;
+        }
         return simState;
     }
 
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
new file mode 100644
index 0000000..ea08175
--- /dev/null
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -0,0 +1,540 @@
+/*
+ * 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.telephony.data;
+
+import android.annotation.CallSuper;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.net.LinkProperties;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
+import android.util.SparseArray;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class of data service. Services that extend DataService must register the service in
+ * their AndroidManifest to be detected by the framework. They must be protected by the permission
+ * "android.permission.BIND_DATA_SERVICE". The data service definition in the manifest must follow
+ * the following format:
+ * ...
+ * <service android:name=".xxxDataService"
+ *     android:permission="android.permission.BIND_DATA_SERVICE" >
+ *     <intent-filter>
+ *         <action android:name="android.telephony.data.DataService" />
+ *     </intent-filter>
+ * </service>
+ * @hide
+ */
+@SystemApi
+public abstract class DataService extends Service {
+    private static final String TAG = DataService.class.getSimpleName();
+
+    public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
+    public static final String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
+
+    private static final int DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE          = 1;
+    private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL                      = 2;
+    private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL                 = 3;
+    private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN               = 4;
+    private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE                     = 5;
+    private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST                   = 6;
+    private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED      = 7;
+    private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED    = 8;
+    private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED            = 9;
+
+    private final HandlerThread mHandlerThread;
+
+    private final DataServiceHandler mHandler;
+
+    private final SparseArray<DataServiceProvider> mServiceMap = new SparseArray<>();
+
+    private final SparseArray<IDataServiceWrapper> mBinderMap = new SparseArray<>();
+
+    /**
+     * The abstract class of the actual data service implementation. The data service provider
+     * must extend this class to support data connection. Note that each instance of data service
+     * provider is associated with one physical SIM slot.
+     */
+    public class DataServiceProvider {
+
+        private final int mSlotId;
+
+        private final List<IDataServiceCallback> mDataCallListChangedCallbacks = new ArrayList<>();
+
+        /**
+         * Constructor
+         * @param slotId SIM slot id the data service provider associated with.
+         */
+        public DataServiceProvider(int slotId) {
+            mSlotId = slotId;
+        }
+
+        /**
+         * @return SIM slot id the data service provider associated with.
+         */
+        public final int getSlotId() {
+            return mSlotId;
+        }
+
+        /**
+         * Setup a data connection. The data service provider must implement this method to support
+         * establishing a packet data connection. When completed or error, the service must invoke
+         * the provided callback to notify the platform.
+         *
+         * @param accessNetworkType Access network type that the data call will be established on.
+         * Must be one of {@link AccessNetworkConstants.AccessNetworkType}.
+         * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
+         * @param isRoaming True if the device is data roaming.
+         * @param allowRoaming True if data roaming is allowed by the user.
+         * @param isHandover True if the request is for IWLAN handover.
+         * @param linkProperties If {@code isHandover} is true, this is the link properties of the
+         * existing data connection, otherwise null.
+         * @param callback The result callback for this request.
+         */
+        public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+                                  boolean allowRoaming, boolean isHandover,
+                                  LinkProperties linkProperties, DataServiceCallback callback) {
+            // The default implementation is to return unsupported.
+            callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
+        }
+
+        /**
+         * Deactivate a data connection. The data service provider must implement this method to
+         * support data connection tear down. When completed or error, the service must invoke the
+         * provided callback to notify the platform.
+         *
+         * @param cid Call id returned in the callback of {@link DataServiceProvider#setupDataCall(
+         * int, DataProfile, boolean, boolean, boolean, LinkProperties, DataServiceCallback)}.
+         * @param reasonRadioShutDown True if the deactivate request reason is device shut down.
+         * @param isHandover True if the request is for IWLAN handover.
+         * @param callback The result callback for this request.
+         */
+        public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
+                                       DataServiceCallback callback) {
+            // The default implementation is to return unsupported.
+            callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+        }
+
+        /**
+         * Set an APN to initial attach network.
+         *
+         * @param dataProfile Data profile used for data call setup. See {@link DataProfile}.
+         * @param isRoaming True if the device is data roaming.
+         * @param callback The result callback for this request.
+         */
+        public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
+                                        DataServiceCallback callback) {
+            // The default implementation is to return unsupported.
+            callback.onSetInitialAttachApnComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+        }
+
+        /**
+         * Send current carrier's data profiles to the data service for data call setup. This is
+         * only for CDMA carrier that can change the profile through OTA. The data service should
+         * always uses the latest data profile sent by the framework.
+         *
+         * @param dps A list of data profiles.
+         * @param isRoaming True if the device is data roaming.
+         * @param callback The result callback for this request.
+         */
+        public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
+                                   DataServiceCallback callback) {
+            // The default implementation is to return unsupported.
+            callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+        }
+
+        /**
+         * Get the active data call list.
+         *
+         * @param callback The result callback for this request.
+         */
+        public void getDataCallList(DataServiceCallback callback) {
+            // The default implementation is to return unsupported.
+            callback.onGetDataCallListComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
+        }
+
+        private void registerForDataCallListChanged(IDataServiceCallback callback) {
+            synchronized (mDataCallListChangedCallbacks) {
+                mDataCallListChangedCallbacks.add(callback);
+            }
+        }
+
+        private void unregisterForDataCallListChanged(IDataServiceCallback callback) {
+            synchronized (mDataCallListChangedCallbacks) {
+                mDataCallListChangedCallbacks.remove(callback);
+            }
+        }
+
+        /**
+         * Notify the system that current data call list changed. Data service must invoke this
+         * method whenever there is any data call status changed.
+         *
+         * @param dataCallList List of the current active data call.
+         */
+        public final void notifyDataCallListChanged(List<DataCallResponse> dataCallList) {
+            synchronized (mDataCallListChangedCallbacks) {
+                for (IDataServiceCallback callback : mDataCallListChangedCallbacks) {
+                    mHandler.obtainMessage(DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED, mSlotId,
+                            0, new DataCallListChangedIndication(dataCallList, callback))
+                            .sendToTarget();
+                }
+            }
+        }
+
+        /**
+         * Called when the instance of data service is destroyed (e.g. got unbind or binder died).
+         */
+        @CallSuper
+        protected void onDestroy() {
+            mDataCallListChangedCallbacks.clear();
+        }
+    }
+
+    private static final class SetupDataCallRequest {
+        public final int accessNetworkType;
+        public final DataProfile dataProfile;
+        public final boolean isRoaming;
+        public final boolean allowRoaming;
+        public final boolean isHandover;
+        public final LinkProperties linkProperties;
+        public final IDataServiceCallback callback;
+        SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
+                             boolean allowRoaming, boolean isHandover,
+                             LinkProperties linkProperties, IDataServiceCallback callback) {
+            this.accessNetworkType = accessNetworkType;
+            this.dataProfile = dataProfile;
+            this.isRoaming = isRoaming;
+            this.allowRoaming = allowRoaming;
+            this.linkProperties = linkProperties;
+            this.isHandover = isHandover;
+            this.callback = callback;
+        }
+    }
+
+    private static final class DeactivateDataCallRequest {
+        public final int cid;
+        public final boolean reasonRadioShutDown;
+        public final boolean isHandover;
+        public final IDataServiceCallback callback;
+        DeactivateDataCallRequest(int cid, boolean reasonRadioShutDown, boolean isHandover,
+                                  IDataServiceCallback callback) {
+            this.cid = cid;
+            this.reasonRadioShutDown = reasonRadioShutDown;
+            this.isHandover = isHandover;
+            this.callback = callback;
+        }
+    }
+
+    private static final class SetInitialAttachApnRequest {
+        public final DataProfile dataProfile;
+        public final boolean isRoaming;
+        public final IDataServiceCallback callback;
+        SetInitialAttachApnRequest(DataProfile dataProfile, boolean isRoaming,
+                                   IDataServiceCallback callback) {
+            this.dataProfile = dataProfile;
+            this.isRoaming = isRoaming;
+            this.callback = callback;
+        }
+    }
+
+    private static final class SetDataProfileRequest {
+        public final List<DataProfile> dps;
+        public final boolean isRoaming;
+        public final IDataServiceCallback callback;
+        SetDataProfileRequest(List<DataProfile> dps, boolean isRoaming,
+                              IDataServiceCallback callback) {
+            this.dps = dps;
+            this.isRoaming = isRoaming;
+            this.callback = callback;
+        }
+    }
+
+    private static final class DataCallListChangedIndication {
+        public final List<DataCallResponse> dataCallList;
+        public final IDataServiceCallback callback;
+        DataCallListChangedIndication(List<DataCallResponse> dataCallList,
+                                      IDataServiceCallback callback) {
+            this.dataCallList = dataCallList;
+            this.callback = callback;
+        }
+    }
+
+    private class DataServiceHandler extends Handler {
+
+        DataServiceHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            IDataServiceCallback callback;
+            final int slotId = message.arg1;
+            DataServiceProvider service;
+
+            synchronized (mServiceMap) {
+                service = mServiceMap.get(slotId);
+            }
+
+            switch (message.what) {
+                case DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE:
+                    service = createDataServiceProvider(message.arg1);
+                    if (service != null) {
+                        mServiceMap.put(slotId, service);
+                    }
+                    break;
+                case DATA_SERVICE_REQUEST_SETUP_DATA_CALL:
+                    if (service == null) break;
+                    SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj;
+                    service.setupDataCall(setupDataCallRequest.accessNetworkType,
+                            setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
+                            setupDataCallRequest.allowRoaming, setupDataCallRequest.isHandover,
+                            setupDataCallRequest.linkProperties,
+                            new DataServiceCallback(setupDataCallRequest.callback));
+
+                    break;
+                case DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL:
+                    if (service == null) break;
+                    DeactivateDataCallRequest deactivateDataCallRequest =
+                            (DeactivateDataCallRequest) message.obj;
+                    service.deactivateDataCall(deactivateDataCallRequest.cid,
+                            deactivateDataCallRequest.reasonRadioShutDown,
+                            deactivateDataCallRequest.isHandover,
+                            new DataServiceCallback(deactivateDataCallRequest.callback));
+                    break;
+                case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN:
+                    if (service == null) break;
+                    SetInitialAttachApnRequest setInitialAttachApnRequest =
+                            (SetInitialAttachApnRequest) message.obj;
+                    service.setInitialAttachApn(setInitialAttachApnRequest.dataProfile,
+                            setInitialAttachApnRequest.isRoaming,
+                            new DataServiceCallback(setInitialAttachApnRequest.callback));
+                    break;
+                case DATA_SERVICE_REQUEST_SET_DATA_PROFILE:
+                    if (service == null) break;
+                    SetDataProfileRequest setDataProfileRequest =
+                            (SetDataProfileRequest) message.obj;
+                    service.setDataProfile(setDataProfileRequest.dps,
+                            setDataProfileRequest.isRoaming,
+                            new DataServiceCallback(setDataProfileRequest.callback));
+                    break;
+                case DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST:
+                    if (service == null) break;
+
+                    service.getDataCallList(new DataServiceCallback(
+                            (IDataServiceCallback) message.obj));
+                    break;
+                case DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED:
+                    if (service == null) break;
+                    service.registerForDataCallListChanged((IDataServiceCallback) message.obj);
+                    break;
+                case DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED:
+                    if (service == null) break;
+                    callback = (IDataServiceCallback) message.obj;
+                    service.unregisterForDataCallListChanged(callback);
+                    break;
+                case DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED:
+                    if (service == null) break;
+                    DataCallListChangedIndication indication =
+                            (DataCallListChangedIndication) message.obj;
+                    try {
+                        indication.callback.onDataCallListChanged(indication.dataCallList);
+                    } catch (RemoteException e) {
+                        loge("Failed to call onDataCallListChanged. " + e);
+                    }
+                    break;
+            }
+        }
+    }
+
+    private DataService() {
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+
+        mHandler = new DataServiceHandler(mHandlerThread.getLooper());
+        log("Data service created");
+    }
+
+    /**
+     * Create the instance of {@link DataServiceProvider}. Data service provider must override
+     * this method to facilitate the creation of {@link DataServiceProvider} instances. The system
+     * will call this method after binding the data service for each active SIM slot id.
+     *
+     * @param slotId SIM slot id the data service associated with.
+     * @return Data service object
+     */
+    public abstract DataServiceProvider createDataServiceProvider(int slotId);
+
+    /** @hide */
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (intent == null || !DATA_SERVICE_INTERFACE.equals(intent.getAction())) {
+            loge("Unexpected intent " + intent);
+            return null;
+        }
+
+        int slotId = intent.getIntExtra(
+                DATA_SERVICE_EXTRA_SLOT_ID, SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+
+        if (!SubscriptionManager.isValidSlotIndex(slotId)) {
+            loge("Invalid slot id " + slotId);
+            return null;
+        }
+
+        log("onBind: slot id=" + slotId);
+
+        IDataServiceWrapper binder = mBinderMap.get(slotId);
+        if (binder == null) {
+            Message msg = mHandler.obtainMessage(DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE);
+            msg.arg1 = slotId;
+            msg.sendToTarget();
+
+            binder = new IDataServiceWrapper(slotId);
+            mBinderMap.put(slotId, binder);
+        }
+
+        return binder;
+    }
+
+    /** @hide */
+    @Override
+    public boolean onUnbind(Intent intent) {
+        int slotId = intent.getIntExtra(DATA_SERVICE_EXTRA_SLOT_ID,
+                SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+        if (mBinderMap.get(slotId) != null) {
+            DataServiceProvider serviceImpl;
+            synchronized (mServiceMap) {
+                serviceImpl = mServiceMap.get(slotId);
+            }
+            if (serviceImpl != null) {
+                serviceImpl.onDestroy();
+            }
+            mBinderMap.remove(slotId);
+        }
+
+        // If all clients unbinds, quit the handler thread
+        if (mBinderMap.size() == 0) {
+            mHandlerThread.quit();
+        }
+
+        return false;
+    }
+
+    /** @hide */
+    @Override
+    public void onDestroy() {
+        synchronized (mServiceMap) {
+            for (int i = 0; i < mServiceMap.size(); i++) {
+                DataServiceProvider serviceImpl = mServiceMap.get(i);
+                if (serviceImpl != null) {
+                    serviceImpl.onDestroy();
+                }
+            }
+            mServiceMap.clear();
+        }
+
+        mHandlerThread.quit();
+    }
+
+    /**
+     * A wrapper around IDataService that forwards calls to implementations of {@link DataService}.
+     */
+    private class IDataServiceWrapper extends IDataService.Stub {
+
+        private final int mSlotId;
+
+        IDataServiceWrapper(int slotId) {
+            mSlotId = slotId;
+        }
+
+        @Override
+        public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
+                                  boolean isRoaming, boolean allowRoaming, boolean isHandover,
+                                  LinkProperties linkProperties, IDataServiceCallback callback) {
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, mSlotId, 0,
+                    new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
+                            allowRoaming, isHandover, linkProperties, callback))
+                    .sendToTarget();
+        }
+
+        @Override
+        public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
+                                       IDataServiceCallback callback) {
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, mSlotId, 0,
+                    new DeactivateDataCallRequest(cid, reasonRadioShutDown, isHandover, callback))
+                    .sendToTarget();
+        }
+
+        @Override
+        public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
+                                        IDataServiceCallback callback) {
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, mSlotId, 0,
+                    new SetInitialAttachApnRequest(dataProfile, isRoaming, callback))
+                    .sendToTarget();
+        }
+
+        @Override
+        public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
+                                   IDataServiceCallback callback) {
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, mSlotId, 0,
+                    new SetDataProfileRequest(dps, isRoaming, callback)).sendToTarget();
+        }
+
+        @Override
+        public void getDataCallList(IDataServiceCallback callback) {
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, mSlotId, 0,
+                    callback).sendToTarget();
+        }
+
+        @Override
+        public void registerForDataCallListChanged(IDataServiceCallback callback) {
+            if (callback == null) {
+                loge("Callback is null");
+                return;
+            }
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, mSlotId,
+                    0, callback).sendToTarget();
+        }
+
+        @Override
+        public void unregisterForDataCallListChanged(IDataServiceCallback callback) {
+            if (callback == null) {
+                loge("Callback is null");
+                return;
+            }
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, mSlotId,
+                    0, callback).sendToTarget();
+        }
+    }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s) {
+        Rlog.e(TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
new file mode 100644
index 0000000..b6a81f9
--- /dev/null
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -0,0 +1,172 @@
+/*
+ * 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.telephony.data;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+import android.telephony.Rlog;
+import android.telephony.data.DataService.DataServiceProvider;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+/**
+ * Data service callback, which is for bound data service to invoke for solicited and unsolicited
+ * response. The caller is responsible to create a callback object for each single asynchronous
+ * request.
+ *
+ * @hide
+ */
+@SystemApi
+public class DataServiceCallback {
+
+    private static final String mTag = DataServiceCallback.class.getSimpleName();
+
+    /**
+     * Result of data requests
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({RESULT_SUCCESS, RESULT_ERROR_UNSUPPORTED, RESULT_ERROR_INVALID_ARG, RESULT_ERROR_BUSY,
+            RESULT_ERROR_ILLEGAL_STATE})
+    public @interface Result {}
+
+    /** Request is completed successfully */
+    public static final int RESULT_SUCCESS              = 0;
+    /** Request is not support */
+    public static final int RESULT_ERROR_UNSUPPORTED    = 1;
+    /** Request contains invalid arguments */
+    public static final int RESULT_ERROR_INVALID_ARG    = 2;
+    /** Service is busy */
+    public static final int RESULT_ERROR_BUSY           = 3;
+    /** Request sent in illegal state */
+    public static final int RESULT_ERROR_ILLEGAL_STATE  = 4;
+
+    private final WeakReference<IDataServiceCallback> mCallback;
+
+    /** @hide */
+    public DataServiceCallback(IDataServiceCallback callback) {
+        mCallback = new WeakReference<>(callback);
+    }
+
+    /**
+     * Called to indicate result for the request {@link DataServiceProvider#setupDataCall(int,
+     * DataProfile, boolean, boolean, boolean, DataServiceCallback)}.
+     *
+     * @param result The result code. Must be one of the {@link Result}.
+     * @param response Setup data call response.
+     */
+    public void onSetupDataCallComplete(@Result int result, DataCallResponse response) {
+        IDataServiceCallback callback = mCallback.get();
+        if (callback != null) {
+            try {
+                callback.onSetupDataCallComplete(result, response);
+            } catch (RemoteException e) {
+                Rlog.e(mTag, "Failed to onSetupDataCallComplete on the remote");
+            }
+        }
+    }
+
+    /**
+     * Called to indicate result for the request {@link DataServiceProvider#deactivateDataCall(int,
+     * boolean, boolean, DataServiceCallback)}.
+     *
+     * @param result The result code. Must be one of the {@link Result}.
+     */
+    public void onDeactivateDataCallComplete(@Result int result) {
+        IDataServiceCallback callback = mCallback.get();
+        if (callback != null) {
+            try {
+                callback.onDeactivateDataCallComplete(result);
+            } catch (RemoteException e) {
+                Rlog.e(mTag, "Failed to onDeactivateDataCallComplete on the remote");
+            }
+        }
+    }
+
+    /**
+     * Called to indicate result for the request {@link DataServiceProvider#setInitialAttachApn(
+     * DataProfile, boolean, DataServiceCallback)}.
+     *
+     * @param result The result code. Must be one of the {@link Result}.
+     */
+    public void onSetInitialAttachApnComplete(@Result int result) {
+        IDataServiceCallback callback = mCallback.get();
+        if (callback != null) {
+            try {
+                callback.onSetInitialAttachApnComplete(result);
+            } catch (RemoteException e) {
+                Rlog.e(mTag, "Failed to onSetInitialAttachApnComplete on the remote");
+            }
+        }
+    }
+
+    /**
+     * Called to indicate result for the request {@link DataServiceProvider#setDataProfile(List,
+     * boolean, DataServiceCallback)}.
+     *
+     * @param result The result code. Must be one of the {@link Result}.
+     */
+    @SystemApi
+    public void onSetDataProfileComplete(@Result int result) {
+        IDataServiceCallback callback = mCallback.get();
+        if (callback != null) {
+            try {
+                callback.onSetDataProfileComplete(result);
+            } catch (RemoteException e) {
+                Rlog.e(mTag, "Failed to onSetDataProfileComplete on the remote");
+            }
+        }
+    }
+
+    /**
+     * Called to indicate result for the request {@link DataServiceProvider#getDataCallList(
+     * DataServiceCallback)}.
+     *
+     * @param result The result code. Must be one of the {@link Result}.
+     * @param dataCallList List of the current active data connection.
+     */
+    public void onGetDataCallListComplete(@Result int result, List<DataCallResponse> dataCallList) {
+        IDataServiceCallback callback = mCallback.get();
+        if (callback != null) {
+            try {
+                callback.onGetDataCallListComplete(result, dataCallList);
+            } catch (RemoteException e) {
+                Rlog.e(mTag, "Failed to onGetDataCallListComplete on the remote");
+            }
+        }
+    }
+
+    /**
+     * Called to indicate that data connection list changed.
+     *
+     * @param dataCallList List of the current active data connection.
+     */
+    public void onDataCallListChanged(List<DataCallResponse> dataCallList) {
+        IDataServiceCallback callback = mCallback.get();
+        if (callback != null) {
+            try {
+                callback.onDataCallListChanged(dataCallList);
+            } catch (RemoteException e) {
+                Rlog.e(mTag, "Failed to onDataCallListChanged on the remote");
+            }
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
new file mode 100644
index 0000000..4eaaa252
--- /dev/null
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.telephony.data;
+
+import android.net.LinkProperties;
+import android.telephony.data.DataProfile;
+import android.telephony.data.IDataServiceCallback;
+
+/**
+ * {@hide}
+ */
+oneway interface IDataService
+{
+    void setupDataCall(int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
+                       boolean allowRoaming, boolean isHandover, in LinkProperties linkProperties,
+                       IDataServiceCallback callback);
+    void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
+                            IDataServiceCallback callback);
+    void setInitialAttachApn(in DataProfile dataProfile, boolean isRoaming,
+                             IDataServiceCallback callback);
+    void setDataProfile(in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback);
+    void getDataCallList(IDataServiceCallback callback);
+    void registerForDataCallListChanged(IDataServiceCallback callback);
+    void unregisterForDataCallListChanged(IDataServiceCallback callback);
+}
diff --git a/telephony/java/android/telephony/data/IDataServiceCallback.aidl b/telephony/java/android/telephony/data/IDataServiceCallback.aidl
new file mode 100644
index 0000000..856185b
--- /dev/null
+++ b/telephony/java/android/telephony/data/IDataServiceCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.telephony.data;
+
+import android.telephony.data.DataCallResponse;
+
+/**
+ * The call back interface
+ * @hide
+ */
+oneway interface IDataServiceCallback
+{
+    void onSetupDataCallComplete(int result, in DataCallResponse dataCallResponse);
+    void onDeactivateDataCallComplete(int result);
+    void onSetInitialAttachApnComplete(int result);
+    void onSetDataProfileComplete(int result);
+    void onGetDataCallListComplete(int result, in List<DataCallResponse> dataCallList);
+    void onDataCallListChanged(in List<DataCallResponse> dataCallList);
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 29849c1..b9ed005 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -15,14 +15,40 @@
  */
 package android.telephony.euicc;
 
+import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.euicc.EuiccProfileInfo;
 import android.util.Log;
 
+import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
+import com.android.internal.telephony.euicc.ICancelSessionCallback;
+import com.android.internal.telephony.euicc.IDeleteProfileCallback;
+import com.android.internal.telephony.euicc.IDisableProfileCallback;
 import com.android.internal.telephony.euicc.IEuiccCardController;
 import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
+import com.android.internal.telephony.euicc.IGetDefaultSmdpAddressCallback;
+import com.android.internal.telephony.euicc.IGetEuiccChallengeCallback;
+import com.android.internal.telephony.euicc.IGetEuiccInfo1Callback;
+import com.android.internal.telephony.euicc.IGetEuiccInfo2Callback;
+import com.android.internal.telephony.euicc.IGetProfileCallback;
+import com.android.internal.telephony.euicc.IGetRulesAuthTableCallback;
+import com.android.internal.telephony.euicc.IGetSmdsAddressCallback;
+import com.android.internal.telephony.euicc.IListNotificationsCallback;
+import com.android.internal.telephony.euicc.ILoadBoundProfilePackageCallback;
+import com.android.internal.telephony.euicc.IPrepareDownloadCallback;
+import com.android.internal.telephony.euicc.IRemoveNotificationFromListCallback;
+import com.android.internal.telephony.euicc.IResetMemoryCallback;
+import com.android.internal.telephony.euicc.IRetrieveNotificationCallback;
+import com.android.internal.telephony.euicc.IRetrieveNotificationListCallback;
+import com.android.internal.telephony.euicc.ISetDefaultSmdpAddressCallback;
+import com.android.internal.telephony.euicc.ISetNicknameCallback;
+import com.android.internal.telephony.euicc.ISwitchToProfileCallback;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * EuiccCardManager is the application interface to an eSIM card.
@@ -34,6 +60,53 @@
 public class EuiccCardManager {
     private static final String TAG = "EuiccCardManager";
 
+    /** Reason for canceling a profile download session */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "CANCEL_REASON_" }, value = {
+            CANCEL_REASON_END_USER_REJECTED,
+            CANCEL_REASON_POSTPONED,
+            CANCEL_REASON_TIMEOUT,
+            CANCEL_REASON_PPR_NOT_ALLOWED
+    })
+    public @interface CancelReason {}
+
+    /**
+     * The end user has rejected the download. The profile will be put into the error state and
+     * cannot be downloaded again without the operator's change.
+     */
+    public static final int CANCEL_REASON_END_USER_REJECTED = 0;
+
+    /** The download has been postponed and can be restarted later. */
+    public static final int CANCEL_REASON_POSTPONED = 1;
+
+    /** The download has been timed out and can be restarted later. */
+    public static final int CANCEL_REASON_TIMEOUT = 2;
+
+    /**
+     * The profile to be downloaded cannot be installed due to its policy rule is not allowed by
+     * the RAT (Rules Authorisation Table) on the eUICC or by other installed profiles. The
+     * download can be restarted later.
+     */
+    public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3;
+
+    /** Options for resetting eUICC memory */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "RESET_OPTION_" }, value = {
+            RESET_OPTION_DELETE_OPERATIONAL_PROFILES,
+            RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES,
+            RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS
+    })
+    public @interface ResetOption {}
+
+    /** Deletes all operational profiles. */
+    public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1;
+
+    /** Deletes all field-loaded testing profiles. */
+    public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 1 << 1;
+
+    /** Resets the default SM-DP+ address. */
+    public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 1 << 2;
+
     /** Result code of execution with no error. */
     public static final int RESULT_OK = 0;
 
@@ -69,7 +142,7 @@
     /**
      * Gets all the profiles on eUicc.
      *
-     * @param callback the callback to get the result code and all the profiles.
+     * @param callback The callback to get the result code and all the profiles.
      */
     public void getAllProfiles(ResultCallback<EuiccProfileInfo[]> callback) {
         try {
@@ -85,4 +158,506 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Gets the profile of the given iccid.
+     *
+     * @param iccid The iccid of the profile.
+     * @param callback The callback to get the result code and profile.
+     */
+    public void getProfile(String iccid, ResultCallback<EuiccProfileInfo> callback) {
+        try {
+            getIEuiccCardController().getProfile(mContext.getOpPackageName(), iccid,
+                    new IGetProfileCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccProfileInfo profile) {
+                            callback.onComplete(resultCode, profile);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getProfile", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Disables the profile of the given iccid.
+     *
+     * @param iccid The iccid of the profile.
+     * @param refresh Whether sending the REFRESH command to modem.
+     * @param callback The callback to get the result code.
+     */
+    public void disableProfile(String iccid, boolean refresh, ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().disableProfile(mContext.getOpPackageName(), iccid, refresh,
+                    new IDisableProfileCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            callback.onComplete(resultCode, null);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling disableProfile", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Switches from the current profile to another profile. The current profile will be disabled
+     * and the specified profile will be enabled.
+     *
+     * @param iccid The iccid of the profile to switch to.
+     * @param refresh Whether sending the REFRESH command to modem.
+     * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
+     */
+    public void switchToProfile(String iccid, boolean refresh,
+            ResultCallback<EuiccProfileInfo> callback) {
+        try {
+            getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), iccid, refresh,
+                    new ISwitchToProfileCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccProfileInfo profile) {
+                            callback.onComplete(resultCode, profile);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling switchToProfile", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the EID of the eUICC.
+     *
+     * @return The EID.
+     */
+    public String getEid() {
+        try {
+            return getIEuiccCardController().getEid();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getEid", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets the nickname of the profile of the given iccid.
+     *
+     * @param iccid The iccid of the profile.
+     * @param nickname The nickname of the profile.
+     * @param callback The callback to get the result code.
+     */
+    public void setNickname(String iccid, String nickname, ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().setNickname(mContext.getOpPackageName(), iccid, nickname,
+                    new ISetNicknameCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            callback.onComplete(resultCode, null);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling setNickname", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Deletes the profile of the given iccid from eUICC.
+     *
+     * @param iccid The iccid of the profile.
+     * @param callback The callback to get the result code.
+     */
+    public void deleteProfile(String iccid, ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().deleteProfile(mContext.getOpPackageName(), iccid,
+                    new IDeleteProfileCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            callback.onComplete(resultCode, null);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling deleteProfile", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Resets the eUICC memory.
+     *
+     * @param options Bits of the options of resetting which parts of the eUICC memory. See
+     *     EuiccCard for details.
+     * @param callback The callback to get the result code.
+     */
+    public void resetMemory(@ResetOption int options, ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().resetMemory(mContext.getOpPackageName(), options,
+                    new IResetMemoryCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            callback.onComplete(resultCode, null);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling resetMemory", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the default SM-DP+ address from eUICC.
+     *
+     * @param callback The callback to get the result code and the default SM-DP+ address.
+     */
+    public void getDefaultSmdpAddress(ResultCallback<String> callback) {
+        try {
+            getIEuiccCardController().getDefaultSmdpAddress(mContext.getOpPackageName(),
+                    new IGetDefaultSmdpAddressCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, String address) {
+                            callback.onComplete(resultCode, address);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getDefaultSmdpAddress", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the SM-DS address from eUICC.
+     *
+     * @param callback The callback to get the result code and the SM-DS address.
+     */
+    public void getSmdsAddress(ResultCallback<String> callback) {
+        try {
+            getIEuiccCardController().getSmdsAddress(mContext.getOpPackageName(),
+                    new IGetSmdsAddressCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, String address) {
+                            callback.onComplete(resultCode, address);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getSmdsAddress", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets the default SM-DP+ address of eUICC.
+     *
+     * @param defaultSmdpAddress The default SM-DP+ address to set.
+     * @param callback The callback to get the result code.
+     */
+    public void setDefaultSmdpAddress(String defaultSmdpAddress, ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().setDefaultSmdpAddress(mContext.getOpPackageName(),
+                    defaultSmdpAddress,
+                    new ISetDefaultSmdpAddressCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            callback.onComplete(resultCode, null);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling setDefaultSmdpAddress", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets Rules Authorisation Table.
+     *
+     * @param callback the callback to get the result code and the rule authorisation table.
+     */
+    public void getRulesAuthTable(ResultCallback<EuiccRulesAuthTable> callback) {
+        try {
+            getIEuiccCardController().getRulesAuthTable(mContext.getOpPackageName(),
+                    new IGetRulesAuthTableCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccRulesAuthTable rat) {
+                            callback.onComplete(resultCode, rat);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getRulesAuthTable", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the eUICC challenge for new profile downloading.
+     *
+     * @param callback the callback to get the result code and the challenge.
+     */
+    public void getEuiccChallenge(ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().getEuiccChallenge(mContext.getOpPackageName(),
+                    new IGetEuiccChallengeCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] challenge) {
+                            callback.onComplete(resultCode, challenge);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getEuiccChallenge", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
+     *
+     * @param callback the callback to get the result code and the info1.
+     */
+    public void getEuiccInfo1(ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().getEuiccInfo1(mContext.getOpPackageName(),
+                    new IGetEuiccInfo1Callback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] info) {
+                            callback.onComplete(resultCode, info);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getEuiccInfo1", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
+     *
+     * @param callback the callback to get the result code and the info2.
+     */
+    public void getEuiccInfo2(ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().getEuiccInfo2(mContext.getOpPackageName(),
+                    new IGetEuiccInfo2Callback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] info) {
+                            callback.onComplete(resultCode, info);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling getEuiccInfo2", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Authenticates the SM-DP+ server by the eUICC.
+     *
+     * @param matchingId the activation code token defined in GSMA RSP v2.0+ or empty when it is not
+     *     required.
+     * @param serverSigned1 ASN.1 data in byte array signed and returned by the SM-DP+ server.
+     * @param serverSignature1 ASN.1 data in byte array indicating a SM-DP+ signature which is
+     *     returned by SM-DP+ server.
+     * @param euiccCiPkIdToBeUsed ASN.1 data in byte array indicating CI Public Key Identifier to be
+     *     used by the eUICC for signature which is returned by SM-DP+ server. This is defined in
+     *     GSMA RSP v2.0+.
+     * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
+     *     SM-DP+ server.
+     * @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 matchingId, byte[] serverSigned1,
+            byte[] serverSignature1, byte[] euiccCiPkIdToBeUsed, byte[] serverCertificate,
+            ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().authenticateServer(
+                    mContext.getOpPackageName(),
+                    matchingId,
+                    serverSigned1,
+                    serverSignature1,
+                    euiccCiPkIdToBeUsed,
+                    serverCertificate,
+                    new IAuthenticateServerCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] response) {
+                            callback.onComplete(resultCode, response);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling authenticateServer", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Prepares the profile download request sent to SM-DP+.
+     *
+     * @param hashCc the hash of confirmation code. It can be null if there is no confirmation code
+     *     required.
+     * @param smdpSigned2 ASN.1 data in byte array indicating the data to be signed by the SM-DP+
+     *     returned by SM-DP+ server.
+     * @param smdpSignature2 ASN.1 data in byte array indicating the SM-DP+ signature returned by
+     *     SM-DP+ server.
+     * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
+     *     by SM-DP+ server.
+     * @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(@Nullable byte[] hashCc, byte[] smdpSigned2,
+            byte[] smdpSignature2, byte[] smdpCertificate, ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().prepareDownload(
+                    mContext.getOpPackageName(),
+                    hashCc,
+                    smdpSigned2,
+                    smdpSignature2,
+                    smdpCertificate,
+                    new IPrepareDownloadCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] response) {
+                            callback.onComplete(resultCode, response);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling prepareDownload", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Loads a downloaded bound profile package onto the eUICC.
+     *
+     * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
+     * @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(byte[] boundProfilePackage,
+            ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().loadBoundProfilePackage(
+                    mContext.getOpPackageName(),
+                    boundProfilePackage,
+                    new ILoadBoundProfilePackageCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] response) {
+                            callback.onComplete(resultCode, response);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling loadBoundProfilePackage", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Cancels the current profile download session.
+     *
+     * @param transactionId the transaction ID returned by SM-DP+ server.
+     * @param reason the cancel reason.
+     * @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(byte[] transactionId, @CancelReason int reason,
+            ResultCallback<byte[]> callback) {
+        try {
+            getIEuiccCardController().cancelSession(
+                    mContext.getOpPackageName(),
+                    transactionId,
+                    reason,
+                    new ICancelSessionCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, byte[] response) {
+                            callback.onComplete(resultCode, response);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling cancelSession", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Lists all notifications of the given {@code notificationEvents}.
+     *
+     * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
+     * @param callback the callback to get the result code and the list of notifications.
+     */
+    public void listNotifications(@EuiccNotification.Event int events,
+            ResultCallback<EuiccNotification[]> callback) {
+        try {
+            getIEuiccCardController().listNotifications(mContext.getOpPackageName(), events,
+                    new IListNotificationsCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccNotification[] notifications) {
+                            callback.onComplete(resultCode, notifications);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling listNotifications", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Retrieves contents of all notification of the given {@code events}.
+     *
+     * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
+     * @param callback the callback to get the result code and the list of notifications.
+     */
+    public void retrieveNotificationList(@EuiccNotification.Event int events,
+            ResultCallback<EuiccNotification[]> callback) {
+        try {
+            getIEuiccCardController().retrieveNotificationList(mContext.getOpPackageName(), events,
+                    new IRetrieveNotificationListCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccNotification[] notifications) {
+                            callback.onComplete(resultCode, notifications);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling retrieveNotificationList", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Retrieves the content of a notification of the given {@code seqNumber}.
+     *
+     * @param seqNumber the sequence number of the notification.
+     * @param callback the callback to get the result code and the notification.
+     */
+    public void retrieveNotification(int seqNumber, ResultCallback<EuiccNotification> callback) {
+        try {
+            getIEuiccCardController().retrieveNotification(mContext.getOpPackageName(), seqNumber,
+                    new IRetrieveNotificationCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccNotification notification) {
+                            callback.onComplete(resultCode, notification);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling retrieveNotification", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Removes a notification from eUICC.
+     *
+     * @param seqNumber the sequence number of the notification.
+     * @param callback the callback to get the result code.
+     */
+    public void removeNotificationFromList(int seqNumber, ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().removeNotificationFromList(
+                    mContext.getOpPackageName(),
+                    seqNumber,
+                    new IRemoveNotificationFromListCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            callback.onComplete(resultCode, null);
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling removeNotificationFromList", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/android/telephony/euicc/EuiccNotification.aidl
similarity index 81%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/android/telephony/euicc/EuiccNotification.aidl
index 4200de1..dad770d 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/android/telephony/euicc/EuiccNotification.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,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.telephony.euicc;
 
-/* @hide */
-parcelable RecoveryData;
+parcelable EuiccNotification;
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl
similarity index 88%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl
index 4200de1..9785a45 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.security.keystore;
+package android.telephony.euicc;
 
-/* @hide */
-parcelable RecoveryData;
+parcelable EuiccRulesAuthTable;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/euicc/EuiccRat.java b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java
similarity index 90%
rename from telephony/java/android/telephony/euicc/EuiccRat.java
rename to telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java
index 6a56503a..7efe043 100644
--- a/telephony/java/android/telephony/euicc/EuiccRat.java
+++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java
@@ -35,7 +35,7 @@
  *
  * TODO(b/35851809): Make this a @SystemApi.
  */
-public final class EuiccRat implements Parcelable {
+public final class EuiccRulesAuthTable implements Parcelable {
     /** Profile policy rule flags */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = {
@@ -50,7 +50,7 @@
     private final CarrierIdentifier[][] mCarrierIds;
     private final int[] mPolicyRuleFlags;
 
-    /** This is used to build new {@link EuiccRat} instance. */
+    /** This is used to build new {@link EuiccRulesAuthTable} instance. */
     public static final class Builder {
         private int[] mPolicyRules;
         private CarrierIdentifier[][] mCarrierIds;
@@ -72,7 +72,7 @@
          * Builds the RAT instance. This builder should not be used anymore after this method is
          * called, otherwise {@link NullPointerException} will be thrown.
          */
-        public EuiccRat build() {
+        public EuiccRulesAuthTable build() {
             if (mPosition != mPolicyRules.length) {
                 throw new IllegalStateException(
                         "Not enough rules are added, expected: "
@@ -80,7 +80,7 @@
                                 + ", added: "
                                 + mPosition);
             }
-            return new EuiccRat(mPolicyRules, mCarrierIds, mPolicyRuleFlags);
+            return new EuiccRulesAuthTable(mPolicyRules, mCarrierIds, mPolicyRuleFlags);
         }
 
         /**
@@ -125,7 +125,8 @@
         return true;
     }
 
-    private EuiccRat(int[] policyRules, CarrierIdentifier[][] carrierIds, int[] policyRuleFlags) {
+    private EuiccRulesAuthTable(int[] policyRules, CarrierIdentifier[][] carrierIds,
+            int[] policyRuleFlags) {
         mPolicyRules = policyRules;
         mCarrierIds = carrierIds;
         mPolicyRuleFlags = policyRuleFlags;
@@ -207,7 +208,7 @@
             return false;
         }
 
-        EuiccRat that = (EuiccRat) obj;
+        EuiccRulesAuthTable that = (EuiccRulesAuthTable) obj;
         if (mCarrierIds.length != that.mCarrierIds.length) {
             return false;
         }
@@ -234,7 +235,7 @@
                 && Arrays.equals(mPolicyRuleFlags, that.mPolicyRuleFlags);
     }
 
-    private EuiccRat(Parcel source) {
+    private EuiccRulesAuthTable(Parcel source) {
         mPolicyRules = source.createIntArray();
         int len = mPolicyRules.length;
         mCarrierIds = new CarrierIdentifier[len][];
@@ -244,16 +245,16 @@
         mPolicyRuleFlags = source.createIntArray();
     }
 
-    public static final Creator<EuiccRat> CREATOR =
-            new Creator<EuiccRat>() {
+    public static final Creator<EuiccRulesAuthTable> CREATOR =
+            new Creator<EuiccRulesAuthTable>() {
                 @Override
-                public EuiccRat createFromParcel(Parcel source) {
-                    return new EuiccRat(source);
+                public EuiccRulesAuthTable createFromParcel(Parcel source) {
+                    return new EuiccRulesAuthTable(source);
                 }
 
                 @Override
-                public EuiccRat[] newArray(int size) {
-                    return new EuiccRat[size];
+                public EuiccRulesAuthTable[] newArray(int size) {
+                    return new EuiccRulesAuthTable[size];
                 }
             };
 }
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
index 4e095e3a..5197107 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.os.Message;
 import android.os.RemoteException;
+import android.telephony.ims.internal.stub.SmsImplBase;
 
 import com.android.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
@@ -28,6 +29,7 @@
 import com.android.ims.internal.IImsMMTelFeature;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.ImsCallSession;
 
@@ -171,6 +173,42 @@
                 return MMTelFeature.this.getMultiEndpointInterface();
             }
         }
+
+        @Override
+        public void setSmsListener(IImsSmsListener l) throws RemoteException {
+            synchronized (mLock) {
+                MMTelFeature.this.setSmsListener(l);
+            }
+        }
+
+        @Override
+        public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
+                byte[] pdu) {
+            synchronized (mLock) {
+                MMTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
+            }
+        }
+
+        @Override
+        public void acknowledgeSms(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MMTelFeature.this.acknowledgeSms(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public void acknowledgeSmsReport(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MMTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public String getSmsFormat() {
+            synchronized (mLock) {
+                return MMTelFeature.this.getSmsFormat();
+            }
+        }
     };
 
     /**
@@ -346,6 +384,39 @@
         return null;
     }
 
+    public void setSmsListener(IImsSmsListener listener) {
+        getSmsImplementation().registerSmsListener(listener);
+    }
+
+    public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
+    }
+
+    public void acknowledgeSms(int token, int messageRef,
+            @SmsImplBase.DeliverStatusResult int result) {
+        getSmsImplementation().acknowledgeSms(token, messageRef, result);
+    }
+
+    public void acknowledgeSmsReport(int token, int messageRef,
+            @SmsImplBase.StatusReportResult int result) {
+        getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
+    }
+
+    /**
+     * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
+     * non-functional implementation is returned.
+     *
+     * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider.
+     */
+    protected SmsImplBase getSmsImplementation() {
+        return new SmsImplBase();
+    }
+
+    public String getSmsFormat() {
+        return getSmsImplementation().getSmsFormat();
+    }
+
     @Override
     public void onFeatureReady() {
 
diff --git a/telephony/java/android/telephony/ims/internal/SmsImplBase.java b/telephony/java/android/telephony/ims/internal/SmsImplBase.java
index eb805a8..33b23d9 100644
--- a/telephony/java/android/telephony/ims/internal/SmsImplBase.java
+++ b/telephony/java/android/telephony/ims/internal/SmsImplBase.java
@@ -17,7 +17,6 @@
 package android.telephony.ims.internal;
 
 import android.annotation.IntDef;
-import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
@@ -37,6 +36,7 @@
 public class SmsImplBase {
   private static final String LOG_TAG = "SmsImplBase";
 
+  /** @hide */
   @IntDef({
           SEND_STATUS_OK,
           SEND_STATUS_ERROR,
@@ -68,6 +68,7 @@
    */
   public static final int SEND_STATUS_ERROR_FALLBACK = 4;
 
+  /** @hide */
   @IntDef({
           DELIVER_STATUS_OK,
           DELIVER_STATUS_ERROR
@@ -84,6 +85,7 @@
    */
   public static final int DELIVER_STATUS_ERROR = 2;
 
+  /** @hide */
   @IntDef({
           STATUS_REPORT_STATUS_OK,
           STATUS_REPORT_STATUS_ERROR
@@ -114,9 +116,9 @@
    * @hide
    */
   public final void registerSmsListener(IImsSmsListener listener) {
-    synchronized (mLock) {
-      mListener = listener;
-    }
+      synchronized (mLock) {
+          mListener = listener;
+      }
   }
 
   /**
@@ -128,8 +130,8 @@
    *             callbacks for this specific message.
    * @param messageRef the message reference.
    * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+   *               {@link SmsMessage#FORMAT_3GPP2}.
    * @param smsc the Short Message Service Center address.
-   * {@link SmsMessage#FORMAT_3GPP2}.
    * @param isRetry whether it is a retry of an already attempted message or not.
    * @param pdu PDUs representing the contents of the message.
    */
@@ -154,7 +156,7 @@
    * @param messageRef the message reference
    */
   public void acknowledgeSms(int token, int messageRef, @DeliverStatusResult int result) {
-
+    Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
   }
 
   /**
@@ -168,7 +170,7 @@
    * @param messageRef the message reference
    */
   public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
-
+    Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
   }
 
   /**
@@ -193,7 +195,6 @@
       }
       try {
         mListener.onSmsReceived(token, format, pdu);
-        acknowledgeSms(token, 0, DELIVER_STATUS_OK);
       } catch (RemoteException e) {
         Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
         acknowledgeSms(token, 0, DELIVER_STATUS_ERROR);
diff --git a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java b/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
new file mode 100644
index 0000000..113dad4
--- /dev/null
+++ b/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
@@ -0,0 +1,271 @@
+/*
+ * 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.telephony.ims.internal.stub;
+
+import android.annotation.IntDef;
+import android.os.RemoteException;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
+import android.telephony.ims.internal.feature.MmTelFeature;
+import android.util.Log;
+
+import com.android.ims.internal.IImsSmsListener;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base implementation for SMS over IMS.
+ *
+ * Any service wishing to provide SMS over IMS should extend this class and implement all methods
+ * that the service supports.
+ * @hide
+ */
+public class SmsImplBase {
+    private static final String LOG_TAG = "SmsImplBase";
+
+    @IntDef({
+            SEND_STATUS_OK,
+            SEND_STATUS_ERROR,
+            SEND_STATUS_ERROR_RETRY,
+            SEND_STATUS_ERROR_FALLBACK
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SendStatusResult {}
+    /**
+     * Message was sent successfully.
+     */
+    public static final int SEND_STATUS_OK = 1;
+
+    /**
+     * IMS provider failed to send the message and platform should not retry falling back to sending
+     * the message using the radio.
+     */
+    public static final int SEND_STATUS_ERROR = 2;
+
+    /**
+     * IMS provider failed to send the message and platform should retry again after setting TP-RD bit
+     * to high.
+     */
+    public static final int SEND_STATUS_ERROR_RETRY = 3;
+
+    /**
+     * IMS provider failed to send the message and platform should retry falling back to sending
+     * the message using the radio.
+     */
+    public static final int SEND_STATUS_ERROR_FALLBACK = 4;
+
+    @IntDef({
+            DELIVER_STATUS_OK,
+            DELIVER_STATUS_ERROR
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeliverStatusResult {}
+    /**
+     * Message was delivered successfully.
+     */
+    public static final int DELIVER_STATUS_OK = 1;
+
+    /**
+     * Message was not delivered.
+     */
+    public static final int DELIVER_STATUS_ERROR = 2;
+
+    @IntDef({
+            STATUS_REPORT_STATUS_OK,
+            STATUS_REPORT_STATUS_ERROR
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StatusReportResult {}
+
+    /**
+     * Status Report was set successfully.
+     */
+    public static final int STATUS_REPORT_STATUS_OK = 1;
+
+    /**
+     * Error while setting status report.
+     */
+    public static final int STATUS_REPORT_STATUS_ERROR = 2;
+
+
+    // Lock for feature synchronization
+    private final Object mLock = new Object();
+    private IImsSmsListener mListener;
+
+    /**
+     * Registers a listener responsible for handling tasks like delivering messages.
+     *
+     * @param listener listener to register.
+     *
+     * @hide
+     */
+    public final void registerSmsListener(IImsSmsListener listener) {
+        synchronized (mLock) {
+            mListener = listener;
+        }
+    }
+
+    /**
+     * This method will be triggered by the platform when the user attempts to send an SMS. This
+     * method should be implemented by the IMS providers to provide implementation of sending an SMS
+     * over IMS.
+     *
+     * @param token unique token generated by the platform that should be used when triggering
+     *             callbacks for this specific message.
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     *               {@link SmsMessage#FORMAT_3GPP2}.
+     * @param smsc the Short Message Service Center address.
+     * @param isRetry whether it is a retry of an already attempted message or not.
+     * @param pdu PDUs representing the contents of the message.
+     */
+    public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        // Base implementation returns error. Should be overridden.
+        try {
+            onSendSmsResult(token, messageRef, SEND_STATUS_ERROR,
+                    SmsManager.RESULT_ERROR_GENERIC_FAILURE);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Can not send sms: " + e.getMessage());
+        }
+    }
+
+    /**
+     * This method will be triggered by the platform after {@link #onSmsReceived(int, String, byte[])}
+     * has been called to deliver the result to the IMS provider.
+     *
+     * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
+     * @param result result of delivering the message. Valid values are defined in
+     * {@link DeliverStatusResult}
+     * @param messageRef the message reference
+     */
+    public void acknowledgeSms(int token, int messageRef, @DeliverStatusResult int result) {
+        Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
+    }
+
+    /**
+     * This method will be triggered by the platform after
+     * {@link #onSmsStatusReportReceived(int, int, String, byte[])} has been called to provide the
+     * result to the IMS provider.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param result result of delivering the message. Valid values are defined in
+     * {@link StatusReportResult}
+     * @param messageRef the message reference
+     */
+    public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
+        Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
+    }
+
+    /**
+     * This method should be triggered by the IMS providers when there is an incoming message. The
+     * platform will deliver the message to the messages database and notify the IMS provider of the
+     * result by calling {@link #acknowledgeSms(int, int, int)}.
+     *
+     * This method must not be called before {@link MmTelFeature#onFeatureReady()} is called.
+     *
+     * @param token unique token generated by IMS providers that the platform will use to trigger
+     *              callbacks for this message.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDUs representing the contents of the message.
+     * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
+     */
+    public final void onSmsReceived(int token, String format, byte[] pdu)
+            throws IllegalStateException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsReceived(token, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
+                acknowledgeSms(token, 0, DELIVER_STATUS_ERROR);
+            }
+        }
+    }
+
+    /**
+     * This method should be triggered by the IMS providers to pass the result of the sent message
+     * to the platform.
+     *
+     * This method must not be called before {@link MmTelFeature#onFeatureReady()} is called.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
+     * @param status result of sending the SMS. Valid values are defined in {@link SendStatusResult}
+     * @param reason reason in case status is failure. Valid values are:
+     *  {@link SmsManager#RESULT_ERROR_NONE},
+     *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
+     *  {@link SmsManager#RESULT_ERROR_RADIO_OFF},
+     *  {@link SmsManager#RESULT_ERROR_NULL_PDU},
+     *  {@link SmsManager#RESULT_ERROR_NO_SERVICE},
+     *  {@link SmsManager#RESULT_ERROR_LIMIT_EXCEEDED},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NOT_ALLOWED},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED}
+     * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
+     * @throws RemoteException if the connection to the framework is not available. If this happens
+     *  attempting to send the SMS should be aborted.
+     */
+    public final void onSendSmsResult(int token, int messageRef, @SendStatusResult int status,
+            int reason) throws IllegalStateException, RemoteException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Feature not ready.");
+            }
+            mListener.onSendSmsResult(token, messageRef, status, reason);
+        }
+    }
+
+    /**
+     * Sets the status report of the sent message.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDUs representing the content of the status report.
+     * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
+     */
+    public final void onSmsStatusReportReceived(int token, int messageRef, String format,
+            byte[] pdu) {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsStatusReportReceived(token, messageRef, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
+                acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
+            }
+        }
+    }
+
+    /**
+     * Returns the SMS format. Default is {@link SmsMessage#FORMAT_3GPP} unless overridden by IMS
+     * Provider.
+     *
+     * @return  the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     */
+    public String getSmsFormat() {
+      return SmsMessage.FORMAT_3GPP;
+    }
+}
diff --git a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
index 52b3853..cce39f4 100644
--- a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
+++ b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
@@ -25,6 +25,7 @@
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 
 import android.os.Message;
@@ -53,4 +54,11 @@
     IImsEcbm getEcbmInterface();
     void setUiTTYMode(int uiTtyMode, in Message onComplete);
     IImsMultiEndpoint getMultiEndpointInterface();
+    // SMS APIs
+    void setSmsListener(IImsSmsListener l);
+    oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
+            in byte[] pdu);
+    oneway void acknowledgeSms(int token, int messageRef, int result);
+    oneway void acknowledgeSmsReport(int token, int messageRef, int result);
+    String getSmsFormat();
 }
diff --git a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl b/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
new file mode 100644
index 0000000..5a4b7e4
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.ims.internal;
+
+/**
+ * See SmsImplBase for more information.
+ * {@hide}
+ */
+interface IImsSmsListener {
+    void onSendSmsResult(int token, int messageRef, int status, int reason);
+    void onSmsStatusReportReceived(int token, int messageRef, in String format,
+            in byte[] pdu);
+    void onSmsReceived(int token, in String format, in byte[] pdu);
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index f3d9335..d57f9af 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -30,16 +30,14 @@
     public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
     /* ABSENT means ICC is missing */
     public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+    /* PRESENT means ICC is present */
+    public static final String INTENT_VALUE_ICC_PRESENT = "PRESENT";
     /* CARD_IO_ERROR means for three consecutive times there was SIM IO error */
     static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR";
     /* CARD_RESTRICTED means card is present but not usable due to carrier restrictions */
     static public final String INTENT_VALUE_ICC_CARD_RESTRICTED = "CARD_RESTRICTED";
     /* LOCKED means ICC is locked by pin or by network */
     public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
-    //TODO: we can remove this state in the future if Bug 18489776 analysis
-    //#42's first race condition is resolved
-    /* INTERNAL LOCKED means ICC is locked by pin or by network */
-    public static final String INTENT_VALUE_ICC_INTERNAL_LOCKED = "INTERNAL_LOCKED";
     /* READY means ICC is ready to access */
     public static final String INTENT_VALUE_ICC_READY = "READY";
     /* IMSI means ICC IMSI is ready in property */
@@ -77,7 +75,8 @@
         NOT_READY,      /** ordinal(6) == {@See TelephonyManager#SIM_STATE_NOT_READY} */
         PERM_DISABLED,  /** ordinal(7) == {@See TelephonyManager#SIM_STATE_PERM_DISABLED} */
         CARD_IO_ERROR,  /** ordinal(8) == {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} */
-        CARD_RESTRICTED;/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */
+        CARD_RESTRICTED,/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */
+        LOADED;         /** ordinal(9) == {@See TelephonyManager#SIM_STATE_LOADED} */
 
         public boolean isPinLocked() {
             return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED));
@@ -85,9 +84,9 @@
 
         public boolean iccCardExist() {
             return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)
-                    || (this == NETWORK_LOCKED) || (this == READY)
+                    || (this == NETWORK_LOCKED) || (this == READY) || (this == NOT_READY)
                     || (this == PERM_DISABLED) || (this == CARD_IO_ERROR)
-                    || (this == CARD_RESTRICTED));
+                    || (this == CARD_RESTRICTED) || (this == LOADED));
         }
 
         public static State intToState(int state) throws IllegalArgumentException {
@@ -102,6 +101,7 @@
                 case 7: return PERM_DISABLED;
                 case 8: return CARD_IO_ERROR;
                 case 9: return CARD_RESTRICTED;
+                case 10: return LOADED;
                 default:
                     throw new IllegalArgumentException();
             }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl
similarity index 71%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl
index 4200de1..8a77bf1 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IAuthenticateServerCallback {
+    void onComplete(int resultCode, in byte[] response);
+}
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl
similarity index 72%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl
index f14e93f..f6b99e2 100644
--- a/core/java/android/os/Seccomp.java
+++ b/telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.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.
@@ -13,12 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.os;
-
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface ICancelSessionCallback {
+    void onComplete(int resultCode, in byte[] response);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IDeleteProfileCallback.aidl
similarity index 74%
rename from core/java/android/os/Seccomp.java
rename to telephony/java/com/android/internal/telephony/euicc/IDeleteProfileCallback.aidl
index f14e93f..23a642e 100644
--- a/core/java/android/os/Seccomp.java
+++ b/telephony/java/com/android/internal/telephony/euicc/IDeleteProfileCallback.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.
@@ -13,12 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.os;
-
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface IDeleteProfileCallback {
+    void onComplete(int resultCode);
 }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.aidl
similarity index 69%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.aidl
index 4200de1..3ee0b3a 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.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.
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
+import android.service.euicc.EuiccProfileInfo;
 
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IDisableProfileCallback {
+    void onComplete(int resultCode);
+}
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
index 2846a1a..abc55c7 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
@@ -17,8 +17,66 @@
 package com.android.internal.telephony.euicc;
 
 import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
+import com.android.internal.telephony.euicc.IGetProfileCallback;
+import com.android.internal.telephony.euicc.IDisableProfileCallback;
+import com.android.internal.telephony.euicc.ISwitchToProfileCallback;
+import com.android.internal.telephony.euicc.ISetNicknameCallback;
+import com.android.internal.telephony.euicc.IDeleteProfileCallback;
+import com.android.internal.telephony.euicc.IResetMemoryCallback;
+import com.android.internal.telephony.euicc.IGetDefaultSmdpAddressCallback;
+import com.android.internal.telephony.euicc.IGetSmdsAddressCallback;
+import com.android.internal.telephony.euicc.ISetDefaultSmdpAddressCallback;
+import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
+import com.android.internal.telephony.euicc.ICancelSessionCallback;
+import com.android.internal.telephony.euicc.IGetEuiccChallengeCallback;
+import com.android.internal.telephony.euicc.IGetEuiccInfo1Callback;
+import com.android.internal.telephony.euicc.IGetEuiccInfo2Callback;
+import com.android.internal.telephony.euicc.IGetRulesAuthTableCallback;
+import com.android.internal.telephony.euicc.IListNotificationsCallback;
+import com.android.internal.telephony.euicc.ILoadBoundProfilePackageCallback;
+import com.android.internal.telephony.euicc.IPrepareDownloadCallback;
+import com.android.internal.telephony.euicc.IRemoveNotificationFromListCallback;
+import com.android.internal.telephony.euicc.IRetrieveNotificationCallback;
+import com.android.internal.telephony.euicc.IRetrieveNotificationListCallback;
 
 /** @hide */
 interface IEuiccCardController {
     oneway void getAllProfiles(String callingPackage, in IGetAllProfilesCallback callback);
+    oneway void getProfile(String callingPackage, String iccid, in IGetProfileCallback callback);
+    oneway void disableProfile(String callingPackage, String iccid, boolean refresh,
+        in IDisableProfileCallback callback);
+    oneway void switchToProfile(String callingPackage, String iccid, boolean refresh,
+        in ISwitchToProfileCallback callback);
+    String getEid();
+    oneway void setNickname(String callingPackage, String iccid, String nickname,
+        in ISetNicknameCallback callback);
+    oneway void deleteProfile(String callingPackage, String iccid,
+        in IDeleteProfileCallback callback);
+    oneway void resetMemory(String callingPackage, int options, in IResetMemoryCallback callback);
+    oneway void getDefaultSmdpAddress(String callingPackage,
+        in IGetDefaultSmdpAddressCallback callback);
+    oneway void getSmdsAddress(String callingPackage, in IGetSmdsAddressCallback callback);
+    oneway void setDefaultSmdpAddress(String callingPackage, String address,
+        in ISetDefaultSmdpAddressCallback callback);
+    oneway void getRulesAuthTable(String callingPackage, in IGetRulesAuthTableCallback callback);
+    oneway void getEuiccChallenge(String callingPackage, in IGetEuiccChallengeCallback callback);
+    oneway void getEuiccInfo1(String callingPackage, in IGetEuiccInfo1Callback callback);
+    oneway void getEuiccInfo2(String callingPackage, in IGetEuiccInfo2Callback callback);
+    oneway void authenticateServer(String callingPackage, String matchingId,
+        in byte[] serverSigned1, in byte[] serverSignature1, in byte[] euiccCiPkIdToBeUsed,
+        in byte[] serverCertificatein, in IAuthenticateServerCallback callback);
+    oneway void prepareDownload(String callingPackage, in byte[] hashCc, in byte[] smdpSigned2,
+        in byte[] smdpSignature2, in byte[] smdpCertificate, in IPrepareDownloadCallback callback);
+    oneway void loadBoundProfilePackage(String callingPackage, in byte[] boundProfilePackage,
+        in ILoadBoundProfilePackageCallback callback);
+    oneway void cancelSession(String callingPackage, in byte[] transactionId, int reason,
+        in ICancelSessionCallback callback);
+    oneway void listNotifications(String callingPackage, int events,
+        in IListNotificationsCallback callback);
+    oneway void retrieveNotificationList(String callingPackage, int events,
+        in IRetrieveNotificationListCallback callback);
+    oneway void retrieveNotification(String callingPackage, int seqNumber,
+        in IRetrieveNotificationCallback callback);
+    oneway void removeNotificationFromList(String callingPackage, int seqNumber,
+            in IRemoveNotificationFromListCallback callback);
 }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.aidl
similarity index 71%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.aidl
index 4200de1..79b659d 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetDefaultSmdpAddressCallback {
+    void onComplete(int resultCode, String address);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl
similarity index 71%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl
index 4200de1..5ffb340 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetEuiccChallengeCallback {
+    void onComplete(int resultCode, in byte[] challenge);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl
similarity index 72%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl
index 4200de1..9592acb 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetEuiccInfo1Callback {
+    void onComplete(int resultCode, in byte[] info);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl
similarity index 72%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl
index 4200de1..5256b35 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetEuiccInfo2Callback {
+    void onComplete(int resultCode, in byte[] info);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.aidl
similarity index 67%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.aidl
index 4200de1..e9fc9e9 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.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.
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
+import android.service.euicc.EuiccProfileInfo;
 
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetProfileCallback {
+    void onComplete(int resultCode, in EuiccProfileInfo profile);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl
similarity index 66%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl
index 4200de1..58f0bde 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.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.
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
+import android.telephony.euicc.EuiccRulesAuthTable;
 
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetRulesAuthTableCallback {
+    void onComplete(int resultCode, in EuiccRulesAuthTable rat);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.aidl
similarity index 72%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.aidl
index 4200de1..09a83aa 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IGetSmdsAddressCallback {
+    void onComplete(int resultCode, String address);
+}
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl
similarity index 66%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl
index f14e93f..65aa302 100644
--- a/core/java/android/os/Seccomp.java
+++ b/telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.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.
@@ -13,12 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.os;
+import android.telephony.euicc.EuiccNotification;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface IListNotificationsCallback {
+    void onComplete(int resultCode, in EuiccNotification[] notifications);
 }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl
similarity index 71%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl
index 4200de1..4ad7081 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface ILoadBoundProfilePackageCallback {
+    void onComplete(int resultCode, in byte[] response);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl
similarity index 71%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl
index 4200de1..c035184 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IPrepareDownloadCallback {
+    void onComplete(int resultCode, in byte[] response);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl
similarity index 68%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl
index 4200de1..b22d0da 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.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.
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
+import android.telephony.euicc.EuiccNotification;
 
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IRemoveNotificationFromListCallback {
+    void onComplete(int resultCode);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.aidl
similarity index 74%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.aidl
index 4200de1..860c158 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IResetMemoryCallback {
+    void onComplete(int resultCode);
+}
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl
similarity index 66%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl
index f14e93f..dd8889a9 100644
--- a/core/java/android/os/Seccomp.java
+++ b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.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.
@@ -13,12 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.os;
+import android.telephony.euicc.EuiccNotification;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface IRetrieveNotificationCallback {
+    void onComplete(int resultCode, in EuiccNotification notification);
 }
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl
similarity index 65%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl
index 4200de1..bc4e451 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.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.
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
+import android.telephony.euicc.EuiccNotification;
 
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface IRetrieveNotificationListCallback {
+    void onComplete(int resultCode, in EuiccNotification[] notifications);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl
similarity index 73%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl
index 4200de1..1e47125 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface ISetDefaultSmdpAddressCallback {
+    void onComplete(int resultCode);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl
similarity index 74%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl
index 4200de1..5899980 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.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.
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
-
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface ISetNicknameCallback {
+    void onComplete(int resultCode);
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl
similarity index 67%
copy from core/java/android/security/keystore/RecoveryData.aidl
copy to telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl
index 4200de1..21ff084 100644
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.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.
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.security.keystore;
+import android.service.euicc.EuiccProfileInfo;
 
-/* @hide */
-parcelable RecoveryData;
+/** @hide */
+oneway interface ISwitchToProfileCallback {
+    void onComplete(int resultCode, in EuiccProfileInfo profile);
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java b/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java
index 11ea361..4ab38a6 100644
--- a/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java
+++ b/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java
@@ -24,6 +24,7 @@
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        TestHelper.initHeaderState(this);
         super.onCreate(savedInstanceState);
         BitmapLoader.clear();
         TestHelper.initBackground(getActivity());
diff --git a/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java b/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java
index 2bf3885..bf408f7 100644
--- a/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java
+++ b/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java
@@ -40,6 +40,7 @@
     public static final String EXTRA_CARD_ROUND_RECT = "extra_card_round_rect";
     public static final String EXTRA_ENTRANCE_TRANSITION = "extra_entrance_transition";
     public static final String EXTRA_BITMAP_UPLOAD = "extra_bitmap_upload";
+    public static final String EXTRA_SHOW_FAST_LANE = "extra_show_fast_lane";
 
     /**
      * Dont change the default values, they gave baseline for measuring the performance
@@ -53,6 +54,7 @@
     static final boolean DEFAULT_CARD_SHADOW = true;
     static final boolean DEFAULT_CARD_ROUND_RECT = true;
     static final boolean DEFAULT_BITMAP_UPLOAD = true;
+    static final boolean DEFAULT_SHOW_FAST_LANE = true;
 
     static long sCardIdSeed = 0;
     static long sRowIdSeed = 0;
@@ -235,4 +237,11 @@
             manager.setBitmap(bitmap);
         }
     }
+
+    public static void initHeaderState(BrowseFragment fragment) {
+        if (!fragment.getActivity().getIntent()
+                .getBooleanExtra(EXTRA_SHOW_FAST_LANE, DEFAULT_SHOW_FAST_LANE)) {
+            fragment.setHeadersState(BrowseFragment.HEADERS_HIDDEN);
+        }
+    }
 }
diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java
index 52da79a..f3c22a5 100644
--- a/tests/net/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/java/android/net/LinkPropertiesTest.java
@@ -79,6 +79,9 @@
         assertTrue(source.isIdenticalDnses(target));
         assertTrue(target.isIdenticalDnses(source));
 
+        assertTrue(source.isIdenticalPrivateDns(target));
+        assertTrue(target.isIdenticalPrivateDns(source));
+
         assertTrue(source.isIdenticalRoutes(target));
         assertTrue(target.isIdenticalRoutes(source));
 
@@ -91,6 +94,9 @@
         assertTrue(source.isIdenticalMtu(target));
         assertTrue(target.isIdenticalMtu(source));
 
+        assertTrue(source.isIdenticalTcpBufferSizes(target));
+        assertTrue(target.isIdenticalTcpBufferSizes(source));
+
         // Check result of equals().
         assertTrue(source.equals(target));
         assertTrue(target.equals(source));
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 1ddab5b..4fbb228 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -353,7 +353,7 @@
     @Test
     public void testRemoveTransportModeTransform() throws Exception {
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-        mIpSecService.removeTransportModeTransforms(pfd, 1);
+        mIpSecService.removeTransportModeTransforms(pfd);
 
         verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
     }
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index b2a27e8..3eba881 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -423,7 +423,7 @@
     @Test
     public void testRemoveTransportModeTransform() throws Exception {
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-        mIpSecService.removeTransportModeTransforms(pfd, 1);
+        mIpSecService.removeTransportModeTransforms(pfd);
 
         verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
     }
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index c29363c..1dbf9b2 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -22,6 +22,7 @@
 import static android.content.pm.UserInfo.FLAG_RESTRICTED;
 import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -436,11 +437,13 @@
                 .addTransportType(TRANSPORT_CELLULAR)
                 .addCapability(NET_CAPABILITY_INTERNET)
                 .addCapability(NET_CAPABILITY_NOT_METERED)
+                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
                 .setLinkDownstreamBandwidthKbps(10));
         networks.put(wifi, new NetworkCapabilities()
                 .addTransportType(TRANSPORT_WIFI)
                 .addCapability(NET_CAPABILITY_INTERNET)
                 .addCapability(NET_CAPABILITY_NOT_ROAMING)
+                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
                 .setLinkUpstreamBandwidthKbps(20));
         setMockedNetworks(networks);
 
@@ -454,6 +457,7 @@
         assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
         Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile }, caps);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
@@ -463,6 +467,7 @@
         assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
         Vpn.updateCapabilities(mConnectivityManager, new Network[] { wifi }, caps);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
@@ -472,6 +477,7 @@
         assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
         Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile, wifi }, caps);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
@@ -481,6 +487,7 @@
         assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
     }
 
     /**
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 8552195..069360e 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -306,10 +306,25 @@
 }
 
 // A value that represents a primitive data type (float, int, boolean, etc.).
-// Corresponds to the fields (type/data) of the C struct android::Res_value.
 message Primitive {
-  uint32 type = 1;
-  uint32 data = 2;
+  message NullType {
+  }
+  message EmptyType {
+  }
+  oneof oneof_value {
+    NullType null_value = 1;
+    EmptyType empty_value = 2;
+    float float_value = 3;
+    float dimension_value = 4;
+    float fraction_value = 5;
+    int32 int_decimal_value = 6;
+    uint32 int_hexidecimal_value = 7;
+    bool boolean_value = 8;
+    uint32 color_argb8_value = 9;
+    uint32 color_rgb8_value = 10;
+    uint32 color_argb4_value = 11;
+    uint32 color_rgb4_value = 12;
+  }
 }
 
 // A value that represents an XML attribute and what values it accepts.
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 964dacf..d80307c 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -47,7 +47,7 @@
   virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
                             IArchiveWriter* writer) = 0;
   virtual bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) = 0;
-  virtual bool SerializeFile(const FileReference* file, IArchiveWriter* writer) = 0;
+  virtual bool SerializeFile(FileReference* file, IArchiveWriter* writer) = 0;
 
   virtual ~IApkSerializer() = default;
 
@@ -65,19 +65,15 @@
   }
 
   if (apk->GetResourceTable() != nullptr) {
-    // Resource table
-    if (!serializer->SerializeTable(apk->GetResourceTable(), writer)) {
-      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                       << "failed to serialize the resource table");
-      return false;
-    }
+    // The table might be modified by below code.
+    auto converted_table = apk->GetResourceTable();
 
     // Resources
-    for (const auto& package : apk->GetResourceTable()->packages) {
+    for (const auto& package : converted_table->packages) {
       for (const auto& type : package->types) {
         for (const auto& entry : type->entries) {
           for (const auto& config_value : entry->values) {
-            const FileReference* file = ValueCast<FileReference>(config_value->value.get());
+            FileReference* file = ValueCast<FileReference>(config_value->value.get());
             if (file != nullptr) {
               if (file->file == nullptr) {
                 context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
@@ -95,6 +91,13 @@
         } // entry
       } // type
     } // package
+
+    // Converted resource table
+    if (!serializer->SerializeTable(converted_table, writer)) {
+      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                       << "failed to serialize the resource table");
+      return false;
+    }
   }
 
   // Other files
@@ -158,7 +161,7 @@
                                         ArchiveEntry::kAlign, writer);
   }
 
-  bool SerializeFile(const FileReference* file, IArchiveWriter* writer) override {
+  bool SerializeFile(FileReference* file, IArchiveWriter* writer) override {
     if (file->type == ResourceFile::Type::kProtoXml) {
       unique_ptr<io::InputStream> in = file->file->OpenInputStream();
       if (in == nullptr) {
@@ -189,6 +192,8 @@
                                           << "failed to serialize to binary XML: " << *file->path);
         return false;
       }
+
+      file->type = ResourceFile::Type::kBinaryXml;
     } else {
       if (!io::CopyFileToArchivePreserveCompression(context_, file->file, *file->path, writer)) {
         context_->GetDiagnostics()->Error(DiagMessage(source_)
@@ -225,7 +230,7 @@
                                   ArchiveEntry::kCompress, writer);
   }
 
-  bool SerializeFile(const FileReference* file, IArchiveWriter* writer) override {
+  bool SerializeFile(FileReference* file, IArchiveWriter* writer) override {
     if (file->type == ResourceFile::Type::kBinaryXml) {
       std::unique_ptr<io::IData> data = file->file->OpenAsData();
       if (!data) {
@@ -247,6 +252,8 @@
                                           << "failed to serialize to proto XML: " << *file->path);
         return false;
       }
+
+      file->type = ResourceFile::Type::kProtoXml;
     } else {
       if (!io::CopyFileToArchivePreserveCompression(context_, file->file, *file->path, writer)) {
         context_->GetDiagnostics()->Error(DiagMessage(source_)
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index d8635a9..064878b 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -23,6 +23,7 @@
 #include "Locale.h"
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
+#include "ResourceValues.h"
 #include "ValueVisitor.h"
 
 using ::android::ResStringPool;
@@ -761,8 +762,66 @@
 
     case pb::Item::kPrim: {
       const pb::Primitive& pb_prim = pb_item.prim();
-      return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
-                                                pb_prim.data());
+      android::Res_value val = {};
+      switch (pb_prim.oneof_value_case()) {
+        case pb::Primitive::kNullValue: {
+          val.dataType = android::Res_value::TYPE_NULL;
+          val.data = android::Res_value::DATA_NULL_UNDEFINED;
+        } break;
+        case pb::Primitive::kEmptyValue: {
+          val.dataType = android::Res_value::TYPE_NULL;
+          val.data = android::Res_value::DATA_NULL_EMPTY;
+        } break;
+        case pb::Primitive::kFloatValue: {
+          val.dataType = android::Res_value::TYPE_FLOAT;
+          float float_val = pb_prim.float_value();
+          val.data = *(uint32_t*)&float_val;
+        } break;
+        case pb::Primitive::kDimensionValue: {
+          val.dataType = android::Res_value::TYPE_DIMENSION;
+          float dimen_val = pb_prim.dimension_value();
+          val.data = *(uint32_t*)&dimen_val;
+        } break;
+        case pb::Primitive::kFractionValue: {
+          val.dataType = android::Res_value::TYPE_FRACTION;
+          float fraction_val = pb_prim.fraction_value();
+          val.data = *(uint32_t*)&fraction_val;
+        } break;
+        case pb::Primitive::kIntDecimalValue: {
+          val.dataType = android::Res_value::TYPE_INT_DEC;
+          val.data = static_cast<uint32_t>(pb_prim.int_decimal_value());
+        } break;
+        case pb::Primitive::kIntHexidecimalValue: {
+          val.dataType = android::Res_value::TYPE_INT_HEX;
+          val.data = pb_prim.int_hexidecimal_value();
+        } break;
+        case pb::Primitive::kBooleanValue: {
+          val.dataType = android::Res_value::TYPE_INT_BOOLEAN;
+          val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0;
+        } break;
+        case pb::Primitive::kColorArgb8Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8;
+          val.data = pb_prim.color_argb8_value();
+        } break;
+        case pb::Primitive::kColorRgb8Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8;
+          val.data = pb_prim.color_rgb8_value();
+        } break;
+        case pb::Primitive::kColorArgb4Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4;
+          val.data = pb_prim.color_argb4_value();
+        } break;
+        case pb::Primitive::kColorRgb4Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4;
+          val.data = pb_prim.color_rgb4_value();
+        } break;
+        default: {
+          LOG(FATAL) << "Unexpected Primitive type: "
+                     << static_cast<uint32_t>(pb_prim.oneof_value_case());
+          return {};
+        } break;
+      }
+      return util::make_unique<BinaryPrimitive>(val);
     } break;
 
     case pb::Item::kId: {
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 78f1281..e9622f5 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -436,8 +436,51 @@
     prim->Flatten(&val);
 
     pb::Primitive* pb_prim = out_value_->mutable_item()->mutable_prim();
-    pb_prim->set_type(val.dataType);
-    pb_prim->set_data(val.data);
+
+    switch (val.dataType) {
+      case android::Res_value::TYPE_NULL: {
+        if (val.data == android::Res_value::DATA_NULL_UNDEFINED) {
+          pb_prim->set_allocated_null_value(new pb::Primitive_NullType());
+        } else if (val.data == android::Res_value::DATA_NULL_EMPTY) {
+          pb_prim->set_allocated_empty_value(new pb::Primitive_EmptyType());
+        } else {
+          LOG(FATAL) << "Unexpected data value for TYPE_NULL BinaryPrimitive: " << val.data;
+        }
+      } break;
+      case android::Res_value::TYPE_FLOAT: {
+        pb_prim->set_float_value(*(float*)&val.data);
+      } break;
+      case android::Res_value::TYPE_DIMENSION: {
+        pb_prim->set_dimension_value(*(float*)&val.data);
+      } break;
+      case android::Res_value::TYPE_FRACTION: {
+        pb_prim->set_fraction_value(*(float*)&val.data);
+      } break;
+      case android::Res_value::TYPE_INT_DEC: {
+        pb_prim->set_int_decimal_value(static_cast<int32_t>(val.data));
+      } break;
+      case android::Res_value::TYPE_INT_HEX: {
+        pb_prim->set_int_hexidecimal_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_BOOLEAN: {
+        pb_prim->set_boolean_value(static_cast<bool>(val.data));
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_ARGB8: {
+        pb_prim->set_color_argb8_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_RGB8: {
+        pb_prim->set_color_rgb8_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_ARGB4: {
+        pb_prim->set_color_argb4_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_RGB4: {
+        pb_prim->set_color_rgb4_value(val.data);
+      } break;
+      default:
+        LOG(FATAL) << "Unexpected BinaryPrimitive type: " << val.dataType;
+        break;
+    }
   }
 
   void Visit(const Attribute* attr) override {
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index ccba5c6..9081ab6 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -254,6 +254,111 @@
   EXPECT_THAT(child_text->text, StrEq("woah there"));
 }
 
+TEST(ProtoSerializeTest, SerializeAndDeserializePrimitives) {
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .AddValue("android:bool/boolean_true",
+                    test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, true))
+          .AddValue("android:bool/boolean_false",
+                    test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, false))
+          .AddValue("android:color/color_rgb8", ResourceUtils::TryParseColor("#AABBCC"))
+          .AddValue("android:color/color_argb8", ResourceUtils::TryParseColor("#11223344"))
+          .AddValue("android:color/color_rgb4", ResourceUtils::TryParseColor("#DEF"))
+          .AddValue("android:color/color_argb4", ResourceUtils::TryParseColor("#5678"))
+          .AddValue("android:integer/integer_444", ResourceUtils::TryParseInt("444"))
+          .AddValue("android:integer/integer_neg_333", ResourceUtils::TryParseInt("-333"))
+          .AddValue("android:integer/hex_int_abcd", ResourceUtils::TryParseInt("0xABCD"))
+          .AddValue("android:dimen/dimen_1.39mm", ResourceUtils::TryParseFloat("1.39mm"))
+          .AddValue("android:fraction/fraction_27", ResourceUtils::TryParseFloat("27%"))
+          .AddValue("android:integer/null", ResourceUtils::MakeEmpty())
+          .Build();
+
+  pb::ResourceTable pb_table;
+  SerializeTableToPb(*table, &pb_table);
+
+  test::TestFile file_a("res/layout/main.xml");
+  MockFileCollection files;
+  EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
+      .WillRepeatedly(::testing::Return(&file_a));
+
+  ResourceTable new_table;
+  std::string error;
+  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
+  EXPECT_THAT(error, IsEmpty());
+
+  BinaryPrimitive* bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:bool/boolean_true", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("true")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:bool/boolean_false",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("false")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb8",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB8));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#AABBCC")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb8",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB8));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#11223344")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb4",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB4));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#DEF")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb4",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB4));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#5678")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/integer_444",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("444")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:integer/integer_neg_333", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("-333")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:integer/hex_int_abcd", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_HEX));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("0xABCD")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/dimen_1.39mm",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("1.39mm")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:fraction/fraction_27", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("27%")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/null",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_NULL));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::MakeEmpty()->value.data));
+}
+
 static void ExpectConfigSerializes(const StringPiece& config_str) {
   const ConfigDescription expected_config = test::ParseConfigOrDie(config_str);
   pb::Configuration pb_config;
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index b692ccf..f5f5b05 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -45,8 +45,18 @@
   Result result = Result::kAdded;
   auto iter = indexed_members_.find(member->GetName());
   if (iter != indexed_members_.end()) {
-    // Overwrite the entry.
-    ordered_members_[iter->second].reset();
+    // Overwrite the entry. Be careful, as the key in indexed_members_ is actually memory owned
+    // by the value at ordered_members_[index]. Since overwriting a value for a key doesn't replace
+    // the key (the initial key inserted into the unordered_map is kept), we must erase and then
+    // insert a new key, whose memory is being kept around. We do all this to avoid using more
+    // memory for each key.
+    size_t index = iter->second;
+
+    // Erase the key + value from the map.
+    indexed_members_.erase(iter);
+
+    // Now clear the memory that was backing the key (now erased).
+    ordered_members_[index].reset();
     result = Result::kOverridden;
   }
 
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index c324238..f4e10ab 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -129,13 +129,16 @@
   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android">
         <permission android:name="android.permission.ACCESS_INTERNET" />
-        <permission android:name="com.android.aapt.test.ACCESS_INTERNET" />
+        <permission android:name="com.android.sample.ACCESS_INTERNET" />
+        <permission android:name="com.android.permission.UNRELATED_PERMISSION" />
+        <permission android:name="com.android.aapt.test.ACCESS_INTERNET" /> -->
       </manifest>)");
 
   std::string actual;
   ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
   EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";"));
   EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";")));
+  EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"com.android.sample.ACCESS_INTERNET\";")));
 }
 
 static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res,
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index 15d39fd..ec40a222 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -270,6 +270,9 @@
             if index:
                 index = int(index)
 
+            if not path.exists(path.join(_fonts_dir, font_file)):
+                continue # Missing font is a valid case. Just ignore the missing font files.
+
             record = FontRecord(
                 name,
                 frozenset(scripts),
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
new file mode 100644
index 0000000..b8d2971
--- /dev/null
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -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.net.wifi;
+
+/**
+ * Interface for Soft AP callback.
+ *
+ * @hide
+ */
+oneway interface ISoftApCallback
+{
+    /**
+     * Service to manager callback providing current soft AP state. The possible
+     * parameter values listed are defined in WifiManager.java
+     *
+     * @param state new AP state. One of WIFI_AP_STATE_DISABLED,
+     *        WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED,
+     *        WIFI_AP_STATE_ENABLING, WIFI_AP_STATE_FAILED
+     * @param failureReason reason when in failed state. One of
+     *        SAP_START_FAILURE_GENERAL, SAP_START_FAILURE_NO_CHANNEL
+     */
+    void onStateChanged(int state, int failureReason);
+
+    /**
+     * Service to manager callback providing number of connected clients.
+     *
+     * @param numClients number of connected clients
+     */
+    void onNumClientsChanged(int numClients);
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 70d6ce4..e9e61a5 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -23,15 +23,15 @@
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.IProvisioningCallback;
 
+import android.net.DhcpInfo;
+import android.net.Network;
+import android.net.wifi.ISoftApCallback;
+import android.net.wifi.PasspointManagementObjectDefinition;
+import android.net.wifi.ScanResult;
+import android.net.wifi.ScanSettings;
+import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
-import android.net.wifi.ScanSettings;
-import android.net.wifi.ScanResult;
-import android.net.wifi.PasspointManagementObjectDefinition;
-import android.net.wifi.WifiActivityEnergyInfo;
-import android.net.Network;
-
-import android.net.DhcpInfo;
 
 import android.os.Messenger;
 import android.os.ResultReceiver;
@@ -178,5 +178,9 @@
     void restoreSupplicantBackupData(in byte[] supplicantData, in byte[] ipConfigData);
 
     void startSubscriptionProvisioning(in OsuProvider provider, in IProvisioningCallback callback);
+
+    void registerSoftApCallback(in IBinder binder, in ISoftApCallback callback, int callbackIdentifier);
+
+    void unregisterSoftApCallback(int callbackIdentifier);
 }
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index aa75a07..99080d6 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -55,6 +56,8 @@
 
 import dalvik.system.CloseGuard;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
 import java.util.Collections;
@@ -432,6 +435,17 @@
      */
     public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode";
 
+    /** @hide */
+    @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = {
+        WIFI_AP_STATE_DISABLING,
+        WIFI_AP_STATE_DISABLED,
+        WIFI_AP_STATE_ENABLING,
+        WIFI_AP_STATE_ENABLED,
+        WIFI_AP_STATE_FAILED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface WifiApState {}
+
     /**
      * Wi-Fi AP is currently being disabled. The state will change to
      * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
@@ -486,6 +500,14 @@
     @SystemApi
     public static final int WIFI_AP_STATE_FAILED = 14;
 
+    /** @hide */
+    @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = {
+        SAP_START_FAILURE_GENERAL,
+        SAP_START_FAILURE_NO_CHANNEL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SapStartFailure {}
+
     /**
      *  If WIFI AP start failed, this reason code means there is no legal channel exists on
      *  user selected band by regulatory
@@ -2324,6 +2346,119 @@
     }
 
     /**
+     * Base class for soft AP callback. Should be extended by applications and set when calling
+     * {@link WifiManager#registerSoftApCallback(SoftApCallback, Handler)}.
+     *
+     * @hide
+     */
+    public interface SoftApCallback {
+        /**
+         * Called when soft AP state changes.
+         *
+         * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED},
+         *        {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
+         *        {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
+         * @param failureReason reason when in failed state. One of
+         *        {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL}
+         */
+        public abstract void onStateChanged(@WifiApState int state,
+                @SapStartFailure int failureReason);
+
+        /**
+         * Called when number of connected clients to soft AP changes.
+         *
+         * @param numClients number of connected clients
+         */
+        public abstract void onNumClientsChanged(int numClients);
+    }
+
+    /**
+     * Callback proxy for SoftApCallback objects.
+     *
+     * @hide
+     */
+    private static class SoftApCallbackProxy extends ISoftApCallback.Stub {
+        private final Handler mHandler;
+        private final SoftApCallback mCallback;
+
+        SoftApCallbackProxy(Looper looper, SoftApCallback callback) {
+            mHandler = new Handler(looper);
+            mCallback = callback;
+        }
+
+        @Override
+        public void onStateChanged(int state, int failureReason) throws RemoteException {
+            Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" +
+                    failureReason);
+            mHandler.post(() -> {
+                mCallback.onStateChanged(state, failureReason);
+            });
+        }
+
+        @Override
+        public void onNumClientsChanged(int numClients) throws RemoteException {
+            Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients);
+            mHandler.post(() -> {
+                mCallback.onNumClientsChanged(numClients);
+            });
+        }
+    }
+
+    /**
+     * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the current
+     * soft AP state and number of connected devices immediately after a successful call to this API
+     * via callback. Note that receiving an immediate WIFI_AP_STATE_FAILED value for soft AP state
+     * indicates that the latest attempt to start soft AP has failed. Caller can unregister a
+     * previously registered callback using {@link unregisterSoftApCallback}
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param callback Callback for soft AP events
+     * @param handler  The Handler on whose thread to execute the callbacks of the {@code callback}
+     *                 object. If null, then the application's main thread will be used.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void registerSoftApCallback(@NonNull SoftApCallback callback,
+                                       @Nullable Handler handler) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler);
+
+        Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
+        Binder binder = new Binder();
+        try {
+            mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback),
+                    callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Allow callers to unregister a previously registered callback. After calling this method,
+     * applications will no longer receive soft AP events.
+     *
+     * @param callback Callback to unregister for soft AP events
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void unregisterSoftApCallback(@NonNull SoftApCallback callback) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);
+
+        try {
+            mService.unregisterSoftApCallback(callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * LocalOnlyHotspotReservation that contains the {@link WifiConfiguration} for the active
      * LocalOnlyHotspot request.
      * <p>
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 0df5615..4b5f645 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -24,11 +24,19 @@
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.*;
 
 import android.content.Context;
@@ -37,6 +45,7 @@
 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
+import android.net.wifi.WifiManager.SoftApCallback;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -66,6 +75,7 @@
     @Mock ApplicationInfo mApplicationInfo;
     @Mock WifiConfiguration mApConfig;
     @Mock IBinder mAppBinder;
+    @Mock SoftApCallback mSoftApCallback;
 
     private Handler mHandler;
     private TestLooper mLooper;
@@ -632,6 +642,149 @@
     }
 
     /**
+     * Verify an IllegalArgumentException is thrown if callback is not provided.
+     */
+    @Test
+    public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
+        try {
+            mWifiManager.registerSoftApCallback(null, mHandler);
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if callback is not provided.
+     */
+    @Test
+    public void unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
+        try {
+            mWifiManager.unregisterSoftApCallback(null);
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * Verify main looper is used when handler is not provided.
+     */
+    @Test
+    public void registerSoftApCallbackUsesMainLooperOnNullArgumentForHandler() {
+        when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        mWifiManager.registerSoftApCallback(mSoftApCallback, null);
+        verify(mContext).getMainLooper();
+    }
+
+    /**
+     * Verify the call to registerSoftApCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+                any(ISoftApCallback.Stub.class), anyInt());
+    }
+
+    /**
+     * Verify the call to unregisterSoftApCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
+        ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+                any(ISoftApCallback.Stub.class), callbackIdentifier.capture());
+
+        mWifiManager.unregisterSoftApCallback(mSoftApCallback);
+        verify(mWifiService).unregisterSoftApCallback(eq((int) callbackIdentifier.getValue()));
+    }
+
+    /*
+     * Verify client provided callback is being called through callback proxy
+     */
+    @Test
+    public void softApCallbackProxyCallsOnStateChanged() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+    }
+
+    /*
+     * Verify client provided callback is being called through callback proxy
+     */
+    @Test
+    public void softApCallbackProxyCallsOnNumClientsChanged() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        final int testNumClients = 3;
+        callbackCaptor.getValue().onNumClientsChanged(testNumClients);
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onNumClientsChanged(testNumClients);
+    }
+
+    /*
+     * Verify client provided callback is being called through callback proxy on multiple events
+     */
+    @Test
+    public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        final int testNumClients = 5;
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
+        callbackCaptor.getValue().onNumClientsChanged(testNumClients);
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
+
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
+        verify(mSoftApCallback).onNumClientsChanged(testNumClients);
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
+    }
+
+    /*
+     * Verify client provided callback is being called on the correct thread
+     */
+    @Test
+    public void softApCallbackIsCalledOnCorrectThread() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        TestLooper altLooper = new TestLooper();
+        Handler altHandler = new Handler(altLooper.getLooper());
+        mWifiManager.registerSoftApCallback(mSoftApCallback, altHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+        altLooper.dispatchAll();
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+    }
+
+    /**
+     * Verify that the handler provided by the caller is used for registering soft AP callback.
+     */
+    @Test
+    public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception {
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        mLooper.dispatchAll();
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+                any(ISoftApCallback.Stub.class), anyInt());
+        verify(mContext, never()).getMainLooper();
+    }
+
+    /**
      * Verify that the handler provided by the caller is used for the observer.
      */
     @Test