Merge "Put contacts/calendar providers in except-idle whitelist"
diff --git a/Android.bp b/Android.bp
index 2685ac3..ae4f974 100644
--- a/Android.bp
+++ b/Android.bp
@@ -324,6 +324,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 +466,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",
@@ -519,9 +523,30 @@
         "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/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/api/current.txt b/api/current.txt
index 8b0cb94..847671e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -602,6 +602,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 +799,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 +857,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 +5859,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 +6361,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 +6375,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,12 +6405,14 @@
     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);
     method public int getLockTaskFeatures(android.content.ComponentName);
     method public java.lang.String[] getLockTaskPackages(android.content.ComponentName);
     method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
+    method public android.content.ComponentName getMandatoryBackupTransport();
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
@@ -6431,6 +6441,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();
@@ -6493,6 +6504,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);
@@ -6502,6 +6514,7 @@
     method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
     method public void setLogoutEnabled(android.content.ComponentName, boolean);
     method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
+    method public void setMandatoryBackupTransport(android.content.ComponentName, android.content.ComponentName);
     method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
@@ -6535,6 +6548,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);
@@ -7066,8 +7080,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();
@@ -7084,6 +7098,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";
@@ -7153,7 +7168,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);
@@ -7172,7 +7190,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);
@@ -11154,7 +11172,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";
@@ -26217,12 +26235,18 @@
   }
 
   public final class IpSecManager {
-    method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
-    method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
-    method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
+    method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
+    method public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    method public void applyTransportModeTransform(java.net.Socket, int, android.net.IpSecTransform) throws java.io.IOException;
+    method public void applyTransportModeTransform(java.net.DatagramSocket, int, android.net.IpSecTransform) throws java.io.IOException;
+    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 removeTransportModeTransform(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
   }
 
   public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
@@ -26245,18 +26269,15 @@
 
   public final class IpSecTransform implements java.lang.AutoCloseable {
     method public void close();
-    field public static final int DIRECTION_IN = 0; // 0x0
-    field public static final int DIRECTION_OUT = 1; // 0x1
   }
 
   public static class IpSecTransform.Builder {
     ctor public IpSecTransform.Builder(android.content.Context);
-    method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
-    method public android.net.IpSecTransform.Builder setAuthenticatedEncryption(int, android.net.IpSecAlgorithm);
-    method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
-    method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    method public android.net.IpSecTransform.Builder setAuthenticatedEncryption(android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setAuthentication(android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setEncryption(android.net.IpSecAlgorithm);
     method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
-    method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
   }
 
   public class LinkAddress implements android.os.Parcelable {
@@ -26276,7 +26297,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;
   }
@@ -32204,6 +32227,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 {
@@ -32460,6 +32484,7 @@
     field public static final java.lang.String DISALLOW_CONFIG_LOCALE = "no_config_locale";
     field public static final java.lang.String DISALLOW_CONFIG_LOCATION_MODE = "no_config_location_mode";
     field public static final java.lang.String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
+    field public static final java.lang.String DISALLOW_CONFIG_SCREEN_TIMEOUT = "no_config_screen_timeout";
     field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
     field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn";
     field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
@@ -47984,7 +48009,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;
@@ -48037,6 +48061,8 @@
     method public void setPackageName(java.lang.CharSequence);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
+    field public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 16; // 0x10
+    field public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 32; // 0x20
     field public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 8; // 0x8
     field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1
     field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2
@@ -52505,6 +52531,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();
@@ -52522,6 +52549,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);
@@ -52618,6 +52646,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);
@@ -52639,7 +52668,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 002c2bd..a29d3a0 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);
@@ -1117,9 +1118,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 +3557,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
@@ -4454,6 +4456,8 @@
     method public deprecated void setDataEnabled(int, boolean);
     method public boolean setRadio(boolean);
     method public boolean setRadioPower(boolean);
+    method public void setSimPowerState(int);
+    method public void setSimPowerStateForSlot(int, int);
     method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
     method public void setVoiceActivationState(int);
     method public deprecated void silenceRinger();
@@ -4463,8 +4467,6 @@
     method public int[] supplyPukReportResult(java.lang.String, java.lang.String);
     method public void toggleRadioOnOff();
     method public void updateServiceLocation();
-    method public void setSimPowerState(int);
-    method public void setSimPowerStateForSlot(int, int);
     field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -4535,6 +4537,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 {
@@ -4647,9 +4681,12 @@
   }
 
   public final class StatsManager {
+    method public boolean addConfiguration(java.lang.String, byte[], java.lang.String, java.lang.String);
     method public boolean addConfiguration(long, byte[], java.lang.String, java.lang.String);
+    method public byte[] getData(java.lang.String);
     method public byte[] getData(long);
     method public byte[] getMetadata();
+    method public boolean removeConfiguration(java.lang.String);
     method public boolean removeConfiguration(long);
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 6941731..6369bb4 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 {
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 2ebbba6..2c35d41 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -199,6 +199,24 @@
 
 include $(BUILD_NATIVE_TEST)
 
+##############################
+# stats proto static java lib
+##############################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := statsdprotolite
+
+LOCAL_SRC_FILES := \
+    src/stats_log.proto \
+    src/statsd_config.proto \
+    src/atoms.proto
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := lite
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    platformprotoslite
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 statsd_common_src:=
 statsd_common_aidl_includes:=
@@ -209,4 +227,4 @@
 
 ##############################
 
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/cmds/statsd/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/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..dcb8eed 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -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/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 2596a5f..393f795 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -56,7 +56,9 @@
 }
 
 message CountMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
+
+  optional DimensionsValue dimensions_in_condition = 3;
 
   repeated CountBucketInfo bucket_info = 2;
 }
@@ -70,7 +72,9 @@
 }
 
 message DurationMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
+
+  optional DimensionsValue dimensions_in_condition = 3;
 
   repeated DurationBucketInfo bucket_info = 2;
 }
@@ -84,7 +88,9 @@
 }
 
 message ValueMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
+
+  optional DimensionsValue dimensions_in_condition = 3;
 
   repeated ValueBucketInfo bucket_info = 2;
 }
@@ -98,7 +104,9 @@
 }
 
 message GaugeMetricData {
-  optional DimensionsValue dimension = 1;
+  optional DimensionsValue dimensions_in_what = 1;
+
+  optional DimensionsValue dimensions_in_condition = 3;
 
   repeated GaugeBucketInfo bucket_info = 2;
 }
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index d45a6b0..ae8a835 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -178,11 +178,13 @@
 
     optional int64 condition = 3;
 
-    optional FieldMatcher dimensions = 4;
+    optional FieldMatcher dimensions_in_what = 4;
 
-    optional TimeUnit bucket = 5;
+    optional FieldMatcher dimensions_in_condition = 5;
 
-    repeated MetricConditionLink links = 6;
+    optional TimeUnit bucket = 6;
+
+    repeated MetricConditionLink links = 7;
 }
 
 message DurationMetric {
@@ -201,9 +203,11 @@
     }
     optional AggregationType aggregation_type = 5 [default = SUM];
 
-    optional FieldMatcher dimensions = 6;
+    optional FieldMatcher dimensions_in_what = 6;
 
-    optional TimeUnit bucket = 7;
+    optional FieldMatcher dimensions_in_condition = 7;
+
+    optional TimeUnit bucket = 8;
 }
 
 message GaugeMetric {
@@ -215,11 +219,13 @@
 
     optional int64 condition = 4;
 
-    optional FieldMatcher dimensions = 5;
+    optional FieldMatcher dimensions_in_what = 5;
 
-    optional TimeUnit bucket = 6;
+    optional FieldMatcher dimensions_in_condition = 6;
 
-    repeated MetricConditionLink links = 7;
+    optional TimeUnit bucket = 7;
+
+    repeated MetricConditionLink links = 8;
 }
 
 message ValueMetric {
@@ -231,14 +237,16 @@
 
     optional int64 condition = 4;
 
-    optional FieldMatcher dimensions = 5;
+    optional FieldMatcher dimensions_in_what = 5;
 
-    optional TimeUnit bucket = 6;
+    optional FieldMatcher dimensions_in_condition = 6;
 
-    repeated MetricConditionLink links = 7;
+    optional TimeUnit bucket = 7;
+
+    repeated MetricConditionLink links = 8;
 
     enum AggregationType { SUM = 1; }
-    optional AggregationType aggregation_type = 8 [default = SUM];
+    optional AggregationType aggregation_type = 9 [default = SUM];
 }
 
 message Alert {
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..178dd71 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -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/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/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 e334aab..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;
@@ -8633,6 +8630,13 @@
      *
      * <p> Backup service is off by default when device owner is present.
      *
+     * <p> If backups are made mandatory by specifying a non-null mandatory backup transport using
+     * the {@link DevicePolicyManager#setMandatoryBackupTransport} method, the backup service is
+     * automatically enabled.
+     *
+     * <p> If the backup service is disabled using this method after the mandatory backup transport
+     * has been set, the mandatory backup transport is cleared.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param enabled {@code true} to enable the backup service, {@code false} to disable it.
      * @throws SecurityException if {@code admin} is not a device owner.
@@ -8664,6 +8668,43 @@
     }
 
     /**
+     * Makes backups mandatory and enforces the usage of the specified backup transport.
+     *
+     * <p>When a {@code null} backup transport is specified, backups are made optional again.
+     * <p>Only device owner can call this method.
+     * <p>If backups were disabled and a non-null backup transport {@link ComponentName} is
+     * specified, backups will be enabled.
+     *
+     * @param admin admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param backupTransportComponent The backup transport layer to be used for mandatory backups.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public void setMandatoryBackupTransport(
+            @NonNull ComponentName admin, @Nullable ComponentName backupTransportComponent) {
+        try {
+            mService.setMandatoryBackupTransport(admin, backupTransportComponent);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the backup transport which has to be used for backups if backups are mandatory or
+     * {@code null} if backups are not mandatory.
+     *
+     * @return a {@link ComponentName} of the backup transport layer to be used if backups are
+     *         mandatory or {@code null} if backups are not mandatory.
+     */
+    public ComponentName getMandatoryBackupTransport() {
+        try {
+            return mService.getMandatoryBackupTransport();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+
+    /**
      * Called by a device owner to control the network logging feature.
      *
      * <p> Network logs contain DNS lookup and connect() library call events. The following library
@@ -8939,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
@@ -8958,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 {
@@ -9064,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
@@ -9080,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 7154053..eac7f7e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -359,6 +359,8 @@
 
     void setBackupServiceEnabled(in ComponentName admin, boolean enabled);
     boolean isBackupServiceEnabled(in ComponentName admin);
+    void setMandatoryBackupTransport(in ComponentName admin, in ComponentName backupTransportComponent);
+    ComponentName getMandatoryBackupTransport();
 
     void setNetworkLoggingEnabled(in ComponentName admin, boolean enabled);
     boolean isNetworkLoggingEnabled(in ComponentName admin);
@@ -389,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/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 792cb5f..f3ca746 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -294,7 +294,8 @@
      *
      * @param transport ComponentName of the service hosting the transport. This is different from
      *                  the transport's name that is returned by {@link BackupTransport#name()}.
-     * @param listener A listener object to get a callback on the transport being selected.
+     * @param listener A listener object to get a callback on the transport being selected. It may
+     *                 be {@code null}.
      *
      * @hide
      */
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 5053dc6..c71bf2e 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -70,6 +70,7 @@
     private final Network network;
 
     private int stopReason; // Default value of stopReason is REASON_CANCELED
+    private String debugStopReason; // Human readable stop reason for debugging.
 
     /** @hide */
     public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
@@ -104,6 +105,14 @@
     }
 
     /**
+     * Reason onStopJob() was called on this job.
+     * @hide
+     */
+    public String getDebugStopReason() {
+        return debugStopReason;
+    }
+
+    /**
      * @return The extras you passed in when constructing this job with
      * {@link android.app.job.JobInfo.Builder#setExtras(android.os.PersistableBundle)}. This will
      * never be null. If you did not set any extras this will be an empty bundle.
@@ -288,11 +297,13 @@
             network = null;
         }
         stopReason = in.readInt();
+        debugStopReason = in.readString();
     }
 
     /** @hide */
-    public void setStopReason(int reason) {
+    public void setStopReason(int reason, String debugStopReason) {
         stopReason = reason;
+        this.debugStopReason = debugStopReason;
     }
 
     @Override
@@ -323,6 +334,7 @@
             dest.writeInt(0);
         }
         dest.writeInt(stopReason);
+        dest.writeString(debugStopReason);
     }
 
     public static final Creator<JobParameters> CREATOR = new Creator<JobParameters>() {
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..db566e8 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1675,6 +1675,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
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/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index deb8dfb..44b4a33 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2535,31 +2535,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
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a18f22e..6d6c02a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6285,6 +6285,31 @@
                 + " " + packageName + "}";
         }
 
+        public String dumpState_temp() {
+            String flags = "";
+            flags += ((applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ? "U" : "");
+            flags += ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? "S" : "");
+            if ("".equals(flags)) {
+                flags = "-";
+            }
+            String privFlags = "";
+            privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ? "P" : "");
+            privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0 ? "O" : "");
+            privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0 ? "V" : "");
+            if ("".equals(privFlags)) {
+                privFlags = "-";
+            }
+            return "Package{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + packageName
+            + ", ver:" + getLongVersionCode()
+            + ", path: " + codePath
+            + ", flags: " + flags
+            + ", privFlags: " + privFlags
+            + ", extra: " + (mExtras == null ? "<<NULL>>" : Integer.toHexString(System.identityHashCode(mExtras)) + "}")
+            + "}";
+        }
+
         @Override
         public int describeContents() {
             return 0;
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 d9b57db..790c80b 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -31,7 +31,7 @@
 interface IIpSecService
 {
     IpSecSpiResponse allocateSecurityParameterIndex(
-            int direction, in String remoteAddress, int requestedSpi, in IBinder binder);
+            in String destinationAddress, int requestedSpi, in IBinder binder);
 
     void releaseSecurityParameterIndex(int resourceId);
 
@@ -43,7 +43,7 @@
 
     void deleteTransportModeTransform(int transformId);
 
-    void applyTransportModeTransform(in ParcelFileDescriptor socket, int transformId);
+    void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId);
 
-    void removeTransportModeTransform(in ParcelFileDescriptor socket, int transformId);
+    void removeTransportModeTransforms(in ParcelFileDescriptor socket);
 }
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 7d752e8..c69a4d4 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -256,13 +256,19 @@
         return getName().equals(AUTH_CRYPT_AES_GCM);
     }
 
+    // Because encryption keys are sensitive and userdebug builds are used by large user pools
+    // such as beta testers, we only allow sensitive info such as keys on eng builds.
+    private static boolean isUnsafeBuild() {
+        return Build.IS_DEBUGGABLE && Build.IS_ENG;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder()
                 .append("{mName=")
                 .append(mName)
                 .append(", mKey=")
-                .append(Build.IS_DEBUGGABLE ? HexDump.toHexString(mKey) : "<hidden>")
+                .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>")
                 .append(", mTruncLenBits=")
                 .append(mTruncLenBits)
                 .append("}")
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index f54ceb5..80b0af3 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -32,59 +32,29 @@
     // MODE_TRANSPORT or MODE_TUNNEL
     private int mMode = IpSecTransform.MODE_TRANSPORT;
 
-    // Needs to be valid only for tunnel mode
     // Preventing this from being null simplifies Java->Native binder
-    private String mLocalAddress = "";
+    private String mSourceAddress = "";
 
     // Preventing this from being null simplifies Java->Native binder
-    private String mRemoteAddress = "";
+    private String mDestinationAddress = "";
 
     // The underlying Network that represents the "gateway" Network
     // for outbound packets. It may also be used to select packets.
     private Network mNetwork;
 
-    /**
-     * This class captures the parameters that specifically apply to inbound or outbound traffic.
-     */
-    public static class Flow {
-        // Minimum requirements for identifying a transform
-        // SPI identifying the IPsec flow in packet processing
-        // and a remote IP address
-        private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
+    // Minimum requirements for identifying a transform
+    // SPI identifying the IPsec SA in packet processing
+    // and a destination IP address
+    private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
 
-        // Encryption Algorithm
-        private IpSecAlgorithm mEncryption;
+    // Encryption Algorithm
+    private IpSecAlgorithm mEncryption;
 
-        // Authentication Algorithm
-        private IpSecAlgorithm mAuthentication;
+    // Authentication Algorithm
+    private IpSecAlgorithm mAuthentication;
 
-        // Authenticated Encryption Algorithm
-        private IpSecAlgorithm mAuthenticatedEncryption;
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{mSpiResourceId=")
-                    .append(mSpiResourceId)
-                    .append(", mEncryption=")
-                    .append(mEncryption)
-                    .append(", mAuthentication=")
-                    .append(mAuthentication)
-                    .append(", mAuthenticatedEncryption=")
-                    .append(mAuthenticatedEncryption)
-                    .append("}")
-                    .toString();
-        }
-
-        static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) {
-            if (lhs == null || rhs == null) return (lhs == rhs);
-            return (lhs.mSpiResourceId == rhs.mSpiResourceId
-                    && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
-                    && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication));
-        }
-    }
-
-    private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()};
+    // Authenticated Encryption Algorithm
+    private IpSecAlgorithm mAuthenticatedEncryption;
 
     // For tunnel mode IPv4 UDP Encapsulation
     // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
@@ -100,36 +70,37 @@
         mMode = mode;
     }
 
-    /** Set the local IP address for Tunnel mode */
-    public void setLocalAddress(String localAddress) {
-        mLocalAddress = localAddress;
+    /** Set the source IP addres for this IPsec transform */
+    public void setSourceAddress(String sourceAddress) {
+        mSourceAddress = sourceAddress;
     }
 
-    /** Set the remote IP address for this IPsec transform */
-    public void setRemoteAddress(String remoteAddress) {
-        mRemoteAddress = remoteAddress;
+    /** Set the destination IP address for this IPsec transform */
+    public void setDestinationAddress(String destinationAddress) {
+        mDestinationAddress = destinationAddress;
     }
 
-    /** Set the SPI for a given direction by resource ID */
-    public void setSpiResourceId(int direction, int resourceId) {
-        mFlow[direction].mSpiResourceId = resourceId;
+    /** Set the SPI by resource ID */
+    public void setSpiResourceId(int resourceId) {
+        mSpiResourceId = resourceId;
     }
 
-    /** Set the encryption algorithm for a given direction */
-    public void setEncryption(int direction, IpSecAlgorithm encryption) {
-        mFlow[direction].mEncryption = encryption;
+    /** Set the encryption algorithm */
+    public void setEncryption(IpSecAlgorithm encryption) {
+        mEncryption = encryption;
     }
 
-    /** Set the authentication algorithm for a given direction */
-    public void setAuthentication(int direction, IpSecAlgorithm authentication) {
-        mFlow[direction].mAuthentication = authentication;
+    /** Set the authentication algorithm */
+    public void setAuthentication(IpSecAlgorithm authentication) {
+        mAuthentication = authentication;
     }
 
-    /** Set the authenticated encryption algorithm for a given direction */
-    public void setAuthenticatedEncryption(int direction, IpSecAlgorithm authenticatedEncryption) {
-        mFlow[direction].mAuthenticatedEncryption = authenticatedEncryption;
+    /** Set the authenticated encryption algorithm */
+    public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) {
+        mAuthenticatedEncryption = authenticatedEncryption;
     }
 
+    /** Set the underlying network that will carry traffic for this transform */
     public void setNetwork(Network network) {
         mNetwork = network;
     }
@@ -155,28 +126,28 @@
         return mMode;
     }
 
-    public String getLocalAddress() {
-        return mLocalAddress;
+    public String getSourceAddress() {
+        return mSourceAddress;
     }
 
-    public int getSpiResourceId(int direction) {
-        return mFlow[direction].mSpiResourceId;
+    public int getSpiResourceId() {
+        return mSpiResourceId;
     }
 
-    public String getRemoteAddress() {
-        return mRemoteAddress;
+    public String getDestinationAddress() {
+        return mDestinationAddress;
     }
 
-    public IpSecAlgorithm getEncryption(int direction) {
-        return mFlow[direction].mEncryption;
+    public IpSecAlgorithm getEncryption() {
+        return mEncryption;
     }
 
-    public IpSecAlgorithm getAuthentication(int direction) {
-        return mFlow[direction].mAuthentication;
+    public IpSecAlgorithm getAuthentication() {
+        return mAuthentication;
     }
 
-    public IpSecAlgorithm getAuthenticatedEncryption(int direction) {
-        return mFlow[direction].mAuthenticatedEncryption;
+    public IpSecAlgorithm getAuthenticatedEncryption() {
+        return mAuthenticatedEncryption;
     }
 
     public Network getNetwork() {
@@ -209,17 +180,13 @@
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mMode);
-        out.writeString(mLocalAddress);
-        out.writeString(mRemoteAddress);
+        out.writeString(mSourceAddress);
+        out.writeString(mDestinationAddress);
         out.writeParcelable(mNetwork, flags);
-        out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId);
-        out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags);
-        out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags);
-        out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption, flags);
-        out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId);
-        out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags);
-        out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags);
-        out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption, flags);
+        out.writeInt(mSpiResourceId);
+        out.writeParcelable(mEncryption, flags);
+        out.writeParcelable(mAuthentication, flags);
+        out.writeParcelable(mAuthenticatedEncryption, flags);
         out.writeInt(mEncapType);
         out.writeInt(mEncapSocketResourceId);
         out.writeInt(mEncapRemotePort);
@@ -231,22 +198,15 @@
 
     private IpSecConfig(Parcel in) {
         mMode = in.readInt();
-        mLocalAddress = in.readString();
-        mRemoteAddress = in.readString();
+        mSourceAddress = in.readString();
+        mDestinationAddress = in.readString();
         mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
-        mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt();
-        mFlow[IpSecTransform.DIRECTION_IN].mEncryption =
+        mSpiResourceId = in.readInt();
+        mEncryption =
                 (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mFlow[IpSecTransform.DIRECTION_IN].mAuthentication =
+        mAuthentication =
                 (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt();
-        mFlow[IpSecTransform.DIRECTION_OUT].mEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption =
+        mAuthenticatedEncryption =
                 (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
         mEncapType = in.readInt();
         mEncapSocketResourceId = in.readInt();
@@ -260,10 +220,10 @@
         strBuilder
                 .append("{mMode=")
                 .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
-                .append(", mLocalAddress=")
-                .append(mLocalAddress)
-                .append(", mRemoteAddress=")
-                .append(mRemoteAddress)
+                .append(", mSourceAddress=")
+                .append(mSourceAddress)
+                .append(", mDestinationAddress=")
+                .append(mDestinationAddress)
                 .append(", mNetwork=")
                 .append(mNetwork)
                 .append(", mEncapType=")
@@ -274,10 +234,14 @@
                 .append(mEncapRemotePort)
                 .append(", mNattKeepaliveInterval=")
                 .append(mNattKeepaliveInterval)
-                .append(", mFlow[OUT]=")
-                .append(mFlow[IpSecTransform.DIRECTION_OUT])
-                .append(", mFlow[IN]=")
-                .append(mFlow[IpSecTransform.DIRECTION_IN])
+                .append("{mSpiResourceId=")
+                .append(mSpiResourceId)
+                .append(", mEncryption=")
+                .append(mEncryption)
+                .append(", mAuthentication=")
+                .append(mAuthentication)
+                .append(", mAuthenticatedEncryption=")
+                .append(mAuthenticatedEncryption)
                 .append("}");
 
         return strBuilder.toString();
@@ -299,17 +263,18 @@
     public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) {
         if (lhs == null || rhs == null) return (lhs == rhs);
         return (lhs.mMode == rhs.mMode
-                && lhs.mLocalAddress.equals(rhs.mLocalAddress)
-                && lhs.mRemoteAddress.equals(rhs.mRemoteAddress)
+                && lhs.mSourceAddress.equals(rhs.mSourceAddress)
+                && lhs.mDestinationAddress.equals(rhs.mDestinationAddress)
                 && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork))
                         || (lhs.mNetwork == rhs.mNetwork))
                 && lhs.mEncapType == rhs.mEncapType
                 && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId
                 && lhs.mEncapRemotePort == rhs.mEncapRemotePort
                 && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
-                && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT],
-                        rhs.mFlow[IpSecTransform.DIRECTION_OUT])
-                && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN],
-                        rhs.mFlow[IpSecTransform.DIRECTION_IN]));
+                && lhs.mSpiResourceId == rhs.mSpiResourceId
+                && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
+                && IpSecAlgorithm.equals(
+                        lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
+                && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication));
     }
 }
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 34cfa9b..2cda58c 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -17,6 +17,7 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -33,6 +34,8 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.Socket;
@@ -53,6 +56,23 @@
     private static final String TAG = "IpSecManager";
 
     /**
+     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
+     * applies to traffic towards the host.
+     */
+    public static final int DIRECTION_IN = 0;
+
+    /**
+     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
+     * applies to traffic from the host.
+     */
+    public static final int DIRECTION_OUT = 1;
+
+    /** @hide */
+    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PolicyDirection {}
+
+    /**
      * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
      *
      * <p>No IPsec packet may contain an SPI of 0.
@@ -125,7 +145,7 @@
      */
     public static final class SecurityParameterIndex implements AutoCloseable {
         private final IIpSecService mService;
-        private final InetAddress mRemoteAddress;
+        private final InetAddress mDestinationAddress;
         private final CloseGuard mCloseGuard = CloseGuard.get();
         private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
         private int mResourceId = INVALID_RESOURCE_ID;
@@ -164,14 +184,14 @@
         }
 
         private SecurityParameterIndex(
-                @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi)
+                @NonNull IIpSecService service, InetAddress destinationAddress, int spi)
                 throws ResourceUnavailableException, SpiUnavailableException {
             mService = service;
-            mRemoteAddress = remoteAddress;
+            mDestinationAddress = destinationAddress;
             try {
                 IpSecSpiResponse result =
                         mService.allocateSecurityParameterIndex(
-                                direction, remoteAddress.getHostAddress(), spi, new Binder());
+                                destinationAddress.getHostAddress(), spi, new Binder());
 
                 if (result == null) {
                     throw new NullPointerException("Received null response from IpSecService");
@@ -216,25 +236,23 @@
     }
 
     /**
-     * Reserve a random SPI for traffic bound to or from the specified remote address.
+     * Reserve a random SPI for traffic bound to or from the specified destination address.
      *
      * <p>If successful, this SPI is guaranteed available until released by a call to {@link
      * SecurityParameterIndex#close()}.
      *
-     * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
-     * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress
+     * @param destinationAddress the destination address for traffic bearing the requested SPI.
+     *     For inbound traffic, the destination should be an address currently assigned on-device.
      * @return the reserved SecurityParameterIndex
-     * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
-     *     for this user
-     * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
+     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+     *     currently allocated for this user
      */
-    public SecurityParameterIndex allocateSecurityParameterIndex(
-            int direction, InetAddress remoteAddress) throws ResourceUnavailableException {
+    public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress)
+            throws ResourceUnavailableException {
         try {
             return new SecurityParameterIndex(
                     mService,
-                    direction,
-                    remoteAddress,
+                    destinationAddress,
                     IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
         } catch (SpiUnavailableException unlikely) {
             throw new ResourceUnavailableException("No SPIs available");
@@ -242,26 +260,27 @@
     }
 
     /**
-     * Reserve the requested SPI for traffic bound to or from the specified remote address.
+     * Reserve the requested SPI for traffic bound to or from the specified destination address.
      *
      * <p>If successful, this SPI is guaranteed available until released by a call to {@link
      * SecurityParameterIndex#close()}.
      *
-     * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
-     * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress
+     * @param destinationAddress the destination address for traffic bearing the requested SPI.
+     *     For inbound traffic, the destination should be an address currently assigned on-device.
      * @param requestedSpi the requested SPI, or '0' to allocate a random SPI
      * @return the reserved SecurityParameterIndex
-     * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
-     *     for this user
-     * @throws SpiUnavailableException indicating that the requested SPI could not be reserved
+     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+     *     currently allocated for this user
+     * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
+     *     reserved
      */
     public SecurityParameterIndex allocateSecurityParameterIndex(
-            int direction, InetAddress remoteAddress, int requestedSpi)
+            InetAddress destinationAddress, int requestedSpi)
             throws SpiUnavailableException, ResourceUnavailableException {
         if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
             throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
         }
-        return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi);
+        return new SecurityParameterIndex(mService, destinationAddress, requestedSpi);
     }
 
     /**
@@ -269,14 +288,14 @@
      *
      * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
      * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
-     * the transform is removed from the socket by calling {@link #removeTransportModeTransform},
+     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
      * unprotected traffic can resume on that socket.
      *
      * <p>For security reasons, the destination address of any traffic on the socket must match the
      * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
      * other IP address will result in an IOException. In addition, reads and writes on the socket
      * will throw IOException if the user deactivates the transform (by calling {@link
-     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}.
+     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
      *
      * <h4>Rekey Procedure</h4>
      *
@@ -287,15 +306,14 @@
      * in-flight packets have been received.
      *
      * @param socket a stream socket
+     * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
-     * @hide
      */
-    public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
+    public void applyTransportModeTransform(
+            Socket socket, int direction, IpSecTransform transform)
             throws IOException {
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
-            applyTransportModeTransform(pfd, transform);
-        }
+        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
     }
 
     /**
@@ -303,14 +321,14 @@
      *
      * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
      * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
-     * the transform is removed from the socket by calling {@link #removeTransportModeTransform},
+     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
      * unprotected traffic can resume on that socket.
      *
      * <p>For security reasons, the destination address of any traffic on the socket must match the
      * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
      * other IP address will result in an IOException. In addition, reads and writes on the socket
      * will throw IOException if the user deactivates the transform (by calling {@link
-     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}.
+     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
      *
      * <h4>Rekey Procedure</h4>
      *
@@ -321,15 +339,13 @@
      * in-flight packets have been received.
      *
      * @param socket a datagram socket
+     * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
-     * @hide
      */
-    public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
-            throws IOException {
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
-            applyTransportModeTransform(pfd, transform);
-        }
+    public void applyTransportModeTransform(
+            DatagramSocket socket, int direction, IpSecTransform transform) throws IOException {
+        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
     }
 
     /**
@@ -337,14 +353,14 @@
      *
      * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
      * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
-     * the transform is removed from the socket by calling {@link #removeTransportModeTransform},
+     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
      * unprotected traffic can resume on that socket.
      *
      * <p>For security reasons, the destination address of any traffic on the socket must match the
      * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
      * other IP address will result in an IOException. In addition, reads and writes on the socket
      * will throw IOException if the user deactivates the transform (by calling {@link
-     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}.
+     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
      *
      * <h4>Rekey Procedure</h4>
      *
@@ -355,24 +371,17 @@
      * in-flight packets have been received.
      *
      * @param socket a socket file descriptor
+     * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
-    public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+    public void applyTransportModeTransform(
+            FileDescriptor socket, int direction, IpSecTransform transform)
             throws IOException {
         // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
-        // constructor takes control and closes the user's FD when we exit the method
-        // This is behaviorally the same as the other versions, but the PFD constructor does not
-        // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup().
+        // constructor takes control and closes the user's FD when we exit the method.
         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
-            applyTransportModeTransform(pfd, transform);
-        }
-    }
-
-    /* Call down to activate a transform */
-    private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
-        try {
-            mService.applyTransportModeTransform(pfd, transform.getResourceId());
+            mService.applyTransportModeTransform(pfd, direction, transform.getResourceId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -396,75 +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
-     * @hide
      */
-    public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(Socket socket)
             throws IOException {
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
-            removeTransportModeTransform(pfd, 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
-     * @hide
      */
-    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(DatagramSocket socket)
             throws IOException {
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
-            removeTransportModeTransform(pfd, 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 removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(FileDescriptor socket)
             throws IOException {
         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
-            removeTransportModeTransform(pfd, transform);
-        }
-    }
-
-    /* Call down to remove a transform */
-    private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
-        try {
-            mService.removeTransportModeTransform(pfd, transform.getResourceId());
+            mService.removeTransportModeTransforms(pfd);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 102ba6d..7b9b483 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -38,13 +38,11 @@
 import java.net.InetAddress;
 
 /**
- * This class represents an IPsec transform, which comprises security associations in one or both
- * directions.
+ * This class represents a transform, which roughly corresponds to an IPsec Security Association.
  *
  * <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
- * object encapsulates the properties and state of an inbound and outbound IPsec security
- * association. That includes, but is not limited to, algorithm choice, key material, and allocated
- * system resources.
+ * object encapsulates the properties and state of an IPsec security association. That includes,
+ * but is not limited to, algorithm choice, key material, and allocated system resources.
  *
  * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
  *     Internet Protocol</a>
@@ -52,23 +50,6 @@
 public final class IpSecTransform implements AutoCloseable {
     private static final String TAG = "IpSecTransform";
 
-    /**
-     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
-     * applies to traffic towards the host.
-     */
-    public static final int DIRECTION_IN = 0;
-
-    /**
-     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
-     * applies to traffic from the host.
-     */
-    public static final int DIRECTION_OUT = 1;
-
-    /** @hide */
-    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface TransformDirection {}
-
     /** @hide */
     public static final int MODE_TRANSPORT = 0;
 
@@ -170,7 +151,7 @@
      *
      * <p>Deactivating a transform while it is still applied to a socket will result in errors on
      * that socket. Make sure to remove transforms by calling {@link
-     * IpSecManager#removeTransportModeTransform}. Note, removing an {@code IpSecTransform} from a
+     * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
      * socket will not deactivate it (because one transform may be applied to multiple sockets).
      *
      * <p>It is safe to call this method on a transform that has already been deactivated.
@@ -272,85 +253,49 @@
         private IpSecConfig mConfig;
 
         /**
-         * Set the encryption algorithm for the given direction.
-         *
-         * <p>If encryption is set for a direction without also providing an SPI for that direction,
-         * creation of an {@code IpSecTransform} will fail when attempting to build the transform.
+         * Set the encryption algorithm.
          *
          * <p>Encryption is mutually exclusive with authenticated encryption.
          *
-         * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
          * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
          */
-        public IpSecTransform.Builder setEncryption(
-                @TransformDirection int direction, IpSecAlgorithm algo) {
+        public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
-            mConfig.setEncryption(direction, algo);
+            Preconditions.checkNotNull(algo);
+            mConfig.setEncryption(algo);
             return this;
         }
 
         /**
-         * Set the authentication (integrity) algorithm for the given direction.
-         *
-         * <p>If authentication is set for a direction without also providing an SPI for that
-         * direction, creation of an {@code IpSecTransform} will fail when attempting to build the
-         * transform.
+         * Set the authentication (integrity) algorithm.
          *
          * <p>Authentication is mutually exclusive with authenticated encryption.
          *
-         * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
          * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
          */
-        public IpSecTransform.Builder setAuthentication(
-                @TransformDirection int direction, IpSecAlgorithm algo) {
+        public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
-            mConfig.setAuthentication(direction, algo);
+            Preconditions.checkNotNull(algo);
+            mConfig.setAuthentication(algo);
             return this;
         }
 
         /**
-         * Set the authenticated encryption algorithm for the given direction.
+         * Set the authenticated encryption algorithm.
          *
-         * <p>If an authenticated encryption algorithm is set for a given direction without also
-         * providing an SPI for that direction, creation of an {@code IpSecTransform} will fail when
-         * attempting to build the transform.
-         *
-         * <p>The Authenticated Encryption (AE) class of algorithms are also known as Authenticated
-         * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as
-         * referred to in <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
+         * <p>The Authenticated Encryption (AE) class of algorithms are also known as
+         * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
+         * algorithms (as referred to in
+         * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
          *
          * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
          *
-         * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
          * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
          *     be applied.
          */
-        public IpSecTransform.Builder setAuthenticatedEncryption(
-                @TransformDirection int direction, IpSecAlgorithm algo) {
-            mConfig.setAuthenticatedEncryption(direction, algo);
-            return this;
-        }
-
-        /**
-         * Set the SPI for the given direction.
-         *
-         * <p>Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies
-         * packets to a given destination address. To prevent SPI collisions, values should be
-         * reserved by calling {@link IpSecManager#allocateSecurityParameterIndex}.
-         *
-         * <p>If the SPI and algorithms are omitted for one direction, traffic in that direction
-         * will not be encrypted or authenticated.
-         *
-         * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
-         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
-         *     traffic
-         */
-        public IpSecTransform.Builder setSpi(
-                @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
-            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
-                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
-            }
-            mConfig.setSpiResourceId(direction, spi.getResourceId());
+        public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
+            Preconditions.checkNotNull(algo);
+            mConfig.setAuthenticatedEncryption(algo);
             return this;
         }
 
@@ -363,7 +308,8 @@
          * @hide
          */
         @SystemApi
-        public IpSecTransform.Builder setUnderlyingNetwork(Network net) {
+        public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) {
+            Preconditions.checkNotNull(net);
             mConfig.setNetwork(net);
             return this;
         }
@@ -382,7 +328,8 @@
          *     encapsulated traffic. In the case of IKEv2, this should be port 4500.
          */
         public IpSecTransform.Builder setIpv4Encapsulation(
-                IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
+                @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
+            Preconditions.checkNotNull(localSocket);
             mConfig.setEncapType(ENCAP_ESPINUDP);
             if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
@@ -419,24 +366,33 @@
          * will not affect any network traffic until it has been applied to one or more sockets.
          *
          * @see IpSecManager#applyTransportModeTransform
-         * @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use
-         *     this transform
+         * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
+         *     this transform; this address must belong to the Network used by all sockets that
+         *     utilize this transform; if provided, then only traffic originating from the
+         *     specified source address will be processed.
+         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
+         *     traffic
          * @throws IllegalArgumentException indicating that a particular combination of transform
          *     properties is invalid
-         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms are
-         *     active
+         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
+         *     are active
          * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
          *     collides with an existing transform
          * @throws IOException indicating other errors
          */
-        public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
+        public IpSecTransform buildTransportModeTransform(
+                @NonNull InetAddress sourceAddress,
+                @NonNull IpSecManager.SecurityParameterIndex spi)
                 throws IpSecManager.ResourceUnavailableException,
                         IpSecManager.SpiUnavailableException, IOException {
-            if (remoteAddress == null) {
-                throw new IllegalArgumentException("Remote address may not be null or empty!");
+            Preconditions.checkNotNull(sourceAddress);
+            Preconditions.checkNotNull(spi);
+            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
+                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
             }
             mConfig.setMode(MODE_TRANSPORT);
-            mConfig.setRemoteAddress(remoteAddress.getHostAddress());
+            mConfig.setSourceAddress(sourceAddress.getHostAddress());
+            mConfig.setSpiResourceId(spi.getResourceId());
             // FIXME: modifying a builder after calling build can change the built transform.
             return new IpSecTransform(mContext, mConfig).activate();
         }
@@ -445,26 +401,33 @@
          * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
          * parameters have interdependencies that are checked at build time.
          *
-         * @param localAddress the {@link InetAddress} that provides the local endpoint for this
+         * @param sourceAddress the {@link InetAddress} that provides the source address for this
          *     IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
          *     that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
-         * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this
-         *     IPsec tunnel.
+         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
+         *     traffic
          * @throws IllegalArgumentException indicating that a particular combination of transform
          *     properties is invalid.
+         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
+         *     are active
+         * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
+         *     collides with an existing transform
+         * @throws IOException indicating other errors
          * @hide
          */
         public IpSecTransform buildTunnelModeTransform(
-                InetAddress localAddress, InetAddress remoteAddress) {
-            if (localAddress == null) {
-                throw new IllegalArgumentException("Local address may not be null or empty!");
+                @NonNull InetAddress sourceAddress,
+                @NonNull IpSecManager.SecurityParameterIndex spi)
+                throws IpSecManager.ResourceUnavailableException,
+                        IpSecManager.SpiUnavailableException, IOException {
+            Preconditions.checkNotNull(sourceAddress);
+            Preconditions.checkNotNull(spi);
+            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
+                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
             }
-            if (remoteAddress == null) {
-                throw new IllegalArgumentException("Remote address may not be null or empty!");
-            }
-            mConfig.setLocalAddress(localAddress.getHostAddress());
-            mConfig.setRemoteAddress(remoteAddress.getHostAddress());
             mConfig.setMode(MODE_TUNNEL);
+            mConfig.setSourceAddress(sourceAddress.getHostAddress());
+            mConfig.setSpiResourceId(spi.getResourceId());
             return new IpSecTransform(mContext, mConfig);
         }
 
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 81c49a3..9ef26a9 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -29,7 +29,6 @@
 import android.net.wifi.WifiInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.telephony.SubscriptionPlan;
 import android.util.DebugUtils;
 import android.util.Pair;
 
@@ -329,7 +328,7 @@
      * to access network when the device is idle or in battery saver mode. Otherwise, false.
      */
     public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
-        return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+        return procState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
     }
 
     /**
@@ -337,7 +336,7 @@
      * to access network when the device is in data saver mode. Otherwise, false.
      */
     public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
-        return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+        return procState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
     }
 
     public static String resolveNetworkId(WifiConfiguration config) {
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 2197484..13b5b5c9 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -238,6 +238,20 @@
     public static final String DISALLOW_AMBIENT_DISPLAY = "no_ambient_display";
 
     /**
+     * Specifies if a user is disallowed from changing screen off timeout.
+     *
+     * <p>The default value is <code>false</code>.
+     *
+     * <p>This user restriction has no effect on managed profiles.
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_CONFIG_SCREEN_TIMEOUT = "no_config_screen_timeout";
+
+    /**
      * Specifies if a user is disallowed from enabling the
      * "Unknown Sources" setting, that allows installation of apps from unknown sources.
      * The default value is <code>false</code>.
@@ -777,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 850aedd..24e56c0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6830,7 +6830,7 @@
          * @hide
          */
         public static final int SHOW_ROTATION_SUGGESTIONS_DEFAULT =
-                SHOW_ROTATION_SUGGESTIONS_DISABLED;
+                SHOW_ROTATION_SUGGESTIONS_ENABLED;
 
         /**
          * Read only list of the service components that the current user has explicitly allowed to
@@ -9852,6 +9852,15 @@
         public static final String FORCED_APP_STANDBY_ENABLED = "forced_app_standby_enabled";
 
         /**
+         * Whether or not to enable Forced App Standby on small battery devices.
+         * Type: int (0 for false, 1 for true)
+         * Default: 0
+         * @hide
+         */
+        public static final String FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED
+                = "forced_app_standby_for_small_battery_enabled";
+
+        /**
          * Whether or not Network Watchlist feature is enabled.
          * Type: int (0 for false, 1 for true)
          * Default: 0
@@ -11300,6 +11309,13 @@
          */
         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";
     }
 
     /**
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/EntryRecoveryData.aidl b/core/java/android/security/keystore/BadCertificateFormatException.java
similarity index 65%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to core/java/android/security/keystore/BadCertificateFormatException.java
index c6c20e3..ddc7bd2 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.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 EntryRecoveryData;
+/**
+ * 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/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/EntryRecoveryData.aidl b/core/java/android/security/keystore/KeychainProtectionParams.aidl
similarity index 94%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to core/java/android/security/keystore/KeychainProtectionParams.aidl
index c6c20e3..0341223 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ b/core/java/android/security/keystore/KeychainProtectionParams.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable EntryRecoveryData;
+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/EntryRecoveryData.aidl b/core/java/android/security/keystore/KeychainSnapshot.aidl
similarity index 95%
rename from core/java/android/security/keystore/EntryRecoveryData.aidl
rename to core/java/android/security/keystore/KeychainSnapshot.aidl
index c6c20e3..b35713f 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ b/core/java/android/security/keystore/KeychainSnapshot.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable EntryRecoveryData;
+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..2029114
--- /dev/null
+++ b/core/java/android/security/keystore/KeychainSnapshot.java
@@ -0,0 +1,207 @@
+/*
+ * 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 int mSnapshotVersion;
+    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;
+    }
+
+    /**
+     * 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 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);
+            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/RecoveryControllerException.java b/core/java/android/security/keystore/RecoveryControllerException.java
new file mode 100644
index 0000000..31fd4af
--- /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 RecoveryManager}.
+ *
+ * @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
index 99bd284..f01ed06 100644
--- a/core/java/android/security/keystore/RecoveryManager.java
+++ b/core/java/android/security/keystore/RecoveryManager.java
@@ -46,6 +46,52 @@
     /** 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 RecoveryManager(ILockSettings binder) {
@@ -75,19 +121,22 @@
      *
      * @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
+     * @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 RecoveryManagerException {
+            throws BadCertificateFormatException, InternalRecoveryServiceException {
         try {
             mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+                throw new BadCertificateFormatException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -97,17 +146,20 @@
      *
      * @param account specific to Recovery agent.
      * @return Data necessary to recover keystore.
-     * @hide
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
-    public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
-            throws RecoveryManagerException {
+    public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account)
+            throws InternalRecoveryServiceException {
         try {
-            RecoveryData recoveryData = mBinder.getRecoveryData(account);
-            return recoveryData;
+            return mBinder.getRecoveryData(account);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) {
+                return null;
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -118,16 +170,17 @@
      *
      * @param intent triggered when new snapshot is available. Unregisters listener if the value is
      *     {@code null}.
-     * @hide
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
     public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
-            throws RecoveryManagerException {
+            throws InternalRecoveryServiceException {
         try {
             mBinder.setSnapshotCreatedPendingIntent(intent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -136,11 +189,12 @@
      * 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
+     * @see KeychainSnapshot#getSnapshotVersion
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
     public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
-            throws RecoveryManagerException {
+            throws InternalRecoveryServiceException {
         try {
             // IPC doesn't support generic Maps.
             @SuppressWarnings("unchecked")
@@ -150,27 +204,27 @@
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(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
+     * {@code KeychainSnapshot.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
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
-    public void setServerParams(byte[] serverParams) throws RecoveryManagerException {
+    public void setServerParams(byte[] serverParams) throws InternalRecoveryServiceException {
         try {
             mBinder.setServerParams(serverParams);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -183,16 +237,18 @@
      * @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, RecoveryManagerException {
+            throws NameNotFoundException, InternalRecoveryServiceException {
         try {
             mBinder.setRecoveryStatus(packageName, aliases, status);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -209,10 +265,10 @@
      *
      * @return {@code Map} from KeyStore alias to recovery status.
      * @see #setRecoveryStatus
-     * @hide
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
-    public Map<String, Integer> getRecoveryStatus()
-            throws RecoveryManagerException {
+    public Map<String, Integer> getRecoveryStatus() throws InternalRecoveryServiceException {
         try {
             // IPC doesn't support generic Maps.
             @SuppressWarnings("unchecked")
@@ -222,7 +278,7 @@
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -230,36 +286,40 @@
      * 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}
+     * @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 @RecoveryMetadata.UserSecretType int[] secretTypes)
-            throws RecoveryManagerException {
+            @NonNull @KeychainProtectionParams.UserSecretType int[] secretTypes)
+            throws InternalRecoveryServiceException {
         try {
             mBinder.setRecoverySecretTypes(secretTypes);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(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 RecoveryData.
+     * necessary to generate KeychainSnapshot.
      *
      * @return list of recovery secret types
-     * @see RecoveryData
+     * @see KeychainSnapshot
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
-    public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes()
-            throws RecoveryManagerException {
+    public @NonNull @KeychainProtectionParams.UserSecretType int[] getRecoverySecretTypes()
+            throws InternalRecoveryServiceException {
         try {
             return mBinder.getRecoverySecretTypes();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -269,37 +329,40 @@
      * called.
      *
      * @return list of recovery secret types
-     * @hide
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
-    public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes()
-            throws RecoveryManagerException {
+    @NonNull
+    public @KeychainProtectionParams.UserSecretType int[] getPendingRecoverySecretTypes()
+            throws InternalRecoveryServiceException {
         try {
             return mBinder.getPendingRecoverySecretTypes();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(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 RecoveryMetadata#clearSecret} to override the secret value in
+     * 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.
-     * @hide
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
-    public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
-            throws RecoveryManagerException {
+    public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
+            throws InternalRecoveryServiceException {
         try {
             mBinder.recoverySecretAvailable(recoverySecret);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -320,14 +383,18 @@
      * @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.
+     * @throws BadCertificateFormatException if the {@code verifierPublicKey} is in an incorrect
+     *     format.
+     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+     *     service.
      */
     public @NonNull byte[] startRecoverySession(
             @NonNull String sessionId,
             @NonNull byte[] verifierPublicKey,
             @NonNull byte[] vaultParams,
             @NonNull byte[] vaultChallenge,
-            @NonNull List<RecoveryMetadata> secrets)
-            throws RecoveryManagerException {
+            @NonNull List<KeychainProtectionParams> secrets)
+            throws BadCertificateFormatException, InternalRecoveryServiceException {
         try {
             byte[] recoveryClaim =
                     mBinder.startRecoverySession(
@@ -340,7 +407,10 @@
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+                throw new BadCertificateFormatException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -352,21 +422,31 @@
      * @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.
+     *     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 String sessionId,
             @NonNull byte[] recoveryKeyBlob,
-            @NonNull List<EntryRecoveryData> applicationKeys)
-            throws RecoveryManagerException {
+            @NonNull List<WrappedApplicationKey> applicationKeys)
+            throws SessionExpiredException, DecryptionFailedException,
+            InternalRecoveryServiceException {
         try {
             return (Map<String, byte[]>) mBinder.recoverKeys(
                     sessionId, recoveryKeyBlob, applicationKeys);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(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);
         }
     }
 
@@ -375,17 +455,23 @@
      * raw material of the key.
      *
      * @param alias The key alias.
-     * @throws RecoveryManagerException if an error occurred generating and storing the
-     *     key.
+     * @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 RecoveryManagerException {
+            throws InternalRecoveryServiceException, LockScreenRequiredException {
         try {
             return mBinder.generateAndStoreKey(alias);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(e);
+            if (e.errorCode == ERROR_INSECURE_USER) {
+                throw new LockScreenRequiredException(e.getMessage());
+            }
+            throw wrapUnexpectedServiceSpecificException(e);
         }
     }
 
@@ -393,14 +479,28 @@
      * 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 RecoveryManagerException {
+    public void removeKey(@NonNull String alias) throws InternalRecoveryServiceException {
         try {
             mBinder.removeKey(alias);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
-            throw RecoveryManagerException.fromServiceSpecificException(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/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/EntryRecoveryData.aidl b/core/java/android/security/keystore/SessionExpiredException.java
similarity index 65%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to core/java/android/security/keystore/SessionExpiredException.java
index c6c20e3..f13e206 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.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 EntryRecoveryData;
+/**
+ * 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/EntryRecoveryData.aidl b/core/java/android/security/keystore/WrappedApplicationKey.aidl
similarity index 94%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to core/java/android/security/keystore/WrappedApplicationKey.aidl
index c6c20e3..a6294fe 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ b/core/java/android/security/keystore/WrappedApplicationKey.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable EntryRecoveryData;
+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/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/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/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 62f9717..e94f91a 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -38,13 +38,13 @@
     static {
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("device_info_v2", "true");
-        DEFAULT_FLAGS.put("settings_search_v2", "true");
         DEFAULT_FLAGS.put("settings_app_info_v2", "true");
         DEFAULT_FLAGS.put("settings_connected_device_v2", "true");
         DEFAULT_FLAGS.put("settings_battery_v2", "false");
         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/util/StatsManager.java b/core/java/android/util/StatsManager.java
index c25b272..e0d085c 100644
--- a/core/java/android/util/StatsManager.java
+++ b/core/java/android/util/StatsManager.java
@@ -42,6 +42,16 @@
     }
 
     /**
+     * Temporary to prevent build failures. Will be deleted.
+     */
+    @RequiresPermission(Manifest.permission.DUMP)
+    public boolean addConfiguration(String configKey, byte[] config, String pkg, String cls) {
+        // To prevent breakages of dependencies on old API.
+
+        return false;
+    }
+
+    /**
      * Clients can send a configuration and simultaneously registers the name of a broadcast
      * receiver that listens for when it should request data.
      *
@@ -70,6 +80,15 @@
     }
 
     /**
+     * Temporary to prevent build failures. Will be deleted.
+     */
+    @RequiresPermission(Manifest.permission.DUMP)
+    public boolean removeConfiguration(String configKey) {
+        // To prevent breakages of old dependencies.
+        return false;
+    }
+
+    /**
      * Remove a configuration from logging.
      *
      * @param configKey Configuration key to remove.
@@ -93,6 +112,16 @@
     }
 
     /**
+     * Temporary to prevent build failures. Will be deleted.
+     */
+    @RequiresPermission(Manifest.permission.DUMP)
+    public byte[] getData(String configKey) {
+        // TODO: remove this and all other methods with String-based config keys.
+        // To prevent build breakages of dependencies.
+        return null;
+    }
+
+    /**
      * Clients can request data with a binder call. This getter is destructive and also clears
      * the retrieved metrics from statsd memory.
      *
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 8c70322..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. */
@@ -294,6 +296,11 @@
     boolean hasNavigationBar();
 
     /**
+    * Get the position of the nav bar
+    */
+    int getNavBarPosition();
+
+    /**
      * Lock the device immediately with the specified options (can be null).
      */
     void lockNow(in Bundle options);
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/view/View.java b/core/java/android/view/View.java
index 0bf6904..f461e45 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3226,6 +3226,11 @@
      */
     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
 
+    /**
+     * The last aggregated visibility. Used to detect when it truly changes.
+     */
+    private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
+
     /* End of masks for mPrivateFlags3 */
 
     /**
@@ -4205,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 {
@@ -4822,6 +4832,8 @@
 
             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
 
+            sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
+
             sCompatibilityDone = true;
         }
     }
@@ -7012,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.
@@ -7024,7 +7036,8 @@
             System.out.println(this + " clearFocus()");
         }
 
-        clearFocusInternal(null, true, true);
+        final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
+        clearFocusInternal(null, true, refocus);
     }
 
     /**
@@ -7219,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);
                 }
             }
@@ -7366,7 +7383,12 @@
      * @hide
      */
     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
-        if (!isShown()) {
+        // Panes disappearing are relevant even if though the view is no longer visible.
+        boolean isWindowStateChanged =
+                (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
+                & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
+        if (!isShown() && !isWindowDisappearedEvent) {
             return;
         }
         onInitializeAccessibilityEvent(event);
@@ -7474,6 +7496,10 @@
      * @hide
      */
     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
+        if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
+                && !TextUtils.isEmpty(getAccessibilityPaneTitle())) {
+            event.getText().add(getAccessibilityPaneTitle());
+        }
     }
 
     /**
@@ -8295,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()),
@@ -11599,6 +11630,23 @@
         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
             return;
         }
+        // Changes to views with a pane title count as window state changes, as the pane title
+        // marks them as significant parts of the UI.
+        if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
+            final AccessibilityEvent event = AccessibilityEvent.obtain();
+            event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+            event.setContentChangeTypes(changeType);
+            onPopulateAccessibilityEvent(event);
+            if (mParent != null) {
+                try {
+                    mParent.requestSendAccessibilityEvent(this, event);
+                } catch (AbstractMethodError e) {
+                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
+                            + " does not fully implement ViewParent", e);
+                }
+            }
+        }
+
         if (mParent != null) {
             try {
                 mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType);
@@ -12412,8 +12460,6 @@
             imm.focusIn(this);
         }
 
-        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
-
         refreshDrawableState();
     }
 
@@ -12532,6 +12578,10 @@
      */
     @CallSuper
     public void onVisibilityAggregated(boolean isVisible) {
+        // Update our internal visibility tracking so we can detect changes
+        boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+        mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
+                : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
         if (isVisible && mAttachInfo != null) {
             initialAwakenScrollBars();
         }
@@ -12572,6 +12622,13 @@
                 }
             }
         }
+        if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
+            if (isVisible != oldVisible) {
+                notifyAccessibilityStateChanged(isVisible
+                        ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
+                        : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
+            }
+        }
     }
 
     /**
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/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index 9c1c9e3..a6f36bb 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -45,6 +45,11 @@
     int PRESENCE_INTERNAL = 1 << 0;
     int PRESENCE_EXTERNAL = 1 << 1;
 
+    // Navigation bar position values
+    int NAV_BAR_LEFT = 1 << 0;
+    int NAV_BAR_RIGHT = 1 << 1;
+    int NAV_BAR_BOTTOM = 1 << 2;
+
     /**
      * Sticky broadcast of the current HDMI plugged state.
      */
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index aa61926..e0f74a7 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -192,9 +192,11 @@
  * <b>TRANSITION TYPES</b></br>
  * </p>
  * <p>
- * <b>Window state changed</b> - represents the event of opening a
- * {@link android.widget.PopupWindow}, {@link android.view.Menu},
- * {@link android.app.Dialog}, etc.</br>
+ * <b>Window state changed</b> - represents the event of a change to a section of
+ * the user interface that is visually distinct. Should be sent from either the
+ * root view of a window or from a view that is marked as a pane
+ * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Not that changes
+ * to true windows are represented by {@link #TYPE_WINDOWS_CHANGED}.</br>
  * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
  * <em>Properties:</em></br>
  * <ul>
@@ -203,7 +205,7 @@
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
- *   <li>{@link #getText()} - The text of the source's sub-tree.</li>
+ *   <li>{@link #getText()} - The text of the source's sub-tree, including the pane titles.</li>
  * </ul>
  * </p>
  * <p>
@@ -436,8 +438,10 @@
     public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
 
     /**
-     * Represents the event of opening a {@link android.widget.PopupWindow},
-     * {@link android.view.Menu}, {@link android.app.Dialog}, etc.
+     * Represents the event of a change to a visually distinct section of the user interface.
+     * These events should only be dispatched from {@link android.view.View}s that have
+     * accessibility pane titles, and replaces {@link #TYPE_WINDOW_CONTENT_CHANGED} for those
+     * sources. Details about the change are available from {@link #getContentChangeTypes()}.
      */
     public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
 
@@ -565,12 +569,30 @@
     public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
 
     /**
-     * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
+     * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
      * The node's pane title changed.
      */
     public static final int CONTENT_CHANGE_TYPE_PANE_TITLE = 0x00000008;
 
     /**
+     * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
+     * The node has a pane title, and either just appeared or just was assigned a title when it
+     * had none before.
+     */
+    public static final int CONTENT_CHANGE_TYPE_PANE_APPEARED = 0x00000010;
+
+    /**
+     * Change type for {@link #TYPE_WINDOW_STATE_CHANGED} event:
+     * Can mean one of two slightly different things. The primary meaning is that the node has
+     * a pane title, and was removed from the node hierarchy. It will also be sent if the pane
+     * title is set to {@code null} after it contained a title.
+     * No source will be returned if the node is no longer on the screen. To make the change more
+     * clear for the user, the first entry in {@link #getText()} will return the value that would
+     * have been returned by {@code getSource().getPaneTitle()}.
+     */
+    public static final int CONTENT_CHANGE_TYPE_PANE_DISAPPEARED = 0x00000020;
+
+    /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window was added.
      */
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 78b41c6..de9b0d7 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -341,6 +341,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 +401,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 +508,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 +645,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 +696,7 @@
                 }
             }
         }
-
-        if (callback != null) {
-            mCallback.onAutofillEvent(view, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
-        }
+        return callback;
     }
 
     /**
@@ -666,9 +709,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 +769,7 @@
                     }
                 }
                 if (mTrackedViews != null) {
-                    mTrackedViews.notifyViewVisibilityChanged(id, isVisible);
+                    mTrackedViews.notifyViewVisibilityChangedLocked(id, isVisible);
                 }
             }
         }
@@ -752,17 +802,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 +839,7 @@
                 }
             }
         }
-
-        if (callback != null) {
-            callback.onAutofillEvent(view, virtualId,
-                    AutofillCallback.EVENT_INPUT_UNAVAILABLE);
-        }
+        return callback;
     }
 
     /**
@@ -792,9 +853,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.
@@ -1155,7 +1223,7 @@
     }
 
     /** @hide */
-    public void onAuthenticationResult(int authenticationId, Intent data) {
+    public void onAuthenticationResult(int authenticationId, Intent data, View focusView) {
         if (!hasAutofillFeature()) {
             return;
         }
@@ -1167,9 +1235,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 +1485,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 +1853,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 +2024,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);
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/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/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..dac6c02 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;
@@ -924,6 +927,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 +1255,18 @@
                 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;
             }
         }
 
@@ -1563,6 +1581,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 +3193,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 +3213,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 +3234,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 +3887,7 @@
      *
      * @param elegant set the paint's elegant metrics flag.
      *
+     * @see #isElegantTextHeight()
      * @see Paint#isElegantTextHeight()
      *
      * @attr ref android.R.styleable#TextView_elegantTextHeight
@@ -4974,6 +5106,28 @@
     }
 
     /**
+     * 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);
+        }
+    }
+
+    /**
      * 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 +9279,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)
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
new file mode 100644
index 0000000..310a7bb
--- /dev/null
+++ b/core/java/android/widget/VideoView2.java
@@ -0,0 +1,363 @@
+/*
+ * 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.widget;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.media.AudioAttributes;
+import android.media.MediaPlayer;
+import android.media.update.ApiLoader;
+import android.media.update.VideoView2Provider;
+import android.media.update.ViewProvider;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
+
+/**
+ * TODO PUBLIC API
+ * @hide
+ */
+public class VideoView2 extends FrameLayout {
+    @IntDef({
+            VIEW_TYPE_TEXTUREVIEW,
+            VIEW_TYPE_SURFACEVIEW
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ViewType {}
+    public static final int VIEW_TYPE_SURFACEVIEW = 1;
+    public static final int VIEW_TYPE_TEXTUREVIEW = 2;
+
+    private final VideoView2Provider mProvider;
+
+    /**
+     * @hide
+     */
+    public VideoView2(@NonNull Context context) {
+        this(context, null);
+    }
+
+    /**
+     * @hide
+     */
+    public VideoView2(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * @hide
+     */
+    public VideoView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    /**
+     * @hide
+     */
+    public VideoView2(
+            @NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        mProvider = ApiLoader.getProvider(context).createVideoView2(this, new SuperProvider());
+    }
+
+    /**
+     * @hide
+     */
+    public VideoView2Provider getProvider() {
+        return mProvider;
+    }
+
+    /**
+     * @hide
+     */
+    public void start() {
+        mProvider.start_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void pause() {
+        mProvider.pause_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public int getDuration() {
+        return mProvider.getDuration_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public int getCurrentPosition() {
+        return mProvider.getCurrentPosition_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void seekTo(int msec) {
+        mProvider.seekTo_impl(msec);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isPlaying() {
+        return mProvider.isPlaying_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public int getBufferPercentage() {
+        return mProvider.getBufferPercentage_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public int getAudioSessionId() {
+        return mProvider.getAudioSessionId_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void showSubtitle() {
+        mProvider.showSubtitle_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void hideSubtitle() {
+        mProvider.hideSubtitle_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void setAudioFocusRequest(int focusGain) {
+        mProvider.setAudioFocusRequest_impl(focusGain);
+    }
+
+    /**
+     * @hide
+     */
+    public void setAudioAttributes(@NonNull AudioAttributes attributes) {
+        mProvider.setAudioAttributes_impl(attributes);
+    }
+
+    /**
+     * @hide
+     */
+    public void setVideoPath(String path) {
+        mProvider.setVideoPath_impl(path);
+    }
+
+    /**
+     * @hide
+     */
+    public void setVideoURI(Uri uri) {
+        mProvider.setVideoURI_impl(uri);
+    }
+
+    /**
+     * @hide
+     */
+    public void setVideoURI(Uri uri, Map<String, String> headers) {
+        mProvider.setVideoURI_impl(uri, headers);
+    }
+
+    /**
+     * @hide
+     */
+    public void setMediaController2(MediaController2 controllerView) {
+        mProvider.setMediaController2_impl(controllerView);
+    }
+
+    /**
+     * @hide
+     */
+    public void setViewType(@ViewType int viewType) {
+        mProvider.setViewType_impl(viewType);
+    }
+
+    /**
+     * @hide
+     */
+    @ViewType
+    public int getViewType() {
+        return mProvider.getViewType_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void stopPlayback() {
+        mProvider.stopPlayback_impl();
+    }
+
+    /**
+     * @hide
+     */
+    public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
+        mProvider.setOnPreparedListener_impl(l);
+    }
+
+    /**
+     * @hide
+     */
+    public void setOnCompletionListener(MediaPlayer.OnCompletionListener l) {
+        mProvider.setOnCompletionListener_impl(l);
+    }
+
+    /**
+     * @hide
+     */
+    public void setOnErrorListener(MediaPlayer.OnErrorListener l) {
+        mProvider.setOnErrorListener_impl(l);
+    }
+
+    /**
+     * @hide
+     */
+    public void setOnInfoListener(MediaPlayer.OnInfoListener l) {
+        mProvider.setOnInfoListener_impl(l);
+    }
+
+    /**
+     * @hide
+     */
+    public void setOnViewTypeChangedListener(OnViewTypeChangedListener l) {
+        mProvider.setOnViewTypeChangedListener_impl(l);
+    }
+
+    /**
+     * @hide
+     */
+    public interface OnViewTypeChangedListener {
+        /**
+         * @hide
+         */
+        void onViewTypeChanged(@ViewType int viewType);
+    }
+
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return mProvider.getAccessibilityClassName_impl();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return mProvider.onTouchEvent_impl(ev);
+    }
+
+    @Override
+    public boolean onTrackballEvent(MotionEvent ev) {
+        return mProvider.onTrackballEvent_impl(ev);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return mProvider.onKeyDown_impl(keyCode, event);
+    }
+
+    @Override
+    public void onFinishInflate() {
+        mProvider.onFinishInflate_impl();
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        return mProvider.dispatchKeyEvent_impl(event);
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        mProvider.setEnabled_impl(enabled);
+    }
+
+    private class SuperProvider implements ViewProvider {
+        @Override
+        public void onAttachedToWindow_impl() {
+            VideoView2.super.onAttachedToWindow();
+        }
+
+        @Override
+        public void onDetachedFromWindow_impl() {
+            VideoView2.super.onDetachedFromWindow();
+        }
+
+        @Override
+        public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
+            VideoView2.super.onLayout(changed, left, top, right, bottom);
+        }
+
+        @Override
+        public void draw_impl(Canvas canvas) {
+            VideoView2.super.draw(canvas);
+        }
+
+        @Override
+        public CharSequence getAccessibilityClassName_impl() {
+            return VideoView2.super.getAccessibilityClassName();
+        }
+
+        @Override
+        public boolean onTouchEvent_impl(MotionEvent ev) {
+            return VideoView2.super.onTouchEvent(ev);
+        }
+
+        @Override
+        public boolean onTrackballEvent_impl(MotionEvent ev) {
+            return VideoView2.super.onTrackballEvent(ev);
+        }
+
+        @Override
+        public boolean onKeyDown_impl(int keyCode, KeyEvent event) {
+            return VideoView2.super.onKeyDown(keyCode, event);
+        }
+
+        @Override
+        public void onFinishInflate_impl() {
+            VideoView2.super.onFinishInflate();
+        }
+
+        @Override
+        public boolean dispatchKeyEvent_impl(KeyEvent event) {
+            return VideoView2.super.dispatchKeyEvent(event);
+        }
+
+        @Override
+        public void setEnabled_impl(boolean enabled) {
+            VideoView2.super.setEnabled(enabled);
+        }
+    }
+}
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/policy/KeyguardDismissCallback.java b/core/java/com/android/internal/policy/KeyguardDismissCallback.java
new file mode 100644
index 0000000..38337ec
--- /dev/null
+++ b/core/java/com/android/internal/policy/KeyguardDismissCallback.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 com.android.internal.policy;
+
+import android.os.RemoteException;
+import com.android.internal.policy.IKeyguardDismissCallback;
+
+/**
+ * @hide
+ */
+public class KeyguardDismissCallback extends IKeyguardDismissCallback.Stub {
+
+    @Override
+    public void onDismissError() throws RemoteException {
+        // To be overidden
+    }
+
+    @Override
+    public void onDismissSucceeded() throws RemoteException {
+        // To be overidden
+    }
+
+    @Override
+    public void onDismissCancelled() throws RemoteException {
+        // To be overidden
+    }
+}
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..6ed8973 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;
 
@@ -64,7 +64,7 @@
     // {@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,10 @@
     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);
 }
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..ed9d0e9 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;
@@ -407,23 +398,9 @@
 
     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_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/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..3ffb254 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -389,8 +389,9 @@
     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;
 
-    // Next tag = 348;
+    // Next tag = 349;
 }
 
 message SecureSettingsProto {
diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/forceappstandbytracker.proto
index 8753bf7..c9f7d52 100644
--- a/core/proto/android/server/forceappstandbytracker.proto
+++ b/core/proto/android/server/forceappstandbytracker.proto
@@ -41,4 +41,13 @@
 
   // Packages that are disallowed OP_RUN_ANY_IN_BACKGROUND.
   repeated RunAnyInBackgroundRestrictedPackages run_any_in_background_restricted_packages = 5;
+
+  // Whether device is a small battery device
+  optional bool is_small_battery_device = 6;
+
+  // Whether force app standby for small battery device setting is enabled
+  optional bool force_all_apps_standby_for_small_battery = 7;
+
+  // Whether device is charging
+  optional bool is_charging = 8;
 }
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..d2a22d0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3692,6 +3692,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-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..fd33dc9 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">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e3a910f..3b02a96 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3249,4 +3249,7 @@
     <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>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 58ae76c..656add6 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2862,6 +2862,9 @@
       <public name="appComponentFactory" />
       <public name="fallbackLineSpacing" />
       <public name="accessibilityPaneTitle" />
+      <public name="firstBaselineToTopHeight" />
+      <public name="lastBaselineToBottomHeight" />
+      <public name="lineHeight" />
     </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..6e33648 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,6 @@
   <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" />
 </resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 410bee0..d5689c7 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,
@@ -212,6 +213,7 @@
                     Settings.Global.FANCY_IME_ANIMATIONS,
                     Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
                     Settings.Global.FORCED_APP_STANDBY_ENABLED,
+                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
                     Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                     Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                     Settings.Global.GLOBAL_HTTP_PROXY_HOST,
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/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/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
index b57e02d..07483f6 100644
--- a/media/java/android/media/update/ApiLoader.java
+++ b/media/java/android/media/update/ApiLoader.java
@@ -49,8 +49,8 @@
                 Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
         sMediaLibrary = libContext.getClassLoader()
                 .loadClass(UPDATE_CLASS)
-                .getMethod(UPDATE_METHOD, Context.class)
-                .invoke(null, appContext);
+                .getMethod(UPDATE_METHOD, Context.class, Context.class)
+                .invoke(null, appContext, libContext);
         return sMediaLibrary;
     }
 }
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 19f01c2..a1e2404 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.widget.MediaController2;
+import android.widget.VideoView2;
 
 /**
  * Interface for connecting the public API to an updatable implementation.
@@ -31,4 +32,5 @@
 public interface StaticProvider {
     MediaController2Provider createMediaController2(
             MediaController2 instance, ViewProvider superProvider);
+    VideoView2Provider createVideoView2(VideoView2 instance, ViewProvider superProvider);
 }
diff --git a/media/java/android/media/update/VideoView2Provider.java b/media/java/android/media/update/VideoView2Provider.java
new file mode 100644
index 0000000..6fc9bdc
--- /dev/null
+++ b/media/java/android/media/update/VideoView2Provider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.update;
+
+import android.media.AudioAttributes;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.widget.MediaController2;
+import android.widget.VideoView2;
+
+import java.util.Map;
+
+/**
+ * Interface for connecting the public API to an updatable implementation.
+ *
+ * Each instance object is connected to one corresponding updatable object which implements the
+ * runtime behavior of that class. There should a corresponding provider method for all public
+ * methods.
+ *
+ * All methods behave as per their namesake in the public API.
+ *
+ * @see android.widget.VideoView2
+ *
+ * @hide
+ */
+// TODO @SystemApi
+public interface VideoView2Provider extends ViewProvider {
+    void start_impl();
+    void pause_impl();
+    int getDuration_impl();
+    int getCurrentPosition_impl();
+    void seekTo_impl(int msec);
+    boolean isPlaying_impl();
+    int getBufferPercentage_impl();
+    int getAudioSessionId_impl();
+    void showSubtitle_impl();
+    void hideSubtitle_impl();
+    void setAudioFocusRequest_impl(int focusGain);
+    void setAudioAttributes_impl(AudioAttributes attributes);
+    void setVideoPath_impl(String path);
+    void setVideoURI_impl(Uri uri);
+    void setVideoURI_impl(Uri uri, Map<String, String> headers);
+    void setMediaController2_impl(MediaController2 controllerView);
+    void setViewType_impl(int viewType);
+    int getViewType_impl();
+    void stopPlayback_impl();
+    void setOnPreparedListener_impl(MediaPlayer.OnPreparedListener l);
+    void setOnCompletionListener_impl(MediaPlayer.OnCompletionListener l);
+    void setOnErrorListener_impl(MediaPlayer.OnErrorListener l);
+    void setOnInfoListener_impl(MediaPlayer.OnInfoListener l);
+    void setOnViewTypeChangedListener_impl(VideoView2.OnViewTypeChangedListener l);
+}
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..d130a61 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -498,8 +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] -->
@@ -556,8 +554,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 -->
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index adb4832..ae24c07 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -16,9 +16,9 @@
 package com.android.settingslib.core.lifecycle;
 
 import static android.arch.lifecycle.Lifecycle.Event.ON_START;
-
 import static com.google.common.truth.Truth.assertThat;
 
+import android.arch.lifecycle.LifecycleOwner;
 import android.content.Context;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -48,6 +48,7 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LifecycleTest {
 
+    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
 
     public static class TestDialogFragment extends ObservableDialogFragment {
@@ -146,7 +147,8 @@
 
     @Before
     public void setUp() {
-        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
index 5d5733e4..050877d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
@@ -17,11 +17,11 @@
 package com.android.settingslib.development;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
+import android.arch.lifecycle.LifecycleOwner;
 import android.os.SystemProperties;
 import android.support.v7.preference.ListPreference;
 import android.support.v7.preference.Preference;
@@ -44,6 +44,7 @@
         shadows = SystemPropertiesTestImpl.class)
 public class LogpersistPreferenceControllerTest {
 
+    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
 
     @Mock
@@ -57,7 +58,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         SystemProperties.set("ro.debuggable", "1");
-        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
         mController = new AbstractLogpersistPreferenceController(RuntimeEnvironment.application,
                 mLifecycle) {
             @Override
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
index 75b6c5f..88c57b5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
@@ -17,13 +17,13 @@
 package com.android.settingslib.widget;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.arch.lifecycle.LifecycleOwner;
 import android.support.v14.preference.PreferenceFragment;
 import android.support.v7.preference.PreferenceManager;
 import android.support.v7.preference.PreferenceScreen;
@@ -49,13 +49,15 @@
     @Mock
     private PreferenceScreen mScreen;
 
+    private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private FooterPreferenceMixin mMixin;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mLifecycle = new Lifecycle(() -> mLifecycle);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
         when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
         when(mFragment.getPreferenceManager().getContext())
                 .thenReturn(ShadowApplication.getInstance().getApplicationContext());
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/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 1be0645..48a3a30 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -28,7 +28,7 @@
     <string name="def_bluetooth_disabled_profiles" translatable="false">0</string>
     <bool name="def_auto_time">true</bool>
     <bool name="def_auto_time_zone">true</bool>
-    <bool name="def_accelerometer_rotation">true</bool>
+    <bool name="def_accelerometer_rotation">false</bool>
     <!-- Default screen brightness, from 0 to 255.  102 is 40%. -->
     <integer name="def_screen_brightness">102</integer>
     <bool name="def_screen_brightness_automatic_mode">false</bool>
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..d33e084 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1122,6 +1122,9 @@
         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);
     }
 
     /** Dump a single {@link SettingsState.Setting} to a proto buf */
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1167d69..175cff6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1584,6 +1584,11 @@
                 restriction = UserManager.DISALLOW_SAFE_BOOT;
                 break;
 
+            case Settings.Global.AIRPLANE_MODE_ON:
+                if ("0".equals(value)) return false;
+                restriction = UserManager.DISALLOW_AIRPLANE_MODE;
+                break;
+
             default:
                 if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
                     if ("0".equals(value)) return false;
@@ -2940,7 +2945,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 150;
+            private static final int SETTINGS_VERSION = 151;
 
             private final int mUserId;
 
@@ -3533,6 +3538,18 @@
                     currentVersion = 150;
                 }
 
+                if (currentVersion == 150) {
+                    // Version 151: Reset rotate locked setting for upgrading users
+                    final SettingsState systemSettings = getSystemSettingsLocked(userId);
+                    systemSettings.insertSettingLocked(
+                            Settings.System.ACCELEROMETER_ROTATION,
+                            getContext().getResources().getBoolean(
+                                    R.bool.def_accelerometer_rotation) ? "1" : "0",
+                            null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+
+                    currentVersion = 151;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
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/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
index 56a3ee3..e25930c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
@@ -50,5 +50,7 @@
         }
 
         void setDarkIntensity(float intensity);
+
+        void setDelayTouchFeedback(boolean shouldDelay);
     }
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
index 674ed5a..6131acc 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
@@ -14,6 +14,7 @@
 
 package com.android.systemui.plugins.statusbar.phone;
 
+import android.graphics.Canvas;
 import android.view.MotionEvent;
 
 import com.android.systemui.plugins.Plugin;
@@ -35,6 +36,12 @@
 
         public void setBarState(boolean vertical, boolean isRtl);
 
+        public void onDraw(Canvas canvas);
+
+        public void onDarkIntensityChange(float intensity);
+
+        public void onLayout(boolean changed, int left, int top, int right, int bottom);
+
         public default void destroy() { }
     }
 
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 347cf1c..9adb550 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -50,16 +50,6 @@
                 android:format12Hour="@string/keyguard_widget_12_hours_format"
                 android:format24Hour="@string/keyguard_widget_24_hours_format"
                 android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
-            <com.android.systemui.ChargingView
-                android:id="@+id/battery_doze"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignTop="@id/clock_view"
-                android:layout_alignBottom="@id/clock_view"
-                android:layout_toEndOf="@id/clock_view"
-                android:visibility="invisible"
-                android:src="@drawable/ic_aod_charging_24dp"
-                android:contentDescription="@string/accessibility_ambient_display_charging" />
             <View
                 android:id="@+id/clock_separator"
                 android:layout_width="16dp"
diff --git a/packages/SystemUI/res/drawable/ic_face_unlock.xml b/packages/SystemUI/res/drawable/ic_face_unlock.xml
new file mode 100644
index 0000000..29c2275
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_face_unlock.xml
@@ -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
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0">
+    <path android:fillColor="?attr/wallpaperTextColor"
+          android:strokeColor="?attr/wallpaperTextColor"
+          android:strokeWidth="1"
+          android:pathData="M9,11.75C8.31,11.75 7.75,12.31 7.75,13C7.75,13.69 8.31,14.25 9,14.25C9.69,14.25 10.25,13.69 10.25,13C10.25,12.31 9.69,11.75 9,11.75ZM15,11.75C14.31,11.75 13.75,12.31 13.75,13C13.75,13.69 14.31,14.25 15,14.25C15.69,14.25 16.25,13.69 16.25,13C16.25,12.31 15.69,11.75 15,11.75ZM12,2C6.48,2 2,6.48 2,12C2,17.52 6.48,22 12,22C17.52,22 22,17.52 22,12C22,6.48 17.52,2 12,2ZM12,20C7.59,20 4,16.41 4,12C4,11.71 4.02,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z"
+    />
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 03bba53..dd74cadd 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -16,5 +16,6 @@
 <inset xmlns:android="http://schemas.android.com/apk/res/android">
     <shape>
         <solid android:color="@color/qs_background_dark"/>
+        <corners android:radius="?android:attr/dialogCornerRadius" />
     </shape>
 </inset>
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/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 2fd4df4..d0d379c 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -40,6 +40,7 @@
             android:gravity="center_horizontal"
             android:textStyle="italic"
             android:textColor="?attr/wallpaperTextColorSecondary"
+            android:textSize="16sp"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:visibility="gone" />
 
@@ -50,6 +51,7 @@
             android:gravity="center_horizontal"
             android:textStyle="italic"
             android:textColor="?attr/wallpaperTextColorSecondary"
+            android:textSize="16sp"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:accessibilityLiveRegion="polite" />
 
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_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index bef0830..c5e5ee1 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -43,6 +43,8 @@
             android:layout_width="@dimen/qs_panel_width"
             android:layout_height="match_parent"
             android:layout_gravity="@integer/notification_panel_layout_gravity"
+            android:layout_marginStart="@dimen/notification_side_paddings"
+            android:layout_marginEnd="@dimen/notification_side_paddings"
             android:clipToPadding="false"
             android:clipChildren="false"
             systemui:viewType="com.android.systemui.plugins.qs.QS" />
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 f244d88..0f4c3b8 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -143,6 +143,9 @@
 
     <color name="remote_input_accent">#eeeeee</color>
 
+    <color name="quick_step_track_background_dark">#61000000</color>
+    <color name="quick_step_track_background_light">#4DFFFFFF</color>
+
     <!-- Keyboard shortcuts colors -->
     <color name="ksh_application_group_color">#fff44336</color>
     <color name="ksh_keyword_color">#d9000000</color>
@@ -153,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 a510c4a..7a670fd 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 -->
@@ -579,6 +579,7 @@
     <dimen name="keyguard_affordance_icon_width">24dp</dimen>
 
     <dimen name="keyguard_indication_margin_bottom">65dp</dimen>
+    <dimen name="keyguard_indication_margin_bottom_ambient">30dp</dimen>
 
     <!-- The text size for battery level -->
     <dimen name="battery_level_text_size">12sp</dimen>
@@ -870,6 +871,8 @@
     <dimen name="rounded_corner_radius">0dp</dimen>
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
+    <dimen name="nav_quick_scrub_track_edge_padding">32dp</dimen>
+    <dimen name="nav_quick_scrub_track_thickness">2dp</dimen>
 
     <!-- Intended corner radius when drawing the mobile signal -->
     <dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen>
@@ -879,4 +882,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/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 173a90a..64fa9c6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -22,4 +22,8 @@
 oneway interface IOverviewProxy {
     void onBind(in ISystemUiProxy sysUiProxy);
     void onMotionEvent(in MotionEvent event);
+    void onQuickSwitch();
+    void onQuickScrubStart();
+    void onQuickScrubEnd();
+    void onQuickScrubProgress(float progress);
 }
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/os/Seccomp.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
similarity index 63%
copy from core/java/android/os/Seccomp.java
copy to packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
index f14e93f..5a85df9 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,14 +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.os;
+package com.android.systemui.shared.system;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
-}
+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/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 8135c61..d80a336 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -151,6 +151,7 @@
 
         mClickActions.clear();
         final int subItemsCount = subItems.size();
+        final int blendedColor = getTextColor();
 
         for (int i = 0; i < subItemsCount; i++) {
             SliceItem item = subItems.get(i);
@@ -159,7 +160,7 @@
             KeyguardSliceButton button = mRow.findViewWithTag(itemTag);
             if (button == null) {
                 button = new KeyguardSliceButton(mContext);
-                button.setTextColor(mTextColor);
+                button.setTextColor(blendedColor);
                 button.setTag(itemTag);
             } else {
                 mRow.removeView(button);
@@ -258,7 +259,7 @@
     }
 
     private void updateTextColors() {
-        final int blendedColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
+        final int blendedColor = getTextColor();
         mTitle.setTextColor(blendedColor);
         int childCount = mRow.getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -322,6 +323,10 @@
         }
     }
 
+    public int getTextColor() {
+        return ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
+    }
+
     /**
      * Representation of an item that appears under the clock on main keyguard message.
      * Shows optional separator.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 4b9a874..2873afb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -16,7 +16,6 @@
 
 package com.android.keyguard;
 
-import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -40,7 +39,6 @@
 import android.widget.TextView;
 
 import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.ChargingView;
 
 import com.google.android.collect.Sets;
 
@@ -60,7 +58,6 @@
     private View mClockSeparator;
     private TextView mOwnerInfo;
     private ViewGroup mClockContainer;
-    private ChargingView mBatteryDoze;
     private KeyguardSliceView mKeyguardSlice;
     private Runnable mPendingMarqueeStart;
     private Handler mHandler;
@@ -155,11 +152,9 @@
             mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
         }
         mOwnerInfo = findViewById(R.id.owner_info);
-        mBatteryDoze = findViewById(R.id.battery_doze);
         mKeyguardSlice = findViewById(R.id.keyguard_status_area);
         mClockSeparator = findViewById(R.id.clock_separator);
-        mVisibleInDoze = Sets.newArraySet(mBatteryDoze, mClockView, mKeyguardSlice,
-                mClockSeparator);
+        mVisibleInDoze = Sets.newArraySet(mClockView, mKeyguardSlice, mClockSeparator);
         mTextColor = mClockView.getCurrentTextColor();
 
         mKeyguardSlice.setListener(this::onSliceContentChanged);
@@ -184,10 +179,6 @@
         mClockView.setTranslationY(translation);
         mClockView.setScaleX(clockScale);
         mClockView.setScaleY(clockScale);
-        final float batteryTranslation =
-                -(mClockView.getWidth() - (mClockView.getWidth() * clockScale)) / 2;
-        mBatteryDoze.setTranslationX(batteryTranslation);
-        mBatteryDoze.setTranslationY(translation);
         mClockSeparator.setVisibility(hasHeader ? VISIBLE : GONE);
     }
 
@@ -310,7 +301,7 @@
         }
     }
 
-    public void setDark(float darkAmount) {
+    public void setDarkAmount(float darkAmount) {
         if (mDarkAmount == darkAmount) {
             return;
         }
@@ -331,7 +322,6 @@
 
         final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, darkAmount);
         updateDozeVisibleViews();
-        mBatteryDoze.setDark(dark);
         mKeyguardSlice.setDark(darkAmount);
         mClockView.setTextColor(blendedTextColor);
         mClockSeparator.setBackgroundColor(blendedTextColor);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ab2bce8..e58ad05 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1613,11 +1613,10 @@
         }
     }
 
-    private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
+    private boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
         final boolean nowPluggedIn = current.isPluggedIn();
         final boolean wasPluggedIn = old.isPluggedIn();
-        final boolean stateChangedWhilePluggedIn =
-            wasPluggedIn == true && nowPluggedIn == true
+        final boolean stateChangedWhilePluggedIn = wasPluggedIn && nowPluggedIn
             && (old.status != current.status);
 
         // change in plug state is always interesting
@@ -1630,6 +1629,11 @@
             return true;
         }
 
+        // change in battery level while keyguard visible
+        if (mKeyguardIsVisible && old.level != current.level) {
+            return true;
+        }
+
         // change where battery needs charging
         if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/ChargingView.java b/packages/SystemUI/src/com/android/systemui/ChargingView.java
deleted file mode 100644
index 33f8b06..0000000
--- a/packages/SystemUI/src/com/android/systemui/ChargingView.java
+++ /dev/null
@@ -1,126 +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.systemui;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.UserHandle;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-
-/**
- * A view that only shows its drawable while the phone is charging.
- *
- * Also reloads its drawable upon density changes.
- */
-public class ChargingView extends ImageView implements
-        BatteryController.BatteryStateChangeCallback,
-        ConfigurationController.ConfigurationListener {
-
-    private static final long CHARGING_INDICATION_DELAY_MS = 1000;
-
-    private final AmbientDisplayConfiguration mConfig;
-    private final Runnable mClearSuppressCharging = this::clearSuppressCharging;
-    private BatteryController mBatteryController;
-    private int mImageResource;
-    private boolean mCharging;
-    private boolean mDark;
-    private boolean mSuppressCharging;
-
-
-    private void clearSuppressCharging() {
-        mSuppressCharging = false;
-        removeCallbacks(mClearSuppressCharging);
-        updateVisibility();
-    }
-
-    public ChargingView(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-
-        mConfig = new AmbientDisplayConfiguration(context);
-
-        TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.src});
-        int srcResId = a.getResourceId(0, 0);
-
-        if (srcResId != 0) {
-            mImageResource = srcResId;
-        }
-
-        a.recycle();
-
-        updateVisibility();
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mBatteryController = Dependency.get(BatteryController.class);
-        mBatteryController.addCallback(this);
-        Dependency.get(ConfigurationController.class).addCallback(this);
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mBatteryController.removeCallback(this);
-        Dependency.get(ConfigurationController.class).removeCallback(this);
-        removeCallbacks(mClearSuppressCharging);
-    }
-
-    @Override
-    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-        boolean startCharging = charging && !mCharging;
-        if (startCharging && deviceWillWakeUpWhenPluggedIn() && mDark) {
-            // We're about to wake up, and thus don't want to show the indicator just for it to be
-            // hidden again.
-            clearSuppressCharging();
-            mSuppressCharging = true;
-            postDelayed(mClearSuppressCharging, CHARGING_INDICATION_DELAY_MS);
-        }
-        mCharging = charging;
-        updateVisibility();
-    }
-
-    private boolean deviceWillWakeUpWhenPluggedIn() {
-        boolean plugTurnsOnScreen = getResources().getBoolean(
-                com.android.internal.R.bool.config_unplugTurnsOnScreen);
-        boolean aod = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
-        return !aod && plugTurnsOnScreen;
-    }
-
-    @Override
-    public void onDensityOrFontScaleChanged() {
-        setImageResource(mImageResource);
-    }
-
-    public void setDark(boolean dark) {
-        mDark = dark;
-        if (!dark) {
-            clearSuppressCharging();
-        }
-        updateVisibility();
-    }
-
-    private void updateVisibility() {
-        setVisibility(mCharging && !mSuppressCharging && mDark ? VISIBLE : INVISIBLE);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index bfe07a9..0486a9d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -373,7 +373,7 @@
             if (menuState == MENU_STATE_FULL) {
                 mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim);
             } else {
-                mMenuContainerAnimator.playTogether(settingsAnim, dismissAnim);
+                mMenuContainerAnimator.playTogether(dismissAnim);
             }
             mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
             mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 33b5268..7f0acc2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -17,13 +17,18 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
 import android.graphics.Point;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.statusbar.ExpandableOutlineView;
 
 /**
  * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
@@ -31,6 +36,7 @@
 public class QSContainerImpl extends FrameLayout {
 
     private final Point mSizePoint = new Point();
+    private final Path mClipPath = new Path();
 
     private int mHeightOverride = -1;
     protected View mQSPanel;
@@ -40,6 +46,7 @@
     private QSCustomizer mQSCustomizer;
     private View mQSFooter;
     private float mFullElevation;
+    private float mRadius;
 
     public QSContainerImpl(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -54,6 +61,8 @@
         mQSCustomizer = findViewById(R.id.qs_customize);
         mQSFooter = findViewById(R.id.qs_footer);
         mFullElevation = mQSPanel.getElevation();
+        mRadius = getResources().getDimensionPixelSize(
+                Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
 
         setClickable(true);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
@@ -93,6 +102,18 @@
         updateExpansion();
     }
 
+    @Override
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        boolean ret;
+        canvas.save();
+        if (child != mQSCustomizer) {
+            canvas.clipPath(mClipPath);
+        }
+        ret = super.drawChild(canvas, child, drawingTime);
+        canvas.restore();
+        return ret;
+    }
+
     /**
      * Overrides the height of this view (post-layout), so that the content is clipped to that
      * height and the background is set to that height.
@@ -110,6 +131,10 @@
         mQSDetail.setBottom(getTop() + height);
         // Pin QS Footer to the bottom of the panel.
         mQSFooter.setTranslationY(height - mQSFooter.getHeight());
+
+        ExpandableOutlineView.getRoundedRectPath(0, 0, getWidth(), height, mRadius,
+                mRadius,
+                mClipPath);
     }
 
     protected int calculateContainerHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index c249e37..0f83078 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -103,7 +103,7 @@
 
             if (iv instanceof SlashImageView) {
                 ((SlashImageView) iv).setAnimationEnabled(shouldAnimate);
-                ((SlashImageView) iv).setState(state.slash, d);
+                ((SlashImageView) iv).setState(null, d);
             } else {
                 iv.setImageDrawable(d);
             }
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 4d0e60d..acd327b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -13,7 +13,12 @@
  */
 package com.android.systemui.qs.tileimpl;
 
+import static com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
@@ -22,16 +27,21 @@
 import android.os.Message;
 import android.service.quicksettings.Tile;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.Switch;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 
 public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
@@ -47,6 +57,12 @@
     private boolean mCollapsedView;
     private boolean mClicked;
 
+    private final ImageView mBg;
+    private final int mColorActive;
+    private final int mColorInactive;
+    private final int mColorDisabled;
+    private int mCircleColor;
+
     public QSTileBaseView(Context context, QSIconView icon) {
         this(context, icon, false);
     }
@@ -60,6 +76,10 @@
         mIconFrame.setForegroundGravity(Gravity.CENTER);
         int size = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
         addView(mIconFrame, new LayoutParams(size, size));
+        mBg = new ImageView(getContext());
+        mBg.setScaleType(ScaleType.FIT_CENTER);
+        mBg.setImageResource(R.drawable.ic_qs_circle);
+        mIconFrame.addView(mBg);
         mIcon = icon;
         FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@@ -73,6 +93,11 @@
         setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         setBackground(mTileBackground);
 
+        mColorActive = Utils.getColorAttr(context, android.R.attr.colorAccent);
+        mColorDisabled = Utils.getDisabled(context,
+                Utils.getColorAttr(context, android.R.attr.textColorTertiary));
+        mColorInactive = Utils.getColorAttr(context, android.R.attr.textColorSecondary);
+
         setPadding(0, 0, 0, 0);
         setClipChildren(false);
         setClipToPadding(false);
@@ -80,6 +105,10 @@
         setFocusable(true);
     }
 
+    public View getBgCicle() {
+        return mBg;
+    }
+
     protected Drawable newTileBackground() {
         final int[] attrs = new int[]{android.R.attr.selectableItemBackgroundBorderless};
         final TypedArray ta = getContext().obtainStyledAttributes(attrs);
@@ -150,6 +179,20 @@
     }
 
     protected void handleStateChanged(QSTile.State state) {
+        int circleColor = getCircleColor(state.state);
+        if (circleColor != mCircleColor) {
+            if (mBg.isShown()) {
+                ValueAnimator animator = ValueAnimator.ofArgb(mCircleColor, circleColor)
+                        .setDuration(QS_ANIM_LENGTH);
+                animator.addUpdateListener(animation -> mBg.setImageTintList(ColorStateList.valueOf(
+                        (Integer) animation.getAnimatedValue())));
+                animator.start();
+            } else {
+                QSIconViewImpl.setTint(mBg, circleColor);
+            }
+            mCircleColor = circleColor;
+        }
+
         setClickable(state.state != Tile.STATE_UNAVAILABLE);
         mIcon.setIcon(state);
         setContentDescription(state.contentDescription);
@@ -163,6 +206,19 @@
         }
     }
 
+    private int getCircleColor(int state) {
+        switch (state) {
+            case Tile.STATE_ACTIVE:
+                return mColorActive;
+            case Tile.STATE_INACTIVE:
+            case Tile.STATE_UNAVAILABLE:
+                return mColorDisabled;
+            default:
+                Log.e(TAG, "Invalid state " + state);
+                return 0;
+        }
+    }
+
     @Override
     public void setClickable(boolean clickable) {
         super.setClickable(clickable);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 576a447..72592829 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -373,11 +373,11 @@
         switch (state) {
             case Tile.STATE_UNAVAILABLE:
                 return Utils.getDisabled(context,
-                        Utils.getColorAttr(context, android.R.attr.colorForeground));
+                        Utils.getColorAttr(context, android.R.attr.textColorSecondary));
             case Tile.STATE_INACTIVE:
-                return Utils.getColorAttr(context, android.R.attr.textColorHint);
+                return Utils.getColorAttr(context, android.R.attr.textColorSecondary);
             case Tile.STATE_ACTIVE:
-                return Utils.getColorAttr(context, android.R.attr.textColorPrimary);
+                return Utils.getColorAttr(context, android.R.attr.colorPrimary);
             default:
                 Log.e("QSTile", "Invalid state " + state);
                 return 0;
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..a226f3c 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;
@@ -28,6 +29,7 @@
 
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
+import com.android.systemui.R.id;
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 
@@ -36,8 +38,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 +90,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 +109,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/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/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 85400a1..43047ed6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -52,6 +52,8 @@
 import com.android.systemui.util.wakelock.SettableWakeLock;
 import com.android.systemui.util.wakelock.WakeLock;
 
+import java.text.NumberFormat;
+
 /**
  * Controls the indications and error messages shown on the Keyguard
  */
@@ -87,6 +89,7 @@
     private boolean mPowerCharged;
     private int mChargingSpeed;
     private int mChargingWattage;
+    private int mBatteryLevel;
     private String mMessageToShowOnScreenOn;
 
     private KeyguardUpdateMonitorCallback mUpdateMonitorCallback;
@@ -285,14 +288,18 @@
             // Walk down a precedence-ordered list of what indication
             // should be shown based on user or device state
             if (mDozing) {
-                // If we're dozing, never show a persistent indication.
+                mTextView.setTextColor(Color.WHITE);
                 if (!TextUtils.isEmpty(mTransientIndication)) {
                     // When dozing we ignore any text color and use white instead, because
                     // colors can be hard to read in low brightness.
-                    mTextView.setTextColor(Color.WHITE);
                     mTextView.switchIndication(mTransientIndication);
+                } else if (mPowerPluggedIn) {
+                    String indication = computePowerIndication();
+                    mTextView.switchIndication(indication);
                 } else {
-                    mTextView.switchIndication(null);
+                    String percentage = NumberFormat.getPercentInstance()
+                            .format(mBatteryLevel / 100f);
+                    mTextView.switchIndication(percentage);
                 }
                 return;
             }
@@ -422,6 +429,7 @@
             mPowerCharged = status.isCharged();
             mChargingWattage = status.maxChargingWattage;
             mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
+            mBatteryLevel = status.level;
             updateIndication();
             if (mDozing) {
                 if (!wasPluggedIn && mPowerPluggedIn) {
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/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 78ee040..9b123cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.graphics.drawable.Drawable;
 import android.view.View;
 
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
@@ -39,6 +38,7 @@
     private Integer mAlpha;
     private Float mDarkIntensity;
     private Integer mVisibility = -1;
+    private Boolean mDelayTouchFeedback;
     private KeyButtonDrawable mImageDrawable;
     private View mCurrentView;
     private boolean mVertical;
@@ -71,10 +71,10 @@
         if (mImageDrawable != null) {
             ((ButtonInterface) view).setImageDrawable(mImageDrawable);
         }
-
-        if (view instanceof  ButtonInterface) {
-            ((ButtonInterface) view).setVertical(mVertical);
+        if (mDelayTouchFeedback != null) {
+            ((ButtonInterface) view).setDelayTouchFeedback(mDelayTouchFeedback);
         }
+        ((ButtonInterface) view).setVertical(mVertical);
     }
 
     public int getId() {
@@ -134,6 +134,14 @@
         }
     }
 
+    public void setDelayTouchFeedback(boolean delay) {
+        mDelayTouchFeedback = delay;
+        final int N = mViews.size();
+        for (int i = 0; i < N; i++) {
+            ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay);
+        }
+    }
+
     public void setOnClickListener(View.OnClickListener clickListener) {
         mClickListener = clickListener;
         final int N = mViews.size();
@@ -166,6 +174,14 @@
         }
     }
 
+    public void setClickable(boolean clickable) {
+        abortCurrentGesture();
+        final int N = mViews.size();
+        for (int i = 0; i < N; i++) {
+            mViews.get(i).setClickable(clickable);
+        }
+    }
+
     public ArrayList<View> getViews() {
         return mViews;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 01b3b44..ca66e98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -51,6 +51,7 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
@@ -166,6 +167,10 @@
     private String mLeftButtonStr;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private boolean mDozing;
+    private int mIndicationBottomMargin;
+    private int mIndicationBottomMarginAmbient;
+    private float mDarkAmount;
+    private int mBurnInXOffset;
 
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
@@ -235,6 +240,10 @@
         mEnterpriseDisclosure = findViewById(
                 R.id.keyguard_indication_enterprise_disclosure);
         mIndicationText = findViewById(R.id.keyguard_indication_text);
+        mIndicationBottomMargin = getResources().getDimensionPixelSize(
+                R.dimen.keyguard_indication_margin_bottom);
+        mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
+                R.dimen.keyguard_indication_margin_bottom_ambient);
         updateCameraVisibility();
         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
         mUnlockMethodCache.addListener(this);
@@ -303,11 +312,13 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        int indicationBottomMargin = getResources().getDimensionPixelSize(
+        mIndicationBottomMargin = getResources().getDimensionPixelSize(
                 R.dimen.keyguard_indication_margin_bottom);
+        mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
+                R.dimen.keyguard_indication_margin_bottom_ambient);
         MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
-        if (mlp.bottomMargin != indicationBottomMargin) {
-            mlp.bottomMargin = indicationBottomMargin;
+        if (mlp.bottomMargin != mIndicationBottomMargin) {
+            mlp.bottomMargin = mIndicationBottomMargin;
             mIndicationArea.setLayoutParams(mlp);
         }
 
@@ -543,6 +554,22 @@
         }
     }
 
+    public void setDarkAmount(float darkAmount) {
+        if (darkAmount == mDarkAmount) {
+            return;
+        }
+        mDarkAmount = darkAmount;
+        // Let's randomize the bottom margin every time we wake up to avoid burn-in.
+        if (darkAmount == 0) {
+            mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
+                    R.dimen.keyguard_indication_margin_bottom_ambient)
+                    + (int) (Math.random() * mIndicationText.getTextSize());
+        }
+        mIndicationArea.setAlpha(MathUtils.lerp(1f, 0.7f, darkAmount));
+        mIndicationArea.setTranslationY(MathUtils.lerp(0,
+                mIndicationBottomMargin - mIndicationBottomMarginAmbient, darkAmount));
+    }
+
     private static boolean isSuccessfulLaunch(int result) {
         return result == ActivityManager.START_SUCCESS
                 || result == ActivityManager.START_DELIVERED_TO_TOP
@@ -687,11 +714,6 @@
         if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
             startFinishDozeAnimationElement(mRightAffordanceView, delay);
         }
-        mIndicationArea.setAlpha(0f);
-        mIndicationArea.animate()
-                .alpha(1f)
-                .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
-                .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
     }
 
     private void startFinishDozeAnimationElement(View element, long delay) {
@@ -815,6 +837,22 @@
         }
     }
 
+    public void dozeTimeTick() {
+        if (mDarkAmount == 1) {
+            // Move indication every minute to avoid burn-in
+            final int dozeTranslation = mIndicationBottomMargin - mIndicationBottomMarginAmbient;
+            mIndicationArea.setTranslationY(dozeTranslation + (float) Math.random() * 5);
+        }
+    }
+
+    public void setBurnInXOffset(int burnInXOffset) {
+        if (mBurnInXOffset == burnInXOffset) {
+            return;
+        }
+        mBurnInXOffset = burnInXOffset;
+        mIndicationArea.setTranslationX(burnInXOffset);
+    }
+
     private class DefaultLeftButton implements IntentButton {
 
         private IconState mIconState = new IconState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 34486db..264f574 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -250,7 +250,7 @@
                 }
                 break;
             case STATE_FACE_UNLOCK:
-                iconRes = R.drawable.ic_account_circle;
+                iconRes = R.drawable.ic_face_unlock;
                 break;
             case STATE_FINGERPRINT:
                 // If screen is off and device asleep, use the draw on animation so the first frame
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 6f636aa..4faa84a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -19,15 +19,14 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.Log;
-import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewConfiguration;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
@@ -37,6 +36,7 @@
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
 import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.utilities.Utilities;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.tuner.TunerService;
 
@@ -72,6 +72,7 @@
     private NavigationBarView mNavigationBarView;
     private boolean mIsVertical;
 
+    private final QuickScrubController mQuickScrubController;
     private final int mScrollTouchSlop;
     private final Matrix mTransformGlobalMatrix = new Matrix();
     private final Matrix mTransformLocalMatrix = new Matrix();
@@ -89,6 +90,7 @@
         mContext = context;
         Resources r = context.getResources();
         mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
+        mQuickScrubController = new QuickScrubController(context);
         Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
     }
 
@@ -101,10 +103,12 @@
         mRecentsComponent = recentsComponent;
         mDivider = divider;
         mNavigationBarView = navigationBarView;
+        mQuickScrubController.setComponents(mNavigationBarView);
     }
 
     public void setBarState(boolean isVertical, boolean isRTL) {
         mIsVertical = isVertical;
+        mQuickScrubController.setBarState(isVertical, isRTL);
     }
 
     private boolean proxyMotionEvents(MotionEvent event) {
@@ -126,7 +130,6 @@
 
     public boolean onInterceptTouchEvent(MotionEvent event) {
         int action = event.getAction();
-        boolean result = false;
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN: {
                 mTouchDownX = (int) event.getX();
@@ -137,24 +140,26 @@
                 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
                 break;
             }
-            case MotionEvent.ACTION_MOVE: {
-                int x = (int) event.getX();
-                int y = (int) event.getY();
-                int xDiff = Math.abs(x - mTouchDownX);
-                int yDiff = Math.abs(y - mTouchDownY);
-                boolean exceededTouchSlop = xDiff > mScrollTouchSlop && xDiff > yDiff
-                        || yDiff > mScrollTouchSlop && yDiff > xDiff;
-                if (exceededTouchSlop) {
-                    result = true;
-                }
-                break;
-            }
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP:
-                break;
         }
-        proxyMotionEvents(event);
-        return result || (mDockWindowEnabled && interceptDockWindowEvent(event));
+        if (!mQuickScrubController.onInterceptTouchEvent(event)) {
+            proxyMotionEvents(event);
+            return false;
+        }
+        return (mDockWindowEnabled && interceptDockWindowEvent(event));
+    }
+
+    public void onDraw(Canvas canvas) {
+        if (mOverviewEventSender.getProxy() != null) {
+            mQuickScrubController.onDraw(canvas);
+        }
+    }
+
+    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        mQuickScrubController.onLayout(changed, left, top, right, bottom);
+    }
+
+    public void onDarkIntensityChange(float intensity) {
+        mQuickScrubController.onDarkIntensityChange(intensity);
     }
 
     private boolean interceptDockWindowEvent(MotionEvent event) {
@@ -294,7 +299,7 @@
     }
 
     public boolean onTouchEvent(MotionEvent event) {
-        boolean result = proxyMotionEvents(event);
+        boolean result = mQuickScrubController.onTouchEvent(event) || proxyMotionEvents(event);
         if (mDockWindowEnabled) {
             result |= handleDockWindowEvent(event);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index bd6421c..b113675 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -138,6 +138,7 @@
         if (mAutoDim) {
             applyLightsOut(false, true);
         }
+        mView.onDarkIntensityChange(darkIntensity);
     }
 
     private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 006a85b..059ce92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -26,6 +26,7 @@
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Canvas;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -625,6 +626,24 @@
         updateRotatedViews();
     }
 
+    public void onDarkIntensityChange(float intensity) {
+        if (mGestureHelper != null) {
+            mGestureHelper.onDarkIntensityChange(intensity);
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        mGestureHelper.onDraw(canvas);
+        super.onDraw(canvas);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        mGestureHelper.onLayout(changed, left, top, right, bottom);
+    }
+
     private void updateRotatedViews() {
         mRotatedViews[Surface.ROTATION_0] =
                 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 32675d3..0cc7f5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -478,6 +478,7 @@
         }
         mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
         mNotificationStackScroller.setDarkShelfOffsetX(mClockPositionResult.clockX);
+        mKeyguardBottomArea.setBurnInXOffset(mClockPositionResult.clockX);
         requestScrollerTopPaddingUpdate(animate);
     }
 
@@ -2608,7 +2609,8 @@
 
     private void setDarkAmount(float amount) {
         mDarkAmount = amount;
-        mKeyguardStatusView.setDark(mDarkAmount);
+        mKeyguardStatusView.setDarkAmount(mDarkAmount);
+        mKeyguardBottomArea.setDarkAmount(mDarkAmount);
         positionClockAndNotifications();
     }
 
@@ -2630,8 +2632,9 @@
         }
     }
 
-    public void refreshTime() {
+    public void dozeTimeTick() {
         mKeyguardStatusView.refreshTime();
+        mKeyguardBottomArea.dozeTimeTick();
         if (mDarkAmount > 0) {
             positionClockAndNotifications();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
new file mode 100644
index 0000000..afd2236
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Display;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.support.annotation.DimenRes;
+import com.android.systemui.Dependency;
+import com.android.systemui.OverviewProxyService;
+import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.utilities.Utilities;
+
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+
+/**
+ * Class to detect gestures on the navigation bar and implement quick scrub and switch.
+ */
+public class QuickScrubController extends GestureDetector.SimpleOnGestureListener implements
+        GestureHelper {
+
+    private static final String TAG = "QuickScrubController";
+    private static final int QUICK_SWITCH_FLING_VELOCITY = 0;
+    private static final int ANIM_DURATION_MS = 200;
+    private static final long LONG_PRESS_DELAY_MS = 150;
+
+    /**
+     * For quick step, set a damping value to allow the button to stick closer its origin position
+     * when dragging before quick scrub is active.
+     */
+    private static final int SWITCH_STICKINESS = 4;
+
+    private NavigationBarView mNavigationBarView;
+    private GestureDetector mGestureDetector;
+
+    private boolean mDraggingActive;
+    private boolean mQuickScrubActive;
+    private float mDownOffset;
+    private float mTranslation;
+    private int mTouchDownX;
+    private int mTouchDownY;
+    private boolean mDragPositive;
+    private boolean mIsVertical;
+    private boolean mIsRTL;
+    private float mMaxTrackPaintAlpha;
+
+    private final Handler mHandler = new Handler();
+    private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
+    private final Rect mTrackRect = new Rect();
+    private final Rect mHomeButtonRect = new Rect();
+    private final Paint mTrackPaint = new Paint();
+    private final int mScrollTouchSlop;
+    private final OverviewProxyService mOverviewEventSender;
+    private final Display mDisplay;
+    private final int mTrackThickness;
+    private final int mTrackPadding;
+    private final ValueAnimator mTrackAnimator;
+    private final ValueAnimator mButtonAnimator;
+    private final AnimatorSet mQuickScrubEndAnimator;
+    private final Context mContext;
+
+    private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> {
+        mTrackPaint.setAlpha(Math.round((float) valueAnimator.getAnimatedValue() * 255));
+        mNavigationBarView.invalidate();
+    };
+
+    private final AnimatorUpdateListener mButtonTranslationListener = animator -> {
+        int pos = (int) animator.getAnimatedValue();
+        if (!mQuickScrubActive) {
+            pos = mDragPositive ? Math.min((int) mTranslation, pos) : Math.max((int) mTranslation, pos);
+        }
+        final View homeView = mNavigationBarView.getHomeButton().getCurrentView();
+        if (mIsVertical) {
+            homeView.setTranslationY(pos);
+        } else {
+            homeView.setTranslationX(pos);
+        }
+    };
+
+    private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mNavigationBarView.getHomeButton().setClickable(true);
+            mQuickScrubActive = false;
+            mTranslation = 0;
+        }
+    };
+
+    private Runnable mLongPressRunnable = this::startQuickScrub;
+
+    private final GestureDetector.SimpleOnGestureListener mGestureListener =
+        new GestureDetector.SimpleOnGestureListener() {
+            @Override
+            public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
+                if (mQuickScrubActive) {
+                    return false;
+                }
+                float velocityX = mIsRTL ? -velX : velX;
+                float absVelY = Math.abs(velY);
+                final boolean isValidFling = velocityX > QUICK_SWITCH_FLING_VELOCITY &&
+                        mIsVertical ? (absVelY > velocityX) : (velocityX > absVelY);
+                if (isValidFling) {
+                    mDraggingActive = false;
+                    mButtonAnimator.setIntValues((int) mTranslation, 0);
+                    mButtonAnimator.start();
+                    mHandler.removeCallbacks(mLongPressRunnable);
+                    try {
+                        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
+                        overviewProxy.onQuickSwitch();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Failed to send start of quick switch.", e);
+                    }
+                }
+                return true;
+            }
+        };
+
+    public QuickScrubController(Context context) {
+        mContext = context;
+        mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        mDisplay = ((WindowManager) context.getSystemService(
+                Context.WINDOW_SERVICE)).getDefaultDisplay();
+        mOverviewEventSender = Dependency.get(OverviewProxyService.class);
+        mGestureDetector = new GestureDetector(mContext, mGestureListener);
+        mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness);
+        mTrackPadding = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_edge_padding);
+
+        mTrackAnimator = ObjectAnimator.ofFloat();
+        mTrackAnimator.addUpdateListener(mTrackAnimatorListener);
+        mButtonAnimator = ObjectAnimator.ofInt();
+        mButtonAnimator.addUpdateListener(mButtonTranslationListener);
+        mQuickScrubEndAnimator = new AnimatorSet();
+        mQuickScrubEndAnimator.playTogether(mTrackAnimator, mButtonAnimator);
+        mQuickScrubEndAnimator.setDuration(ANIM_DURATION_MS);
+        mQuickScrubEndAnimator.addListener(mQuickScrubEndListener);
+        mQuickScrubEndAnimator.setInterpolator(mQuickScrubEndInterpolator);
+    }
+
+    public void setComponents(NavigationBarView navigationBarView) {
+        mNavigationBarView = navigationBarView;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
+        final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
+        if (overviewProxy == null) {
+            homeButton.setDelayTouchFeedback(false);
+            return false;
+        }
+        mGestureDetector.onTouchEvent(event);
+        int action = event.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN: {
+                int x = (int) event.getX();
+                int y = (int) event.getY();
+                if (mHomeButtonRect.contains(x, y)) {
+                    mTouchDownX = x;
+                    mTouchDownY = y;
+                    homeButton.setDelayTouchFeedback(true);
+                    mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS);
+                } else {
+                    mTouchDownX = mTouchDownY = -1;
+                }
+                break;
+            }
+            case MotionEvent.ACTION_MOVE: {
+                if (mTouchDownX != -1) {
+                    int x = (int) event.getX();
+                    int y = (int) event.getY();
+                    int xDiff = Math.abs(x - mTouchDownX);
+                    int yDiff = Math.abs(y - mTouchDownY);
+                    boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
+                    boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
+                    boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
+                    int pos, touchDown, offset, trackSize;
+
+                    if (mIsVertical) {
+                        exceededTouchSlop = exceededTouchSlopY;
+                        exceededPerpendicularTouchSlop = exceededTouchSlopX;
+                        pos = y;
+                        touchDown = mTouchDownY;
+                        offset = pos - mTrackRect.top;
+                        trackSize = mTrackRect.height();
+                    } else {
+                        exceededTouchSlop = exceededTouchSlopX;
+                        exceededPerpendicularTouchSlop = exceededTouchSlopY;
+                        pos = x;
+                        touchDown = mTouchDownX;
+                        offset = pos - mTrackRect.left;
+                        trackSize = mTrackRect.width();
+                    }
+                    // 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();
+                    }
+
+                    // Control the button movement
+                    if (!mDraggingActive && exceededTouchSlop) {
+                        boolean allowDrag = !mDragPositive
+                                ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
+                        if (allowDrag) {
+                            mDownOffset = offset;
+                            homeButton.setClickable(false);
+                            mDraggingActive = true;
+                        }
+                    }
+                    if (mDraggingActive && (mDragPositive && offset >= 0
+                            || !mDragPositive && offset <= 0)) {
+                        float scrubFraction =
+                                Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
+                        mTranslation = !mDragPositive
+                            ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
+                            : Utilities.clamp(offset - mDownOffset, 0, trackSize);
+                        if (mQuickScrubActive) {
+                            try {
+                                overviewProxy.onQuickScrubProgress(scrubFraction);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "Failed to send progress of quick scrub.", e);
+                            }
+                        } else {
+                            mTranslation /= SWITCH_STICKINESS;
+                        }
+                        if (mIsVertical) {
+                            homeButton.getCurrentView().setTranslationY(mTranslation);
+                        } else {
+                            homeButton.getCurrentView().setTranslationX(mTranslation);
+                        }
+                    }
+                }
+                break;
+            }
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                endQuickScrub();
+                break;
+        }
+        return mDraggingActive || mQuickScrubActive;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        canvas.drawRect(mTrackRect, mTrackPaint);
+    }
+
+    @Override
+    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        final int width = right - left;
+        final int height = bottom - top;
+        final int x1, x2, y1, y2;
+        if (mIsVertical) {
+            x1 = (width - mTrackThickness) / 2;
+            x2 = x1 + mTrackThickness;
+            y1 = mDragPositive ? height / 2 : mTrackPadding;
+            y2 = y1 + height / 2 - mTrackPadding;
+        } else {
+            y1 = (height - mTrackThickness) / 2;
+            y2 = y1 + mTrackThickness;
+            x1 = mDragPositive ? width / 2 : mTrackPadding;
+            x2 = x1 + width / 2 - mTrackPadding;
+        }
+        mTrackRect.set(x1, y1, x2, y2);
+
+        // Get the touch rect of the home button location
+        View homeView = mNavigationBarView.getHomeButton().getCurrentView();
+        if (homeView != null) {
+            int[] globalHomePos = homeView.getLocationOnScreen();
+            int[] globalNavBarPos = mNavigationBarView.getLocationOnScreen();
+            int homeX = globalHomePos[0] - globalNavBarPos[0];
+            int homeY = globalHomePos[1] - globalNavBarPos[1];
+            mHomeButtonRect.set(homeX, homeY, homeX + homeView.getMeasuredWidth(),
+                    homeY + homeView.getMeasuredHeight());
+        }
+    }
+
+    @Override
+    public void onDarkIntensityChange(float intensity) {
+        if (intensity == 0) {
+            mTrackPaint.setColor(mContext.getColor(R.color.quick_step_track_background_light));
+        } else if (intensity == 1) {
+            mTrackPaint.setColor(mContext.getColor(R.color.quick_step_track_background_dark));
+        }
+        mMaxTrackPaintAlpha = mTrackPaint.getAlpha() * 1f / 255;
+        mTrackPaint.setAlpha(0);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_UP) {
+            endQuickScrub();
+        }
+        return false;
+    }
+
+    @Override
+    public void setBarState(boolean isVertical, boolean isRTL) {
+        mIsVertical = isVertical;
+        mIsRTL = isRTL;
+        try {
+            int navbarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
+            mDragPositive = navbarPos == NAV_BAR_LEFT || navbarPos == NAV_BAR_BOTTOM;
+            if (isRTL) {
+                mDragPositive = !mDragPositive;
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to get nav bar position.", e);
+        }
+    }
+
+    private void startQuickScrub() {
+        if (!mQuickScrubActive) {
+            mQuickScrubActive = true;
+            mTrackAnimator.setFloatValues(0, mMaxTrackPaintAlpha);
+            mTrackAnimator.start();
+            try {
+                mOverviewEventSender.getProxy().onQuickScrubStart();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to send start of quick scrub.", e);
+            }
+        }
+    }
+
+    private void endQuickScrub() {
+        mHandler.removeCallbacks(mLongPressRunnable);
+        if (mDraggingActive || mQuickScrubActive) {
+            mButtonAnimator.setIntValues((int) mTranslation, 0);
+            mTrackAnimator.setFloatValues(mTrackPaint.getAlpha() * 1f / 255, 0);
+            mQuickScrubEndAnimator.start();
+            try {
+                mOverviewEventSender.getProxy().onQuickScrubEnd();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to send end of quick scrub.", e);
+            }
+        }
+        mDraggingActive = false;
+    }
+
+    private int getDimensionPixelSize(Context context, @DimenRes int resId) {
+        return context.getResources().getDimensionPixelSize(resId);
+    }
+}
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 bc5440d..5e08ec3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4645,7 +4645,7 @@
 
         @Override
         public void dozeTimeTick() {
-            mNotificationPanel.refreshTime();
+            mNotificationPanel.dozeTimeTick();
         }
 
         @Override
@@ -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/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index cc7943b..a2bec98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -26,9 +26,11 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
+import android.os.Handler;
 import android.view.DisplayListCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.animation.Interpolator;
 
 import com.android.systemui.Interpolators;
@@ -56,14 +58,17 @@
     private float mGlowAlpha = 0f;
     private float mGlowScale = 1f;
     private boolean mPressed;
+    private boolean mVisible;
     private boolean mDrawingHardwareGlow;
     private int mMaxWidth;
     private boolean mLastDark;
     private boolean mDark;
+    private boolean mDelayTouchFeedback;
 
     private final Interpolator mInterpolator = new LogInterpolator();
     private boolean mSupportHardware;
     private final View mTargetView;
+    private final Handler mHandler = new Handler();
 
     private final HashSet<Animator> mRunningAnimations = new HashSet<>();
     private final ArrayList<Animator> mTmpArray = new ArrayList<>();
@@ -77,6 +82,10 @@
         mDark = darkIntensity >= 0.5f;
     }
 
+    public void setDelayTouchFeedback(boolean delay) {
+        mDelayTouchFeedback = delay;
+    }
+
     private Paint getRipplePaint() {
         if (mRipplePaint == null) {
             mRipplePaint = new Paint();
@@ -211,7 +220,16 @@
         }
     }
 
+    /**
+     * Abort the ripple while it is delayed and before shown used only when setShouldDelayStartTouch
+     * is enabled.
+     */
+    public void abortDelayedRipple() {
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
     private void cancelAnimations() {
+        mVisible = false;
         mTmpArray.addAll(mRunningAnimations);
         int size = mTmpArray.size();
         for (int i = 0; i < size; i++) {
@@ -220,11 +238,21 @@
         }
         mTmpArray.clear();
         mRunningAnimations.clear();
+        mHandler.removeCallbacksAndMessages(null);
     }
 
     private void setPressedSoftware(boolean pressed) {
         if (pressed) {
-            enterSoftware();
+            if (mDelayTouchFeedback) {
+                if (mRunningAnimations.isEmpty()) {
+                    mHandler.removeCallbacksAndMessages(null);
+                    mHandler.postDelayed(this::enterSoftware, ViewConfiguration.getTapTimeout());
+                } else if (mVisible) {
+                    enterSoftware();
+                }
+            } else {
+                enterSoftware();
+            }
         } else {
             exitSoftware();
         }
@@ -232,6 +260,7 @@
 
     private void enterSoftware() {
         cancelAnimations();
+        mVisible = true;
         mGlowAlpha = getMaxGlowAlpha();
         ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
                 0f, GLOW_MAX_SCALE_FACTOR);
@@ -240,6 +269,12 @@
         scaleAnimator.addListener(mAnimatorListener);
         scaleAnimator.start();
         mRunningAnimations.add(scaleAnimator);
+
+        // With the delay, it could eventually animate the enter animation with no pressed state,
+        // then immediately show the exit animation. If this is skipped there will be no ripple.
+        if (mDelayTouchFeedback && !mPressed) {
+            exitSoftware();
+        }
     }
 
     private void exitSoftware() {
@@ -253,7 +288,16 @@
 
     private void setPressedHardware(boolean pressed) {
         if (pressed) {
-            enterHardware();
+            if (mDelayTouchFeedback) {
+                if (mRunningAnimations.isEmpty()) {
+                    mHandler.removeCallbacksAndMessages(null);
+                    mHandler.postDelayed(this::enterHardware, ViewConfiguration.getTapTimeout());
+                } else if (mVisible) {
+                    enterHardware();
+                }
+            } else {
+                enterHardware();
+            }
         } else {
             exitHardware();
         }
@@ -302,6 +346,7 @@
 
     private void enterHardware() {
         cancelAnimations();
+        mVisible = true;
         mDrawingHardwareGlow = true;
         setExtendStart(CanvasProperty.createFloat(getExtendSize() / 2));
         final RenderNodeAnimator startAnim = new RenderNodeAnimator(getExtendStart(),
@@ -343,6 +388,12 @@
         mRunningAnimations.add(endAnim);
 
         invalidateSelf();
+
+        // With the delay, it could eventually animate the enter animation with no pressed state,
+        // then immediately show the exit animation. If this is skipped there will be no ripple.
+        if (mDelayTouchFeedback && !mPressed) {
+            exitHardware();
+        }
     }
 
     private void exitHardware() {
@@ -366,6 +417,7 @@
         public void onAnimationEnd(Animator animation) {
             mRunningAnimations.remove(animation);
             if (mRunningAnimations.isEmpty() && !mPressed) {
+                mVisible = false;
                 mDrawingHardwareGlow = false;
                 invalidateSelf();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 0501771..077c6c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -284,6 +284,7 @@
     @Override
     public void abortCurrentGesture() {
         setPressed(false);
+        mRipple.abortDelayedRipple();
         mGestureAborted = true;
     }
 
@@ -301,6 +302,11 @@
     }
 
     @Override
+    public void setDelayTouchFeedback(boolean shouldDelay) {
+        mRipple.setDelayTouchFeedback(shouldDelay);
+    }
+
+    @Override
     public void setVertical(boolean vertical) {
         //no op
     }
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/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index bc98140..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/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/BackupPolicyEnforcer.java b/services/backup/java/com/android/server/backup/BackupPolicyEnforcer.java
new file mode 100644
index 0000000..158084a
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/BackupPolicyEnforcer.java
@@ -0,0 +1,25 @@
+package com.android.server.backup;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A helper class to decouple this service from {@link DevicePolicyManager} in order to improve
+ * testability.
+ */
+@VisibleForTesting
+public class BackupPolicyEnforcer {
+    private DevicePolicyManager mDevicePolicyManager;
+
+    public BackupPolicyEnforcer(Context context) {
+        mDevicePolicyManager =
+                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+    }
+
+    public ComponentName getMandatoryBackupTransport() {
+        return mDevicePolicyManager.getMandatoryBackupTransport();
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 350d7af..5188910 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -38,6 +38,7 @@
 import android.app.IActivityManager;
 import android.app.IBackupAgent;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
 import android.app.backup.BackupManager;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.FullBackup;
@@ -681,6 +682,8 @@
     @GuardedBy("mQueueLock")
     private ArrayList<FullBackupEntry> mFullBackupQueue;
 
+    private BackupPolicyEnforcer mBackupPolicyEnforcer;
+
     // Utility: build a new random integer token. The low bits are the ordinal of the
     // operation for near-time uniqueness, and the upper bits are random for app-
     // side unpredictability.
@@ -872,6 +875,8 @@
 
         // Power management
         mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
+
+        mBackupPolicyEnforcer = new BackupPolicyEnforcer(context);
     }
 
     private void initPackageTracking() {
@@ -2774,6 +2779,10 @@
     public void setBackupEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                 "setBackupEnabled");
+        if (!enable && mBackupPolicyEnforcer.getMandatoryBackupTransport() != null) {
+            Slog.w(TAG, "Cannot disable backups when the mandatory backups policy is active.");
+            return;
+        }
 
         Slog.i(TAG, "Backup enabled => " + enable);
 
@@ -3009,6 +3018,12 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "selectBackupTransport");
 
+        if (!isAllowedByMandatoryBackupTransportPolicy(transportName)) {
+            // Don't change the transport if it is not allowed.
+            Slog.w(TAG, "Failed to select transport - disallowed by device owner policy.");
+            return mTransportManager.getCurrentTransportName();
+        }
+
         final long oldId = Binder.clearCallingIdentity();
         try {
             String previousTransportName = mTransportManager.selectTransport(transportName);
@@ -3023,10 +3038,20 @@
 
     @Override
     public void selectBackupTransportAsync(
-            ComponentName transportComponent, ISelectBackupTransportCallback listener) {
+            ComponentName transportComponent, @Nullable ISelectBackupTransportCallback listener) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "selectBackupTransportAsync");
-
+        if (!isAllowedByMandatoryBackupTransportPolicy(transportComponent)) {
+            try {
+                if (listener != null) {
+                    Slog.w(TAG, "Failed to select transport - disallowed by device owner policy.");
+                    listener.onFailure(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "ISelectBackupTransportCallback listener not available");
+            }
+            return;
+        }
         final long oldId = Binder.clearCallingIdentity();
         try {
             String transportString = transportComponent.flattenToShortString();
@@ -3048,10 +3073,12 @@
                         }
 
                         try {
-                            if (transportName != null) {
-                                listener.onSuccess(transportName);
-                            } else {
-                                listener.onFailure(result);
+                            if (listener != null) {
+                                if (transportName != null) {
+                                    listener.onSuccess(transportName);
+                                } else {
+                                    listener.onFailure(result);
+                                }
                             }
                         } catch (RemoteException e) {
                             Slog.e(TAG, "ISelectBackupTransportCallback listener not available");
@@ -3062,6 +3089,38 @@
         }
     }
 
+    /**
+     * Returns if the specified transport can be set as the current transport without violating the
+     * mandatory backup transport policy.
+     */
+    private boolean isAllowedByMandatoryBackupTransportPolicy(String transportName) {
+        ComponentName mandatoryBackupTransport = mBackupPolicyEnforcer.getMandatoryBackupTransport();
+        if (mandatoryBackupTransport == null) {
+            return true;
+        }
+        final String mandatoryBackupTransportName;
+        try {
+            mandatoryBackupTransportName =
+                    mTransportManager.getTransportName(mandatoryBackupTransport);
+        } catch (TransportNotRegisteredException e) {
+            Slog.e(TAG, "mandatory backup transport not registered!");
+            return false;
+        }
+        return TextUtils.equals(mandatoryBackupTransportName, transportName);
+    }
+
+    /**
+     * Returns if the specified transport can be set as the current transport without violating the
+     * mandatory backup transport policy.
+     */
+    private boolean isAllowedByMandatoryBackupTransportPolicy(ComponentName transport) {
+        ComponentName mandatoryBackupTransport = mBackupPolicyEnforcer.getMandatoryBackupTransport();
+        if (mandatoryBackupTransport == null) {
+            return true;
+        }
+        return mandatoryBackupTransport.equals(transport);
+    }
+
     private void updateStateForTransport(String newTransportName) {
         // Publish the name change
         Settings.Secure.putString(mContext.getContentResolver(),
@@ -3081,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..30fd25a 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;
@@ -574,8 +572,6 @@
             return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
         }
 
-        EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transportString, 1);
-
         int result;
         try {
             String transportName = transport.name();
@@ -587,7 +583,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;
         }
 
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/Android.bp b/services/core/Android.bp
index 9fb2681..3369458 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -16,6 +16,7 @@
         ":installd_aidl",
         ":storaged_aidl",
         ":vold_aidl",
+        ":mediaupdateservice_aidl",
         "java/com/android/server/EventLogTags.logtags",
         "java/com/android/server/am/EventLogTags.logtags",
     ],
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index af0b66d..04d292f 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -293,15 +293,10 @@
 
     private void updateBatteryWarningLevelLocked() {
         final ContentResolver resolver = mContext.getContentResolver();
-        final int defWarnLevel = mContext.getResources().getInteger(
+        int defWarnLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
-        final int lowPowerModeTriggerLevel = Settings.Global.getInt(resolver,
+        mLowBatteryWarningLevel = Settings.Global.getInt(resolver,
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
-
-        // NOTE: Keep the logic in sync with PowerUI.java in systemUI.
-        // TODO: Propagate this value from BatteryService to system UI, really.
-        mLowBatteryWarningLevel = Math.min(defWarnLevel, lowPowerModeTriggerLevel);
-
         if (mLowBatteryWarningLevel == 0) {
             mLowBatteryWarningLevel = defWarnLevel;
         }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index d9713a5..337406d 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);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 77521df..9574545 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -131,6 +131,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 +401,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 +890,7 @@
         mMultinetworkPolicyTracker.start();
 
         mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
+        registerPrivateDnsSettingsCallbacks();
     }
 
     private Tethering makeTethering() {
@@ -946,6 +951,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++;
     }
@@ -2114,36 +2125,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 +2217,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 +2267,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 +2458,7 @@
                 } catch (Exception e) {
                     loge("Exception removing network: " + e);
                 }
+                mDnsManager.removeNetwork(nai.network);
             }
             synchronized (mNetworkForNetId) {
                 mNetIdInUse.delete(nai.network.netId);
@@ -2898,6 +3005,9 @@
                     handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
                     break;
                 }
+                case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
+                    handlePrivateDnsSettingsChanged();
+                    break;
             }
         }
     }
@@ -4587,11 +4697,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..4551611 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -26,6 +26,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -89,6 +91,9 @@
 
     private final MyHandler mHandler;
 
+    @VisibleForTesting
+    FeatureFlagsObserver mFlagsObserver;
+
     /**
      * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
      */
@@ -98,6 +103,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];
 
@@ -111,13 +119,32 @@
     boolean mStarted;
 
     @GuardedBy("mLock")
-    boolean mForceAllAppsStandby;   // True if device is in extreme battery saver mode
+    boolean mIsCharging;
 
     @GuardedBy("mLock")
-    boolean mForcedAppStandbyEnabled;   // True if the forced app standby feature is enabled
+    boolean mBatterySaverEnabled;
 
-    private class FeatureFlagObserver extends ContentObserver {
-        FeatureFlagObserver() {
+    /**
+     * True if the forced app standby is currently enabled
+     */
+    @GuardedBy("mLock")
+    boolean mForceAllAppsStandby;
+
+    /**
+     * True if the forced app standby for small battery devices feature is enabled in settings
+     */
+    @GuardedBy("mLock")
+    boolean mForceAllAppStandbyForSmallBattery;
+
+    /**
+     * True if the forced app standby feature is enabled in settings
+     */
+    @GuardedBy("mLock")
+    boolean mForcedAppStandbyEnabled;
+
+    @VisibleForTesting
+    class FeatureFlagsObserver extends ContentObserver {
+        FeatureFlagsObserver() {
             super(null);
         }
 
@@ -125,6 +152,9 @@
             mContext.getContentResolver().registerContentObserver(
                     Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
                     false, this);
+
+            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
         }
 
         boolean isForcedAppStandbyEnabled() {
@@ -132,20 +162,43 @@
                     Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
         }
 
+        boolean isForcedAppStandbyForSmallBatteryEnabled() {
+            return Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
+        }
+
         @Override
-        public void onChange(boolean selfChange) {
-            final boolean enabled = isForcedAppStandbyEnabled();
-            synchronized (mLock) {
-                if (mForcedAppStandbyEnabled == enabled) {
-                    return;
+        public void onChange(boolean selfChange, Uri uri) {
+            if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
+                final boolean enabled = isForcedAppStandbyEnabled();
+                synchronized (mLock) {
+                    if (mForcedAppStandbyEnabled == enabled) {
+                        return;
+                    }
+                    mForcedAppStandbyEnabled = enabled;
+                    if (DEBUG) {
+                        Slog.d(TAG,
+                                "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled);
+                    }
                 }
-                mForcedAppStandbyEnabled = enabled;
-                if (DEBUG) {
-                    Slog.d(TAG,
-                            "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled);
+                mHandler.notifyForcedAppStandbyFeatureFlagChanged();
+            } else if (Settings.Global.getUriFor(
+                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
+                final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
+                synchronized (mLock) {
+                    if (mForceAllAppStandbyForSmallBattery == enabled) {
+                        return;
+                    }
+                    mForceAllAppStandbyForSmallBattery = enabled;
+                    if (DEBUG) {
+                        Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
+                                + mForceAllAppStandbyForSmallBattery);
+                    }
+                    updateForceAllAppStandbyState();
                 }
+            } else {
+                Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
             }
-            mHandler.notifyFeatureFlagChanged();
         }
     }
 
@@ -286,9 +339,11 @@
             mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
             mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
             mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
-            final FeatureFlagObserver flagObserver = new FeatureFlagObserver();
-            flagObserver.register();
-            mForcedAppStandbyEnabled = flagObserver.isForcedAppStandbyEnabled();
+            mFlagsObserver = new FeatureFlagsObserver();
+            mFlagsObserver.register();
+            mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
+            mForceAllAppStandbyForSmallBattery =
+                    mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
 
             try {
                 mIActivityManager.registerUidObserver(new UidObserver(),
@@ -303,16 +358,24 @@
 
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_USER_REMOVED);
+            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
             mContext.registerReceiver(new MyReceiver(), filter);
 
             refreshForcedAppStandbyUidPackagesLocked();
 
             mPowerManagerInternal.registerLowPowerModeObserver(
                     ServiceType.FORCE_ALL_APPS_STANDBY,
-                    (state) -> updateForceAllAppsStandby(state.batterySaverEnabled));
+                    (state) -> {
+                        synchronized (mLock) {
+                            mBatterySaverEnabled = state.batterySaverEnabled;
+                            updateForceAllAppStandbyState();
+                        }
+                    });
 
-            updateForceAllAppsStandby(mPowerManagerInternal.getLowPowerState(
-                    ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled);
+            mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
+                    ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
+
+            updateForceAllAppStandbyState();
         }
     }
 
@@ -337,6 +400,11 @@
         return LocalServices.getService(PowerManagerInternal.class);
     }
 
+    @VisibleForTesting
+    boolean isSmallBatteryDevice() {
+        return ActivityManager.isSmallBatteryDevice();
+    }
+
     /**
      * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
      */
@@ -366,18 +434,29 @@
         }
     }
 
+    private void updateForceAllAppStandbyState() {
+        synchronized (mLock) {
+            if (mIsCharging) {
+                toggleForceAllAppsStandbyLocked(false);
+            } else if (mForceAllAppStandbyForSmallBattery
+                    && isSmallBatteryDevice()) {
+                toggleForceAllAppsStandbyLocked(true);
+            } else {
+                toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
+            }
+        }
+    }
+
     /**
      * Update {@link #mForceAllAppsStandby} and notifies the listeners.
      */
-    void updateForceAllAppsStandby(boolean enable) {
-        synchronized (mLock) {
-            if (enable == mForceAllAppsStandby) {
-                return;
-            }
-            mForceAllAppsStandby = enable;
-
-            mHandler.notifyForceAllAppsStandbyChanged();
+    private void toggleForceAllAppsStandbyLocked(boolean enable) {
+        if (enable == mForceAllAppsStandby) {
+            return;
         }
+        mForceAllAppsStandby = enable;
+
+        mHandler.notifyForceAllAppsStandbyChanged();
     }
 
     private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
@@ -512,6 +591,13 @@
                 if (userId > 0) {
                     mHandler.doUserRemoved(userId);
                 }
+            } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
+                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+                synchronized (mLock) {
+                    mIsCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING
+                            || status == BatteryManager.BATTERY_STATUS_FULL);
+                }
+                updateForceAllAppStandbyState();
             }
         }
     }
@@ -530,7 +616,7 @@
         private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
         private static final int MSG_FORCE_ALL_CHANGED = 6;
         private static final int MSG_USER_REMOVED = 7;
-        private static final int MSG_FEATURE_FLAG_CHANGED = 8;
+        private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
 
         public MyHandler(Looper looper) {
             super(looper);
@@ -560,8 +646,8 @@
             obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
         }
 
-        public void notifyFeatureFlagChanged() {
-            obtainMessage(MSG_FEATURE_FLAG_CHANGED).sendToTarget();
+        public void notifyForcedAppStandbyFeatureFlagChanged() {
+            obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
         }
 
         public void doUserRemoved(int userId) {
@@ -615,7 +701,7 @@
                         l.onForceAllAppsStandbyChanged(sender);
                     }
                     return;
-                case MSG_FEATURE_FLAG_CHANGED:
+                case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
                     // Feature flag for forced app standby changed.
                     final boolean unblockAlarms;
                     synchronized (mLock) {
@@ -839,6 +925,18 @@
             pw.println(isForceAllAppsStandbyEnabled());
 
             pw.print(indent);
+            pw.print("Small Battery Device: ");
+            pw.println(isSmallBatteryDevice());
+
+            pw.print(indent);
+            pw.print("Force all apps standby for small battery device: ");
+            pw.println(mForceAllAppStandbyForSmallBattery);
+
+            pw.print(indent);
+            pw.print("Charging: ");
+            pw.println(mIsCharging);
+
+            pw.print(indent);
             pw.print("Foreground uids: [");
 
             String sep = "";
@@ -877,6 +975,11 @@
             final long token = proto.start(fieldId);
 
             proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
+            proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
+                    isSmallBatteryDevice());
+            proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
+                    mForceAllAppStandbyForSmallBattery);
+            proto.write(ForceAppStandbyTrackerProto.IS_CHARGING, mIsCharging);
 
             for (int i = 0; i < mForegroundUids.size(); i++) {
                 if (mForegroundUids.valueAt(i)) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 02cfe3d..46a35ec 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -25,6 +25,7 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.IIpSecService;
 import android.net.INetd;
 import android.net.IpSecAlgorithm;
@@ -62,7 +63,6 @@
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import libcore.io.IoUtils;
 
@@ -83,7 +83,7 @@
 
     private static final String NETD_SERVICE_NAME = "netd";
     private static final int[] DIRECTIONS =
-            new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN};
+            new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN};
 
     private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
     private static final int MAX_PORT_BIND_ATTEMPTS = 10;
@@ -104,10 +104,10 @@
     private final Context mContext;
 
     /**
-     * The next non-repeating global ID for tracking resources between users, this service,
-     * and kernel data structures. Accessing this variable is not thread safe, so it is
-     * only read or modified within blocks synchronized on IpSecService.this. We want to
-     * avoid -1 (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it).
+     * The next non-repeating global ID for tracking resources between users, this service, and
+     * kernel data structures. Accessing this variable is not thread safe, so it is only read or
+     * modified within blocks synchronized on IpSecService.this. We want to avoid -1
+     * (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it).
      */
     @GuardedBy("IpSecService.this")
     private int mNextResourceId = 1;
@@ -536,14 +536,14 @@
 
     private final class TransformRecord extends KernelResourceRecord {
         private final IpSecConfig mConfig;
-        private final SpiRecord[] mSpis;
+        private final SpiRecord mSpi;
         private final EncapSocketRecord mSocket;
 
         TransformRecord(
-                int resourceId, IpSecConfig config, SpiRecord[] spis, EncapSocketRecord socket) {
+                int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
             super(resourceId);
             mConfig = config;
-            mSpis = spis;
+            mSpi = spi;
             mSocket = socket;
         }
 
@@ -551,29 +551,26 @@
             return mConfig;
         }
 
-        public SpiRecord getSpiRecord(int direction) {
-            return mSpis[direction];
+        public SpiRecord getSpiRecord() {
+            return mSpi;
         }
 
         /** always guarded by IpSecService#this */
         @Override
         public void freeUnderlyingResources() {
-            for (int direction : DIRECTIONS) {
-                int spi = mSpis[direction].getSpi();
-                try {
-                    mSrvConfig
-                            .getNetdInstance()
-                            .ipSecDeleteSecurityAssociation(
-                                    mResourceId,
-                                    direction,
-                                    mConfig.getLocalAddress(),
-                                    mConfig.getRemoteAddress(),
-                                    spi);
-                } catch (ServiceSpecificException e) {
-                    // FIXME: get the error code and throw is at an IOException from Errno Exception
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to delete SA with ID: " + mResourceId);
-                }
+            int spi = mSpi.getSpi();
+            try {
+                mSrvConfig
+                        .getNetdInstance()
+                        .ipSecDeleteSecurityAssociation(
+                                mResourceId,
+                                mConfig.getSourceAddress(),
+                                mConfig.getDestinationAddress(),
+                                spi);
+            } catch (ServiceSpecificException e) {
+                // FIXME: get the error code and throw is at an IOException from Errno Exception
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to delete SA with ID: " + mResourceId);
             }
 
             getResourceTracker().give();
@@ -597,10 +594,8 @@
                     .append(super.toString())
                     .append(", mSocket=")
                     .append(mSocket)
-                    .append(", mSpis[OUT].mResourceId=")
-                    .append(mSpis[IpSecTransform.DIRECTION_OUT].mResourceId)
-                    .append(", mSpis[IN].mResourceId=")
-                    .append(mSpis[IpSecTransform.DIRECTION_IN].mResourceId)
+                    .append(", mSpi.mResourceId=")
+                    .append(mSpi.mResourceId)
                     .append(", mConfig=")
                     .append(mConfig)
                     .append("}");
@@ -609,23 +604,16 @@
     }
 
     private final class SpiRecord extends KernelResourceRecord {
-        private final int mDirection;
-        private final String mLocalAddress;
-        private final String mRemoteAddress;
+        private final String mSourceAddress;
+        private final String mDestinationAddress;
         private int mSpi;
 
         private boolean mOwnedByTransform = false;
 
-        SpiRecord(
-                int resourceId,
-                int direction,
-                String localAddress,
-                String remoteAddress,
-                int spi) {
+        SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) {
             super(resourceId);
-            mDirection = direction;
-            mLocalAddress = localAddress;
-            mRemoteAddress = remoteAddress;
+            mSourceAddress = sourceAddress;
+            mDestinationAddress = destinationAddress;
             mSpi = spi;
         }
 
@@ -646,7 +634,7 @@
                 mSrvConfig
                         .getNetdInstance()
                         .ipSecDeleteSecurityAssociation(
-                                mResourceId, mDirection, mLocalAddress, mRemoteAddress, mSpi);
+                                mResourceId, mSourceAddress, mDestinationAddress, mSpi);
             } catch (ServiceSpecificException e) {
                 // FIXME: get the error code and throw is at an IOException from Errno Exception
             } catch (RemoteException e) {
@@ -662,6 +650,10 @@
             return mSpi;
         }
 
+        public String getDestinationAddress() {
+            return mDestinationAddress;
+        }
+
         public void setOwnedByTransform() {
             if (mOwnedByTransform) {
                 // Programming error
@@ -689,12 +681,10 @@
                     .append(super.toString())
                     .append(", mSpi=")
                     .append(mSpi)
-                    .append(", mDirection=")
-                    .append(mDirection)
-                    .append(", mLocalAddress=")
-                    .append(mLocalAddress)
-                    .append(", mRemoteAddress=")
-                    .append(mRemoteAddress)
+                    .append(", mSourceAddress=")
+                    .append(mSourceAddress)
+                    .append(", mDestinationAddress=")
+                    .append(mDestinationAddress)
                     .append(", mOwnedByTransform=")
                     .append(mOwnedByTransform)
                     .append("}");
@@ -772,14 +762,17 @@
     /** @hide */
     @VisibleForTesting
     public IpSecService(Context context, IpSecServiceConfiguration config) {
-        this(context, config, (fd, uid) ->  {
-            try{
-                TrafficStats.setThreadStatsUid(uid);
-                TrafficStats.tagFileDescriptor(fd);
-            } finally {
-                TrafficStats.clearThreadStatsUid();
-            }
-        });
+        this(
+                context,
+                config,
+                (fd, uid) -> {
+                    try {
+                        TrafficStats.setThreadStatsUid(uid);
+                        TrafficStats.tagFileDescriptor(fd);
+                    } finally {
+                        TrafficStats.clearThreadStatsUid();
+                    }
+                });
     }
 
     /** @hide */
@@ -845,8 +838,8 @@
      */
     private static void checkDirection(int direction) {
         switch (direction) {
-            case IpSecTransform.DIRECTION_OUT:
-            case IpSecTransform.DIRECTION_IN:
+            case IpSecManager.DIRECTION_OUT:
+            case IpSecManager.DIRECTION_IN:
                 return;
         }
         throw new IllegalArgumentException("Invalid Direction: " + direction);
@@ -855,10 +848,8 @@
     /** Get a new SPI and maintain the reservation in the system server */
     @Override
     public synchronized IpSecSpiResponse allocateSecurityParameterIndex(
-            int direction, String remoteAddress, int requestedSpi, IBinder binder)
-            throws RemoteException {
-        checkDirection(direction);
-        checkInetAddress(remoteAddress);
+            String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException {
+        checkInetAddress(destinationAddress);
         /* requestedSpi can be anything in the int range, so no check is needed. */
         checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
 
@@ -866,28 +857,21 @@
         final int resourceId = mNextResourceId++;
 
         int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
-        String localAddress = "";
-
         try {
             if (!userRecord.mSpiQuotaTracker.isAvailable()) {
                 return new IpSecSpiResponse(
                         IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
             }
+
             spi =
                     mSrvConfig
                             .getNetdInstance()
-                            .ipSecAllocateSpi(
-                                    resourceId,
-                                    direction,
-                                    localAddress,
-                                    remoteAddress,
-                                    requestedSpi);
+                            .ipSecAllocateSpi(resourceId, "", destinationAddress, requestedSpi);
             Log.d(TAG, "Allocated SPI " + spi);
             userRecord.mSpiRecords.put(
                     resourceId,
                     new RefcountedResource<SpiRecord>(
-                            new SpiRecord(resourceId, direction, localAddress, remoteAddress, spi),
-                            binder));
+                            new SpiRecord(resourceId, "", destinationAddress, spi), binder));
         } catch (ServiceSpecificException e) {
             // TODO: Add appropriate checks when other ServiceSpecificException types are supported
             return new IpSecSpiResponse(
@@ -1032,27 +1016,27 @@
     }
 
     @VisibleForTesting
-    void validateAlgorithms(IpSecConfig config, int direction) throws IllegalArgumentException {
-            IpSecAlgorithm auth = config.getAuthentication(direction);
-            IpSecAlgorithm crypt = config.getEncryption(direction);
-            IpSecAlgorithm aead = config.getAuthenticatedEncryption(direction);
+    void validateAlgorithms(IpSecConfig config) throws IllegalArgumentException {
+        IpSecAlgorithm auth = config.getAuthentication();
+        IpSecAlgorithm crypt = config.getEncryption();
+        IpSecAlgorithm aead = config.getAuthenticatedEncryption();
 
-            // Validate the algorithm set
-            Preconditions.checkArgument(
-                    aead != null || crypt != null || auth != null,
-                    "No Encryption or Authentication algorithms specified");
-            Preconditions.checkArgument(
-                    auth == null || auth.isAuthentication(),
-                    "Unsupported algorithm for Authentication");
-            Preconditions.checkArgument(
+        // Validate the algorithm set
+        Preconditions.checkArgument(
+                aead != null || crypt != null || auth != null,
+                "No Encryption or Authentication algorithms specified");
+        Preconditions.checkArgument(
+                auth == null || auth.isAuthentication(),
+                "Unsupported algorithm for Authentication");
+        Preconditions.checkArgument(
                 crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption");
-            Preconditions.checkArgument(
-                    aead == null || aead.isAead(),
-                    "Unsupported algorithm for Authenticated Encryption");
-            Preconditions.checkArgument(
-                    aead == null || (auth == null && crypt == null),
-                    "Authenticated Encryption is mutually exclusive with other Authentication "
-                                    + "or Encryption algorithms");
+        Preconditions.checkArgument(
+                aead == null || aead.isAead(),
+                "Unsupported algorithm for Authenticated Encryption");
+        Preconditions.checkArgument(
+                aead == null || (auth == null && crypt == null),
+                "Authenticated Encryption is mutually exclusive with other Authentication "
+                        + "or Encryption algorithms");
     }
 
     /**
@@ -1062,29 +1046,6 @@
     private void checkIpSecConfig(IpSecConfig config) {
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
 
-        if (config.getLocalAddress() == null) {
-            throw new IllegalArgumentException("Invalid null Local InetAddress");
-        }
-
-        if (config.getRemoteAddress() == null) {
-            throw new IllegalArgumentException("Invalid null Remote InetAddress");
-        }
-
-        switch (config.getMode()) {
-            case IpSecTransform.MODE_TRANSPORT:
-                if (!config.getLocalAddress().isEmpty()) {
-                    throw new IllegalArgumentException("Non-empty Local Address");
-                }
-                // Must be valid, and not a wildcard
-                checkInetAddress(config.getRemoteAddress());
-                break;
-            case IpSecTransform.MODE_TUNNEL:
-                break;
-            default:
-                throw new IllegalArgumentException(
-                        "Invalid IpSecTransform.mode: " + config.getMode());
-        }
-
         switch (config.getEncapType()) {
             case IpSecTransform.ENCAP_NONE:
                 break;
@@ -1103,11 +1064,36 @@
                 throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType());
         }
 
-        for (int direction : DIRECTIONS) {
-            validateAlgorithms(config, direction);
+        validateAlgorithms(config);
 
-            // Retrieve SPI record; will throw IllegalArgumentException if not found
-            userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction));
+        // Retrieve SPI record; will throw IllegalArgumentException if not found
+        SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId());
+
+        // If no remote address is supplied, then use one from the SPI.
+        if (TextUtils.isEmpty(config.getDestinationAddress())) {
+            config.setDestinationAddress(s.getDestinationAddress());
+        }
+
+        // All remote addresses must match
+        if (!config.getDestinationAddress().equals(s.getDestinationAddress())) {
+            throw new IllegalArgumentException("Mismatched remote addresseses.");
+        }
+
+        // This check is technically redundant due to the chain of custody between the SPI and
+        // the IpSecConfig, but in the future if the dest is allowed to be set explicitly in
+        // the transform, this will prevent us from messing up.
+        checkInetAddress(config.getDestinationAddress());
+
+        // Require a valid source address for all transforms.
+        checkInetAddress(config.getSourceAddress());
+
+        switch (config.getMode()) {
+            case IpSecTransform.MODE_TRANSPORT:
+            case IpSecTransform.MODE_TUNNEL:
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Invalid IpSecTransform.mode: " + config.getMode());
         }
     }
 
@@ -1127,13 +1113,12 @@
 
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
 
-        // Avoid resizing by creating a dependency array of min-size 3 (1 UDP encap + 2 SPIs)
-        List<RefcountedResource> dependencies = new ArrayList<>(3);
+        // Avoid resizing by creating a dependency array of min-size 2 (1 UDP encap + 1 SPI)
+        List<RefcountedResource> dependencies = new ArrayList<>(2);
 
         if (!userRecord.mTransformQuotaTracker.isAvailable()) {
             return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
         }
-        SpiRecord[] spis = new SpiRecord[DIRECTIONS.length];
 
         int encapType, encapLocalPort = 0, encapRemotePort = 0;
         EncapSocketRecord socketRecord = null;
@@ -1149,51 +1134,46 @@
             encapRemotePort = c.getEncapRemotePort();
         }
 
-        for (int direction : DIRECTIONS) {
-            IpSecAlgorithm auth = c.getAuthentication(direction);
-            IpSecAlgorithm crypt = c.getEncryption(direction);
-            IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction);
+        IpSecAlgorithm auth = c.getAuthentication();
+        IpSecAlgorithm crypt = c.getEncryption();
+        IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
 
-            RefcountedResource<SpiRecord> refcountedSpiRecord =
-                    userRecord.mSpiRecords.getRefcountedResourceOrThrow(
-                            c.getSpiResourceId(direction));
-            dependencies.add(refcountedSpiRecord);
+        RefcountedResource<SpiRecord> refcountedSpiRecord =
+                userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
+        dependencies.add(refcountedSpiRecord);
+        SpiRecord spiRecord = refcountedSpiRecord.getResource();
 
-            spis[direction] = refcountedSpiRecord.getResource();
-            int spi = spis[direction].getSpi();
-            try {
-                mSrvConfig
-                        .getNetdInstance()
-                        .ipSecAddSecurityAssociation(
-                                resourceId,
-                                c.getMode(),
-                                direction,
-                                c.getLocalAddress(),
-                                c.getRemoteAddress(),
-                                (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0,
-                                spi,
-                                (auth != null) ? auth.getName() : "",
-                                (auth != null) ? auth.getKey() : new byte[] {},
-                                (auth != null) ? auth.getTruncationLengthBits() : 0,
-                                (crypt != null) ? crypt.getName() : "",
-                                (crypt != null) ? crypt.getKey() : new byte[] {},
-                                (crypt != null) ? crypt.getTruncationLengthBits() : 0,
-                                (authCrypt != null) ? authCrypt.getName() : "",
-                                (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
-                                (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
-                                encapType,
-                                encapLocalPort,
-                                encapRemotePort);
-            } catch (ServiceSpecificException e) {
-                // FIXME: get the error code and throw is at an IOException from Errno Exception
-                return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
-            }
+        try {
+            mSrvConfig
+                    .getNetdInstance()
+                    .ipSecAddSecurityAssociation(
+                            resourceId,
+                            c.getMode(),
+                            c.getSourceAddress(),
+                            c.getDestinationAddress(),
+                            (c.getNetwork() != null) ? c.getNetwork().netId : 0,
+                            spiRecord.getSpi(),
+                            (auth != null) ? auth.getName() : "",
+                            (auth != null) ? auth.getKey() : new byte[] {},
+                            (auth != null) ? auth.getTruncationLengthBits() : 0,
+                            (crypt != null) ? crypt.getName() : "",
+                            (crypt != null) ? crypt.getKey() : new byte[] {},
+                            (crypt != null) ? crypt.getTruncationLengthBits() : 0,
+                            (authCrypt != null) ? authCrypt.getName() : "",
+                            (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
+                            (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
+                            encapType,
+                            encapLocalPort,
+                            encapRemotePort);
+        } catch (ServiceSpecificException e) {
+            // FIXME: get the error code and throw is at an IOException from Errno Exception
+            return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
         }
         // Both SAs were created successfully, time to construct a record and lock it away
         userRecord.mTransformRecords.put(
                 resourceId,
                 new RefcountedResource<TransformRecord>(
-                        new TransformRecord(resourceId, c, spis, socketRecord),
+                        new TransformRecord(resourceId, c, spiRecord, socketRecord),
                         binder,
                         dependencies.toArray(new RefcountedResource[dependencies.size()])));
         return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId);
@@ -1217,9 +1197,9 @@
      */
     @Override
     public synchronized void applyTransportModeTransform(
-            ParcelFileDescriptor socket, int resourceId) throws RemoteException {
+            ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException {
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
+        checkDirection(direction);
         // Get transform record; if no transform is found, will throw IllegalArgumentException
         TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
 
@@ -1230,17 +1210,15 @@
 
         IpSecConfig c = info.getConfig();
         try {
-            for (int direction : DIRECTIONS) {
-                mSrvConfig
-                        .getNetdInstance()
-                        .ipSecApplyTransportModeTransform(
-                                socket.getFileDescriptor(),
-                                resourceId,
-                                direction,
-                                c.getLocalAddress(),
-                                c.getRemoteAddress(),
-                                info.getSpiRecord(direction).getSpi());
-            }
+            mSrvConfig
+                    .getNetdInstance()
+                    .ipSecApplyTransportModeTransform(
+                            socket.getFileDescriptor(),
+                            resourceId,
+                            direction,
+                            c.getSourceAddress(),
+                            c.getDestinationAddress(),
+                            info.getSpiRecord().getSpi());
         } catch (ServiceSpecificException e) {
             if (e.errorCode == EINVAL) {
                 throw new IllegalArgumentException(e.toString());
@@ -1251,13 +1229,13 @@
     }
 
     /**
-     * Remove a transport mode transform from a socket, applying the default (empty) policy. This
-     * will ensure that NO IPsec policy is applied to the socket (would be the equivalent of
-     * applying a policy that performs no IPsec). Today the resourceId parameter is passed but not
-     * used: reserved for future improved input validation.
+     * Remove transport mode transforms from a socket, applying the default (empty) policy. This
+     * ensures that NO IPsec policy is applied to the socket (would be the equivalent of applying a
+     * policy that performs no IPsec). Today the resourceId parameter is passed but not used:
+     * reserved for future improved input validation.
      */
     @Override
-    public synchronized void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId)
+    public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
             throws RemoteException {
         try {
             mSrvConfig
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..30432df 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 7167dcf..6e33afa 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;
 
@@ -370,6 +371,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;
 
@@ -397,6 +399,7 @@
 import com.android.internal.os.TransferPipe;
 import com.android.internal.os.Zygote;
 import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.internal.policy.KeyguardDismissCallback;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
@@ -6242,7 +6245,7 @@
 
                     // Clear its pending alarms
                     AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
-                    ami.removeAlarmsForUid(uid);
+                    ami.removeAlarmsForUid(appInfo.uid);
                 }
             } catch (RemoteException e) {
             }
@@ -8393,21 +8396,11 @@
                     // entering picture-in-picture (this will prompt the user to authenticate if the
                     // device is currently locked).
                     try {
-                        dismissKeyguard(token, new IKeyguardDismissCallback.Stub() {
-                            @Override
-                            public void onDismissError() throws RemoteException {
-                                // Do nothing
-                            }
-
+                        dismissKeyguard(token, new KeyguardDismissCallback() {
                             @Override
                             public void onDismissSucceeded() throws RemoteException {
                                 mHandler.post(enterPipRunnable);
                             }
-
-                            @Override
-                            public void onDismissCancelled() throws RemoteException {
-                                // Do nothing
-                            }
                         }, null /* message */);
                     } catch (RemoteException e) {
                         // Local call
@@ -13683,7 +13676,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!");
         }
     }
@@ -13742,9 +13736,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);
 
@@ -13776,9 +13768,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);
 
@@ -25142,6 +25132,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;
+        }
     }
 
     /**
@@ -25446,4 +25451,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 b74c8da..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;
@@ -1609,15 +1619,18 @@
             mStackSupervisor.mStoppingActivities.remove(this);
             mStackSupervisor.mGoingToSleepActivities.remove(this);
 
-            // If an activity is not in the paused state when becoming visible, cycle to the paused
-            // state.
-            if (state != PAUSED) {
+            // 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.
@@ -2778,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/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..c7210a8 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")
@@ -1189,7 +1201,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 +1812,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 +2116,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..ed26858 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/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index 40a93c1..51499f7 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -122,10 +122,12 @@
 
             final long startUptime = mJobStartUptimes.get(jobId);
             final long nowUptime = SystemClock.uptimeMillis();
+            final long runtime = nowUptime - startUptime;
+
             if (startUptime == 0) {
                 wtf("Job " + jobId + " start uptime not found: "
                         + " params=" + jobParametersToString(params));
-            } else if ((nowUptime - startUptime) > 60 * 1000) {
+            } else if (runtime > 60 * 1000) {
                 // WTF if startSyncH() hasn't happened, *unless* onStopJob() was called too soon.
                 // (1 minute threshold.)
                 if (!mStartedSyncs.get(jobId)) {
@@ -134,6 +136,12 @@
                             + " nowUptime=" + nowUptime
                             + " params=" + jobParametersToString(params));
                 }
+            } else if (runtime < 10 * 1000) {
+                // Job stopped too soon. WTF.
+                wtf("Job " + jobId + " stopped in " + runtime + " ms: "
+                        + " startUptime=" + startUptime
+                        + " nowUptime=" + nowUptime
+                        + " params=" + jobParametersToString(params));
             }
 
             mStartedSyncs.delete(jobId);
@@ -183,6 +191,7 @@
             return "job:null";
         } else {
             return "job:#" + params.getJobId() + ":"
+                    + "sr=[" + params.getStopReason() + "/" + params.getDebugStopReason() + "]:"
                     + SyncOperation.maybeCreateFromJobExtras(params.getExtras());
         }
     }
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/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 02e4fe0..9f18045 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) {
+                if (updateLogicalDisplaysLocked()) {
+                    scheduleTraversalLocked(false);
+                }
+            }
+        }
     }
 }
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/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 733ed3d..bd1dbf9 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -934,12 +934,14 @@
      * @param uid Uid of the calling client.
      * @param jobId Id of the job, provided at schedule-time.
      */
-    public boolean cancelJob(int uid, int jobId) {
+    public boolean cancelJob(int uid, int jobId, int callingUid) {
         JobStatus toCancel;
         synchronized (mLock) {
             toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
             if (toCancel != null) {
-                cancelJobImplLocked(toCancel, null, "cancel() called by app");
+                cancelJobImplLocked(toCancel, null,
+                        "cancel() called by app, callingUid=" + callingUid
+                        + " uid=" + uid + " jobId=" + jobId);
             }
             return (toCancel != null);
         }
@@ -2341,7 +2343,8 @@
             final int uid = Binder.getCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                JobSchedulerService.this.cancelJobsForUid(uid, "cancelAll() called by app");
+                JobSchedulerService.this.cancelJobsForUid(uid,
+                        "cancelAll() called by app, callingUid=" + uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -2353,7 +2356,7 @@
 
             long ident = Binder.clearCallingIdentity();
             try {
-                JobSchedulerService.this.cancelJob(uid, jobId);
+                JobSchedulerService.this.cancelJob(uid, jobId, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -2466,7 +2469,7 @@
             for (int i=0; i<mActiveServices.size(); i++) {
                 final JobServiceContext jc = mActiveServices.get(i);
                 final JobStatus js = jc.getRunningJobLocked();
-                if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId)) {
+                if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) {
                     foundSome = true;
                     pw.print("Timing out: ");
                     js.printUniqueId(pw);
@@ -2506,7 +2509,7 @@
             }
         } else {
             pw.println("Canceling job " + pkgName + "/#" + jobId + " in user " + userId);
-            if (!cancelJob(pkgUid, jobId)) {
+            if (!cancelJob(pkgUid, jobId, Process.SHELL_UID)) {
                 pw.println("No matching job found.");
             }
         }
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 709deeb..83a3c19 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -312,13 +312,14 @@
         return mTimeoutElapsed;
     }
 
-    boolean timeoutIfExecutingLocked(String pkgName, int userId, boolean matchJobId, int jobId) {
+    boolean timeoutIfExecutingLocked(String pkgName, int userId, boolean matchJobId, int jobId,
+            String reason) {
         final JobStatus executing = getRunningJobLocked();
         if (executing != null && (userId == UserHandle.USER_ALL || userId == executing.getUserId())
                 && (pkgName == null || pkgName.equals(executing.getSourcePackageName()))
                 && (!matchJobId || jobId == executing.getJobId())) {
             if (mVerb == VERB_EXECUTING) {
-                mParams.setStopReason(JobParameters.REASON_TIMEOUT);
+                mParams.setStopReason(JobParameters.REASON_TIMEOUT, reason);
                 sendStopMessageLocked("force timeout from shell");
                 return true;
             }
@@ -537,7 +538,7 @@
             }
             return;
         }
-        mParams.setStopReason(arg1);
+        mParams.setStopReason(arg1, debugReason);
         if (arg1 == JobParameters.REASON_PREEMPT) {
             mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
                     NO_PREFERRED_UID;
@@ -687,7 +688,7 @@
                 // Not an error - client ran out of time.
                 Slog.i(TAG, "Client timed out while executing (no jobFinished received), " +
                         "sending onStop: " + getRunningJobNameLocked());
-                mParams.setStopReason(JobParameters.REASON_TIMEOUT);
+                mParams.setStopReason(JobParameters.REASON_TIMEOUT, "client timed out");
                 sendStopMessageLocked("timeout while executing");
                 break;
             default:
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/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/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ee08c38..7bd1ae9 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,7 +2022,7 @@
     @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);
@@ -2030,7 +2030,7 @@
 
     @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 +2112,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 +2183,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 +2203,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 +2334,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 +2354,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 +2402,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 +2438,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 +2561,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 +2584,9 @@
             setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
                     requestedQuality, userId);
             mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
-            return true;
         }
+        onAuthTokenKnownForUser(userId, result.authToken);
+        return true;
     }
 
     @Override
@@ -2529,6 +2606,7 @@
             }
         }
         unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
+        onAuthTokenKnownForUser(userId, authResult.authToken);
     }
 
     @Override
@@ -2610,6 +2688,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 +2707,8 @@
                     reportDeviceSetupComplete();
                     clearFrpCredentialIfOwnerNotSecure();
                 }
+            } else if (mUserSetupCompleteUri.equals(uri)) {
+                cleanSpCache();
             }
         }
 
@@ -2678,6 +2760,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 5fe11b1..a29e1be 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;
         }
@@ -232,8 +231,8 @@
         byte[] vaultParams = KeySyncUtils.packVaultParams(
                 publicKey,
                 counterId,
-                deviceId,
-                TRUSTED_HARDWARE_MAX_ATTEMPTS);
+                TRUSTED_HARDWARE_MAX_ATTEMPTS,
+                vaultHandle);
 
         byte[] encryptedRecoveryKey;
         try {
@@ -251,12 +250,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);
@@ -265,7 +264,7 @@
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
 
         // TODO: use Builder.
-        mRecoverySnapshotStorage.put(recoveryAgentUid, new RecoveryData(
+        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot(
                 snapshotVersion,
                 /*recoveryMetadata=*/ metadataList,
                 /*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
@@ -308,7 +307,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 +330,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 +400,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..219f6e1 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(new byte[VAULT_HANDLE_LENGTH_BYTES]) // TODO: replace with real 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..801dc54 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.RecoveryManager.ERROR_BAD_CERTIFICATE_FORMAT;
+import static android.security.keystore.RecoveryManager.ERROR_DECRYPTION_FAILED;
+import static android.security.keystore.RecoveryManager.ERROR_INSECURE_USER;
+import static android.security.keystore.RecoveryManager.ERROR_NO_SNAPSHOT_PENDING;
+import static android.security.keystore.RecoveryManager.ERROR_SERVICE_INTERNAL_ERROR;
+import static android.security.keystore.RecoveryManager.ERROR_SESSION_EXPIRED;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,9 +33,9 @@
 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.KeychainProtectionParams;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.WrappedApplicationKey;
 import android.security.keystore.RecoveryManager;
 import android.util.Log;
 
@@ -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;
@@ -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,17 +423,15 @@
             // 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());
         }
     }
 
@@ -457,12 +455,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 +472,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 +485,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/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/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/media/MediaUpdateService.java b/services/core/java/com/android/server/media/MediaUpdateService.java
new file mode 100644
index 0000000..016d062
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaUpdateService.java
@@ -0,0 +1,151 @@
+/*
+ * 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.media;
+
+import android.content.Context;
+import android.content.Intent;
+import android.media.IMediaResourceMonitor;
+import android.os.Binder;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.SystemService;
+
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.PatternMatcher;
+import android.os.ServiceManager;
+import android.media.IMediaExtractorUpdateService;
+
+import java.lang.Exception;
+
+/** This class provides a system service that manages media framework updates. */
+public class MediaUpdateService extends SystemService {
+    private static final String TAG = "MediaUpdateService";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final String MEDIA_UPDATE_PACKAGE_NAME = "com.android.media.update";
+    private static final String EXTRACTOR_UPDATE_SERVICE_NAME = "media.extractor.update";
+
+    private IMediaExtractorUpdateService mMediaExtractorUpdateService;
+
+    public MediaUpdateService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        // TODO: Uncomment below once sepolicy change is landed.
+        /*
+        if ("userdebug".equals(android.os.Build.TYPE) || "eng".equals(android.os.Build.TYPE)) {
+            connect();
+            registerBroadcastReceiver();
+        }
+        */
+    }
+
+    private void connect() {
+        IBinder binder = ServiceManager.getService(EXTRACTOR_UPDATE_SERVICE_NAME);
+        if (binder != null) {
+            try {
+                binder.linkToDeath(new IBinder.DeathRecipient() {
+                    @Override
+                    public void binderDied() {
+                        Slog.w(TAG, "mediaextractor died; reconnecting");
+                        mMediaExtractorUpdateService = null;
+                        connect();
+                    }
+                }, 0);
+            } catch (Exception e) {
+                binder = null;
+            }
+        }
+        if (binder != null) {
+            mMediaExtractorUpdateService = IMediaExtractorUpdateService.Stub.asInterface(binder);
+            packageStateChanged();
+        } else {
+            Slog.w(TAG, EXTRACTOR_UPDATE_SERVICE_NAME + " not found.");
+        }
+    }
+
+    private void registerBroadcastReceiver() {
+        BroadcastReceiver updateReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM)
+                            != UserHandle.USER_SYSTEM) {
+                        // Ignore broadcast for non system users. We don't want to update system
+                        // service multiple times.
+                        return;
+                    }
+                    switch (intent.getAction()) {
+                        case Intent.ACTION_PACKAGE_REMOVED:
+                            if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
+                                // The existing package is updated. Will be handled with the
+                                // following ACTION_PACKAGE_ADDED case.
+                                return;
+                            }
+                            packageStateChanged();
+                            break;
+                        case Intent.ACTION_PACKAGE_CHANGED:
+                            packageStateChanged();
+                            break;
+                        case Intent.ACTION_PACKAGE_ADDED:
+                            packageStateChanged();
+                            break;
+                    }
+                }
+        };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addDataScheme("package");
+        filter.addDataSchemeSpecificPart(MEDIA_UPDATE_PACKAGE_NAME, PatternMatcher.PATTERN_LITERAL);
+
+        getContext().registerReceiverAsUser(updateReceiver, UserHandle.ALL, filter,
+                null /* broadcast permission */, null /* handler */);
+    }
+
+    private void packageStateChanged() {
+        ApplicationInfo packageInfo = null;
+        boolean pluginsAvailable = false;
+        try {
+            packageInfo = getContext().getPackageManager().getApplicationInfo(
+                    MEDIA_UPDATE_PACKAGE_NAME, PackageManager.MATCH_SYSTEM_ONLY);
+            pluginsAvailable = packageInfo.enabled;
+        } catch (Exception e) {
+            Slog.v(TAG, "package '" + MEDIA_UPDATE_PACKAGE_NAME + "' not installed");
+        }
+        loadExtractorPlugins(
+                (packageInfo != null && pluginsAvailable) ? packageInfo.sourceDir : "");
+    }
+
+    private void loadExtractorPlugins(String apkPath) {
+        try {
+            if (mMediaExtractorUpdateService != null) {
+                mMediaExtractorUpdateService.loadPlugins(apkPath);
+            }
+        } catch (Exception e) {
+            Slog.w(TAG, "Error in loadPlugins", e);
+        }
+    }
+}
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/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/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/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b06b583..1717b3d 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -652,6 +652,7 @@
                             activityInfo.name.equals(component.getClassName())) {
                         // Found an activity with category launcher that matches
                         // this component so ok to launch.
+                        launchIntent.setPackage(null);
                         launchIntent.setComponent(component);
                         mContext.startActivityAsUser(launchIntent, opts, user);
                         return;
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/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1e2f2b2..711ea13 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2697,6 +2697,12 @@
                                 mSettings.getDisabledSystemPkgLPr(ps.name);
                         if (disabledPs.codePath == null || !disabledPs.codePath.exists()
                                 || disabledPs.pkg == null) {
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Possibly deleted app: " + ps.dumpState_temp()
+        + "; path: " + (disabledPs.codePath == null ? "<<NULL>>":disabledPs.codePath)
+        + "; pkg: " + (disabledPs.pkg==null?"<<NULL>>":disabledPs.pkg.toString()));
+}
                             possiblyDeletedUpdatedSystemApps.add(ps.name);
                         }
                     }
@@ -2748,6 +2754,10 @@
                 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
                     PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
                     mSettings.removeDisabledSystemPackageLPw(deletedAppName);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "remove update; name: " + deletedAppName + ", exists? " + (deletedPkg != null));
+}
                     final String msg;
                     if (deletedPkg == null) {
                         // should have found an update, but, we didn't; remove everything
@@ -8311,6 +8321,8 @@
         return scannedPkg;
     }
 
+    // Temporary to catch potential issues with refactoring
+    private static boolean REFACTOR_DEBUG = true;
     /**
      * Adds a new package to the internal data structures during platform initialization.
      * <p>After adding, the package is known to the system and available for querying.
@@ -8351,6 +8363,10 @@
         synchronized (mPackages) {
             renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage);
             final String realPkgName = getRealPackageName(pkg, renamedPkgName);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Add pkg: " + pkg.packageName + (realPkgName==null?"":", realName: " + realPkgName));
+}
             if (realPkgName != null) {
                 ensurePackageRenamed(pkg, renamedPkgName);
             }
@@ -8365,6 +8381,12 @@
             if (DEBUG_INSTALL && isSystemPkgUpdated) {
                 Slog.d(TAG, "updatedPkg = " + disabledPkgSetting);
             }
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "SSP? " + scanSystemPartition
+        + ", exists? " + pkgAlreadyExists + (pkgAlreadyExists?" "+pkgSetting.toString():"")
+        + ", upgraded? " + isSystemPkgUpdated + (isSystemPkgUpdated?" "+disabledPkgSetting.toString():""));
+}
 
             final SharedUserSetting sharedUserSetting = (pkg.mSharedUserId != null)
                     ? mSettings.getSharedUserLPw(pkg.mSharedUserId,
@@ -8376,6 +8398,12 @@
                 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId
                         + " (uid=" + sharedUserSetting.userId + "):"
                         + " packages=" + sharedUserSetting.packages);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Shared UserID " + pkg.mSharedUserId
+        + " (uid=" + sharedUserSetting.userId + "):"
+        + " packages=" + sharedUserSetting.packages);
+}
             }
 
             if (scanSystemPartition) {
@@ -8384,6 +8412,10 @@
                 // version on /data, cycle through all of its children packages and
                 // remove children that are no longer defined.
                 if (isSystemPkgUpdated) {
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Disable child packages");
+}
                     final int scannedChildCount = (pkg.childPackages != null)
                             ? pkg.childPackages.size() : 0;
                     final int disabledChildCount = disabledPkgSetting.childPackageNames != null
@@ -8395,11 +8427,19 @@
                         for (int j = 0; j < scannedChildCount; j++) {
                             PackageParser.Package childPkg = pkg.childPackages.get(j);
                             if (childPkg.packageName.equals(disabledChildPackageName)) {
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Ignore " + disabledChildPackageName);
+}
                                 disabledPackageAvailable = true;
                                 break;
                             }
                         }
                         if (!disabledPackageAvailable) {
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Disable " + disabledChildPackageName);
+}
                             mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName);
                         }
                     }
@@ -8408,17 +8448,44 @@
                             disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */,
                             null /* originalPkgSetting */, null, parseFlags, scanFlags,
                             (pkg == mPlatformPackage), user);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Scan disabled system package");
+Slog.e("TODD",
+        "Pre: " + request.pkgSetting.dumpState_temp());
+}
+final ScanResult result =
                     scanPackageOnlyLI(request, mFactoryTest, -1L);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Post: " + (result.success?result.pkgSetting.dumpState_temp():"FAILED scan"));
+}
                 }
             }
         }
 
         final boolean newPkgChangedPaths =
                 pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "paths changed? " + newPkgChangedPaths
+        + "; old: " + pkg.codePath
+        + ", new: " + (pkgSetting==null?"<<NULL>>":pkgSetting.codePathString));
+}
         final boolean newPkgVersionGreater =
                 pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode;
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "version greater? " + newPkgVersionGreater
+        + "; old: " + pkg.getLongVersionCode()
+        + ", new: " + (pkgSetting==null?"<<NULL>>":pkgSetting.versionCode));
+}
         final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
                 && newPkgChangedPaths && newPkgVersionGreater;
+if (REFACTOR_DEBUG) {
+    Slog.e("TODD",
+            "system better? " + isSystemPkgBetter);
+}
         if (isSystemPkgBetter) {
             // The version of the application on /system is greater than the version on
             // /data. Switch back to the application on /system.
@@ -8434,6 +8501,13 @@
                     + " name: " + pkgSetting.name
                     + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
                     + "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "System package changed;"
+        + " name: " + pkgSetting.name
+        + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
+        + "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
+}
 
             final InstallArgs args = createInstallArgsForExisting(
                     packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString,
@@ -8445,6 +8519,10 @@
         }
 
         if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "THROW exception; system pkg version not good enough");
+}
             // The version of the application on the /system partition is less than or
             // equal to the version on the /data partition. Throw an exception and use
             // the application already installed on the /data partition.
@@ -8470,6 +8548,11 @@
                 logCriticalInfo(Log.WARN,
                         "System package signature mismatch;"
                         + " name: " + pkgSetting.name);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "System package signature mismatch;"
+        + " name: " + pkgSetting.name);
+}
                 try (PackageFreezer freezer = freezePackage(pkg.packageName,
                         "scanPackageInternalLI")) {
                     deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
@@ -8484,6 +8567,13 @@
                         + " name: " + pkgSetting.name
                         + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
                         + "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "System package enabled;"
+        + " name: " + pkgSetting.name
+        + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
+        + "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
+}
                 InstallArgs args = createInstallArgsForExisting(
                         packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString,
                         pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting));
@@ -8500,13 +8590,35 @@
                         + " name: " + pkgSetting.name
                         + "; old: " + pkgSetting.codePathString + " @ " + pkgSetting.versionCode
                         + "; new: " + pkg.codePath + " @ " + pkg.codePath);
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "System package disabled;"
+        + " name: " + pkgSetting.name
+        + "; old: " + pkgSetting.codePathString + " @ " + pkgSetting.versionCode
+        + "; new: " + pkg.codePath + " @ " + pkg.codePath);
+}
             }
         }
 
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Scan package");
+Slog.e("TODD",
+        "Pre: " + (pkgSetting==null?"<<NONE>>":pkgSetting.dumpState_temp()));
+}
         final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags
                 | SCAN_UPDATE_SIGNATURE, currentTime, user);
+if (REFACTOR_DEBUG) {
+pkgSetting = mSettings.getPackageLPr(pkg.packageName);
+Slog.e("TODD",
+        "Post: " + (pkgSetting==null?"<<NONE>>":pkgSetting.dumpState_temp()));
+}
 
         if (shouldHideSystemApp) {
+if (REFACTOR_DEBUG) {
+Slog.e("TODD",
+        "Disable package: " + pkg.packageName);
+}
             synchronized (mPackages) {
                 mSettings.disableSystemPackageLPw(pkg.packageName, true);
             }
@@ -10652,6 +10764,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 + ".");
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index bd1cd33..11b8041 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;
@@ -72,6 +73,7 @@
 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;
@@ -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;
@@ -2607,6 +2619,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/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 2b91b7d..2a2430c 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -97,6 +97,35 @@
             + " " + name + "/" + appId + "}";
     }
 
+    // Temporary to catch potential issues with refactoring
+    public String dumpState_temp() {
+        String flags = "";
+        flags += ((pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ? "U" : "");
+        flags += ((pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 ? "S" : "");
+        if ("".equals(flags)) {
+            flags = "-";
+        }
+        String privFlags = "";
+        privFlags += ((pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ? "P" : "");
+        privFlags += ((pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0 ? "O" : "");
+        privFlags += ((pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0 ? "V" : "");
+        if ("".equals(privFlags)) {
+            privFlags = "-";
+        }
+        return "PackageSetting{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " " + name + (realName == null ? "" : "("+realName+")") + "/" + appId + (sharedUser==null?"":" u:" + sharedUser.name+"("+sharedUserId+")")
+                + ", ver:" + versionCode
+                + ", path: " + codePath
+                + ", pABI: " + primaryCpuAbiString
+                + ", sABI: " + secondaryCpuAbiString
+                + ", oABI: " + cpuAbiOverrideString
+                + ", flags: " + flags
+                + ", privFlags: " + privFlags
+                + ", pkg: " + (pkg == null ? "<<NULL>>" : pkg.dumpState_temp())
+                + "}";
+    }
+
     public void copyFrom(PackageSetting orig) {
         super.copyFrom(orig);
         doCopy(orig);
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/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 50690cb..cc07d82 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -25,12 +25,14 @@
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
@@ -119,7 +121,8 @@
             UserManager.DISALLOW_AIRPLANE_MODE,
             UserManager.DISALLOW_CONFIG_BRIGHTNESS,
             UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,
-            UserManager.DISALLOW_AMBIENT_DISPLAY
+            UserManager.DISALLOW_AMBIENT_DISPLAY,
+            UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT
     });
 
     /**
@@ -542,6 +545,22 @@
                             android.provider.Settings.Global.SAFE_BOOT_DISALLOWED,
                             newValue ? 1 : 0);
                     break;
+                case UserManager.DISALLOW_AIRPLANE_MODE:
+                    if (newValue) {
+                        final boolean airplaneMode = Settings.Global.getInt(
+                                context.getContentResolver(),
+                                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+                        if (airplaneMode) {
+                            android.provider.Settings.Global.putInt(
+                                    context.getContentResolver(),
+                                    android.provider.Settings.Global.AIRPLANE_MODE_ON, 0);
+                            // Post the intent.
+                            Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+                            intent.putExtra("state", 0);
+                            context.sendBroadcastAsUser(intent, UserHandle.ALL);
+                        }
+                    }
+                    break;
             }
         } finally {
             Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
index d6281c5..a517d6d 100644
--- a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
@@ -111,6 +111,7 @@
 
         final long ident = mInjector.clearCallingIdentity();
         try {
+            launchIntent.setPackage(null);
             launchIntent.setComponent(component);
             mContext.startActivityAsUser(launchIntent,
                     ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(), user);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8aab028..88e4270 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -269,6 +269,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
+import com.android.internal.policy.KeyguardDismissCallback;
 import com.android.internal.policy.PhoneWindow;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ArrayUtils;
@@ -4211,20 +4212,23 @@
             if (isKeyguardShowingAndNotOccluded()) {
                 // don't launch home if keyguard showing
                 return;
-            }
-
-            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
+            } else if (mKeyguardOccluded && mKeyguardDelegate.isShowing()) {
+                mKeyguardDelegate.dismiss(new KeyguardDismissCallback() {
+                    @Override
+                    public void onDismissSucceeded() throws RemoteException {
+                        mHandler.post(() -> {
+                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
+                        });
+                    }
+                }, null /* message */);
+                return;
+            } else if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
                 // when in keyguard restricted mode, must first verify unlock
                 // before launching home
                 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
                     @Override
                     public void onKeyguardExitResult(boolean success) {
                         if (success) {
-                            try {
-                                ActivityManager.getService().stopAppSwitches();
-                            } catch (RemoteException e) {
-                            }
-                            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
                             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
                         }
                     }
@@ -4234,11 +4238,11 @@
         }
 
         // no keyguard stuff to worry about, just launch home!
-        try {
-            ActivityManager.getService().stopAppSwitches();
-        } catch (RemoteException e) {
-        }
         if (mRecentsVisible) {
+            try {
+                ActivityManager.getService().stopAppSwitches();
+            } catch (RemoteException e) {}
+
             // Hide Recents and notify it to launch Home
             if (awakenFromDreams) {
                 awakenDreams();
@@ -4246,7 +4250,6 @@
             hideRecentApps(false, true);
         } else {
             // Otherwise, just launch Home
-            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
             startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
         }
     }
@@ -5652,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
@@ -7633,6 +7632,11 @@
     }
 
     void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
+        try {
+            ActivityManager.getService().stopAppSwitches();
+        } catch (RemoteException e) {}
+        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
+
         if (awakenFromDreams) {
             awakenDreams();
         }
@@ -7672,11 +7676,6 @@
         }
         if (false) {
             // This code always brings home to the front.
-            try {
-                ActivityManager.getService().stopAppSwitches();
-            } catch (RemoteException e) {
-            }
-            sendCloseSystemWindows();
             startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
         } else {
             // This code brings home to the front or, if it is already
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 64a280c..c05dd2a 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -138,11 +138,6 @@
  * </dl>
  */
 public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
-    // Navigation bar position values
-    int NAV_BAR_LEFT = 1 << 0;
-    int NAV_BAR_RIGHT = 1 << 1;
-    int NAV_BAR_BOTTOM = 1 << 2;
-
     @Retention(SOURCE)
     @IntDef({NAV_BAR_LEFT, NAV_BAR_RIGHT, NAV_BAR_BOTTOM})
     @interface NavigationBarPosition {}
@@ -1211,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/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 1b5a521..48a196d 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -32,6 +32,7 @@
 import android.view.Surface;
 
 import java.io.PrintWriter;
+import java.util.List;
 
 /**
  * A special helper class used by the WindowManager
@@ -90,7 +91,28 @@
         mHandler = handler;
         mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
         mRate = rate;
-        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_DEVICE_ORIENTATION);
+        List<Sensor> l = mSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION);
+        Sensor wakeUpDeviceOrientationSensor = null;
+        Sensor nonWakeUpDeviceOrientationSensor = null;
+        /**
+         *  Prefer the wakeup form of the sensor if implemented.
+         *  It's OK to look for just two types of this sensor and use
+         *  the last found. Typical devices will only have one sensor of
+         *  this type.
+         */
+        for (Sensor s : l) {
+            if (s.isWakeUpSensor()) {
+                wakeUpDeviceOrientationSensor = s;
+            } else {
+                nonWakeUpDeviceOrientationSensor = s;
+            }
+        }
+
+        if (wakeUpDeviceOrientationSensor != null) {
+            mSensor = wakeUpDeviceOrientationSensor;
+        } else {
+            mSensor = nonWakeUpDeviceOrientationSensor;
+        }
 
         if (mSensor != null) {
             mOrientationJudge = new OrientationSensorJudge();
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..261065f 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
@@ -1611,27 +1617,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 +1770,7 @@
                 "AppWindowToken");
 
         clearThumbnail();
+        setClientHidden(isHidden());
 
         if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
             getDisplayContent().computeImeTarget(true /* updateImeTarget */);
@@ -1884,6 +1901,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..ef48661 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;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 03c0768..0cf8d2f 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;
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 28b4c1d..0171b56 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -136,7 +136,7 @@
             outSurface.copyFrom(surface);
             final IBinder winBinder = window.asBinder();
             IBinder token = new Binder();
-            mDragState = new DragState(mService, token, surface, flags, winBinder);
+            mDragState = new DragState(mService, this, token, surface, flags, winBinder);
             mDragState.mPid = callerPid;
             mDragState.mUid = callerUid;
             mDragState.mOriginalAlpha = alpha;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index b9f437a..1ac9b88 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -42,6 +42,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.IUserManager;
+import android.os.UserManagerInternal;
 import android.util.Slog;
 import android.view.Display;
 import android.view.DragEvent;
@@ -55,6 +56,7 @@
 import android.view.animation.Interpolator;
 
 import com.android.internal.view.IDragAndDropPermissions;
+import com.android.server.LocalServices;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
 
@@ -116,10 +118,10 @@
     private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
     private Point mDisplaySize = new Point();
 
-    DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
-            int flags, IBinder localWin) {
+    DragState(WindowManagerService service, DragDropController controller, IBinder token,
+            SurfaceControl surface, int flags, IBinder localWin) {
         mService = service;
-        mDragDropController = service.mDragDropController;
+        mDragDropController = controller;
         mToken = token;
         mSurfaceControl = surface;
         mFlags = flags;
@@ -318,15 +320,9 @@
 
         mSourceUserId = UserHandle.getUserId(mUid);
 
-        final IUserManager userManager =
-                (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
-        try {
-            mCrossProfileCopyAllowed = !userManager.getUserRestrictions(mSourceUserId).getBoolean(
-                    UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
-        } catch (RemoteException e) {
-            Slog.e(TAG_WM, "Remote Exception calling UserManager: " + e);
-            mCrossProfileCopyAllowed = false;
-        }
+        final UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
+        mCrossProfileCopyAllowed = !userManager.getUserRestriction(
+                mSourceUserId, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
 
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
@@ -534,7 +530,8 @@
         final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
 
         final DragAndDropPermissionsHandler dragAndDropPermissions;
-        if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0) {
+        if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
+                && mData != null) {
             dragAndDropPermissions = new DragAndDropPermissionsHandler(
                     mData,
                     mUid,
@@ -546,7 +543,9 @@
             dragAndDropPermissions = null;
         }
         if (mSourceUserId != targetUserId){
-            mData.fixUris(mSourceUserId);
+            if (mData != null) {
+                mData.fixUris(mSourceUserId);
+            }
         }
         final int myPid = Process.myPid();
         final IBinder token = touchedWin.mClient.asBinder();
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 69cbe46..62519e1 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -360,14 +360,19 @@
      * Sets the Ime state and height.
      */
     void setAdjustedForIme(boolean adjustedForIme, int imeHeight) {
-        // Return early if there is no state change
-        if (mIsImeShowing == adjustedForIme && mImeHeight == imeHeight) {
+        // Due to the order of callbacks from the system, we may receive an ime height even when
+        // {@param adjustedForIme} is false, and also a zero height when {@param adjustedForIme}
+        // is true.  Instead, ensure that the ime state changes with the height and if the ime is
+        // showing, then the height is non-zero.
+        final boolean imeShowing = adjustedForIme && imeHeight > 0;
+        imeHeight = imeShowing ? imeHeight : 0;
+        if (imeShowing == mIsImeShowing && imeHeight == mImeHeight) {
             return;
         }
 
-        mIsImeShowing = adjustedForIme;
+        mIsImeShowing = imeShowing;
         mImeHeight = imeHeight;
-        notifyImeVisibilityChanged(adjustedForIme, imeHeight);
+        notifyImeVisibilityChanged(imeShowing, imeHeight);
         notifyMovementBoundsChanged(true /* fromImeAdjustment */);
     }
 
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/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 7b33533..0fedc79 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()) {
@@ -5894,6 +5907,7 @@
      * the screen is.
      * @see WindowManagerPolicy#getNavBarPosition()
      */
+    @Override
     @WindowManagerPolicy.NavigationBarPosition
     public int getNavBarPosition() {
         synchronized (mWindowMap) {
@@ -6599,6 +6613,7 @@
     public void onOverlayChanged() {
         synchronized (mWindowMap) {
             mPolicy.onOverlayChangedLw();
+            mDisplayManagerInternal.onOverlayChanged();
             requestTraversal();
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d068c49..db30db0 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;
@@ -3952,6 +3953,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 +4004,7 @@
             mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
         }
 
-        if (!mAnimatingExit) {
+        if (!isSelfOrAncestorWindowAnimatingExit()) {
             return;
         }
 
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 bf2b137..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;
@@ -226,6 +227,7 @@
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -790,6 +792,9 @@
         private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
         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;
 
@@ -906,6 +911,14 @@
         // The blacklist data is stored in a file whose name is stored in the XML
         String passwordBlacklistFile = null;
 
+        // The component name of the backup transport which has to be used if backups are mandatory
+        // 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;
@@ -1169,6 +1182,21 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutEnabled));
                 out.endTag(null, TAG_IS_LOGOUT_ENABLED);
             }
+            if (mandatoryBackupTransport != null) {
+                out.startTag(null, TAG_MANDATORY_BACKUP_TRANSPORT);
+                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,
@@ -1347,6 +1375,23 @@
                 } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
                     isLogoutEnabled = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } 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);
@@ -3201,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);
             }
         }
     }
@@ -4503,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();
@@ -4521,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,
@@ -7319,6 +7394,7 @@
         policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
         policy.mAffiliationIds.clear();
         policy.mLockTaskPackages.clear();
+        updateLockTaskPackagesLocked(policy.mLockTaskPackages, userId);
         policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
         saveSettingsLocked(userId);
 
@@ -10096,6 +10172,11 @@
                 updateMaximumTimeToLockLocked(userId);
             }
         }
+
+        @Override
+        public boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
+            return DevicePolicyManagerService.this.canUserHaveUntrustedCredentialReset(userId);
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
@@ -11337,7 +11418,12 @@
         }
         Preconditions.checkNotNull(admin);
         synchronized (this) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(
+                    admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            if (!enabled) {
+                activeAdmin.mandatoryBackupTransport = null;
+                saveSettingsLocked(UserHandle.USER_SYSTEM);
+            }
         }
 
         final long ident = mInjector.binderClearCallingIdentity();
@@ -11372,6 +11458,50 @@
     }
 
     @Override
+    public void setMandatoryBackupTransport(
+            ComponentName admin, ComponentName backupTransportComponent) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(admin);
+        synchronized (this) {
+            ActiveAdmin activeAdmin =
+                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            if (!Objects.equals(backupTransportComponent, activeAdmin.mandatoryBackupTransport)) {
+                activeAdmin.mandatoryBackupTransport = backupTransportComponent;
+                saveSettingsLocked(UserHandle.USER_SYSTEM);
+            }
+        }
+        final long identity = mInjector.binderClearCallingIdentity();
+        try {
+            IBackupManager ibm = mInjector.getIBackupManager();
+            if (ibm != null && backupTransportComponent != null) {
+                if (!ibm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
+                    ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+                }
+                ibm.selectBackupTransportAsync(backupTransportComponent, null);
+                ibm.setBackupEnabled(true);
+            }
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Failed to set mandatory backup transport.", e);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public ComponentName getMandatoryBackupTransport() {
+        if (!mHasFeature) {
+            return null;
+        }
+        synchronized (this) {
+            ActiveAdmin activeAdmin = getDeviceOwnerAdminLocked();
+            return activeAdmin == null ? null : activeAdmin.mandatoryBackupTransport;
+        }
+    }
+
+
+    @Override
     public boolean bindDeviceAdminServiceAsUser(
             @NonNull ComponentName admin, @NonNull IApplicationThread caller,
             @Nullable IBinder activtiyToken, @NonNull Intent serviceIntent,
@@ -11943,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
@@ -11960,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 {
@@ -12005,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 {
@@ -12061,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 4310a98..3199bfa 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -80,6 +80,7 @@
 import com.android.server.lights.LightsService;
 import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
+import com.android.server.media.MediaUpdateService;
 import com.android.server.media.MediaSessionService;
 import com.android.server.media.projection.MediaProjectionManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
@@ -1442,6 +1443,10 @@
             mSystemServiceManager.startService(MediaSessionService.class);
             traceEnd();
 
+            traceBeginAndSlog("StartMediaUpdateService");
+            mSystemServiceManager.startService(MediaUpdateService.class);
+            traceEnd();
+
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
                 traceBeginAndSlog("StartHdmiControlService");
                 mSystemServiceManager.startService(HdmiControlService.class);
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/BackupManagerServiceRoboTest.java
deleted file mode 100644
index bf58224..0000000
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.backup;
-
-import static com.android.server.backup.testing.TransportData.backupTransport;
-import static com.android.server.backup.testing.TransportData.d2dTransport;
-import static com.android.server.backup.testing.TransportData.localTransport;
-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;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.robolectric.Shadows.shadowOf;
-import static org.testng.Assert.expectThrows;
-
-import android.app.backup.BackupManager;
-import android.app.backup.ISelectBackupTransportCallback;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ContextWrapper;
-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.TransportData;
-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 org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowContextWrapper;
-import org.robolectric.shadows.ShadowLog;
-import org.robolectric.shadows.ShadowLooper;
-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,
-    sdk = 26,
-    shadows = {ShadowAppBackupUtils.class}
-)
-@SystemLoaderClasses({RefactoredBackupManagerService.class, TransportManager.class})
-@Presubmit
-public class BackupManagerServiceRoboTest {
-    private static final String TAG = "BMSTest";
-
-    @Mock private TransportManager mTransportManager;
-    private HandlerThread mBackupThread;
-    private ShadowLooper mShadowBackupLooper;
-    private File mBaseStateDir;
-    private File mDataDir;
-    private ShadowContextWrapper mShadowContext;
-    private Context mContext;
-    private TransportData mTransport;
-    private String mTransportName;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        mTransport = backupTransport();
-        mTransportName = mTransport.transportName;
-
-        mBackupThread = new HandlerThread("backup-test");
-        mBackupThread.setUncaughtExceptionHandler(
-                (t, e) -> ShadowLog.e(TAG, "Uncaught exception in test thread " + t.getName(), e));
-        mBackupThread.start();
-        mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
-
-        ContextWrapper context = RuntimeEnvironment.application;
-        mContext = context;
-        mShadowContext = shadowOf(context);
-
-        File cacheDir = mContext.getCacheDir();
-        mBaseStateDir = new File(cacheDir, "base_state_dir");
-        mDataDir = new File(cacheDir, "data_dir");
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mBackupThread.quit();
-        ShadowAppBackupUtils.reset();
-    }
-
-    /* Tests for destination string */
-
-    @Test
-    public void testDestinationString() throws Exception {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
-                .thenReturn("destinationString");
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        String destination = backupManagerService.getDestinationString(mTransportName);
-
-        assertThat(destination).isEqualTo("destinationString");
-    }
-
-    @Test
-    public void testDestinationString_whenTransportNotRegistered() throws Exception {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
-                .thenThrow(TransportNotRegisteredException.class);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        String destination = backupManagerService.getDestinationString(mTransportName);
-
-        assertThat(destination).isNull();
-    }
-
-    @Test
-    public void testDestinationString_withoutPermission() throws Exception {
-        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
-                .thenThrow(TransportNotRegisteredException.class);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        expectThrows(
-                SecurityException.class,
-                () -> backupManagerService.getDestinationString(mTransportName));
-    }
-
-    /* Tests for app eligibility */
-
-    @Test
-    public void testIsAppEligibleForBackup_whenAppEligible() throws Exception {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
-        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        boolean result = backupManagerService.isAppEligibleForBackup("app.package");
-
-        assertThat(result).isTrue();
-
-        verify(mTransportManager)
-                .disposeOfTransportClient(eq(transportMock.transportClient), any());
-    }
-
-    @Test
-    public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        setUpCurrentTransport(mTransportManager, mTransport);
-        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        boolean result = backupManagerService.isAppEligibleForBackup("app.package");
-
-        assertThat(result).isFalse();
-    }
-
-    @Test
-    public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
-        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        setUpCurrentTransport(mTransportManager, mTransport);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        expectThrows(
-                SecurityException.class,
-                () -> backupManagerService.isAppEligibleForBackup("app.package"));
-    }
-
-    @Test
-    public void testFilterAppsEligibleForBackup() throws Exception {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport);
-        Map<String, Boolean> packagesMap = new HashMap<>();
-        packagesMap.put("package.a", true);
-        packagesMap.put("package.b", false);
-        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = packagesMap::get;
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-        String[] packages = packagesMap.keySet().toArray(new String[packagesMap.size()]);
-
-        String[] filtered = backupManagerService.filterAppsEligibleForBackup(packages);
-
-        assertThat(filtered).asList().containsExactly("package.a");
-        verify(mTransportManager)
-                .disposeOfTransportClient(eq(transportMock.transportClient), any());
-    }
-
-    @Test
-    public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        String[] filtered =
-                backupManagerService.filterAppsEligibleForBackup(
-                        new String[] {"package.a", "package.b"});
-
-        assertThat(filtered).isEmpty();
-    }
-
-    @Test
-    public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception {
-        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        setUpCurrentTransport(mTransportManager, mTransport);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        expectThrows(
-                SecurityException.class,
-                () ->
-                        backupManagerService.filterAppsEligibleForBackup(
-                                new String[] {"package.a", "package.b"}));
-    }
-
-    /* Tests for select transport */
-
-    private TransportData mNewTransport;
-    private TransportData mOldTransport;
-    private ComponentName mNewTransportComponent;
-
-    private void setUpForSelectTransport() throws Exception {
-        mNewTransport = backupTransport();
-        mNewTransportComponent = mNewTransport.getTransportComponent();
-        mOldTransport = d2dTransport();
-        setUpTransports(mTransportManager, mNewTransport, mOldTransport, localTransport());
-        when(mTransportManager.selectTransport(eq(mNewTransport.transportName)))
-                .thenReturn(mOldTransport.transportName);
-    }
-
-    @Test
-    public void testSelectBackupTransport() throws Exception {
-        setUpForSelectTransport();
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        String oldTransport =
-                backupManagerService.selectBackupTransport(mNewTransport.transportName);
-
-        assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
-        assertThat(oldTransport).isEqualTo(mOldTransport.transportName);
-    }
-
-    @Test
-    public void testSelectBackupTransport_withoutPermission() throws Exception {
-        setUpForSelectTransport();
-        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-
-        expectThrows(
-                SecurityException.class,
-                () -> backupManagerService.selectBackupTransport(mNewTransport.transportName));
-    }
-
-    @Test
-    public void testSelectBackupTransportAsync() throws Exception {
-        setUpForSelectTransport();
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
-                .thenReturn(BackupManager.SUCCESS);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-
-        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
-
-        mShadowBackupLooper.runToEndOfTasks();
-        assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
-        verify(callback).onSuccess(eq(mNewTransport.transportName));
-    }
-
-    @Test
-    public void testSelectBackupTransportAsync_whenRegistrationFails() throws Exception {
-        setUpForSelectTransport();
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
-                .thenReturn(BackupManager.ERROR_TRANSPORT_UNAVAILABLE);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-
-        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
-
-        mShadowBackupLooper.runToEndOfTasks();
-        assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName);
-        verify(callback).onFailure(anyInt());
-    }
-
-    @Test
-    public void testSelectBackupTransportAsync_whenTransportGetsUnregistered() throws Exception {
-        setUpTransports(mTransportManager, mTransport.unregistered());
-        ComponentName newTransportComponent = mTransport.getTransportComponent();
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        when(mTransportManager.registerAndSelectTransport(eq(newTransportComponent)))
-                .thenReturn(BackupManager.SUCCESS);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-
-        backupManagerService.selectBackupTransportAsync(newTransportComponent, callback);
-
-        mShadowBackupLooper.runToEndOfTasks();
-        assertThat(getSettingsTransport()).isNotEqualTo(mTransportName);
-        verify(callback).onFailure(anyInt());
-    }
-
-    @Test
-    public void testSelectBackupTransportAsync_withoutPermission() throws Exception {
-        setUpForSelectTransport();
-        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        RefactoredBackupManagerService backupManagerService =
-                createInitializedBackupManagerService();
-        ComponentName newTransportComponent = mNewTransport.getTransportComponent();
-
-        expectThrows(
-                SecurityException.class,
-                () ->
-                        backupManagerService.selectBackupTransportAsync(
-                                newTransportComponent, mock(ISelectBackupTransportCallback.class)));
-    }
-
-    private String getSettingsTransport() {
-        return ShadowSettings.ShadowSecure.getString(
-                mContext.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
-    }
-
-    /* Miscellaneous tests */
-
-    @Test
-    public void testConstructor_postRegisterTransports() {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-
-        createBackupManagerService();
-
-        mShadowBackupLooper.runToEndOfTasks();
-        verify(mTransportManager).registerTransports();
-    }
-
-    @Test
-    public void testConstructor_doesNotRegisterTransportsSynchronously() {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-
-        createBackupManagerService();
-
-        // Operations posted to mBackupThread only run with mShadowBackupLooper.runToEndOfTasks()
-        verify(mTransportManager, never()).registerTransports();
-    }
-
-    private RefactoredBackupManagerService createBackupManagerService() {
-        return new RefactoredBackupManagerService(
-                mContext,
-                new Trampoline(mContext),
-                mBackupThread,
-                mBaseStateDir,
-                mDataDir,
-                mTransportManager);
-    }
-
-    private RefactoredBackupManagerService createInitializedBackupManagerService() {
-        RefactoredBackupManagerService backupManagerService =
-                new RefactoredBackupManagerService(
-                        mContext,
-                        new Trampoline(mContext),
-                        mBackupThread,
-                        mBaseStateDir,
-                        mDataDir,
-                        mTransportManager);
-        mShadowBackupLooper.runToEndOfTasks();
-        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
-        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
-        // specific time to the looper the time of those messages will be before the looper's time.
-        // To fix this we advance SystemClock as well since that is from where the handlers read
-        // time.
-        ShadowSystemClock.setCurrentTimeMillis(mShadowBackupLooper.getScheduler().getCurrentTime());
-        return backupManagerService;
-    }
-}
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
new file mode 100644
index 0000000..e072800
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -0,0 +1,679 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup;
+
+import static com.android.server.backup.testing.TransportData.backupTransport;
+import static com.android.server.backup.testing.TransportData.d2dTransport;
+import static com.android.server.backup.testing.TransportData.localTransport;
+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;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+import static org.testng.Assert.expectThrows;
+
+import android.app.backup.BackupManager;
+import android.app.backup.ISelectBackupTransportCallback;
+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.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;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.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;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+    manifest = Config.NONE,
+    sdk = 26,
+    shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class}
+)
+@SystemLoaderClasses({RefactoredBackupManagerService.class, TransportManager.class})
+@Presubmit
+public class BackupManagerServiceTest {
+    private static final String TAG = "BMSTest";
+
+    @Mock private TransportManager mTransportManager;
+    private HandlerThread mBackupThread;
+    private ShadowLooper mShadowBackupLooper;
+    private File mBaseStateDir;
+    private File mDataDir;
+    private ShadowContextWrapper mShadowContext;
+    private Context mContext;
+    private TransportData mTransport;
+    private String mTransportName;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mTransport = backupTransport();
+        mTransportName = mTransport.transportName;
+
+        mBackupThread = new HandlerThread("backup-test");
+        mBackupThread.setUncaughtExceptionHandler(
+                (t, e) -> ShadowLog.e(TAG, "Uncaught exception in test thread " + t.getName(), e));
+        mBackupThread.start();
+        mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
+
+        ContextWrapper context = RuntimeEnvironment.application;
+        mContext = context;
+        mShadowContext = shadowOf(context);
+
+        File cacheDir = mContext.getCacheDir();
+        mBaseStateDir = new File(cacheDir, "base_state_dir");
+        mDataDir = new File(cacheDir, "data_dir");
+
+        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mBackupThread.quit();
+        ShadowAppBackupUtils.reset();
+        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null);
+    }
+
+    /* Tests for destination string */
+
+    @Test
+    public void testDestinationString() throws Exception {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
+                .thenReturn("destinationString");
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        String destination = backupManagerService.getDestinationString(mTransportName);
+
+        assertThat(destination).isEqualTo("destinationString");
+    }
+
+    @Test
+    public void testDestinationString_whenTransportNotRegistered() throws Exception {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
+                .thenThrow(TransportNotRegisteredException.class);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        String destination = backupManagerService.getDestinationString(mTransportName);
+
+        assertThat(destination).isNull();
+    }
+
+    @Test
+    public void testDestinationString_withoutPermission() throws Exception {
+        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
+                .thenThrow(TransportNotRegisteredException.class);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                SecurityException.class,
+                () -> backupManagerService.getDestinationString(mTransportName));
+    }
+
+    /* Tests for app eligibility */
+
+    @Test
+    public void testIsAppEligibleForBackup_whenAppEligible() throws Exception {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
+        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        boolean result = backupManagerService.isAppEligibleForBackup("app.package");
+
+        assertThat(result).isTrue();
+
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(transportMock.transportClient), any());
+    }
+
+    @Test
+    public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        setUpCurrentTransport(mTransportManager, mTransport);
+        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        boolean result = backupManagerService.isAppEligibleForBackup("app.package");
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
+        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+        setUpCurrentTransport(mTransportManager, mTransport);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                SecurityException.class,
+                () -> backupManagerService.isAppEligibleForBackup("app.package"));
+    }
+
+    @Test
+    public void testFilterAppsEligibleForBackup() throws Exception {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport);
+        Map<String, Boolean> packagesMap = new HashMap<>();
+        packagesMap.put("package.a", true);
+        packagesMap.put("package.b", false);
+        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = packagesMap::get;
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+        String[] packages = packagesMap.keySet().toArray(new String[packagesMap.size()]);
+
+        String[] filtered = backupManagerService.filterAppsEligibleForBackup(packages);
+
+        assertThat(filtered).asList().containsExactly("package.a");
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(transportMock.transportClient), any());
+    }
+
+    @Test
+    public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        String[] filtered =
+                backupManagerService.filterAppsEligibleForBackup(
+                        new String[] {"package.a", "package.b"});
+
+        assertThat(filtered).isEmpty();
+    }
+
+    @Test
+    public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception {
+        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+        setUpCurrentTransport(mTransportManager, mTransport);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                SecurityException.class,
+                () ->
+                        backupManagerService.filterAppsEligibleForBackup(
+                                new String[] {"package.a", "package.b"}));
+    }
+
+    /* Tests for select transport */
+
+    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();
+        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);
+    }
+
+    @Test
+    public void testSelectBackupTransport() throws Exception {
+        setUpForSelectTransport();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        String oldTransport =
+                backupManagerService.selectBackupTransport(mNewTransport.transportName);
+
+        assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
+        assertThat(oldTransport).isEqualTo(mOldTransport.transportName);
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any());
+    }
+
+    @Test
+    public void testSelectBackupTransport_withoutPermission() throws Exception {
+        setUpForSelectTransport();
+        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        expectThrows(
+                SecurityException.class,
+                () -> backupManagerService.selectBackupTransport(mNewTransport.transportName));
+    }
+
+    @Test
+    public void testSelectBackupTransportAsync() throws Exception {
+        setUpForSelectTransport();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
+                .thenReturn(BackupManager.SUCCESS);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName);
+        verify(callback).onSuccess(eq(mNewTransport.transportName));
+        verify(mTransportManager)
+                .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any());
+    }
+
+    @Test
+    public void testSelectBackupTransportAsync_whenMandatoryTransport() throws Exception {
+        setUpForSelectTransport();
+        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mNewTransportComponent);
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
+                .thenReturn(BackupManager.SUCCESS);
+        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
+
+        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 {
+        setUpForSelectTransport();
+        ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mOldTransportComponent);
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
+                .thenReturn(BackupManager.SUCCESS);
+        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+
+        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName);
+        verify(callback).onFailure(eq(BackupManager.ERROR_BACKUP_NOT_ALLOWED));
+    }
+
+    @Test
+    public void testSelectBackupTransportAsync_whenRegistrationFails() throws Exception {
+        setUpForSelectTransport();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
+                .thenReturn(BackupManager.ERROR_TRANSPORT_UNAVAILABLE);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+        backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName);
+        verify(callback).onFailure(anyInt());
+    }
+
+    @Test
+    public void testSelectBackupTransportAsync_whenTransportGetsUnregistered() throws Exception {
+        setUpTransports(mTransportManager, mTransport.unregistered());
+        ComponentName newTransportComponent = mTransport.getTransportComponent();
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        when(mTransportManager.registerAndSelectTransport(eq(newTransportComponent)))
+                .thenReturn(BackupManager.SUCCESS);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+        ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+        backupManagerService.selectBackupTransportAsync(newTransportComponent, callback);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        assertThat(getSettingsTransport()).isNotEqualTo(mTransportName);
+        verify(callback).onFailure(anyInt());
+    }
+
+    @Test
+    public void testSelectBackupTransportAsync_withoutPermission() throws Exception {
+        setUpForSelectTransport();
+        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
+        RefactoredBackupManagerService backupManagerService =
+                createInitializedBackupManagerService();
+        ComponentName newTransportComponent = mNewTransport.getTransportComponent();
+
+        expectThrows(
+                SecurityException.class,
+                () ->
+                        backupManagerService.selectBackupTransportAsync(
+                                newTransportComponent, mock(ISelectBackupTransportCallback.class)));
+    }
+
+    private String getSettingsTransport() {
+        return ShadowSettings.ShadowSecure.getString(
+                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
+    public void testConstructor_postRegisterTransports() {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+
+        createBackupManagerService();
+
+        mShadowBackupLooper.runToEndOfTasks();
+        verify(mTransportManager).registerTransports();
+    }
+
+    @Test
+    public void testConstructor_doesNotRegisterTransportsSynchronously() {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+
+        createBackupManagerService();
+
+        // Operations posted to mBackupThread only run with mShadowBackupLooper.runToEndOfTasks()
+        verify(mTransportManager, never()).registerTransports();
+    }
+
+    private RefactoredBackupManagerService createBackupManagerService() {
+        return new RefactoredBackupManagerService(
+                mContext,
+                new Trampoline(mContext),
+                mBackupThread,
+                mBaseStateDir,
+                mDataDir,
+                mTransportManager);
+    }
+
+    private RefactoredBackupManagerService createInitializedBackupManagerService() {
+        RefactoredBackupManagerService backupManagerService =
+                new RefactoredBackupManagerService(
+                        mContext,
+                        new Trampoline(mContext),
+                        mBackupThread,
+                        mBaseStateDir,
+                        mDataDir,
+                        mTransportManager);
+        mShadowBackupLooper.runToEndOfTasks();
+        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
+        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
+        // specific time to the looper the time of those messages will be before the looper's time.
+        // To fix this we advance SystemClock as well since that is from where the handlers read
+        // time.
+        ShadowSystemClock.setCurrentTimeMillis(mShadowBackupLooper.getScheduler().getCurrentTime());
+        return backupManagerService;
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java b/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
new file mode 100644
index 0000000..88b30da
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
@@ -0,0 +1,24 @@
+package com.android.server.backup.testing;
+
+import android.content.ComponentName;
+
+import com.android.server.backup.BackupPolicyEnforcer;
+import com.android.server.backup.RefactoredBackupManagerService;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(BackupPolicyEnforcer.class)
+public class ShadowBackupPolicyEnforcer {
+
+    private static ComponentName sMandatoryBackupTransport;
+
+    public static void setMandatoryBackupTransport(ComponentName backupTransportComponent) {
+        sMandatoryBackupTransport = backupTransportComponent;
+    }
+
+    @Implementation
+    public ComponentName getMandatoryBackupTransport() {
+        return sMandatoryBackupTransport;
+    }
+}
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/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
index 66d0da1..6a21931 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
@@ -42,6 +42,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager.ServiceType;
@@ -50,13 +51,17 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
 import android.util.ArraySet;
 import android.util.Pair;
 
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.ForceAppStandbyTracker.Listener;
 
 import org.junit.Before;
@@ -102,6 +107,9 @@
         PowerManagerInternal injectPowerManagerInternal() {
             return mMockPowerManagerInternal;
         }
+
+        @Override
+        boolean isSmallBatteryDevice() { return mIsSmallBatteryDevice; };
     }
 
     private static final int UID_1 = Process.FIRST_APPLICATION_UID + 1;
@@ -137,7 +145,11 @@
     private Consumer<PowerSaveState> mPowerSaveObserver;
     private BroadcastReceiver mReceiver;
 
+    private MockContentResolver mMockContentResolver;
+    private FakeSettingsProvider mFakeSettingsProvider;
+
     private boolean mPowerSaveMode;
+    private boolean mIsSmallBatteryDevice;
 
     private final ArraySet<Pair<Integer, String>> mRestrictedPackages = new ArraySet();
 
@@ -174,13 +186,17 @@
     }
 
     private void callStart(ForceAppStandbyTrackerTestable instance) throws RemoteException {
-
         // Set up functions that start() calls.
         when(mMockPowerManagerInternal.getLowPowerState(eq(ServiceType.FORCE_ALL_APPS_STANDBY)))
                 .thenAnswer(inv -> getPowerSaveState());
         when(mMockAppOpsManager.getPackagesForOps(
                 any(int[].class)
-                )).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
+        )).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
+
+        mMockContentResolver = new MockContentResolver();
+        mFakeSettingsProvider = new FakeSettingsProvider();
+        when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+        mMockContentResolver.addProvider(Settings.AUTHORITY, mFakeSettingsProvider);
 
         // Call start.
         instance.start();
@@ -208,7 +224,6 @@
         verify(mMockPowerManagerInternal).registerLowPowerModeObserver(
                 eq(ServiceType.FORCE_ALL_APPS_STANDBY),
                 powerSaveObserverCaptor.capture());
-
         verify(mMockContext).registerReceiver(
                 receiverCaptor.capture(), any(IntentFilter.class));
 
@@ -221,6 +236,7 @@
         assertNotNull(mAppOpsCallback);
         assertNotNull(mPowerSaveObserver);
         assertNotNull(mReceiver);
+        assertNotNull(instance.mFlagsObserver);
     }
 
     private void setAppOps(int uid, String packageName, boolean restrict) throws RemoteException {
@@ -822,6 +838,33 @@
         assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
     }
 
+    @Test
+    public void testSmallBatteryAndCharging() throws Exception {
+        // This is a small battery device
+        mIsSmallBatteryDevice = true;
+
+        final ForceAppStandbyTrackerTestable instance = newInstance();
+        callStart(instance);
+        assertFalse(instance.isForceAllAppsStandbyEnabled());
+
+        // Setting/experiment for all app standby for small battery is enabled
+        Global.putInt(mMockContentResolver, Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 1);
+        instance.mFlagsObserver.onChange(true,
+                Global.getUriFor(Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED));
+        assertTrue(instance.isForceAllAppsStandbyEnabled());
+
+        // When battery is charging, force app standby is disabled
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_CHARGING);
+        mReceiver.onReceive(mMockContext, intent);
+        assertFalse(instance.isForceAllAppsStandbyEnabled());
+
+        // When battery stops charging, force app standby is enabled
+        intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_DISCHARGING);
+        mReceiver.onReceive(mMockContext, intent);
+        assertTrue(instance.isForceAllAppsStandbyEnabled());
+    }
+
     static int[] array(int... appIds) {
         Arrays.sort(appIds);
         return appIds;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index b38a413..9923fa8 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -22,6 +22,7 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
@@ -122,7 +123,15 @@
         mActivity.makeVisibleIfNeeded(null /* starting */);
 
         assertEquals(mActivity.state, PAUSING);
+
         assertTrue(pauseFound.value);
+
+        // Make sure that the state does not change for current non-stopping states.
+        mActivity.state = INITIALIZING;
+
+        mActivity.makeVisibleIfNeeded(null /* starting */);
+
+        assertEquals(mActivity.state, INITIALIZING);
     }
 
     @Test
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..c6fc675 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, 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,
@@ -283,9 +283,9 @@
                 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);
@@ -296,15 +296,15 @@
         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);
+        WrappedApplicationKey keyData = applicationKeys.get(0);
         assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
         assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
         byte[] appKey = KeySyncUtils.decryptApplicationKey(
@@ -322,14 +322,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 +352,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 +378,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 +405,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 +471,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..ba6b274 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, 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,37 @@
     }
 
     @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);
+        // TODO: Fix this once we fix the code in the KeySyncUtils class
+        assertArrayEquals(new byte[VAULT_HANDLE_LENGTH_BYTES], 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..767472a 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),
@@ -295,7 +294,7 @@
             fail("should have thrown");
         } catch (ServiceSpecificException e) {
             assertThat(e.getMessage()).startsWith(
-                    "Only a single RecoveryMetadata is supported");
+                    "Only a single KeychainProtectionParams is supported");
         }
     }
 
@@ -308,7 +307,7 @@
                     TEST_VAULT_PARAMS,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new RecoveryMetadata(
+                            new KeychainProtectionParams(
                                     TYPE_LOCKSCREEN,
                                     TYPE_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -330,7 +329,7 @@
                     vaultParams,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new RecoveryMetadata(
+                            new KeychainProtectionParams(
                                     TYPE_LOCKSCREEN,
                                     TYPE_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -348,7 +347,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 +362,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 +386,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 +396,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 +418,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 +429,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/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/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 ce76a22..ac29163 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -16,27 +16,38 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.ClipData;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManagerInternal;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.InputChannel;
 import android.view.Surface;
 import android.view.SurfaceSession;
+import android.view.View;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+
 /**
  * Tests for the {@link DragDropController} class.
  *
@@ -46,36 +57,92 @@
 @RunWith(AndroidJUnit4.class)
 @Presubmit
 public class DragDropControllerTests extends WindowTestsBase {
-    private static final int TIMEOUT_MS = 1000;
-    private DragDropController mTarget;
+    private static final int TIMEOUT_MS = 3000;
+    private TestDragDropController mTarget;
     private WindowState mWindow;
     private IBinder mToken;
 
+    static class TestDragDropController extends DragDropController {
+        @GuardedBy("sWm.mWindowMap")
+        private Runnable mCloseCallback;
+
+        TestDragDropController(WindowManagerService service, Looper looper) {
+            super(service, looper);
+        }
+
+        void setOnClosedCallbackLocked(Runnable runnable) {
+            assertTrue(dragDropActiveLocked());
+            mCloseCallback = runnable;
+        }
+
+        @Override
+        void onDragStateClosedLocked(DragState dragState) {
+            super.onDragStateClosedLocked(dragState);
+            if (mCloseCallback != null) {
+                mCloseCallback.run();
+                mCloseCallback = null;
+            }
+        }
+    }
+
+    /**
+     * Creates a window state which can be used as a drop target.
+     */
+    private WindowState createDropTargetWindow(String name, int ownerId) {
+        final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(
+                mDisplayContent);
+        final TaskStack stack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
+        final Task task = createTaskInStack(stack, ownerId);
+        task.addChild(token, 0);
+
+        final WindowState window = createWindow(
+                null, TYPE_BASE_APPLICATION, token, name, ownerId, false);
+        window.mInputChannel = new InputChannel();
+        window.mHasSurface = true;
+        return window;
+    }
+
     @Before
     public void setUp() throws Exception {
+        final UserManagerInternal userManager = mock(UserManagerInternal.class);
+        LocalServices.addService(UserManagerInternal.class, userManager);
+
         super.setUp();
-        assertNotNull(sWm.mDragDropController);
-        mTarget = sWm.mDragDropController;
-        mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
+
+        mTarget = new TestDragDropController(sWm, sWm.mH.getLooper());
+        mDisplayContent = spy(mDisplayContent);
+        mWindow = createDropTargetWindow("Drag test window", 0);
+        when(mDisplayContent.getTouchableWinAtPointLocked(0, 0)).thenReturn(mWindow);
+        when(sWm.mInputManager.transferTouchFocus(any(), any())).thenReturn(true);
+
         synchronized (sWm.mWindowMap) {
-            // Because sWm is a static object, the previous operation may remain.
-            assertFalse(mTarget.dragDropActiveLocked());
+            sWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
         }
     }
 
     @After
-    public void tearDown() {
-        if (mToken != null) {
-            mTarget.cancelDragAndDrop(mToken);
+    public void tearDown() throws Exception {
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+        final CountDownLatch latch;
+        synchronized (sWm.mWindowMap) {
+            if (!mTarget.dragDropActiveLocked()) {
+                return;
+            }
+            if (mToken != null) {
+                mTarget.cancelDragAndDrop(mToken);
+            }
+            latch = new CountDownLatch(1);
+            mTarget.setOnClosedCallbackLocked(() -> {
+                latch.countDown();
+            });
         }
+        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
     }
 
     @Test
-    public void testPrepareDrag() throws Exception {
-        final Surface surface = new Surface();
-        mToken = mTarget.prepareDrag(
-                new SurfaceSession(), 0, 0, mWindow.mClient, 0, 100, 100, surface);
-        assertNotNull(mToken);
+    public void testDragFlow() throws Exception {
+        dragFlow(0, ClipData.newPlainText("label", "Test"), 0, 0);
     }
 
     @Test
@@ -85,4 +152,33 @@
                 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);
+    }
+
+    @Test
+    public void testPerformDrag_NullDataToOtherUser() throws Exception {
+        final WindowState otherUsersWindow =
+                createDropTargetWindow("Other user's window", 1 * UserHandle.PER_USER_RANGE);
+        when(mDisplayContent.getTouchableWinAtPointLocked(10, 10))
+                .thenReturn(otherUsersWindow);
+
+        dragFlow(0, null, 10, 10);
+    }
+
+    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);
+
+        assertTrue(sWm.mInputManager.transferTouchFocus(null, null));
+        assertTrue(mTarget.performDrag(
+                mWindow.mClient, mToken, 0, 0, 0, 0, 0, data));
+
+        mTarget.handleMotionEvent(false, dropX, dropY);
+        mToken = mWindow.mClient.asBinder();
+    }
 }
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/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/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index c699a94..69b1378 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -230,20 +230,22 @@
             boolean ownerCanAddInternalSystemWindow) {
         final WindowToken token = createWindowToken(
                 dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
-        return createWindow(parent, type, token, name, ownerCanAddInternalSystemWindow);
+        return createWindow(parent, type, token, name, 0 /* ownerId */,
+                ownerCanAddInternalSystemWindow);
     }
 
     static WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
-        return createWindow(parent, type, token, name, false /* ownerCanAddInternalSystemWindow */);
+        return createWindow(parent, type, token, name, 0 /* ownerId */,
+                false /* ownerCanAddInternalSystemWindow */);
     }
 
     static WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
-            boolean ownerCanAddInternalSystemWindow) {
+            int ownerId, boolean ownerCanAddInternalSystemWindow) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
         attrs.setTitle(name);
 
         final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
-                0, attrs, VISIBLE, 0, ownerCanAddInternalSystemWindow);
+                0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow);
         // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
         // adding it to the token...
         token.addWindow(w);
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/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/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5a1a3e3..ce0b551 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -960,8 +960,9 @@
     public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
 
     /**
-     * String to identify carrier name in CarrierConfig app. This string is used only if
-     * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true
+     * String to identify carrier name in CarrierConfig app. This string overrides SPN if
+     * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true; otherwise, it will be used if its value is provided
+     * and SPN is unavailable
      * @hide
      */
     public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
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/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%
rename from core/java/android/security/keystore/RecoveryData.aidl
rename 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/EntryRecoveryData.aidl b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl
similarity index 88%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to telephony/java/android/telephony/euicc/EuiccRulesAuthTable.aidl
index c6c20e3..9785a45 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.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 EntryRecoveryData;
+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/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl
similarity index 71%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl
index f14e93f..8a77bf1 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 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%
copy from core/java/android/os/Seccomp.java
copy 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/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.aidl
similarity index 69%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.aidl
index f14e93f..3ee0b3a 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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.service.euicc.EuiccProfileInfo;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @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/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.aidl
similarity index 71%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.aidl
index f14e93f..79b659d 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IGetDefaultSmdpAddressCallback {
+    void onComplete(int resultCode, String address);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl
similarity index 71%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl
index f14e93f..5ffb340 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IGetEuiccChallengeCallback {
+    void onComplete(int resultCode, in byte[] challenge);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl
similarity index 72%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl
index f14e93f..9592acb 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IGetEuiccInfo1Callback {
+    void onComplete(int resultCode, in byte[] info);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl
similarity index 72%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl
index f14e93f..5256b35 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IGetEuiccInfo2Callback {
+    void onComplete(int resultCode, in byte[] info);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.aidl
similarity index 67%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.aidl
index f14e93f..e9fc9e9 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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.service.euicc.EuiccProfileInfo;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface IGetProfileCallback {
+    void onComplete(int resultCode, in EuiccProfileInfo profile);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl
similarity index 66%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl
index f14e93f..58f0bde 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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.EuiccRulesAuthTable;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface IGetRulesAuthTableCallback {
+    void onComplete(int resultCode, in EuiccRulesAuthTable rat);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.aidl
similarity index 72%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.aidl
index f14e93f..09a83aa 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 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/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl
similarity index 71%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl
index f14e93f..4ad7081 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 ILoadBoundProfilePackageCallback {
+    void onComplete(int resultCode, in byte[] response);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl
similarity index 71%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl
index f14e93f..c035184 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IPrepareDownloadCallback {
+    void onComplete(int resultCode, in byte[] response);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl
similarity index 68%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl
index f14e93f..b22d0da 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IRemoveNotificationFromListCallback {
+    void onComplete(int resultCode);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.aidl
similarity index 74%
rename from core/java/android/os/Seccomp.java
rename to telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.aidl
index f14e93f..860c158 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 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/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl
similarity index 65%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl
index f14e93f..bc4e451 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 IRetrieveNotificationListCallback {
+    void onComplete(int resultCode, in EuiccNotification[] notifications);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl
similarity index 73%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl
index f14e93f..1e47125 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 ISetDefaultSmdpAddressCallback {
+    void onComplete(int resultCode);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl
similarity index 74%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl
index f14e93f..5899980 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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 ISetNicknameCallback {
+    void onComplete(int resultCode);
 }
diff --git a/core/java/android/os/Seccomp.java b/telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl
similarity index 67%
copy from core/java/android/os/Seccomp.java
copy to telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl
index f14e93f..21ff084 100644
--- a/core/java/android/os/Seccomp.java
+++ 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,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.service.euicc.EuiccProfileInfo;
 
-/**
- * @hide
- */
-public final class Seccomp {
-    public static final native void setPolicy();
+/** @hide */
+oneway interface ISwitchToProfileCallback {
+    void onComplete(int resultCode, in EuiccProfileInfo profile);
 }
diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java
index efc01f2a..f6c5532 100644
--- a/tests/net/java/android/net/IpSecConfigTest.java
+++ b/tests/net/java/android/net/IpSecConfigTest.java
@@ -36,19 +36,16 @@
     public void testDefaults() throws Exception {
         IpSecConfig c = new IpSecConfig();
         assertEquals(IpSecTransform.MODE_TRANSPORT, c.getMode());
-        assertEquals("", c.getLocalAddress());
-        assertEquals("", c.getRemoteAddress());
+        assertEquals("", c.getSourceAddress());
+        assertEquals("", c.getDestinationAddress());
         assertNull(c.getNetwork());
         assertEquals(IpSecTransform.ENCAP_NONE, c.getEncapType());
         assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getEncapSocketResourceId());
         assertEquals(0, c.getEncapRemotePort());
         assertEquals(0, c.getNattKeepaliveInterval());
-        for (int direction :
-                new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}) {
-            assertNull(c.getEncryption(direction));
-            assertNull(c.getAuthentication(direction));
-            assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId(direction));
-        }
+        assertNull(c.getEncryption());
+        assertNull(c.getAuthentication());
+        assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId());
     }
 
     @Test
@@ -57,34 +54,21 @@
 
         IpSecConfig c = new IpSecConfig();
         c.setMode(IpSecTransform.MODE_TUNNEL);
-        c.setLocalAddress("0.0.0.0");
-        c.setRemoteAddress("1.2.3.4");
+        c.setSourceAddress("0.0.0.0");
+        c.setDestinationAddress("1.2.3.4");
         c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP);
         c.setEncapSocketResourceId(7);
         c.setEncapRemotePort(22);
         c.setNattKeepaliveInterval(42);
         c.setEncryption(
-                IpSecTransform.DIRECTION_OUT,
                 new IpSecAlgorithm(
                         IpSecAlgorithm.CRYPT_AES_CBC,
                         new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}));
         c.setAuthentication(
-                IpSecTransform.DIRECTION_OUT,
                 new IpSecAlgorithm(
                         IpSecAlgorithm.AUTH_HMAC_MD5,
                         new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
-        c.setSpiResourceId(IpSecTransform.DIRECTION_OUT, 1984);
-        c.setEncryption(
-                IpSecTransform.DIRECTION_IN,
-                new IpSecAlgorithm(
-                        IpSecAlgorithm.CRYPT_AES_CBC,
-                        new byte[] {2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}));
-        c.setAuthentication(
-                IpSecTransform.DIRECTION_IN,
-                new IpSecAlgorithm(
-                        IpSecAlgorithm.AUTH_HMAC_MD5,
-                        new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 1}));
-        c.setSpiResourceId(IpSecTransform.DIRECTION_IN, 99);
+        c.setSpiResourceId(1984);
         assertParcelingIsLossless(c);
     }
 
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index 0f40b45..cc3366f 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -81,15 +81,13 @@
         IpSecSpiResponse spiResp =
                 new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
         when(mMockIpSecService.allocateSecurityParameterIndex(
-                        eq(IpSecTransform.DIRECTION_IN),
                         eq(GOOGLE_DNS_4.getHostAddress()),
                         eq(DROID_SPI),
                         anyObject()))
                 .thenReturn(spiResp);
 
         IpSecManager.SecurityParameterIndex droidSpi =
-                mIpSecManager.allocateSecurityParameterIndex(
-                        IpSecTransform.DIRECTION_IN, GOOGLE_DNS_4, DROID_SPI);
+                mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, DROID_SPI);
         assertEquals(DROID_SPI, droidSpi.getSpi());
 
         droidSpi.close();
@@ -103,15 +101,13 @@
         IpSecSpiResponse spiResp =
                 new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
         when(mMockIpSecService.allocateSecurityParameterIndex(
-                        eq(IpSecTransform.DIRECTION_OUT),
                         eq(GOOGLE_DNS_4.getHostAddress()),
                         eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
                         anyObject()))
                 .thenReturn(spiResp);
 
         IpSecManager.SecurityParameterIndex randomSpi =
-                mIpSecManager.allocateSecurityParameterIndex(
-                        IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4);
+                mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
 
         assertEquals(DROID_SPI, randomSpi.getSpi());
 
@@ -124,16 +120,15 @@
      * Throws resource unavailable exception
      */
     @Test
-    public void testAllocSpiResUnavaiableExeption() throws Exception {
+    public void testAllocSpiResUnavailableException() throws Exception {
         IpSecSpiResponse spiResp =
                 new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0);
         when(mMockIpSecService.allocateSecurityParameterIndex(
-                        anyInt(), anyString(), anyInt(), anyObject()))
+                        anyString(), anyInt(), anyObject()))
                 .thenReturn(spiResp);
 
         try {
-            mIpSecManager.allocateSecurityParameterIndex(
-                    IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4);
+            mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
             fail("ResourceUnavailableException was not thrown");
         } catch (IpSecManager.ResourceUnavailableException e) {
         }
@@ -143,15 +138,14 @@
      * Throws spi unavailable exception
      */
     @Test
-    public void testAllocSpiSpiUnavaiableExeption() throws Exception {
+    public void testAllocSpiSpiUnavailableException() throws Exception {
         IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0);
         when(mMockIpSecService.allocateSecurityParameterIndex(
-                        anyInt(), anyString(), anyInt(), anyObject()))
+                        anyString(), anyInt(), anyObject()))
                 .thenReturn(spiResp);
 
         try {
-            mIpSecManager.allocateSecurityParameterIndex(
-                    IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4);
+            mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4);
             fail("ResourceUnavailableException was not thrown");
         } catch (IpSecManager.ResourceUnavailableException e) {
         }
@@ -163,8 +157,7 @@
     @Test
     public void testRequestAllocInvalidSpi() throws Exception {
         try {
-            mIpSecManager.allocateSecurityParameterIndex(
-                    IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4, 0);
+            mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, 0);
             fail("Able to allocate invalid spi");
         } catch (IllegalArgumentException e) {
         }
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 2282c13..4fbb228 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -32,7 +32,6 @@
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
 import android.net.IpSecSpiResponse;
-import android.net.IpSecTransform;
 import android.net.IpSecTransformResponse;
 import android.net.NetworkUtils;
 import android.os.Binder;
@@ -54,14 +53,14 @@
 @RunWith(Parameterized.class)
 public class IpSecServiceParameterizedTest {
 
-    private static final int TEST_SPI_OUT = 0xD1201D;
-    private static final int TEST_SPI_IN = TEST_SPI_OUT + 1;
+    private static final int TEST_SPI = 0xD1201D;
 
-    private final String mRemoteAddr;
+    private final String mDestinationAddr;
+    private final String mSourceAddr;
 
     @Parameterized.Parameters
     public static Collection ipSecConfigs() {
-        return Arrays.asList(new Object[][] {{"8.8.4.4"}, {"2601::10"}});
+        return Arrays.asList(new Object[][] {{"1.2.3.4", "8.8.4.4"}, {"2601::2", "2601::10"}});
     }
 
     private static final byte[] AEAD_KEY = {
@@ -96,11 +95,9 @@
     private static final IpSecAlgorithm AEAD_ALGO =
             new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
 
-    private static final int[] DIRECTIONS =
-            new int[] {IpSecTransform.DIRECTION_IN, IpSecTransform.DIRECTION_OUT};
-
-    public IpSecServiceParameterizedTest(String remoteAddr) {
-        mRemoteAddr = remoteAddr;
+    public IpSecServiceParameterizedTest(String sourceAddr, String destAddr) {
+        mSourceAddr = sourceAddr;
+        mDestinationAddr = destAddr;
     }
 
     @Before
@@ -116,44 +113,30 @@
 
     @Test
     public void testIpSecServiceReserveSpi() throws Exception {
-        when(mMockNetd.ipSecAllocateSpi(
-                        anyInt(),
-                        eq(IpSecTransform.DIRECTION_OUT),
-                        anyString(),
-                        eq(mRemoteAddr),
-                        eq(TEST_SPI_OUT)))
-                .thenReturn(TEST_SPI_OUT);
+        when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
+                .thenReturn(TEST_SPI);
 
         IpSecSpiResponse spiResp =
                 mIpSecService.allocateSecurityParameterIndex(
-                        IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder());
+                        mDestinationAddr, TEST_SPI, new Binder());
         assertEquals(IpSecManager.Status.OK, spiResp.status);
-        assertEquals(TEST_SPI_OUT, spiResp.spi);
+        assertEquals(TEST_SPI, spiResp.spi);
     }
 
     @Test
     public void testReleaseSecurityParameterIndex() throws Exception {
-        when(mMockNetd.ipSecAllocateSpi(
-                        anyInt(),
-                        eq(IpSecTransform.DIRECTION_OUT),
-                        anyString(),
-                        eq(mRemoteAddr),
-                        eq(TEST_SPI_OUT)))
-                .thenReturn(TEST_SPI_OUT);
+        when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
+                .thenReturn(TEST_SPI);
 
         IpSecSpiResponse spiResp =
                 mIpSecService.allocateSecurityParameterIndex(
-                        IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder());
+                        mDestinationAddr, TEST_SPI, new Binder());
 
         mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(spiResp.resourceId),
-                        anyInt(),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_OUT));
+                        eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
 
         // Verify quota and RefcountedResource objects cleaned up
         IpSecService.UserRecord userRecord =
@@ -169,17 +152,12 @@
 
     @Test
     public void testSecurityParameterIndexBinderDeath() throws Exception {
-        when(mMockNetd.ipSecAllocateSpi(
-                        anyInt(),
-                        eq(IpSecTransform.DIRECTION_OUT),
-                        anyString(),
-                        eq(mRemoteAddr),
-                        eq(TEST_SPI_OUT)))
-                .thenReturn(TEST_SPI_OUT);
+        when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
+                .thenReturn(TEST_SPI);
 
         IpSecSpiResponse spiResp =
                 mIpSecService.allocateSecurityParameterIndex(
-                        IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT, new Binder());
+                        mDestinationAddr, TEST_SPI, new Binder());
 
         IpSecService.UserRecord userRecord =
                 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
@@ -190,11 +168,7 @@
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(spiResp.resourceId),
-                        anyInt(),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_OUT));
+                        eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
 
         // Verify quota and RefcountedResource objects cleaned up
         assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
@@ -206,14 +180,12 @@
         }
     }
 
-    private int getNewSpiResourceId(int direction, String remoteAddress, int returnSpi)
-            throws Exception {
-        when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
+    private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception {
+        when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt()))
                 .thenReturn(returnSpi);
 
         IpSecSpiResponse spi =
                 mIpSecService.allocateSecurityParameterIndex(
-                        direction,
                         NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
                         IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
                         new Binder());
@@ -221,20 +193,14 @@
     }
 
     private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception {
-        config.setSpiResourceId(
-                IpSecTransform.DIRECTION_OUT,
-                getNewSpiResourceId(IpSecTransform.DIRECTION_OUT, mRemoteAddr, TEST_SPI_OUT));
-        config.setSpiResourceId(
-                IpSecTransform.DIRECTION_IN,
-                getNewSpiResourceId(IpSecTransform.DIRECTION_IN, mRemoteAddr, TEST_SPI_IN));
-        config.setRemoteAddress(mRemoteAddr);
+        config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI));
+        config.setSourceAddress(mSourceAddr);
+        config.setDestinationAddress(mDestinationAddr);
     }
 
     private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception {
-        for (int direction : DIRECTIONS) {
-            config.setEncryption(direction, CRYPT_ALGO);
-            config.setAuthentication(direction, AUTH_ALGO);
-        }
+        config.setEncryption(CRYPT_ALGO);
+        config.setAuthentication(AUTH_ALGO);
     }
 
     @Test
@@ -251,32 +217,10 @@
                 .ipSecAddSecurityAssociation(
                         eq(createTransformResp.resourceId),
                         anyInt(),
-                        eq(IpSecTransform.DIRECTION_OUT),
                         anyString(),
                         anyString(),
                         anyLong(),
-                        eq(TEST_SPI_OUT),
-                        eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
-                        eq(AUTH_KEY),
-                        anyInt(),
-                        eq(IpSecAlgorithm.CRYPT_AES_CBC),
-                        eq(CRYPT_KEY),
-                        anyInt(),
-                        eq(""),
-                        eq(new byte[] {}),
-                        eq(0),
-                        anyInt(),
-                        anyInt(),
-                        anyInt());
-        verify(mMockNetd)
-                .ipSecAddSecurityAssociation(
-                        eq(createTransformResp.resourceId),
-                        anyInt(),
-                        eq(IpSecTransform.DIRECTION_IN),
-                        anyString(),
-                        anyString(),
-                        anyLong(),
-                        eq(TEST_SPI_IN),
+                        eq(TEST_SPI),
                         eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
                         eq(AUTH_KEY),
                         anyInt(),
@@ -296,8 +240,7 @@
         IpSecConfig ipSecConfig = new IpSecConfig();
         addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
 
-        ipSecConfig.setAuthenticatedEncryption(IpSecTransform.DIRECTION_OUT, AEAD_ALGO);
-        ipSecConfig.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
+        ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
 
         IpSecTransformResponse createTransformResp =
                 mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
@@ -307,32 +250,10 @@
                 .ipSecAddSecurityAssociation(
                         eq(createTransformResp.resourceId),
                         anyInt(),
-                        eq(IpSecTransform.DIRECTION_OUT),
                         anyString(),
                         anyString(),
                         anyLong(),
-                        eq(TEST_SPI_OUT),
-                        eq(""),
-                        eq(new byte[] {}),
-                        eq(0),
-                        eq(""),
-                        eq(new byte[] {}),
-                        eq(0),
-                        eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
-                        eq(AEAD_KEY),
-                        anyInt(),
-                        anyInt(),
-                        anyInt(),
-                        anyInt());
-        verify(mMockNetd)
-                .ipSecAddSecurityAssociation(
-                        eq(createTransformResp.resourceId),
-                        anyInt(),
-                        eq(IpSecTransform.DIRECTION_IN),
-                        anyString(),
-                        anyString(),
-                        anyLong(),
-                        eq(TEST_SPI_IN),
+                        eq(TEST_SPI),
                         eq(""),
                         eq(new byte[] {}),
                         eq(0),
@@ -359,18 +280,7 @@
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
-                        eq(IpSecTransform.DIRECTION_OUT),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_OUT));
-        verify(mMockNetd)
-                .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
-                        eq(IpSecTransform.DIRECTION_IN),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_IN));
+                        eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
 
         // Verify quota and RefcountedResource objects cleaned up
         IpSecService.UserRecord userRecord =
@@ -404,18 +314,7 @@
 
         verify(mMockNetd)
                 .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
-                        eq(IpSecTransform.DIRECTION_OUT),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_OUT));
-        verify(mMockNetd)
-                .ipSecDeleteSecurityAssociation(
-                        eq(createTransformResp.resourceId),
-                        eq(IpSecTransform.DIRECTION_IN),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_IN));
+                        eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI));
 
         // Verify quota and RefcountedResource objects cleaned up
         assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
@@ -439,30 +338,22 @@
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
 
         int resourceId = createTransformResp.resourceId;
-        mIpSecService.applyTransportModeTransform(pfd, resourceId);
+        mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
 
         verify(mMockNetd)
                 .ipSecApplyTransportModeTransform(
                         eq(pfd.getFileDescriptor()),
                         eq(resourceId),
-                        eq(IpSecTransform.DIRECTION_OUT),
+                        eq(IpSecManager.DIRECTION_OUT),
                         anyString(),
                         anyString(),
-                        eq(TEST_SPI_OUT));
-        verify(mMockNetd)
-                .ipSecApplyTransportModeTransform(
-                        eq(pfd.getFileDescriptor()),
-                        eq(resourceId),
-                        eq(IpSecTransform.DIRECTION_IN),
-                        anyString(),
-                        anyString(),
-                        eq(TEST_SPI_IN));
+                        eq(TEST_SPI));
     }
 
     @Test
     public void testRemoveTransportModeTransform() throws Exception {
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-        mIpSecService.removeTransportModeTransform(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 0467989..3eba881 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -105,9 +105,6 @@
     private static final IpSecAlgorithm AEAD_ALGO =
             new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
 
-    private static final int[] DIRECTIONS =
-            new int[] {IpSecTransform.DIRECTION_IN, IpSecTransform.DIRECTION_OUT};
-
     static {
         try {
             INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
@@ -303,83 +300,75 @@
 
     @Test
     public void testValidateAlgorithmsAuth() {
-        for (int direction : DIRECTIONS) {
-            // Validate that correct algorithm type succeeds
-            IpSecConfig config = new IpSecConfig();
-            config.setAuthentication(direction, AUTH_ALGO);
-            mIpSecService.validateAlgorithms(config, direction);
+        // Validate that correct algorithm type succeeds
+        IpSecConfig config = new IpSecConfig();
+        config.setAuthentication(AUTH_ALGO);
+        mIpSecService.validateAlgorithms(config);
 
-            // Validate that incorrect algorithm types fails
-            for (IpSecAlgorithm algo : new IpSecAlgorithm[] {CRYPT_ALGO, AEAD_ALGO}) {
-                try {
-                    config = new IpSecConfig();
-                    config.setAuthentication(direction, algo);
-                    mIpSecService.validateAlgorithms(config, direction);
-                    fail("Did not throw exception on invalid algorithm type");
-                } catch (IllegalArgumentException expected) {
-                }
+        // Validate that incorrect algorithm types fails
+        for (IpSecAlgorithm algo : new IpSecAlgorithm[] {CRYPT_ALGO, AEAD_ALGO}) {
+            try {
+                config = new IpSecConfig();
+                config.setAuthentication(algo);
+                mIpSecService.validateAlgorithms(config);
+                fail("Did not throw exception on invalid algorithm type");
+            } catch (IllegalArgumentException expected) {
             }
         }
     }
 
     @Test
     public void testValidateAlgorithmsCrypt() {
-        for (int direction : DIRECTIONS) {
-            // Validate that correct algorithm type succeeds
-            IpSecConfig config = new IpSecConfig();
-            config.setEncryption(direction, CRYPT_ALGO);
-            mIpSecService.validateAlgorithms(config, direction);
+        // Validate that correct algorithm type succeeds
+        IpSecConfig config = new IpSecConfig();
+        config.setEncryption(CRYPT_ALGO);
+        mIpSecService.validateAlgorithms(config);
 
-            // Validate that incorrect algorithm types fails
-            for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, AEAD_ALGO}) {
-                try {
-                    config = new IpSecConfig();
-                    config.setEncryption(direction, algo);
-                    mIpSecService.validateAlgorithms(config, direction);
-                    fail("Did not throw exception on invalid algorithm type");
-                } catch (IllegalArgumentException expected) {
-                }
+        // Validate that incorrect algorithm types fails
+        for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, AEAD_ALGO}) {
+            try {
+                config = new IpSecConfig();
+                config.setEncryption(algo);
+                mIpSecService.validateAlgorithms(config);
+                fail("Did not throw exception on invalid algorithm type");
+            } catch (IllegalArgumentException expected) {
             }
         }
     }
 
     @Test
     public void testValidateAlgorithmsAead() {
-        for (int direction : DIRECTIONS) {
-            // Validate that correct algorithm type succeeds
-            IpSecConfig config = new IpSecConfig();
-            config.setAuthenticatedEncryption(direction, AEAD_ALGO);
-            mIpSecService.validateAlgorithms(config, direction);
+        // Validate that correct algorithm type succeeds
+        IpSecConfig config = new IpSecConfig();
+        config.setAuthenticatedEncryption(AEAD_ALGO);
+        mIpSecService.validateAlgorithms(config);
 
-            // Validate that incorrect algorithm types fails
-            for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, CRYPT_ALGO}) {
-                try {
-                    config = new IpSecConfig();
-                    config.setAuthenticatedEncryption(direction, algo);
-                    mIpSecService.validateAlgorithms(config, direction);
-                    fail("Did not throw exception on invalid algorithm type");
-                } catch (IllegalArgumentException expected) {
-                }
+        // Validate that incorrect algorithm types fails
+        for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, CRYPT_ALGO}) {
+            try {
+                config = new IpSecConfig();
+                config.setAuthenticatedEncryption(algo);
+                mIpSecService.validateAlgorithms(config);
+                fail("Did not throw exception on invalid algorithm type");
+            } catch (IllegalArgumentException expected) {
             }
         }
     }
 
     @Test
     public void testValidateAlgorithmsAuthCrypt() {
-        for (int direction : DIRECTIONS) {
-            // Validate that correct algorithm type succeeds
-            IpSecConfig config = new IpSecConfig();
-            config.setAuthentication(direction, AUTH_ALGO);
-            config.setEncryption(direction, CRYPT_ALGO);
-            mIpSecService.validateAlgorithms(config, direction);
-        }
+        // Validate that correct algorithm type succeeds
+        IpSecConfig config = new IpSecConfig();
+        config.setAuthentication(AUTH_ALGO);
+        config.setEncryption(CRYPT_ALGO);
+        mIpSecService.validateAlgorithms(config);
     }
 
     @Test
     public void testValidateAlgorithmsNoAlgorithms() {
         IpSecConfig config = new IpSecConfig();
         try {
-            mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+            mIpSecService.validateAlgorithms(config);
             fail("Expected exception; no algorithms specified");
         } catch (IllegalArgumentException expected) {
         }
@@ -388,10 +377,10 @@
     @Test
     public void testValidateAlgorithmsAeadWithAuth() {
         IpSecConfig config = new IpSecConfig();
-        config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
-        config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO);
+        config.setAuthenticatedEncryption(AEAD_ALGO);
+        config.setAuthentication(AUTH_ALGO);
         try {
-            mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+            mIpSecService.validateAlgorithms(config);
             fail("Expected exception; both AEAD and auth algorithm specified");
         } catch (IllegalArgumentException expected) {
         }
@@ -400,10 +389,10 @@
     @Test
     public void testValidateAlgorithmsAeadWithCrypt() {
         IpSecConfig config = new IpSecConfig();
-        config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
-        config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO);
+        config.setAuthenticatedEncryption(AEAD_ALGO);
+        config.setEncryption(CRYPT_ALGO);
         try {
-            mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+            mIpSecService.validateAlgorithms(config);
             fail("Expected exception; both AEAD and crypt algorithm specified");
         } catch (IllegalArgumentException expected) {
         }
@@ -412,11 +401,11 @@
     @Test
     public void testValidateAlgorithmsAeadWithAuthAndCrypt() {
         IpSecConfig config = new IpSecConfig();
-        config.setAuthenticatedEncryption(IpSecTransform.DIRECTION_IN, AEAD_ALGO);
-        config.setAuthentication(IpSecTransform.DIRECTION_IN, AUTH_ALGO);
-        config.setEncryption(IpSecTransform.DIRECTION_IN, CRYPT_ALGO);
+        config.setAuthenticatedEncryption(AEAD_ALGO);
+        config.setAuthentication(AUTH_ALGO);
+        config.setEncryption(CRYPT_ALGO);
         try {
-            mIpSecService.validateAlgorithms(config, IpSecTransform.DIRECTION_IN);
+            mIpSecService.validateAlgorithms(config);
             fail("Expected exception; AEAD, auth and crypt algorithm specified");
         } catch (IllegalArgumentException expected) {
         }
@@ -434,7 +423,7 @@
     @Test
     public void testRemoveTransportModeTransform() throws Exception {
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-        mIpSecService.removeTransportModeTransform(pfd, 1);
+        mIpSecService.removeTransportModeTransforms(pfd);
 
         verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
     }
@@ -447,7 +436,7 @@
             try {
                 IpSecSpiResponse spiResp =
                         mIpSecService.allocateSecurityParameterIndex(
-                                IpSecTransform.DIRECTION_OUT, address, DROID_SPI, new Binder());
+                                address, DROID_SPI, new Binder());
                 fail("Invalid address was passed through IpSecService validation: " + address);
             } catch (IllegalArgumentException e) {
             } catch (Exception e) {
@@ -519,7 +508,6 @@
         // tracks the resource ID.
         when(mMockNetd.ipSecAllocateSpi(
                         anyInt(),
-                        eq(IpSecTransform.DIRECTION_OUT),
                         anyString(),
                         eq(InetAddress.getLoopbackAddress().getHostAddress()),
                         anyInt()))
@@ -528,7 +516,6 @@
         for (int i = 0; i < MAX_NUM_SPIS; i++) {
             IpSecSpiResponse newSpi =
                     mIpSecService.allocateSecurityParameterIndex(
-                            0x1,
                             InetAddress.getLoopbackAddress().getHostAddress(),
                             DROID_SPI + i,
                             new Binder());
@@ -544,7 +531,6 @@
         // Try to reserve one more SPI, and should fail.
         IpSecSpiResponse extraSpi =
                 mIpSecService.allocateSecurityParameterIndex(
-                        0x1,
                         InetAddress.getLoopbackAddress().getHostAddress(),
                         DROID_SPI + MAX_NUM_SPIS,
                         new Binder());
@@ -558,7 +544,6 @@
         // Should successfully reserve one more spi.
         extraSpi =
                 mIpSecService.allocateSecurityParameterIndex(
-                        0x1,
                         InetAddress.getLoopbackAddress().getHostAddress(),
                         DROID_SPI + MAX_NUM_SPIS,
                         new Binder());
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/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/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,