Merge "Add carrier config to indicate if cep is supported on peer." into rvc-dev
diff --git a/Android.bp b/Android.bp
index 874d76f..d4ca706 100644
--- a/Android.bp
+++ b/Android.bp
@@ -911,6 +911,7 @@
 filegroup {
     name: "incremental_aidl",
     srcs: [
+        "core/java/android/os/incremental/IIncrementalServiceConnector.aidl",
         "core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl",
     ],
     path: "core/java",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 9abb308..2fd2e33 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -9,6 +9,7 @@
                core/jni/
                libs/input/
                services/core/jni/
+               services/incremental/
 
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
diff --git a/aidl_api/libincremental_aidl/current/android/os/incremental/IncrementalFileSystemControlParcel.aidl b/aidl_api/libincremental_aidl/current/android/os/incremental/IncrementalFileSystemControlParcel.aidl
deleted file mode 100644
index d777e34..0000000
--- a/aidl_api/libincremental_aidl/current/android/os/incremental/IncrementalFileSystemControlParcel.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.os.incremental;
-/* @hide */
-parcelable IncrementalFileSystemControlParcel {
-  ParcelFileDescriptor cmd;
-  ParcelFileDescriptor pendingReads;
-  ParcelFileDescriptor log;
-}
diff --git a/aidl_api/libincremental_manager_aidl/current/android/os/incremental/IIncrementalService.aidl b/aidl_api/libincremental_manager_aidl/current/android/os/incremental/IIncrementalService.aidl
deleted file mode 100644
index 5e1f013..0000000
--- a/aidl_api/libincremental_manager_aidl/current/android/os/incremental/IIncrementalService.aidl
+++ /dev/null
@@ -1,44 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.os.incremental;
-/* @hide */
-interface IIncrementalService {
-  int openStorage(in @utf8InCpp String path);
-  int createStorage(in @utf8InCpp String path, in android.content.pm.DataLoaderParamsParcel params, in android.content.pm.IDataLoaderStatusListener listener, int createMode);
-  int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
-  int makeBindMount(int storageId, in @utf8InCpp String sourcePath, in @utf8InCpp String targetFullPath, int bindType);
-  int deleteBindMount(int storageId, in @utf8InCpp String targetFullPath);
-  int makeDirectory(int storageId, in @utf8InCpp String path);
-  int makeDirectories(int storageId, in @utf8InCpp String path);
-  int makeFile(int storageId, in @utf8InCpp String path, in android.os.incremental.IncrementalNewFileParams params);
-  int makeFileFromRange(int storageId, in @utf8InCpp String targetPath, in @utf8InCpp String sourcePath, long start, long end);
-  int makeLink(int sourceStorageId, in @utf8InCpp String sourcePath, int destStorageId, in @utf8InCpp String destPath);
-  int unlink(int storageId, in @utf8InCpp String path);
-  boolean isFileRangeLoaded(int storageId, in @utf8InCpp String path, long start, long end);
-  byte[] getMetadataByPath(int storageId, in @utf8InCpp String path);
-  byte[] getMetadataById(int storageId, in byte[] fileId);
-  boolean startLoading(int storageId);
-  void deleteStorage(int storageId);
-  boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi);
-  const int CREATE_MODE_TEMPORARY_BIND = 1;
-  const int CREATE_MODE_PERMANENT_BIND = 2;
-  const int CREATE_MODE_CREATE = 4;
-  const int CREATE_MODE_OPEN_EXISTING = 8;
-  const int BIND_TEMPORARY = 0;
-  const int BIND_PERMANENT = 1;
-}
diff --git a/aidl_api/libincremental_manager_aidl/current/android/os/incremental/IncrementalNewFileParams.aidl b/aidl_api/libincremental_manager_aidl/current/android/os/incremental/IncrementalNewFileParams.aidl
deleted file mode 100644
index c737877..0000000
--- a/aidl_api/libincremental_manager_aidl/current/android/os/incremental/IncrementalNewFileParams.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
-//
-// You must not make a backward incompatible changes to the AIDL files built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.os.incremental;
-/* @hide */
-parcelable IncrementalNewFileParams {
-  long size;
-  byte[] fileId;
-  byte[] metadata;
-  @nullable byte[] signature;
-}
diff --git a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
index 8633c96..8139a2e 100644
--- a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
@@ -30,6 +30,7 @@
 import android.view.DisplayCutout;
 import android.view.IWindow;
 import android.view.IWindowSession;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.View;
@@ -120,6 +121,7 @@
                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
         final MergedConfiguration mOutMergedConfiguration = new MergedConfiguration();
         final InsetsState mOutInsetsState = new InsetsState();
+        final InsetsSourceControl[] mOutControls = new InsetsSourceControl[0];
         final IWindow mWindow;
         final View mView;
         final WindowManager.LayoutParams mParams;
@@ -152,7 +154,7 @@
                         mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame,
                         mOutContentInsets, mOutVisibleInsets, mOutStableInsets,
                         mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration,
-                        mOutSurfaceControl, mOutInsetsState, mOutSurfaceSize,
+                        mOutSurfaceControl, mOutInsetsState, mOutControls, mOutSurfaceSize,
                         mOutBlastSurfaceControl);
             }
         }
diff --git a/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java
index 4ac3adf..c72cc9d 100644
--- a/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java
@@ -29,6 +29,7 @@
 import android.view.DisplayCutout;
 import android.view.IWindowSession;
 import android.view.InputChannel;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.View;
 import android.view.WindowManager;
@@ -91,6 +92,7 @@
         final DisplayCutout.ParcelableWrapper mOutDisplayCutout =
                 new DisplayCutout.ParcelableWrapper();
         final InsetsState mOutInsetsState = new InsetsState();
+        final InsetsSourceControl[] mOutControls = new InsetsSourceControl[0];
 
         TestWindow() {
             mLayoutParams.setTitle(TestWindow.class.getName());
@@ -109,7 +111,7 @@
                 long startTime = SystemClock.elapsedRealtimeNanos();
                 session.addToDisplay(this, mSeq, mLayoutParams, View.VISIBLE,
                         Display.DEFAULT_DISPLAY, mOutFrame, mOutContentInsets, mOutStableInsets,
-                        mOutDisplayCutout, inputChannel, mOutInsetsState);
+                        mOutDisplayCutout, inputChannel, mOutInsetsState, mOutControls);
                 final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime;
                 state.addExtraResult("add", elapsedTimeNsOfAdd);
 
diff --git a/apex/extservices/Android.bp b/apex/extservices/Android.bp
index 021246c..68350af 100644
--- a/apex/extservices/Android.bp
+++ b/apex/extservices/Android.bp
@@ -21,6 +21,7 @@
 apex_defaults {
     name: "com.android.extservices-defaults",
     updatable: true,
+    min_sdk_version: "R",
     key: "com.android.extservices.key",
     certificate: ":com.android.extservices.certificate",
     apps: ["ExtServices"],
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index edf25ae..e533b7a 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -499,20 +499,58 @@
             })
     public @interface ParserName {}
 
+    /** Parser name returned by {@link #getParserName()} when no parser has been selected yet. */
     public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
+    /**
+     * Parser for the Matroska container format, as defined in the <a
+     * href="https://matroska.org/technical/specs/">spec</a>.
+     */
     public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser";
+    /**
+     * Parser for fragmented files using the MP4 container format, as defined in ISO/IEC 14496-12.
+     */
     public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser";
+    /**
+     * Parser for non-fragmented files using the MP4 container format, as defined in ISO/IEC
+     * 14496-12.
+     */
     public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser";
+    /** Parser for the MP3 container format, as defined in ISO/IEC 11172-3. */
     public static final String PARSER_NAME_MP3 = "android.media.mediaparser.Mp3Parser";
+    /** Parser for the ADTS container format, as defined in ISO/IEC 13818-7. */
     public static final String PARSER_NAME_ADTS = "android.media.mediaparser.AdtsParser";
+    /**
+     * Parser for the AC-3 container format, as defined in Digital Audio Compression Standard
+     * (AC-3).
+     */
     public static final String PARSER_NAME_AC3 = "android.media.mediaparser.Ac3Parser";
+    /** Parser for the TS container format, as defined in ISO/IEC 13818-1. */
     public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
+    /**
+     * Parser for the FLV container format, as defined in Adobe Flash Video File Format
+     * Specification.
+     */
     public static final String PARSER_NAME_FLV = "android.media.mediaparser.FlvParser";
+    /** Parser for the OGG container format, as defined in RFC 3533. */
     public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
+    /** Parser for the PS container format, as defined in ISO/IEC 11172-1. */
     public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
+    /**
+     * Parser for the WAV container format, as defined in Multimedia Programming Interface and Data
+     * Specifications.
+     */
     public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
+    /** Parser for the AMR container format, as defined in RFC 4867. */
     public static final String PARSER_NAME_AMR = "android.media.mediaparser.AmrParser";
+    /**
+     * Parser for the AC-4 container format, as defined by Dolby AC-4: Audio delivery for
+     * Next-Generation Entertainment Services.
+     */
     public static final String PARSER_NAME_AC4 = "android.media.mediaparser.Ac4Parser";
+    /**
+     * Parser for the FLAC container format, as defined in the <a
+     * href="https://xiph.org/flac/">spec</a>.
+     */
     public static final String PARSER_NAME_FLAC = "android.media.mediaparser.FlacParser";
 
     // MediaParser parameters.
diff --git a/apex/permission/Android.bp b/apex/permission/Android.bp
index 0171b0d..71a52bb 100644
--- a/apex/permission/Android.bp
+++ b/apex/permission/Android.bp
@@ -21,6 +21,7 @@
 apex_defaults {
     name: "com.android.permission-defaults",
     updatable: true,
+    min_sdk_version: "R",
     key: "com.android.permission.key",
     certificate: ":com.android.permission.certificate",
     java_libs: [
diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp
index 5cdcdd3..2eb7e99 100644
--- a/apex/permission/service/Android.bp
+++ b/apex/permission/service/Android.bp
@@ -48,5 +48,5 @@
     name: "service-permission-stubs",
     srcs: [":service-permission-stubs-srcs"],
     defaults: ["service-module-stubs-defaults"],
-    visibility: ["//visibility:private"]
+    visibility: ["//frameworks/base/services/core"]
 }
diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp
index 322d5e1..fc26e08 100644
--- a/apex/sdkextensions/Android.bp
+++ b/apex/sdkextensions/Android.bp
@@ -27,6 +27,7 @@
 apex_defaults {
     name: "com.android.sdkext-defaults",
     updatable: true,
+    min_sdk_version: "R",
     java_libs: [ "framework-sdkextensions" ],
     prebuilts: [
         "derive_sdk.rc",
diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp
index 2df3eea..15d7495 100644
--- a/apex/statsd/Android.bp
+++ b/apex/statsd/Android.bp
@@ -33,6 +33,7 @@
     prebuilts: ["com.android.os.statsd.init.rc"],
     name: "com.android.os.statsd-defaults",
     updatable: true,
+    min_sdk_version: "R",
     key: "com.android.os.statsd.key",
     certificate: ":com.android.os.statsd.certificate",
 }
@@ -66,7 +67,6 @@
         "liblog",  // Has a stable abi - should not be copied into apex.
         "libstatssocket",
     ],
-    //TODO: is libc++_static correct?
     stl: "libc++_static",
     cflags: [
         "-Wall",
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 7480ec8..6f29141 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -146,7 +146,8 @@
     visibility: [
         "//frameworks/base", // Framework
         "//frameworks/base/apex/statsd", // statsd apex
-        "//frameworks/opt/net/wifi/service" // wifi service
+        "//frameworks/opt/net/wifi/service", // wifi service
+        "//packages/providers/MediaProvider", // MediaProvider apk
     ],
 }
 
diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp
index 2d64f19..0df96e1 100644
--- a/apex/statsd/tests/libstatspull/Android.bp
+++ b/apex/statsd/tests/libstatspull/Android.bp
@@ -32,7 +32,7 @@
         "protos/**/*.proto",
         ],
     test_suites: [
-        "general-tests",
+        "device-tests",
     ],
     platform_apis: true,
     privileged: true,
diff --git a/api/current.txt b/api/current.txt
index 1c1d142..b4db1f7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6833,13 +6833,6 @@
     method public final android.os.IBinder onBind(android.content.Intent);
   }
 
-  public class DevicePolicyKeyguardService extends android.app.Service {
-    ctor public DevicePolicyKeyguardService();
-    method @Nullable public void dismiss();
-    method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
-    method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage onCreateKeyguardSurface(@NonNull android.os.IBinder);
-  }
-
   public class DevicePolicyManager {
     method public void addCrossProfileIntentFilter(@NonNull android.content.ComponentName, android.content.IntentFilter, int);
     method public boolean addCrossProfileWidgetProvider(@NonNull android.content.ComponentName, String);
@@ -7055,7 +7048,6 @@
     method public boolean setResetPasswordToken(android.content.ComponentName, byte[]);
     method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName);
     method public void setScreenCaptureDisabled(@NonNull android.content.ComponentName, boolean);
-    method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setSecureSetting(@NonNull android.content.ComponentName, String, String);
     method public void setSecurityLoggingEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setShortSupportMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
@@ -7082,7 +7074,6 @@
     field public static final String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
     field public static final String ACTION_ADMIN_POLICY_COMPLIANCE = "android.app.action.ADMIN_POLICY_COMPLIANCE";
     field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
-    field public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE = "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
     field public static final String ACTION_CHECK_POLICY_COMPLIANCE = "android.app.action.CHECK_POLICY_COMPLIANCE";
     field public static final String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
     field public static final String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
@@ -30284,6 +30275,7 @@
     field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
     field public static final int NET_CAPABILITY_RCS = 8; // 0x8
     field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
+    field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19
     field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe
     field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10
     field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
diff --git a/api/system-current.txt b/api/system-current.txt
index c664bed..c5d319c 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -848,6 +848,13 @@
 
 package android.app.admin {
 
+  public class DevicePolicyKeyguardService extends android.app.Service {
+    ctor public DevicePolicyKeyguardService();
+    method @Nullable public void dismiss();
+    method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
+    method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage onCreateKeyguardSurface(@NonNull android.os.IBinder);
+  }
+
   public class DevicePolicyManager {
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
@@ -872,8 +879,10 @@
     method @Deprecated @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException;
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
     method @Deprecated @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName);
+    method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean);
     field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
     field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
+    field public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE = "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
     field public static final String ACTION_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION";
     field public static final String ACTION_PROVISION_FINANCED_DEVICE = "android.app.action.PROVISION_FINANCED_DEVICE";
     field public static final String ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE = "android.app.action.PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE";
diff --git a/api/test-current.txt b/api/test-current.txt
index 0ca8b2d..c29f1c4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1504,6 +1504,13 @@
     ctor public AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String);
   }
 
+  public class AudioSystem {
+    method public static float getMasterBalance();
+    method public static final int getNumStreamTypes();
+    method public static int setMasterBalance(float);
+    field public static final int STREAM_DEFAULT = -1; // 0xffffffff
+  }
+
   public static final class AudioTrack.MetricsConstants {
     field public static final String ATTRIBUTES = "android.media.audiotrack.attributes";
     field public static final String CHANNEL_MASK = "android.media.audiotrack.channelMask";
@@ -1513,6 +1520,10 @@
     field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
   }
 
+  public final class MediaCas implements java.lang.AutoCloseable {
+    method public void forceResourceLost();
+  }
+
   public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
@@ -3518,6 +3529,32 @@
 
 }
 
+package android.service.watchdog {
+
+  public abstract class ExplicitHealthCheckService extends android.app.Service {
+    ctor public ExplicitHealthCheckService();
+    method public final void notifyHealthCheckPassed(@NonNull String);
+    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void onCancelHealthCheck(@NonNull String);
+    method @NonNull public abstract java.util.List<java.lang.String> onGetRequestedPackages();
+    method @NonNull public abstract java.util.List<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> onGetSupportedPackages();
+    method public abstract void onRequestHealthCheck(@NonNull String);
+    method public void setCallback(@Nullable android.os.RemoteCallback);
+    field public static final String BIND_PERMISSION = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
+    field public static final String SERVICE_INTERFACE = "android.service.watchdog.ExplicitHealthCheckService";
+  }
+
+  public static final class ExplicitHealthCheckService.PackageConfig implements android.os.Parcelable {
+    ctor public ExplicitHealthCheckService.PackageConfig(@NonNull String, long);
+    method public int describeContents();
+    method public long getHealthCheckTimeoutMillis();
+    method @NonNull public String getPackageName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> CREATOR;
+  }
+
+}
+
 package android.telecom {
 
   public final class Call {
@@ -4677,7 +4714,6 @@
     field public static final String FFLAG_OVERRIDE_PREFIX = "sys.fflag.override.";
     field public static final String FFLAG_PREFIX = "sys.fflag.";
     field public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
-    field public static final String NOTIF_CONVO_BYPASS_SHORTCUT_REQ = "settings_notif_convo_bypass_shortcut_req";
     field public static final String PERSIST_PREFIX = "persist.sys.fflag.override.";
     field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
     field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
@@ -4778,7 +4814,14 @@
 
   public final class Display {
     method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
+    method public int getType();
     method public boolean hasAccess(int);
+    field public static final int TYPE_EXTERNAL = 2; // 0x2
+    field public static final int TYPE_INTERNAL = 1; // 0x1
+    field public static final int TYPE_OVERLAY = 4; // 0x4
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_VIRTUAL = 5; // 0x5
+    field public static final int TYPE_WIFI = 3; // 0x3
   }
 
   public class FocusFinder {
@@ -4816,6 +4859,13 @@
     method public abstract String asyncImpl() default "";
   }
 
+  public final class SurfaceControl implements android.os.Parcelable {
+    ctor public SurfaceControl(@NonNull android.view.SurfaceControl);
+    method public static long acquireFrameRateFlexibilityToken();
+    method public boolean isSameSurface(@NonNull android.view.SurfaceControl);
+    method public static void releaseFrameRateFlexibilityToken(long);
+  }
+
   public class SurfaceControlViewHost {
     method public void relayout(android.view.WindowManager.LayoutParams);
     method public void setView(@NonNull android.view.View, @NonNull android.view.WindowManager.LayoutParams);
diff --git a/cmds/hid/README.md b/cmds/hid/README.md
index 7e22d08..620336f 100644
--- a/cmds/hid/README.md
+++ b/cmds/hid/README.md
@@ -38,17 +38,21 @@
 Register a new uhid device
 
 | Field         | Type          | Description                |
-|:-------------:|:-------------:|:--------------------------|
+|:-------------:|:-------------:|:-------------------------- |
 | id            | integer       | Device id                  |
 | command       | string        | Must be set to "register"  |
 | name          | string        | Device name                |
 | vid           | 16-bit integer| Vendor id                  |
 | pid           | 16-bit integer| Product id                 |
+| bus           | string        | Bus that device should use |
 | descriptor    | byte array    | USB HID report descriptor  |
 
 Device ID is used for matching the subsequent commands to a specific device
 to avoid ambiguity when multiple devices are registered.
 
+Device bus is used to determine how the uhid device is connected to the host.
+The options are "usb" and "bluetooth".
+
 USB HID report descriptor should be generated according the the USB HID spec
 and can be checked by reverse parsing using a variety of tools, for example
 [usbdescreqparser][5].
@@ -61,6 +65,7 @@
   "name": "Odie (Test)",
   "vid": 0x18d1,
   "pid": 0x2c40,
+  "bus": "usb",
   "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x05, 0x09, 0x0a, 0x01, 0x00,
     0x0a, 0x02, 0x00, 0x0a, 0x04, 0x00, 0x0a, 0x05, 0x00, 0x0a, 0x07, 0x00, 0x0a, 0x08, 0x00,
     0x0a, 0x0e, 0x00, 0x0a, 0x0f, 0x00, 0x0a, 0x0d, 0x00, 0x05, 0x0c, 0x0a, 0x24, 0x02, 0x0a,
@@ -142,4 +147,4 @@
 [3]: ../../../../cts/tests/tests/hardware/res/raw/
 [4]: https://developer.android.com/training/game-controllers/controller-input.html#button
 [5]: http://eleccelerator.com/usbdescreqparser/
-[6]: https://developer.android.com/training/game-controllers/controller-input.html
\ No newline at end of file
+[6]: https://developer.android.com/training/game-controllers/controller-input.html
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index a321460..65061d0 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -56,7 +56,6 @@
         "src/condition/condition_util.cpp",
         "src/condition/ConditionWizard.cpp",
         "src/condition/SimpleConditionTracker.cpp",
-        "src/condition/StateConditionTracker.cpp",
         "src/config/ConfigKey.cpp",
         "src/config/ConfigListener.cpp",
         "src/config/ConfigManager.cpp",
@@ -114,17 +113,18 @@
     static_libs: [
         "libbase",
         "libcutils",
+        "libgtest_prod",
         "libprotoutil",
         "libstatsmetadata",
         "libstatslog_statsd",
         "libsysutils",
         "libutils",
+        "statsd-aidl-ndk_platform",
     ],
     shared_libs: [
         "libbinder_ndk",
         "libincident",
         "liblog",
-        "statsd-aidl-ndk_platform",
     ],
 }
 
@@ -269,10 +269,11 @@
 
     proto: {
         type: "lite",
+        static: true,
     },
+    stl: "libc++_static",
 
     shared_libs: [
-        "libgtest_prod",
         "libstatssocket",
     ],
 
@@ -315,7 +316,6 @@
         "tests/condition/CombinationConditionTracker_test.cpp",
         "tests/condition/ConditionTimer_test.cpp",
         "tests/condition/SimpleConditionTracker_test.cpp",
-        "tests/condition/StateConditionTracker_test.cpp",
         "tests/ConfigManager_test.cpp",
         "tests/e2e/Alarm_e2e_test.cpp",
         "tests/e2e/Anomaly_count_e2e_test.cpp",
@@ -337,6 +337,7 @@
         "tests/external/StatsPullerManager_test.cpp",
         "tests/FieldValue_test.cpp",
         "tests/guardrail/StatsdStats_test.cpp",
+        "tests/HashableDimensionKey_test.cpp",
         "tests/indexed_priority_queue_test.cpp",
         "tests/log_event/LogEventQueue_test.cpp",
         "tests/LogEntryMatcher_test.cpp",
diff --git a/cmds/statsd/benchmark/metric_util.cpp b/cmds/statsd/benchmark/metric_util.cpp
index 4bce89f..482d66f 100644
--- a/cmds/statsd/benchmark/metric_util.cpp
+++ b/cmds/statsd/benchmark/metric_util.cpp
@@ -370,13 +370,6 @@
     return processor;
 }
 
-AttributionNodeInternal CreateAttribution(const int& uid, const string& tag) {
-    AttributionNodeInternal attribution;
-    attribution.set_uid(uid);
-    attribution.set_tag(tag);
-    return attribution;
-}
-
 void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events) {
   std::sort(events->begin(), events->end(),
             [](const std::unique_ptr<LogEvent>& a, const std::unique_ptr<LogEvent>& b) {
diff --git a/cmds/statsd/benchmark/metric_util.h b/cmds/statsd/benchmark/metric_util.h
index 6199fa9..c5fcf7c 100644
--- a/cmds/statsd/benchmark/metric_util.h
+++ b/cmds/statsd/benchmark/metric_util.h
@@ -120,9 +120,6 @@
                                              const vector<string>& attributionTags,
                                              const string& name);
 
-// Helper function to create an AttributionNodeInternal proto.
-AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
-
 // Create a statsd log event processor upon the start time in seconds, config and key.
 sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,
                                               const ConfigKey& key);
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 967fd32..3536e5a 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "annotations.h"
 
 namespace android {
 namespace os {
@@ -357,6 +358,56 @@
     Value& operator=(const Value& that);
 };
 
+class Annotations {
+public:
+    Annotations() {}
+
+    // This enum stores where particular annotations can be found in the
+    // bitmask. Note that these pos do not correspond to annotation ids.
+    enum {
+        NESTED_POS = 0x0,
+        PRIMARY_POS = 0x1,
+        EXCLUSIVE_POS = 0x2
+    };
+
+    inline void setNested(bool nested) { setBitmaskAtPos(NESTED_POS, nested); }
+
+    inline void setPrimaryField(bool primary) { setBitmaskAtPos(PRIMARY_POS, primary); }
+
+    inline void setExclusiveState(bool exclusive) { setBitmaskAtPos(EXCLUSIVE_POS, exclusive); }
+
+    inline void setResetState(int resetState) { mResetState = resetState; }
+
+    // Default value = false
+    inline bool isNested() const { return getValueFromBitmask(NESTED_POS); }
+
+    // Default value = false
+    inline bool isPrimaryField() const { return getValueFromBitmask(PRIMARY_POS); }
+
+    // Default value = false
+    inline bool isExclusiveState() const { return getValueFromBitmask(EXCLUSIVE_POS); }
+
+    // If a reset state is not sent in the StatsEvent, returns -1. Note that a
+    // reset satate is only sent if and only if a reset should be triggered.
+    inline int getResetState() const { return mResetState; }
+
+private:
+    inline void setBitmaskAtPos(int pos, bool value) {
+        mBooleanBitmask &= ~(1 << pos); // clear
+        mBooleanBitmask |= (value << pos); // set
+    }
+
+    inline bool getValueFromBitmask(int pos) const {
+        return (mBooleanBitmask >> pos) & 0x1;
+    }
+
+    // This is a bitmask over all annotations stored in boolean form. Because
+    // there are only 3 booleans, just one byte is required.
+    uint8_t mBooleanBitmask = 0;
+
+    int mResetState = -1;
+};
+
 /**
  * Represents a log item, or a dimension item (They are essentially the same).
  */
@@ -384,6 +435,7 @@
 
     Field mField;
     Value mValue;
+    Annotations mAnnotations;
 };
 
 bool HasPositionANY(const FieldMatcher& matcher);
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index 23d8f59..29249f4 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -230,6 +230,47 @@
     }
 }
 
+bool containsLinkedStateValues(const HashableDimensionKey& whatKey,
+                               const HashableDimensionKey& primaryKey,
+                               const vector<Metric2State>& stateLinks, const int32_t stateAtomId) {
+    if (whatKey.getValues().size() < primaryKey.getValues().size()) {
+        ALOGE("Contains linked values false: whatKey is too small");
+        return false;
+    }
+
+    for (const auto& primaryValue : primaryKey.getValues()) {
+        bool found = false;
+        for (const auto& whatValue : whatKey.getValues()) {
+            if (linked(stateLinks, stateAtomId, primaryValue.mField, whatValue.mField) &&
+                primaryValue.mValue == whatValue.mValue) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool linked(const vector<Metric2State>& stateLinks, const int32_t stateAtomId,
+            const Field& stateField, const Field& metricField) {
+    for (auto stateLink : stateLinks) {
+        if (stateLink.stateAtomId != stateAtomId) {
+            continue;
+        }
+
+        for (size_t i = 0; i < stateLink.stateFields.size(); i++) {
+            if (stateLink.stateFields[i].mMatcher == stateField &&
+                stateLink.metricFields[i].mMatcher == metricField) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 bool LessThan(const vector<FieldValue>& s1, const vector<FieldValue>& s2) {
     if (s1.size() != s2.size()) {
         return s1.size() < s2.size();
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index a766bba..33a5024 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -110,6 +110,10 @@
         return mStateValuesKey;
     }
 
+    inline HashableDimensionKey* getMutableStateValuesKey() {
+        return &mStateValuesKey;
+    }
+
     inline void setStateValuesKey(const HashableDimensionKey& key) {
         mStateValuesKey = key;
     }
@@ -169,6 +173,32 @@
 void getDimensionForState(const std::vector<FieldValue>& eventValues, const Metric2State& link,
                           HashableDimensionKey* statePrimaryKey);
 
+/**
+ * Returns true if the primaryKey values are a subset of the whatKey values.
+ * The values from the primaryKey come from the state atom, so we need to
+ * check that a link exists between the state atom field and what atom field.
+ *
+ * Example:
+ * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}]
+ * statePrimaryKey = [Atom: 27, {uid: 1005}]
+ * Returns true IF one of the Metric2State links Atom 10's uid to Atom 27's uid
+ *
+ * Example:
+ * whatKey = [Atom: 10, {uid: 1005, wakelock_name: "compose"}]
+ * statePrimaryKey = [Atom: 59, {uid: 1005, package_name: "system"}]
+ * Returns false
+ */
+bool containsLinkedStateValues(const HashableDimensionKey& whatKey,
+                               const HashableDimensionKey& primaryKey,
+                               const std::vector<Metric2State>& stateLinks,
+                               const int32_t stateAtomId);
+
+/**
+ * Returns true if there is a Metric2State link that links the stateField and
+ * the metricField (they are equal fields from different atoms).
+ */
+bool linked(const std::vector<Metric2State>& stateLinks, const int32_t stateAtomId,
+            const Field& stateField, const Field& metricField);
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 14585c3..97512ed 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -334,6 +334,11 @@
     FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedState);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStateMapped);
+    FRIEND_TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
 
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
diff --git a/cmds/statsd/src/annotations.h b/cmds/statsd/src/annotations.h
new file mode 100644
index 0000000..cf7f543
--- /dev/null
+++ b/cmds/statsd/src/annotations.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android {
+namespace os {
+namespace statsd {
+
+const uint8_t ANNOTATION_ID_IS_UID = 1;
+const uint8_t ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
+const uint8_t ANNOTATION_ID_PRIMARY_FIELD = 3;
+const uint8_t ANNOTATION_ID_EXCLUSIVE_STATE = 4;
+const uint8_t ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5;
+const uint8_t ANNOTATION_ID_TRIGGER_STATE_RESET = 7;
+const uint8_t ANNOTATION_ID_STATE_NESTED = 8;
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index afee79d..8527185 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -23,25 +23,12 @@
 
 import "google/protobuf/descriptor.proto";
 
-enum StateField {
-    // Default value for fields that are not a primary or exclusive state field.
-    STATE_FIELD_UNSET = 0;
-    // Fields that represent the key that the state belongs to.
-    // Used on simple proto fields. Do not use on attribution chains.
-    PRIMARY_FIELD = 1;
-    // The field that represents the state. It's an exclusive state.
-    EXCLUSIVE_STATE = 2;
-    // Used on an attribution chain field to indicate that the first uid is the
-    // primary field.
-    PRIMARY_FIELD_FIRST_UID = 3;
-}
-
 // Used to annotate an atom that represents a state change. A state change atom must have exactly
 // ONE exclusive state field, and any number of primary key fields. For example, message
 // UidProcessStateChanged {
-//    optional int32 uid = 1 [(state_field_option).option = PRIMARY_FIELD];
-//    optional android.app.ProcessStateEnum state = 2 [(state_field_option).option =
-//    EXCLUSIVE_STATE];
+//    optional int32 uid = 1 [(state_field_option).primary_field = true];
+//    optional android.app.ProcessStateEnum state =
+//            2 [(state_field_option).exclusive_state = true];
 //  }
 // Each UidProcessStateChanged atom event represents a state change for a specific uid.
 // A new state automatically overrides the previous state.
@@ -50,23 +37,23 @@
 // primary fields are the primary key.
 // For example:
 // message ThreadStateChanged {
-//    optional int32 pid = 1  [(state_field_option).option = PRIMARY_FIELD];
-//    optional int32 tid = 2  [(state_field_option).option = PRIMARY_FIELD];
-//    optional int32 state = 3 [(state_field_option).option = EXCLUSIVE_STATE];
+//    optional int32 pid = 1  [(state_field_option).primary_field = true];
+//    optional int32 tid = 2  [(state_field_option).primary_field = true];
+//    optional int32 state = 3 [(state_field_option).exclusive_state = true];
 // }
 //
 // Sometimes, there is no primary key field, when the state is GLOBAL.
 // For example,
 // message ScreenStateChanged {
-//    optional android.view.DisplayStateEnum state = 1 [(state_field_option).option =
-//    EXCLUSIVE_STATE];
+//    optional android.view.DisplayStateEnum state =
+//          1 [(state_field_option).exclusive_state = true];
 // }
 //
 // For state atoms with attribution chain, sometimes the primary key is the first uid in the chain.
 // For example:
 // message AudioStateChanged {
 //   repeated AttributionNode attribution_node = 1
-//       [(stateFieldOption).option = PRIMARY_KEY_FIRST_UID];
+//       [(stateFieldOption).primary_field_first_uid = true];
 //
 //    enum State {
 //      OFF = 0;
@@ -74,10 +61,19 @@
 //      // RESET indicates all audio stopped. Used when it (re)starts (e.g. after it crashes).
 //      RESET = 2;
 //    }
-//    optional State state = 2 [(stateFieldOption).option = EXCLUSIVE_STATE];
+//    optional State state = 2 [(stateFieldOption).exclusive_state = true];
 // }
 message StateAtomFieldOption {
-    optional StateField option = 1 [default = STATE_FIELD_UNSET];
+    // Fields that represent the key that the state belongs to.
+    // Used on simple proto fields. Do not use on attribution chains.
+    optional bool primary_field = 1 [default = false];
+
+    // The field that represents the state. It's an exclusive state.
+    optional bool exclusive_state = 2 [default = false];
+
+    // Used on an attribution chain field to indicate that the first uid is the
+    // primary field.
+    optional bool primary_field_first_uid = 3 [default = false];
 
     // Note: We cannot annotate directly on the enums because many enums are imported from other
     // proto files in the platform. proto-lite cc library does not support annotations unfortunately
@@ -85,14 +81,14 @@
     // Knowing the default state value allows state trackers to remove entries that become the
     // default state. If there is no default value specified, the default value is unknown, and all
     // states will be tracked in memory.
-    optional int32 default_state_value = 2;
+    optional int32 default_state_value = 4;
 
     // A reset state signals all states go to default value. For example, BLE reset means all active
     // BLE scans are to be turned off.
-    optional int32 reset_state_value = 3;
+    optional int32 trigger_state_reset_value = 5;
 
     // If the state change needs to count nesting.
-    optional bool nested = 4 [default = true];
+    optional bool nested = 6 [default = true];
 }
 
 // Used to generate StatsLog.write APIs.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6a4338f..bd15264 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -123,7 +123,8 @@
         BatteryLevelChanged battery_level_changed =
                 30 [(module) = "framework", (module) = "statsdtest"];
         ChargingStateChanged charging_state_changed = 31 [(module) = "framework"];
-        PluggedStateChanged plugged_state_changed = 32 [(module) = "framework"];
+        PluggedStateChanged plugged_state_changed = 32
+                [(module) = "framework", (module) = "statsdtest"];
         InteractiveStateChanged interactive_state_changed = 33 [(module) = "framework"];
         TouchEventReported touch_event_reported = 34;
         WakeupAlarmOccurred wakeup_alarm_occurred = 35 [(module) = "framework"];
@@ -609,7 +610,7 @@
 message ScreenStateChanged {
     // New screen state, from frameworks/base/core/proto/android/view/enums.proto.
     optional android.view.DisplayStateEnum state = 1
-            [(state_field_option).option = EXCLUSIVE_STATE, (state_field_option).nested = false];
+            [(state_field_option).exclusive_state = true, (state_field_option).nested = false];
 }
 
 /**
@@ -620,11 +621,11 @@
  *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
  */
 message UidProcessStateChanged {
-    optional int32 uid = 1 [(state_field_option).option = PRIMARY_FIELD, (is_uid) = true];
+    optional int32 uid = 1 [(state_field_option).primary_field = true, (is_uid) = true];
 
     // The state, from frameworks/base/core/proto/android/app/enums.proto.
     optional android.app.ProcessStateEnum state = 2
-            [(state_field_option).option = EXCLUSIVE_STATE, (state_field_option).nested = false];
+            [(state_field_option).exclusive_state = true, (state_field_option).nested = false];
 }
 
 /**
@@ -656,7 +657,7 @@
         ASLEEP = 1;
         AWAKE = 2;
     }
-    optional State state = 1 [(state_field_option).option = EXCLUSIVE_STATE];
+    optional State state = 1 [(state_field_option).exclusive_state = true];
 }
 
 /**
@@ -675,7 +676,7 @@
         CRITICAL = 4;   // critical memory.
 
     }
-    optional State factor = 1 [(state_field_option).option = EXCLUSIVE_STATE];
+    optional State factor = 1 [(state_field_option).exclusive_state = true];
 }
 
 /**
@@ -853,7 +854,7 @@
  */
 message BleScanStateChanged {
     repeated AttributionNode attribution_node = 1
-            [(state_field_option).option = PRIMARY_FIELD_FIRST_UID];
+            [(state_field_option).primary_field_first_uid = true];
 
     enum State {
         OFF = 0;
@@ -862,18 +863,18 @@
         RESET = 2;
     }
     optional State state = 2 [
-        (state_field_option).option = EXCLUSIVE_STATE,
+        (state_field_option).exclusive_state = true,
         (state_field_option).default_state_value = 0 /* State.OFF */,
-        (state_field_option).reset_state_value = 2 /* State.RESET */,
+        (state_field_option).trigger_state_reset_value = 2 /* State.RESET */,
         (state_field_option).nested = true
     ];
 
     // Does the scan have a filter.
-    optional bool is_filtered = 3 [(state_field_option).option = PRIMARY_FIELD];
+    optional bool is_filtered = 3 [(state_field_option).primary_field = true];
     // Whether the scan is a CALLBACK_TYPE_FIRST_MATCH scan. Called 'background' scan internally.
-    optional bool is_first_match = 4 [(state_field_option).option = PRIMARY_FIELD];
+    optional bool is_first_match = 4 [(state_field_option).primary_field = true];
     // Whether the scan set to piggy-back off the results of other scans (SCAN_MODE_OPPORTUNISTIC).
-    optional bool is_opportunistic = 5 [(state_field_option).option = PRIMARY_FIELD];
+    optional bool is_opportunistic = 5 [(state_field_option).primary_field = true];
 }
 
 /**
@@ -1104,15 +1105,14 @@
  */
 message WakelockStateChanged {
     repeated AttributionNode attribution_node = 1
-            [(state_field_option).option = PRIMARY_FIELD_FIRST_UID];
+            [(state_field_option).primary_field_first_uid = true];
 
     // The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock.
     // From frameworks/base/core/proto/android/os/enums.proto.
-    optional android.os.WakeLockLevelEnum type = 2 [(state_field_option).option = PRIMARY_FIELD];
-    ;
+    optional android.os.WakeLockLevelEnum type = 2 [(state_field_option).primary_field = true];
 
     // The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
-    optional string tag = 3 [(state_field_option).option = PRIMARY_FIELD];
+    optional string tag = 3 [(state_field_option).primary_field = true];
 
     enum State {
         RELEASE = 0;
@@ -1121,7 +1121,7 @@
         CHANGE_ACQUIRE = 3;
     }
     optional State state = 4 [
-        (state_field_option).option = EXCLUSIVE_STATE,
+        (state_field_option).exclusive_state = true,
         (state_field_option).default_state_value = 0,
         (state_field_option).nested = true
     ];
@@ -3493,9 +3493,9 @@
  *     services/core/java/com/android/server/wm/Session.java
  */
 message OverlayStateChanged {
-    optional int32 uid = 1 [(state_field_option).option = PRIMARY_FIELD, (is_uid) = true];
+    optional int32 uid = 1 [(state_field_option).primary_field = true, (is_uid) = true];
 
-    optional string package_name = 2 [(state_field_option).option = PRIMARY_FIELD];
+    optional string package_name = 2 [(state_field_option).primary_field = true];
 
     optional bool using_alert_window = 3;
 
@@ -3504,7 +3504,7 @@
         EXITED = 2;
     }
     optional State state = 4 [
-        (state_field_option).option = EXCLUSIVE_STATE,
+        (state_field_option).exclusive_state = true,
         (state_field_option).nested = false,
         (state_field_option).default_state_value = 2
     ];
@@ -3712,7 +3712,7 @@
  */
 message AppDied {
     // timestamp(elapsedRealtime) of record creation
-    optional uint64 timestamp_millis = 1 [(state_field_option).option = EXCLUSIVE_STATE];
+    optional uint64 timestamp_millis = 1 [(state_field_option).exclusive_state = true];
 }
 
 /**
@@ -4234,7 +4234,7 @@
         DIALOG_LINE_ITEM = 5;
     }
 
-    optional Type type = 1 [(state_field_option).option = EXCLUSIVE_STATE];
+    optional Type type = 1 [(state_field_option).exclusive_state = true];
 
     // Used if the type is LINE_ITEM
     optional string package_name = 2;
@@ -5810,7 +5810,7 @@
  */
 message PackageNotificationPreferences {
     // Uid under which the package is installed.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     // Notification importance, which specifies when and how a notification is displayed.
     // Specified under core/java/android/app/NotificationManager.java.
     optional int32 importance = 2;
@@ -5827,7 +5827,7 @@
  */
 message PackageNotificationChannelPreferences {
     // Uid under which the package is installed.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     // Channel's ID. Should always be available.
     optional string channel_id = 2;
     // Channel's name. Should always be available.
@@ -5850,7 +5850,7 @@
  */
 message PackageNotificationChannelGroupPreferences {
     // Uid under which the package is installed.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     // Channel Group's ID. Should always be available.
     optional string group_id = 2;
     // Channel Group's name. Should always be available.
@@ -8697,13 +8697,12 @@
     // Name of the package accessing app op
     optional string package_name = 2;
 
-    // operation string id per OPSTR_ constants in AppOpsManager.java
-    optional string op = 3;
+    // deprecated - set to empty string
+    optional string op_deprecated = 3 [deprecated = true];
 
     // attribution_tag; provided by developer when accessing related API, limited at 50 chars by
-    // API.
-    // Attributions must be provided through manifest using <attribution> tag available in R and
-    // above.
+    // API. Attributions must be provided through manifest using <attribution> tag available in R
+    // and above.
     optional string attribution_tag = 4;
 
     // message related to app op access, limited to 600 chars by API
@@ -8718,6 +8717,9 @@
 
     // sampling strategy used to collect this message
     optional SamplingStrategy sampling_strategy = 6;
+
+    // operation id
+    optional android.app.AppOpEnum op = 7 [default = APP_OP_NONE];
 }
 
 /*
diff --git a/cmds/statsd/src/condition/StateConditionTracker.cpp b/cmds/statsd/src/condition/StateConditionTracker.cpp
deleted file mode 100644
index d19a176..0000000
--- a/cmds/statsd/src/condition/StateConditionTracker.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define DEBUG false  // STOPSHIP if true
-#include "Log.h"
-
-#include "StateConditionTracker.h"
-#include "guardrail/StatsdStats.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-using std::vector;
-
-StateConditionTracker::StateConditionTracker(const ConfigKey& key, const int64_t& id, const int index,
-                           const SimplePredicate& simplePredicate,
-                           const unordered_map<int64_t, int>& trackerNameIndexMap,
-                           const vector<Matcher> primaryKeys)
-    : ConditionTracker(id, index), mConfigKey(key), mPrimaryKeys(primaryKeys) {
-    if (simplePredicate.has_start()) {
-        auto pair = trackerNameIndexMap.find(simplePredicate.start());
-        if (pair == trackerNameIndexMap.end()) {
-            ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
-            return;
-        }
-        mStartLogMatcherIndex = pair->second;
-        mTrackerIndex.insert(mStartLogMatcherIndex);
-    } else {
-        ALOGW("Condition %lld must have a start matcher", (long long)id);
-        return;
-    }
-
-    if (simplePredicate.has_dimensions()) {
-        translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
-        if (mOutputDimensions.size() > 0) {
-            mSliced = true;
-            mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
-        } else {
-            ALOGW("Condition %lld has invalid dimensions", (long long)id);
-            return;
-        }
-    } else {
-        ALOGW("Condition %lld being a state tracker, but has no dimension", (long long)id);
-        return;
-    }
-
-    if (simplePredicate.initial_value() == SimplePredicate_InitialValue_FALSE) {
-        mInitialValue = ConditionState::kFalse;
-    } else {
-        mInitialValue = ConditionState::kUnknown;
-    }
-
-    mNonSlicedConditionState = mInitialValue;
-    mInitialized = true;
-}
-
-StateConditionTracker::~StateConditionTracker() {
-    VLOG("~StateConditionTracker()");
-}
-
-bool StateConditionTracker::init(const vector<Predicate>& allConditionConfig,
-                        const vector<sp<ConditionTracker>>& allConditionTrackers,
-                        const unordered_map<int64_t, int>& conditionIdIndexMap,
-                        vector<bool>& stack) {
-    return mInitialized;
-}
-
-void StateConditionTracker::dumpState() {
-    VLOG("StateConditionTracker %lld DUMP:", (long long)mConditionId);
-    for (const auto& value : mSlicedState) {
-        VLOG("\t%s -> %s", value.first.toString().c_str(), value.second.toString().c_str());
-    }
-    VLOG("Last Changed to True: ");
-    for (const auto& value : mLastChangedToTrueDimensions) {
-        VLOG("%s", value.toString().c_str());
-    }
-    VLOG("Last Changed to False: ");
-    for (const auto& value : mLastChangedToFalseDimensions) {
-        VLOG("%s", value.toString().c_str());
-    }
-}
-
-bool StateConditionTracker::hitGuardRail(const HashableDimensionKey& newKey) {
-    if (mSlicedState.find(newKey) != mSlicedState.end()) {
-        // if the condition is not sliced or the key is not new, we are good!
-        return false;
-    }
-    // 1. Report the tuple count if the tuple count > soft limit
-    if (mSlicedState.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
-        size_t newTupleCount = mSlicedState.size() + 1;
-        StatsdStats::getInstance().noteConditionDimensionSize(mConfigKey, mConditionId, newTupleCount);
-        // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
-        if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
-            ALOGE("Predicate %lld dropping data for dimension key %s",
-                (long long)mConditionId, newKey.toString().c_str());
-            return true;
-        }
-    }
-    return false;
-}
-
-void StateConditionTracker::evaluateCondition(const LogEvent& event,
-                                     const vector<MatchingState>& eventMatcherValues,
-                                     const vector<sp<ConditionTracker>>& mAllConditions,
-                                     vector<ConditionState>& conditionCache,
-                                     vector<bool>& conditionChangedCache) {
-    mLastChangedToTrueDimensions.clear();
-    mLastChangedToFalseDimensions.clear();
-    if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
-        // it has been evaluated.
-        VLOG("Yes, already evaluated, %lld %d", (long long)mConditionId, conditionCache[mIndex]);
-        return;
-    }
-
-    if (mStartLogMatcherIndex >= 0 &&
-        eventMatcherValues[mStartLogMatcherIndex] != MatchingState::kMatched) {
-        conditionCache[mIndex] =
-                mSlicedState.size() > 0 ? ConditionState::kTrue : ConditionState::kFalse;
-        conditionChangedCache[mIndex] = false;
-        return;
-    }
-
-    VLOG("StateConditionTracker evaluate event %s", event.ToString().c_str());
-
-    // Primary key can exclusive fields must be simple fields. so there won't be more than
-    // one keys matched.
-    HashableDimensionKey primaryKey;
-    HashableDimensionKey state;
-    if ((mPrimaryKeys.size() > 0 && !filterValues(mPrimaryKeys, event.getValues(), &primaryKey)) ||
-        !filterValues(mOutputDimensions, event.getValues(), &state)) {
-        ALOGE("Failed to filter fields in the event?? panic now!");
-        conditionCache[mIndex] =
-                mSlicedState.size() > 0 ? ConditionState::kTrue : ConditionState::kFalse;
-        conditionChangedCache[mIndex] = false;
-        return;
-    }
-    hitGuardRail(primaryKey);
-
-    VLOG("StateConditionTracker: key %s state %s", primaryKey.toString().c_str(), state.toString().c_str());
-
-    auto it = mSlicedState.find(primaryKey);
-    if (it == mSlicedState.end()) {
-        mSlicedState[primaryKey] = state;
-        conditionCache[mIndex] = ConditionState::kTrue;
-        mLastChangedToTrueDimensions.insert(state);
-        conditionChangedCache[mIndex] = true;
-    } else if (!(it->second == state)) {
-        mLastChangedToFalseDimensions.insert(it->second);
-        mLastChangedToTrueDimensions.insert(state);
-        mSlicedState[primaryKey] = state;
-        conditionCache[mIndex] = ConditionState::kTrue;
-        conditionChangedCache[mIndex] = true;
-    } else {
-        conditionCache[mIndex] = ConditionState::kTrue;
-        conditionChangedCache[mIndex] = false;
-    }
-
-    if (DEBUG) {
-        dumpState();
-    }
-    return;
-}
-
-void StateConditionTracker::isConditionMet(
-        const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
-        const bool isPartialLink,
-        vector<ConditionState>& conditionCache) const {
-    if (conditionCache[mIndex] != ConditionState::kNotEvaluated) {
-        // it has been evaluated.
-        VLOG("Yes, already evaluated, %lld %d", (long long)mConditionId, conditionCache[mIndex]);
-        return;
-    }
-
-    const auto pair = conditionParameters.find(mConditionId);
-    if (pair == conditionParameters.end()) {
-        if (mSlicedState.size() > 0) {
-            conditionCache[mIndex] = ConditionState::kTrue;
-        } else {
-            conditionCache[mIndex] = ConditionState::kUnknown;
-        }
-        return;
-    }
-
-    const auto& primaryKey = pair->second;
-    conditionCache[mIndex] = mInitialValue;
-    auto it = mSlicedState.find(primaryKey);
-    if (it != mSlicedState.end()) {
-        conditionCache[mIndex] = ConditionState::kTrue;
-    }
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/condition/StateConditionTracker.h b/cmds/statsd/src/condition/StateConditionTracker.h
deleted file mode 100644
index 0efe1fb..0000000
--- a/cmds/statsd/src/condition/StateConditionTracker.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <gtest/gtest_prod.h>
-#include "ConditionTracker.h"
-#include "config/ConfigKey.h"
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-#include "stats_util.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-class StateConditionTracker : public virtual ConditionTracker {
-public:
-    StateConditionTracker(const ConfigKey& key, const int64_t& id, const int index,
-                 const SimplePredicate& simplePredicate,
-                 const std::unordered_map<int64_t, int>& trackerNameIndexMap,
-                 const vector<Matcher> primaryKeys);
-
-    ~StateConditionTracker();
-
-    bool init(const std::vector<Predicate>& allConditionConfig,
-              const std::vector<sp<ConditionTracker>>& allConditionTrackers,
-              const std::unordered_map<int64_t, int>& conditionIdIndexMap,
-              std::vector<bool>& stack) override;
-
-    void evaluateCondition(const LogEvent& event,
-                           const std::vector<MatchingState>& eventMatcherValues,
-                           const std::vector<sp<ConditionTracker>>& mAllConditions,
-                           std::vector<ConditionState>& conditionCache,
-                           std::vector<bool>& changedCache) override;
-
-    /**
-     * Note: dimensionFields will be ignored in StateConditionTracker, because we demand metrics
-     * must take the entire dimension fields from StateConditionTracker. This is to make implementation
-     * simple and efficient.
-     *
-     * For example: wakelock duration by uid process states:
-     *              dimension in condition must be {uid, process state}.
-     */
-    void isConditionMet(const ConditionKey& conditionParameters,
-                        const std::vector<sp<ConditionTracker>>& allConditions,
-                        const bool isPartialLink,
-                        std::vector<ConditionState>& conditionCache) const override;
-
-    virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(
-            const std::vector<sp<ConditionTracker>>& allConditions) const {
-        return &mLastChangedToTrueDimensions;
-    }
-
-    virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
-            const std::vector<sp<ConditionTracker>>& allConditions) const {
-        return &mLastChangedToFalseDimensions;
-    }
-
-    bool IsChangedDimensionTrackable() const  override { return true; }
-
-    bool IsSimpleCondition() const  override { return true; }
-
-    bool equalOutputDimensions(
-        const std::vector<sp<ConditionTracker>>& allConditions,
-        const vector<Matcher>& dimensions) const override {
-            return equalDimensions(mOutputDimensions, dimensions);
-    }
-
-    void getTrueSlicedDimensions(
-            const std::vector<sp<ConditionTracker>>& allConditions,
-            std::set<HashableDimensionKey>* dimensions) const override {
-        for (const auto& itr : mSlicedState) {
-            dimensions->insert(itr.second);
-        }
-    }
-
-private:
-    const ConfigKey mConfigKey;
-
-    // The index of the LogEventMatcher which defines the start.
-    int mStartLogMatcherIndex;
-
-    std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
-    std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
-
-    std::vector<Matcher> mOutputDimensions;
-    std::vector<Matcher> mPrimaryKeys;
-
-    ConditionState mInitialValue;
-
-    int mDimensionTag;
-
-    void dumpState();
-
-    bool hitGuardRail(const HashableDimensionKey& newKey);
-
-    // maps from [primary_key] to [primary_key, exclusive_state].
-    std::unordered_map<HashableDimensionKey, HashableDimensionKey> mSlicedState;
-
-    FRIEND_TEST(StateConditionTrackerTest, TestStateChange);
-};
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index a3701a7..79a7e8d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -41,15 +41,50 @@
 namespace os {
 namespace statsd {
 
+// Stores the puller as a wp to avoid holding a reference in case it is unregistered and
+// pullAtomCallbackDied is never called.
+struct PullAtomCallbackDeathCookie {
+    PullAtomCallbackDeathCookie(sp<StatsPullerManager> pullerManager, const PullerKey& pullerKey,
+                                const wp<StatsPuller>& puller)
+        : mPullerManager(pullerManager), mPullerKey(pullerKey), mPuller(puller) {
+    }
+
+    sp<StatsPullerManager> mPullerManager;
+    PullerKey mPullerKey;
+    wp<StatsPuller> mPuller;
+};
+
+void StatsPullerManager::pullAtomCallbackDied(void* cookie) {
+    PullAtomCallbackDeathCookie* cookie_ = static_cast<PullAtomCallbackDeathCookie*>(cookie);
+    sp<StatsPullerManager>& thiz = cookie_->mPullerManager;
+    const PullerKey& pullerKey = cookie_->mPullerKey;
+    wp<StatsPuller> puller = cookie_->mPuller;
+
+    // Erase the mapping from the puller key to the puller if the mapping still exists.
+    // Note that we are removing the StatsPuller object, which internally holds the binder
+    // IPullAtomCallback. However, each new registration creates a new StatsPuller, so this works.
+    lock_guard<mutex> lock(thiz->mLock);
+    const auto& it = thiz->kAllPullAtomInfo.find(pullerKey);
+    if (it != thiz->kAllPullAtomInfo.end() && puller != nullptr && puller == it->second) {
+        StatsdStats::getInstance().notePullerCallbackRegistrationChanged(pullerKey.atomTag,
+                                                                         /*registered=*/false);
+        thiz->kAllPullAtomInfo.erase(pullerKey);
+    }
+    // The death recipient corresponding to this specific IPullAtomCallback can never
+    // be triggered again, so free up resources.
+    delete cookie_;
+}
+
 // Values smaller than this may require to update the alarm.
 const int64_t NO_ALARM_UPDATE = INT64_MAX;
 
 StatsPullerManager::StatsPullerManager()
     : kAllPullAtomInfo({
               // TrainInfo.
-              {{.atomTag = util::TRAIN_INFO, .uid = -1}, new TrainInfoPuller()},
+              {{.atomTag = util::TRAIN_INFO, .uid = AID_STATSD}, new TrainInfoPuller()},
       }),
-      mNextPullTimeNs(NO_ALARM_UPDATE) {
+      mNextPullTimeNs(NO_ALARM_UPDATE),
+      mPullAtomCallbackDeathRecipient(AIBinder_DeathRecipient_new(pullAtomCallbackDied)) {
 }
 
 bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey,
@@ -310,19 +345,28 @@
                                                   bool useUid) {
     std::lock_guard<std::mutex> _l(mLock);
     VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
-    // TODO(b/146439412): linkToDeath with the callback so that we can remove it
-    // and delete the puller.
+
     StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
     int64_t actualCoolDownNs = coolDownNs < kMinCoolDownNs ? kMinCoolDownNs : coolDownNs;
     int64_t actualTimeoutNs = timeoutNs > kMaxTimeoutNs ? kMaxTimeoutNs : timeoutNs;
-    kAllPullAtomInfo[{.atomTag = atomTag, .uid = useUid ? uid : -1}] = new StatsCallbackPuller(
-            atomTag, callback, actualCoolDownNs, actualTimeoutNs, additiveFields);
+
+    sp<StatsCallbackPuller> puller = new StatsCallbackPuller(atomTag, callback, actualCoolDownNs,
+                                                             actualTimeoutNs, additiveFields);
+    PullerKey key = {.atomTag = atomTag, .uid = useUid ? uid : -1};
+    AIBinder_linkToDeath(callback->asBinder().get(), mPullAtomCallbackDeathRecipient.get(),
+                         new PullAtomCallbackDeathCookie(this, key, puller));
+    kAllPullAtomInfo[key] = puller;
 }
 
-void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
+void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag,
+                                                    bool useUids) {
     std::lock_guard<std::mutex> _l(mLock);
-    StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
-    kAllPullAtomInfo.erase({.atomTag = atomTag});
+    PullerKey key = {.atomTag = atomTag, .uid = useUids ? uid : -1};
+    if (kAllPullAtomInfo.find(key) != kAllPullAtomInfo.end()) {
+        StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag,
+                                                                         /*registered=*/false);
+        kAllPullAtomInfo.erase(key);
+    }
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index c5824a8..ab0ccee 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -101,11 +101,11 @@
     // If the metric wants to make any change to the data, like timestamps, they
     // should make a copy as this data may be shared with multiple metrics.
     virtual bool Pull(int tagId, const ConfigKey& configKey,
-                      vector<std::shared_ptr<LogEvent>>* data, bool useUids = false);
+                      vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
 
     // Same as above, but directly specify the allowed uids to pull from.
     virtual bool Pull(int tagId, const vector<int32_t>& uids,
-                      vector<std::shared_ptr<LogEvent>>* data, bool useUids = false);
+                      vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
 
     // Clear pull data cache immediately.
     int ForceClearPullerCache();
@@ -118,9 +118,9 @@
     void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
                                   const int64_t timeoutNs, const vector<int32_t>& additiveFields,
                                   const shared_ptr<IPullAtomCallback>& callback,
-                                  bool useUid = false);
+                                  bool useUid = true);
 
-    void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
+    void UnregisterPullAtomCallback(const int uid, const int32_t atomTag, bool useUids = true);
 
     std::map<const PullerKey, sp<StatsPuller>> kAllPullAtomInfo;
 
@@ -152,7 +152,7 @@
     std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
 
     bool PullLocked(int tagId, const ConfigKey& configKey, vector<std::shared_ptr<LogEvent>>* data,
-                    bool useUids = false);
+                    bool useUids = true);
 
     bool PullLocked(int tagId, const vector<int32_t>& uids, vector<std::shared_ptr<LogEvent>>* data,
                     bool useUids);
@@ -164,6 +164,15 @@
 
     int64_t mNextPullTimeNs;
 
+    // Death recipient that is triggered when the process holding the IPullAtomCallback has died.
+    ::ndk::ScopedAIBinder_DeathRecipient mPullAtomCallbackDeathRecipient;
+
+    /**
+     * Death recipient callback that is called when a pull atom callback dies.
+     * The cookie is a pointer to a PullAtomCallbackDeathCookie.
+     */
+    static void pullAtomCallbackDied(void* cookie);
+
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 3b3d0b6..96bf04f 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -17,13 +17,14 @@
 #define DEBUG false  // STOPSHIP if true
 #include "logd/LogEvent.h"
 
+#include <android-base/stringprintf.h>
+#include <android/binder_ibinder.h>
+#include <private/android_filesystem_config.h>
+
+#include "annotations.h"
 #include "stats_log_util.h"
 #include "statslog_statsd.h"
 
-#include <android/binder_ibinder.h>
-#include <android-base/stringprintf.h>
-#include <private/android_filesystem_config.h>
-
 namespace android {
 namespace os {
 namespace statsd {
@@ -75,77 +76,7 @@
 }
 
 LogEvent::LogEvent(int32_t uid, int32_t pid)
-    : mLogdTimestampNs(time(nullptr)),
-      mLogUid(uid),
-      mLogPid(pid) {
-}
-
-LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
-    mLogdTimestampNs = wallClockTimestampNs;
-    mElapsedTimestampNs = elapsedTimestampNs;
-    mTagId = tagId;
-    mLogUid = 0;
-    mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
-    if (mContext) {
-        android_log_write_int64(mContext, elapsedTimestampNs);
-        android_log_write_int32(mContext, tagId);
-    }
-}
-
-LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
-                   int32_t uid,
-                   const std::map<int32_t, int32_t>& int_map,
-                   const std::map<int32_t, int64_t>& long_map,
-                   const std::map<int32_t, std::string>& string_map,
-                   const std::map<int32_t, float>& float_map) {
-    mLogdTimestampNs = wallClockTimestampNs;
-    mElapsedTimestampNs = elapsedTimestampNs;
-    mTagId = util::KEY_VALUE_PAIRS_ATOM;
-    mLogUid = uid;
-
-    int pos[] = {1, 1, 1};
-
-    mValues.push_back(FieldValue(Field(mTagId, pos, 0 /* depth */), Value(uid)));
-    pos[0]++;
-    for (const auto&itr : int_map) {
-        pos[2] = 1;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
-        pos[2] = 2;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
-        mValues.back().mField.decorateLastPos(2);
-        pos[1]++;
-    }
-
-    for (const auto&itr : long_map) {
-        pos[2] = 1;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
-        pos[2] = 3;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
-        mValues.back().mField.decorateLastPos(2);
-        pos[1]++;
-    }
-
-    for (const auto&itr : string_map) {
-        pos[2] = 1;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
-        pos[2] = 4;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
-        mValues.back().mField.decorateLastPos(2);
-        pos[1]++;
-    }
-
-    for (const auto&itr : float_map) {
-        pos[2] = 1;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.first)));
-        pos[2] = 5;
-        mValues.push_back(FieldValue(Field(mTagId, pos, 2 /* depth */), Value(itr.second)));
-        mValues.back().mField.decorateLastPos(2);
-        pos[1]++;
-    }
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-        mValues.at(mValues.size() - 2).mField.decorateLastPos(1);
-    }
+    : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
 }
 
 LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
@@ -183,17 +114,6 @@
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
 }
 
-LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
-    mLogdTimestampNs = timestampNs;
-    mTagId = tagId;
-    mLogUid = uid;
-    mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
-    if (mContext) {
-        android_log_write_int64(mContext, timestampNs);
-        android_log_write_int32(mContext, tagId);
-    }
-}
-
 LogEvent::~LogEvent() {
     if (mContext) {
         // This is for the case when LogEvent is created using the test interface
@@ -202,154 +122,6 @@
     }
 }
 
-bool LogEvent::write(int32_t value) {
-    if (mContext) {
-        return android_log_write_int32(mContext, value) >= 0;
-    }
-    return false;
-}
-
-bool LogEvent::write(uint32_t value) {
-    if (mContext) {
-        return android_log_write_int32(mContext, value) >= 0;
-    }
-    return false;
-}
-
-bool LogEvent::write(int64_t value) {
-    if (mContext) {
-        return android_log_write_int64(mContext, value) >= 0;
-    }
-    return false;
-}
-
-bool LogEvent::write(uint64_t value) {
-    if (mContext) {
-        return android_log_write_int64(mContext, value) >= 0;
-    }
-    return false;
-}
-
-bool LogEvent::write(const string& value) {
-    if (mContext) {
-        return android_log_write_string8_len(mContext, value.c_str(), value.length()) >= 0;
-    }
-    return false;
-}
-
-bool LogEvent::write(float value) {
-    if (mContext) {
-        return android_log_write_float32(mContext, value) >= 0;
-    }
-    return false;
-}
-
-bool LogEvent::writeBytes(const string& value) {
-    /* if (mContext) {
-        return android_log_write_char_array(mContext, value.c_str(), value.length()) >= 0;
-    }*/
-    return false;
-}
-
-bool LogEvent::writeKeyValuePairs(int32_t uid,
-                                  const std::map<int32_t, int32_t>& int_map,
-                                  const std::map<int32_t, int64_t>& long_map,
-                                  const std::map<int32_t, std::string>& string_map,
-                                  const std::map<int32_t, float>& float_map) {
-    if (mContext) {
-         if (android_log_write_list_begin(mContext) < 0) {
-            return false;
-         }
-         write(uid);
-         for (const auto& itr : int_map) {
-             if (android_log_write_list_begin(mContext) < 0) {
-                return false;
-             }
-             write(itr.first);
-             write(itr.second);
-             if (android_log_write_list_end(mContext) < 0) {
-                return false;
-             }
-         }
-
-         for (const auto& itr : long_map) {
-             if (android_log_write_list_begin(mContext) < 0) {
-                return false;
-             }
-             write(itr.first);
-             write(itr.second);
-             if (android_log_write_list_end(mContext) < 0) {
-                return false;
-             }
-         }
-
-         for (const auto& itr : string_map) {
-             if (android_log_write_list_begin(mContext) < 0) {
-                return false;
-             }
-             write(itr.first);
-             write(itr.second.c_str());
-             if (android_log_write_list_end(mContext) < 0) {
-                return false;
-             }
-         }
-
-         for (const auto& itr : float_map) {
-             if (android_log_write_list_begin(mContext) < 0) {
-                return false;
-             }
-             write(itr.first);
-             write(itr.second);
-             if (android_log_write_list_end(mContext) < 0) {
-                return false;
-             }
-         }
-
-         if (android_log_write_list_end(mContext) < 0) {
-            return false;
-         }
-         return true;
-    }
-    return false;
-}
-
-bool LogEvent::write(const std::vector<AttributionNodeInternal>& nodes) {
-    if (mContext) {
-         if (android_log_write_list_begin(mContext) < 0) {
-            return false;
-         }
-         for (size_t i = 0; i < nodes.size(); ++i) {
-             if (!write(nodes[i])) {
-                return false;
-             }
-         }
-         if (android_log_write_list_end(mContext) < 0) {
-            return false;
-         }
-         return true;
-    }
-    return false;
-}
-
-bool LogEvent::write(const AttributionNodeInternal& node) {
-    if (mContext) {
-         if (android_log_write_list_begin(mContext) < 0) {
-            return false;
-         }
-         if (android_log_write_int32(mContext, node.uid()) < 0) {
-            return false;
-         }
-         if (android_log_write_string8(mContext, node.tag().c_str()) < 0) {
-            return false;
-         }
-         if (android_log_write_list_end(mContext) < 0) {
-            return false;
-         }
-         return true;
-    }
-    return false;
-}
-
 void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
     int32_t value = readNextValue<int32_t>();
     addToValues(pos, depth, value, last);
@@ -419,7 +191,7 @@
         uint8_t typeInfo = readNextValue<uint8_t>();
         switch (getTypeId(typeInfo)) {
             case INT32_TYPE:
-                pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
+                pos[2] = 2;  // pos[2] determined by index of type in KeyValuePair in atoms.proto
                 parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
                 break;
             case INT64_TYPE:
@@ -447,6 +219,7 @@
 
 void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
                                      uint8_t numAnnotations) {
+    int firstUidInChainIndex = mValues.size();
     int32_t numNodes = readNextValue<uint8_t>();
     for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
         last[1] = (pos[1] == numNodes);
@@ -461,26 +234,114 @@
         parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
     }
 
-    parseAnnotations(numAnnotations);
+    parseAnnotations(numAnnotations, firstUidInChainIndex);
 
     pos[1] = pos[2] = 1;
     last[1] = last[2] = false;
 }
 
-// TODO(b/151109630): store annotation information within LogEvent
-void LogEvent::parseAnnotations(uint8_t numAnnotations) {
+void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
+    if (mValues.empty() || annotationType != BOOL_TYPE) {
+        mValid = false;
+        return;
+    }
+
+    bool isUid = readNextValue<uint8_t>();
+    if (isUid) mUidFieldIndex = mValues.size() - 1;
+}
+
+void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
+    if (!mValues.empty() || annotationType != BOOL_TYPE) {
+        mValid = false;
+        return;
+    }
+
+    mTruncateTimestamp = readNextValue<uint8_t>();
+}
+
+void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType) {
+    if (mValues.empty() || annotationType != BOOL_TYPE) {
+        mValid = false;
+        return;
+    }
+
+    const bool primaryField = readNextValue<uint8_t>();
+    mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
+}
+
+void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
+                                                   int firstUidInChainIndex) {
+    if (mValues.empty() || annotationType != BOOL_TYPE || -1 == firstUidInChainIndex) {
+        mValid = false;
+        return;
+    }
+
+    const bool primaryField = readNextValue<uint8_t>();
+    mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField);
+}
+
+void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType) {
+    if (mValues.empty() || annotationType != BOOL_TYPE) {
+        mValid = false;
+        return;
+    }
+
+    const bool exclusiveState = readNextValue<uint8_t>();
+    mValues[mValues.size() - 1].mAnnotations.setExclusiveState(exclusiveState);
+}
+
+void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType) {
+    if (mValues.empty() || annotationType != INT32_TYPE) {
+        mValid = false;
+        return;
+    }
+
+    int32_t resetState = readNextValue<int32_t>();
+    mValues[mValues.size() - 1].mAnnotations.setResetState(resetState);
+}
+
+void LogEvent::parseStateNestedAnnotation(uint8_t annotationType) {
+    if (mValues.empty() || annotationType != BOOL_TYPE) {
+        mValid = false;
+        return;
+    }
+
+    bool nested = readNextValue<uint8_t>();
+    mValues[mValues.size() - 1].mAnnotations.setNested(nested);
+}
+
+// firstUidInChainIndex is a default parameter that is only needed when parsing
+// annotations for attribution chains.
+void LogEvent::parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex) {
     for (uint8_t i = 0; i < numAnnotations; i++) {
-        /*uint8_t annotationId = */ readNextValue<uint8_t>();
+        uint8_t annotationId = readNextValue<uint8_t>();
         uint8_t annotationType = readNextValue<uint8_t>();
-        switch (annotationType) {
-            case BOOL_TYPE:
-                /*bool annotationValue = */ readNextValue<uint8_t>();
+
+        switch (annotationId) {
+            case ANNOTATION_ID_IS_UID:
+                parseIsUidAnnotation(annotationType);
                 break;
-            case INT32_TYPE:
-                /*int32_t annotationValue =*/ readNextValue<int32_t>();
+            case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
+                parseTruncateTimestampAnnotation(annotationType);
+                break;
+            case ANNOTATION_ID_PRIMARY_FIELD:
+                parsePrimaryFieldAnnotation(annotationType);
+                break;
+            case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
+                parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
+                break;
+            case ANNOTATION_ID_EXCLUSIVE_STATE:
+                parseExclusiveStateAnnotation(annotationType);
+                break;
+            case ANNOTATION_ID_TRIGGER_STATE_RESET:
+                parseTriggerStateResetAnnotation(annotationType);
+                break;
+            case ANNOTATION_ID_STATE_NESTED:
+                parseStateNestedAnnotation(annotationType);
                 break;
             default:
                 mValid = false;
+                return;
         }
     }
 }
@@ -509,9 +370,8 @@
     typeInfo = readNextValue<uint8_t>();
     if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
     mTagId = readNextValue<int32_t>();
-    parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
     numElements--;
-
+    parseAnnotations(getNumAnnotations(typeInfo));  // atom-level annotations
 
     for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
         last[0] = (pos[0] == numElements);
@@ -520,7 +380,7 @@
         uint8_t typeId = getTypeId(typeInfo);
 
         // TODO(b/144373276): handle errors passed to the socket
-        switch(typeId) {
+        switch (typeId) {
             case BOOL_TYPE:
                 parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
                 break;
@@ -544,6 +404,7 @@
                 break;
             case ATTRIBUTION_CHAIN_TYPE:
                 parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+                if (mAttributionChainIndex == -1) mAttributionChainIndex = pos[0];
                 break;
             default:
                 mValid = false;
@@ -556,11 +417,11 @@
 }
 
 uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
-    return typeInfo & 0x0F; // type id in lower 4 bytes
+    return typeInfo & 0x0F;  // type id in lower 4 bytes
 }
 
 uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
-    return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes
+    return (typeInfo >> 4) & 0x0F;  // num annotations in upper 4 bytes
 }
 
 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
@@ -671,17 +532,17 @@
 std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
     int field = getSimpleField(key);
     for (const auto& value : mValues) {
-      if (value.mField.getField() == field) {
-        if (value.mValue.getType() == STORAGE) {
-          return value.mValue.storage_value;
-        } else {
-          *err = BAD_TYPE;
-          return vector<uint8_t>();
+        if (value.mField.getField() == field) {
+            if (value.mValue.getType() == STORAGE) {
+                return value.mValue.storage_value;
+            } else {
+                *err = BAD_TYPE;
+                return vector<uint8_t>();
+            }
         }
-      }
-      if ((size_t)value.mField.getPosAtDepth(0) > key) {
-        break;
-      }
+        if ((size_t)value.mField.getPosAtDepth(0) > key) {
+            break;
+        }
     }
 
     *err = BAD_INDEX;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 6537f13..9e21c77 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -28,27 +28,6 @@
 namespace os {
 namespace statsd {
 
-struct AttributionNodeInternal {
-    void set_uid(int32_t id) {
-        mUid = id;
-    }
-
-    void set_tag(const std::string& value) {
-        mTag = value;
-    }
-
-    int32_t uid() const {
-        return mUid;
-    }
-
-    const std::string& tag() const {
-        return mTag;
-    }
-
-    int32_t mUid;
-    std::string mTag;
-};
-
 struct InstallTrainInfo {
     int64_t trainVersionCode;
     std::string trainName;
@@ -83,28 +62,6 @@
      */
     bool parseBuffer(uint8_t* buf, size_t len);
 
-    // TODO(b/149590301): delete unused functions below once LogEvent uses the
-    // new socket schema within test code. Really we would like the only entry
-    // points into LogEvent to be the above constructor and parseBuffer functions.
-
-    /**
-     * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
-     */
-    explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
-
-    // For testing. The timestamp is used as both elapsed real time and logd timestamp.
-    explicit LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid);
-
-    /**
-     * Constructs a KeyValuePairsAtom LogEvent from value maps.
-     */
-    explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
-                      int32_t uid,
-                      const std::map<int32_t, int32_t>& int_map,
-                      const std::map<int32_t, int64_t>& long_map,
-                      const std::map<int32_t, std::string>& string_map,
-                      const std::map<int32_t, float>& float_map);
-
     // Constructs a BinaryPushStateChanged LogEvent from API call.
     explicit LogEvent(const std::string& trainName, int64_t trainVersionCode, bool requiresStaging,
                       bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
@@ -152,25 +109,6 @@
     std::vector<uint8_t> GetStorage(size_t key, status_t* err) const;
 
     /**
-     * Write test data to the LogEvent. This can only be used when the LogEvent is constructed
-     * using LogEvent(tagId, timestampNs). You need to call init() before you can read from it.
-     */
-    bool write(uint32_t value);
-    bool write(int32_t value);
-    bool write(uint64_t value);
-    bool write(int64_t value);
-    bool write(const std::string& value);
-    bool write(float value);
-    bool write(const std::vector<AttributionNodeInternal>& nodes);
-    bool write(const AttributionNodeInternal& node);
-    bool writeBytes(const std::string& value);
-    bool writeKeyValuePairs(int32_t uid,
-                            const std::map<int32_t, int32_t>& int_map,
-                            const std::map<int32_t, int64_t>& long_map,
-                            const std::map<int32_t, std::string>& string_map,
-                            const std::map<int32_t, float>& float_map);
-
-    /**
      * Return a string representation of this event.
      */
     std::string ToString() const;
@@ -206,6 +144,32 @@
         return &mValues;
     }
 
+    // Default value = false
+    inline bool shouldTruncateTimestamp() {
+        return mTruncateTimestamp;
+    }
+
+    // Returns the index of the uid field within the FieldValues vector if the
+    // uid exists. If there is no uid field, returns -1.
+    //
+    // If the index within the atom definition is desired, do the following:
+    //    int vectorIndex = LogEvent.getUidFieldIndex();
+    //    if (vectorIndex != -1) {
+    //        FieldValue& v = LogEvent.getValues()[vectorIndex];
+    //        int atomIndex = v.mField.getPosAtDepth(0);
+    //    }
+    // Note that atomIndex is 1-indexed.
+    inline int getUidFieldIndex() {
+        return mUidFieldIndex;
+    }
+
+    // Returns the index of (the first) attribution chain within the atom
+    // definition. Note that the value is 1-indexed. If there is no attribution
+    // chain, returns -1.
+    inline int getAttributionChainIndex() {
+        return mAttributionChainIndex;
+    }
+
     inline LogEvent makeCopy() {
         return LogEvent(*this);
     }
@@ -240,15 +204,20 @@
     void parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
     void parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
     void parseAttributionChain(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
-    void parseAnnotations(uint8_t numAnnotations);
+
+    void parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex = -1);
+    void parseIsUidAnnotation(uint8_t annotationType);
+    void parseTruncateTimestampAnnotation(uint8_t annotationType);
+    void parsePrimaryFieldAnnotation(uint8_t annotationType);
+    void parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType, int firstUidInChainIndex);
+    void parseExclusiveStateAnnotation(uint8_t annotationType);
+    void parseTriggerStateResetAnnotation(uint8_t annotationType);
+    void parseStateNestedAnnotation(uint8_t annotationType);
 
     /**
      * The below three variables are only valid during the execution of
      * parseBuffer. There are no guarantees about the state of these variables
      * before/after.
-     *
-     * TODO (b/150312423): These shouldn't be member variables. We should pass
-     * them around as parameters.
      */
     uint8_t* mBuf;
     uint32_t mRemainingLen; // number of valid bytes left in the buffer being parsed
@@ -322,6 +291,11 @@
 
     // The pid of the logging client (defaults to -1).
     int32_t mLogPid = -1;
+
+    // Annotations
+    bool mTruncateTimestamp = false;
+    int mUidFieldIndex = -1;
+    int mAttributionChainIndex = -1;
 };
 
 void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, std::vector<uint8_t>* protoOut);
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index e85b975..0de92f3 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -55,6 +55,7 @@
 const int FIELD_ID_DIMENSION_IN_WHAT = 1;
 const int FIELD_ID_BUCKET_INFO = 3;
 const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
+const int FIELD_ID_SLICE_BY_STATE = 6;
 // for DurationBucketInfo
 const int FIELD_ID_DURATION = 3;
 const int FIELD_ID_BUCKET_NUM = 4;
@@ -115,6 +116,14 @@
     }
     mUnSlicedPartCondition = ConditionState::kUnknown;
 
+    for (const auto& stateLink : metric.state_link()) {
+        Metric2State ms;
+        ms.stateAtomId = stateLink.state_atom_id();
+        translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
+        translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
+        mMetric2StateLinks.push_back(ms);
+    }
+
     mUseWhatDimensionAsInternalDimension = equalDimensions(mDimensionsInWhat, mInternalDimensions);
     if (mWizard != nullptr && mConditionTrackerIndex >= 0 &&
             mMetric2ConditionLinks.size() == 1) {
@@ -150,21 +159,49 @@
     return anomalyTracker;
 }
 
+void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
+                                            const HashableDimensionKey& primaryKey,
+                                            const int32_t oldState, const int32_t newState) {
+    // Create a FieldValue object to hold the new state.
+    FieldValue value;
+    value.mValue.setInt(newState);
+    // Check if this metric has a StateMap. If so, map the new state value to
+    // the correct state group id.
+    mapStateValue(atomId, &value);
+
+    flushIfNeededLocked(eventTimeNs);
+
+    // Each duration tracker is mapped to a different whatKey (a set of values from the
+    // dimensionsInWhat fields). We notify all trackers iff the primaryKey field values from the
+    // state change event are a subset of the tracker's whatKey field values.
+    //
+    // Ex. For a duration metric dimensioned on uid and tag:
+    // DurationTracker1 whatKey = uid: 1001, tag: 1
+    // DurationTracker2 whatKey = uid: 1002, tag 1
+    //
+    // If the state change primaryKey = uid: 1001, we only notify DurationTracker1 of a state
+    // change.
+    for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
+        if (!containsLinkedStateValues(whatIt.first, primaryKey, mMetric2StateLinks, atomId)) {
+            continue;
+        }
+        whatIt.second->onStateChanged(eventTimeNs, atomId, value);
+    }
+}
+
 unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
         const MetricDimensionKey& eventKey) const {
     switch (mAggregationType) {
         case DurationMetric_AggregationType_SUM:
             return make_unique<OringDurationTracker>(
-                    mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
-                    mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
-                    mTimeBaseNs, mBucketSizeNs, mConditionSliced,
-                    mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
+                    mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
+                    mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs,
+                    mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
         case DurationMetric_AggregationType_MAX_SPARSE:
             return make_unique<MaxDurationTracker>(
-                    mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
-                    mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
-                    mTimeBaseNs, mBucketSizeNs, mConditionSliced,
-                    mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
+                    mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
+                    mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs,
+                    mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
     }
 }
 
@@ -364,6 +401,13 @@
             writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInWhat(),
                                            FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
         }
+        // Then fill slice_by_state.
+        for (auto state : dimensionKey.getStateValuesKey().getValues()) {
+            uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                                     FIELD_ID_SLICE_BY_STATE);
+            writeStateToProto(state, protoOutput);
+            protoOutput->end(stateToken);
+        }
         // Then fill bucket_info (DurationBucketInfo).
         for (const auto& bucket : pair.second) {
             uint64_t bucketInfoToken = protoOutput->start(
@@ -460,7 +504,6 @@
                                               const ConditionKey& conditionKeys,
                                               bool condition, const LogEvent& event) {
     const auto& whatKey = eventKey.getDimensionKeyInWhat();
-
     auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatKey);
     if (whatIt == mCurrentSlicedDurationTrackerMap.end()) {
         if (hitGuardRailLocked(eventKey)) {
@@ -471,19 +514,18 @@
 
     auto it = mCurrentSlicedDurationTrackerMap.find(whatKey);
     if (mUseWhatDimensionAsInternalDimension) {
-        it->second->noteStart(whatKey, condition,
-                              event.GetElapsedTimestampNs(), conditionKeys);
+        it->second->noteStart(whatKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
         return;
     }
 
     if (mInternalDimensions.empty()) {
-        it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
-                              event.GetElapsedTimestampNs(), conditionKeys);
+        it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, event.GetElapsedTimestampNs(),
+                              conditionKeys);
     } else {
         HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY;
         filterValues(mInternalDimensions, event.getValues(), &dimensionKey);
-        it->second->noteStart(
-            dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
+        it->second->noteStart(dimensionKey, condition, event.GetElapsedTimestampNs(),
+                              conditionKeys);
     }
 
 }
@@ -519,6 +561,41 @@
         filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
     }
 
+    // Stores atom id to primary key pairs for each state atom that the metric is
+    // sliced by.
+    std::map<int, HashableDimensionKey> statePrimaryKeys;
+
+    // For states with primary fields, use MetricStateLinks to get the primary
+    // field values from the log event. These values will form a primary key
+    // that will be used to query StateTracker for the correct state value.
+    for (const auto& stateLink : mMetric2StateLinks) {
+        getDimensionForState(event.getValues(), stateLink,
+                             &statePrimaryKeys[stateLink.stateAtomId]);
+    }
+
+    // For each sliced state, query StateTracker for the state value using
+    // either the primary key from the previous step or the DEFAULT_DIMENSION_KEY.
+    //
+    // Expected functionality: for any case where the MetricStateLinks are
+    // initialized incorrectly (ex. # of state links != # of primary fields, no
+    // links are provided for a state with primary fields, links are provided
+    // in the wrong order, etc.), StateTracker will simply return kStateUnknown
+    // when queried using an incorrect key.
+    HashableDimensionKey stateValuesKey = DEFAULT_DIMENSION_KEY;
+    for (auto atomId : mSlicedStateAtoms) {
+        FieldValue value;
+        if (statePrimaryKeys.find(atomId) != statePrimaryKeys.end()) {
+            // found a primary key for this state, query using the key
+            queryStateValue(atomId, statePrimaryKeys[atomId], &value);
+        } else {
+            // if no MetricStateLinks exist for this state atom,
+            // query using the default dimension key (empty HashableDimensionKey)
+            queryStateValue(atomId, DEFAULT_DIMENSION_KEY, &value);
+        }
+        mapStateValue(atomId, &value);
+        stateValuesKey.addValue(value);
+    }
+
     // Handles Stop events.
     if (matcherIndex == mStopIndex) {
         if (mUseWhatDimensionAsInternalDimension) {
@@ -559,8 +636,8 @@
 
     condition = condition && mIsActive;
 
-    handleStartEvent(MetricDimensionKey(dimensionInWhat, DEFAULT_DIMENSION_KEY), conditionKey,
-                     condition, event);
+    handleStartEvent(MetricDimensionKey(dimensionInWhat, stateValuesKey), conditionKey, condition,
+                     event);
 }
 
 size_t DurationMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 06da0f6..cc48f99 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -54,6 +54,10 @@
     sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
                                          const sp<AlarmMonitor>& anomalyAlarmMonitor) override;
 
+    void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
+                        const HashableDimensionKey& primaryKey, const int32_t oldState,
+                        const int32_t newState) override;
+
 protected:
     void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;
 
@@ -137,7 +141,7 @@
 
     // Helper function to create a duration tracker given the metric aggregation type.
     std::unique_ptr<DurationTracker> createDurationTracker(
-        const MetricDimensionKey& eventKey) const;
+            const MetricDimensionKey& eventKey) const;
 
     // This hides the base class's std::vector<sp<AnomalyTracker>> mAnomalyTrackers
     std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index be754e2..2518d85 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -120,12 +120,13 @@
         FieldValue value;
         if (statePrimaryKeys.find(atomId) != statePrimaryKeys.end()) {
             // found a primary key for this state, query using the key
-            getMappedStateValue(atomId, statePrimaryKeys[atomId], &value);
+            queryStateValue(atomId, statePrimaryKeys[atomId], &value);
         } else {
             // if no MetricStateLinks exist for this state atom,
             // query using the default dimension key (empty HashableDimensionKey)
-            getMappedStateValue(atomId, DEFAULT_DIMENSION_KEY, &value);
+            queryStateValue(atomId, DEFAULT_DIMENSION_KEY, &value);
         }
+        mapStateValue(atomId, &value);
         stateValuesKey.addValue(value);
     }
 
@@ -264,15 +265,17 @@
     }
 }
 
-void MetricProducer::getMappedStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
-                                         FieldValue* value) {
+void MetricProducer::queryStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
+                                     FieldValue* value) {
     if (!StateManager::getInstance().getStateValue(atomId, queryKey, value)) {
         value->mValue = Value(StateTracker::kStateUnknown);
         value->mField.setTag(atomId);
         ALOGW("StateTracker not found for state atom %d", atomId);
         return;
     }
+}
 
+void MetricProducer::mapStateValue(const int32_t atomId, FieldValue* value) {
     // check if there is a state map for this atom
     auto atomIt = mStateGroupMap.find(atomId);
     if (atomIt == mStateGroupMap.end()) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 4c4cd89..4550e65 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -187,7 +187,8 @@
     };
 
     void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                        const HashableDimensionKey& primaryKey, int oldState, int newState){};
+                        const HashableDimensionKey& primaryKey, const int32_t oldState,
+                        const int32_t newState){};
 
     // Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
     // This method clears all the past buckets.
@@ -379,11 +380,15 @@
         return (endNs - mTimeBaseNs) / mBucketSizeNs - 1;
     }
 
-    // Query StateManager for original state value.
-    // If no state map exists for this atom, return the original value.
-    // Otherwise, return the group_id mapped to the atom and original value.
-    void getMappedStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
-                             FieldValue* value);
+    // Query StateManager for original state value using the queryKey.
+    // The field and value are output.
+    void queryStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
+                         FieldValue* value);
+
+    // If a state map exists for the given atom, replace the original state
+    // value with the group id mapped to the value.
+    // If no state map exists, keep the original state value.
+    void mapStateValue(const int32_t atomId, FieldValue* value);
 
     DropEvent buildDropEvent(const int64_t dropTimeNs, const BucketDropReason reason);
 
@@ -467,6 +472,11 @@
     FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedState);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStateMapped);
+    FRIEND_TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
 
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 3fb9166..1fd6572 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -329,6 +329,11 @@
     FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedState);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStateMapped);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSuperset);
+    FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
 
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index afe93d4..8d59d13 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -56,11 +56,19 @@
     int64_t mDuration;
 };
 
+struct DurationValues {
+    // Recorded duration for current partial bucket.
+    int64_t mDuration;
+
+    // Sum of past partial bucket durations in current full bucket.
+    // Used for anomaly detection.
+    int64_t mDurationFullBucket;
+};
+
 class DurationTracker {
 public:
     DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
-                    sp<ConditionWizard> wizard, int conditionIndex,
-                    bool nesting,
+                    sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
                     int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs,
                     int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
                     const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
@@ -73,7 +81,6 @@
           mNested(nesting),
           mCurrentBucketStartTimeNs(currentBucketStartNs),
           mDuration(0),
-          mDurationFullBucket(0),
           mCurrentBucketNum(currentBucketNum),
           mStartTimeNs(startTimeNs),
           mConditionSliced(conditionSliced),
@@ -82,8 +89,8 @@
 
     virtual ~DurationTracker(){};
 
-    virtual void noteStart(const HashableDimensionKey& key, bool condition,
-                           const int64_t eventTime, const ConditionKey& conditionKey) = 0;
+    virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
+                           const ConditionKey& conditionKey) = 0;
     virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
                           const bool stopAll) = 0;
     virtual void noteStopAll(const int64_t eventTime) = 0;
@@ -91,6 +98,9 @@
     virtual void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) = 0;
     virtual void onConditionChanged(bool condition, const int64_t timestamp) = 0;
 
+    virtual void onStateChanged(const int64_t timestamp, const int32_t atomId,
+                                const FieldValue& newState) = 0;
+
     // Flush stale buckets if needed, and return true if the tracker has no on-going duration
     // events, so that the owner can safely remove the tracker.
     virtual bool flushIfNeeded(
@@ -109,9 +119,12 @@
     // Dump internal states for debugging
     virtual void dumpStates(FILE* out, bool verbose) const = 0;
 
-    void setEventKey(const MetricDimensionKey& eventKey) {
-         mEventKey = eventKey;
-    }
+    virtual int64_t getCurrentStateKeyDuration() const = 0;
+
+    virtual int64_t getCurrentStateKeyFullBucketDuration() const = 0;
+
+    // Replace old value with new value for the given state atom.
+    virtual void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState) = 0;
 
 protected:
     int64_t getCurrentBucketEndTimeNs() const {
@@ -140,10 +153,11 @@
         }
     }
 
-    void addPastBucketToAnomalyTrackers(const int64_t& bucketValue, const int64_t& bucketNum) {
+    void addPastBucketToAnomalyTrackers(const MetricDimensionKey eventKey,
+                                        const int64_t& bucketValue, const int64_t& bucketNum) {
         for (auto& anomalyTracker : mAnomalyTrackers) {
             if (anomalyTracker != nullptr) {
-                anomalyTracker->addPastBucket(mEventKey, bucketValue, bucketNum);
+                anomalyTracker->addPastBucket(eventKey, bucketValue, bucketNum);
             }
         }
     }
@@ -164,6 +178,10 @@
         return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
     }
 
+    void setEventKey(const MetricDimensionKey& eventKey) {
+        mEventKey = eventKey;
+    }
+
     // A reference to the DurationMetricProducer's config key.
     const ConfigKey& mConfigKey;
 
@@ -183,7 +201,8 @@
 
     int64_t mDuration;  // current recorded duration result (for partial bucket)
 
-    int64_t mDurationFullBucket;  // Sum of past partial buckets in current full bucket.
+    // Recorded duration results for each state key in the current partial bucket.
+    std::unordered_map<HashableDimensionKey, DurationValues> mStateKeyDurationMap;
 
     int64_t mCurrentBucketNum;
 
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 2be5855..ee4e167 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -26,15 +26,14 @@
 
 MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id,
                                        const MetricDimensionKey& eventKey,
-                                       sp<ConditionWizard> wizard, int conditionIndex,
-                                       bool nesting,
+                                       sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
                                        int64_t currentBucketStartNs, int64_t currentBucketNum,
                                        int64_t startTimeNs, int64_t bucketSizeNs,
                                        bool conditionSliced, bool fullLink,
                                        const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
-    : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting,
-                      currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
-                      conditionSliced, fullLink, anomalyTrackers) {
+    : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
+                      currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink,
+                      anomalyTrackers) {
 }
 
 bool MaxDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) {
@@ -91,7 +90,6 @@
     }
 }
 
-
 void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const int64_t eventTime,
                                   bool forceStop) {
     VLOG("MaxDuration: key %s stop", key.toString().c_str());
@@ -240,6 +238,11 @@
     }
 }
 
+void MaxDurationTracker::onStateChanged(const int64_t timestamp, const int32_t atomId,
+                                        const FieldValue& newState) {
+    ALOGE("MaxDurationTracker does not handle sliced state changes.");
+}
+
 void MaxDurationTracker::onConditionChanged(bool condition, const int64_t timestamp) {
     for (auto& pair : mInfos) {
         noteConditionChanged(pair.first, condition, timestamp);
@@ -309,6 +312,20 @@
     fprintf(out, "\t\t current duration %lld\n", (long long)mDuration);
 }
 
+int64_t MaxDurationTracker::getCurrentStateKeyDuration() const {
+    ALOGE("MaxDurationTracker does not handle sliced state changes.");
+    return -1;
+}
+
+int64_t MaxDurationTracker::getCurrentStateKeyFullBucketDuration() const {
+    ALOGE("MaxDurationTracker does not handle sliced state changes.");
+    return -1;
+}
+
+void MaxDurationTracker::updateCurrentStateKey(const int32_t atomId, const FieldValue& newState) {
+    ALOGE("MaxDurationTracker does not handle sliced state changes.");
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index efb8dc7..2891c6e 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -54,10 +54,19 @@
     void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) override;
     void onConditionChanged(bool condition, const int64_t timestamp) override;
 
+    void onStateChanged(const int64_t timestamp, const int32_t atomId,
+                        const FieldValue& newState) override;
+
     int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
                                       const int64_t currentTimestamp) const override;
     void dumpStates(FILE* out, bool verbose) const override;
 
+    int64_t getCurrentStateKeyDuration() const override;
+
+    int64_t getCurrentStateKeyFullBucketDuration() const override;
+
+    void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState);
+
 private:
     // Returns true if at least one of the mInfos is started.
     bool anyStarted();
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 57f3965..19b2fe8 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -26,13 +26,12 @@
 
 OringDurationTracker::OringDurationTracker(
         const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
-        sp<ConditionWizard> wizard, int conditionIndex,
-        bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum,
-        int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
-        const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
-    : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting,
-                      currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
-                      conditionSliced, fullLink, anomalyTrackers),
+        sp<ConditionWizard> wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs,
+        int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
+        bool fullLink, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+    : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
+                      currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink,
+                      anomalyTrackers),
       mStarted(),
       mPaused() {
     mLastStartTime = 0;
@@ -90,10 +89,14 @@
             mConditionKeyMap.erase(key);
         }
         if (mStarted.empty()) {
-            mDuration += (timestamp - mLastStartTime);
-            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
-            VLOG("record duration %lld, total %lld ", (long long)timestamp - mLastStartTime,
-                 (long long)mDuration);
+            mStateKeyDurationMap[mEventKey.getStateValuesKey()].mDuration +=
+                    (timestamp - mLastStartTime);
+            detectAndDeclareAnomaly(
+                    timestamp, mCurrentBucketNum,
+                    getCurrentStateKeyDuration() + getCurrentStateKeyFullBucketDuration());
+            VLOG("record duration %lld, total duration %lld for state key %s",
+                 (long long)timestamp - mLastStartTime, (long long)getCurrentStateKeyDuration(),
+                 mEventKey.getStateValuesKey().toString().c_str());
         }
     }
 
@@ -112,10 +115,14 @@
 
 void OringDurationTracker::noteStopAll(const int64_t timestamp) {
     if (!mStarted.empty()) {
-        mDuration += (timestamp - mLastStartTime);
-        VLOG("Oring Stop all: record duration %lld %lld ", (long long)timestamp - mLastStartTime,
-             (long long)mDuration);
-        detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
+        mStateKeyDurationMap[mEventKey.getStateValuesKey()].mDuration +=
+                (timestamp - mLastStartTime);
+        VLOG("Oring Stop all: record duration %lld, total duration %lld for state key %s",
+             (long long)timestamp - mLastStartTime, (long long)getCurrentStateKeyDuration(),
+             mEventKey.getStateValuesKey().toString().c_str());
+        detectAndDeclareAnomaly(
+                timestamp, mCurrentBucketNum,
+                getCurrentStateKeyDuration() + getCurrentStateKeyFullBucketDuration());
     }
 
     stopAnomalyAlarm(timestamp);
@@ -146,21 +153,36 @@
 
     // Process the current bucket.
     if (mStarted.size() > 0) {
-        mDuration += (currentBucketEndTimeNs - mLastStartTime);
+        // Calculate the duration for the current state key.
+        mStateKeyDurationMap[mEventKey.getStateValuesKey()].mDuration +=
+                (currentBucketEndTimeNs - mLastStartTime);
     }
-    if (mDuration > 0) {
-        DurationBucket current_info;
-        current_info.mBucketStartNs = mCurrentBucketStartTimeNs;
-        current_info.mBucketEndNs = currentBucketEndTimeNs;
-        current_info.mDuration = mDuration;
-        (*output)[mEventKey].push_back(current_info);
-        mDurationFullBucket += mDuration;
-        VLOG("  duration: %lld", (long long)current_info.mDuration);
-    }
-    if (eventTimeNs > fullBucketEnd) {
-        // End of full bucket, can send to anomaly tracker now.
-        addPastBucketToAnomalyTrackers(mDurationFullBucket, mCurrentBucketNum);
-        mDurationFullBucket = 0;
+    // Store DurationBucket info for each whatKey, stateKey pair.
+    // Note: The whatKey stored in mEventKey is constant for each DurationTracker, while the
+    // stateKey stored in mEventKey is only the current stateKey. mStateKeyDurationMap is used to
+    // store durations for each stateKey, so we need to flush the bucket by creating a
+    // DurationBucket for each stateKey.
+    for (auto& durationIt : mStateKeyDurationMap) {
+        if (durationIt.second.mDuration > 0) {
+            DurationBucket current_info;
+            current_info.mBucketStartNs = mCurrentBucketStartTimeNs;
+            current_info.mBucketEndNs = currentBucketEndTimeNs;
+            current_info.mDuration = durationIt.second.mDuration;
+            (*output)[MetricDimensionKey(mEventKey.getDimensionKeyInWhat(), durationIt.first)]
+                    .push_back(current_info);
+
+            durationIt.second.mDurationFullBucket += durationIt.second.mDuration;
+            VLOG("  duration: %lld", (long long)current_info.mDuration);
+        }
+
+        if (eventTimeNs > fullBucketEnd) {
+            // End of full bucket, can send to anomaly tracker now.
+            addPastBucketToAnomalyTrackers(
+                    MetricDimensionKey(mEventKey.getDimensionKeyInWhat(), durationIt.first),
+                    getCurrentStateKeyFullBucketDuration(), mCurrentBucketNum);
+            durationIt.second.mDurationFullBucket = 0;
+        }
+        durationIt.second.mDuration = 0;
     }
 
     if (mStarted.size() > 0) {
@@ -169,20 +191,19 @@
             info.mBucketStartNs = fullBucketEnd + mBucketSizeNs * (i - 1);
             info.mBucketEndNs = info.mBucketStartNs + mBucketSizeNs;
             info.mDuration = mBucketSizeNs;
+            // Full duration buckets are attributed to the current stateKey.
             (*output)[mEventKey].push_back(info);
             // Safe to send these buckets to anomaly tracker since they must be full buckets.
             // If it's a partial bucket, numBucketsForward would be 0.
-            addPastBucketToAnomalyTrackers(info.mDuration, mCurrentBucketNum + i);
+            addPastBucketToAnomalyTrackers(mEventKey, info.mDuration, mCurrentBucketNum + i);
             VLOG("  add filling bucket with duration %lld", (long long)info.mDuration);
         }
     } else {
         if (numBucketsForward >= 2) {
-            addPastBucketToAnomalyTrackers(0, mCurrentBucketNum + numBucketsForward - 1);
+            addPastBucketToAnomalyTrackers(mEventKey, 0, mCurrentBucketNum + numBucketsForward - 1);
         }
     }
 
-    mDuration = 0;
-
     if (numBucketsForward > 0) {
         mCurrentBucketStartTimeNs = fullBucketEnd + (numBucketsForward - 1) * mBucketSizeNs;
         mCurrentBucketNum += numBucketsForward;
@@ -229,10 +250,14 @@
         }
 
         if (mStarted.empty()) {
-            mDuration += (timestamp - mLastStartTime);
-            VLOG("Duration add %lld , to %lld ", (long long)(timestamp - mLastStartTime),
-                 (long long)mDuration);
-            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
+            mStateKeyDurationMap[mEventKey.getStateValuesKey()].mDuration +=
+                    (timestamp - mLastStartTime);
+            VLOG("record duration %lld, total duration %lld for state key %s",
+                 (long long)(timestamp - mLastStartTime), (long long)getCurrentStateKeyDuration(),
+                 mEventKey.getStateValuesKey().toString().c_str());
+            detectAndDeclareAnomaly(
+                    timestamp, mCurrentBucketNum,
+                    getCurrentStateKeyDuration() + getCurrentStateKeyFullBucketDuration());
         }
     }
 
@@ -288,10 +313,13 @@
     } else {
         if (!mStarted.empty()) {
             VLOG("Condition false, all paused");
-            mDuration += (timestamp - mLastStartTime);
+            mStateKeyDurationMap[mEventKey.getStateValuesKey()].mDuration +=
+                    (timestamp - mLastStartTime);
             mPaused.insert(mStarted.begin(), mStarted.end());
             mStarted.clear();
-            detectAndDeclareAnomaly(timestamp, mCurrentBucketNum, mDuration + mDurationFullBucket);
+            detectAndDeclareAnomaly(
+                    timestamp, mCurrentBucketNum,
+                    getCurrentStateKeyDuration() + getCurrentStateKeyFullBucketDuration());
         }
     }
     if (mStarted.empty()) {
@@ -299,6 +327,20 @@
     }
 }
 
+void OringDurationTracker::onStateChanged(const int64_t timestamp, const int32_t atomId,
+                                          const FieldValue& newState) {
+    // If no keys are being tracked, update the current state key and return.
+    if (mStarted.empty()) {
+        updateCurrentStateKey(atomId, newState);
+        return;
+    }
+    // Add the current duration length to the previous state key and then update
+    // the last start time and current state key.
+    mStateKeyDurationMap[mEventKey.getStateValuesKey()].mDuration += (timestamp - mLastStartTime);
+    mLastStartTime = timestamp;
+    updateCurrentStateKey(atomId, newState);
+}
+
 int64_t OringDurationTracker::predictAnomalyTimestampNs(
         const DurationAnomalyTracker& anomalyTracker, const int64_t eventTimestampNs) const {
 
@@ -308,12 +350,13 @@
     // The timestamp of the current bucket end.
     const int64_t currentBucketEndNs = getCurrentBucketEndTimeNs();
 
-    // The past duration ns for the current bucket.
-    int64_t currentBucketPastNs = mDuration + mDurationFullBucket;
+    // The past duration ns for the current bucket of the current stateKey.
+    int64_t currentStateBucketPastNs =
+            getCurrentStateKeyDuration() + getCurrentStateKeyFullBucketDuration();
 
     // As we move into the future, old buckets get overwritten (so their old data is erased).
     // Sum of past durations. Will change as we overwrite old buckets.
-    int64_t pastNs = currentBucketPastNs + anomalyTracker.getSumOverPastBuckets(mEventKey);
+    int64_t pastNs = currentStateBucketPastNs + anomalyTracker.getSumOverPastBuckets(mEventKey);
 
     // The refractory period end timestamp for dimension mEventKey.
     const int64_t refractoryPeriodEndNs =
@@ -372,7 +415,7 @@
                     mEventKey,
                     mCurrentBucketNum - anomalyTracker.getNumOfPastBuckets() + futureBucketIdx);
         } else if (futureBucketIdx == anomalyTracker.getNumOfPastBuckets()) {
-            pastNs -= (currentBucketPastNs + (currentBucketEndNs - eventTimestampNs));
+            pastNs -= (currentStateBucketPastNs + (currentBucketEndNs - eventTimestampNs));
         }
     }
 
@@ -382,7 +425,34 @@
 void OringDurationTracker::dumpStates(FILE* out, bool verbose) const {
     fprintf(out, "\t\t started count %lu\n", (unsigned long)mStarted.size());
     fprintf(out, "\t\t paused count %lu\n", (unsigned long)mPaused.size());
-    fprintf(out, "\t\t current duration %lld\n", (long long)mDuration);
+    fprintf(out, "\t\t current duration %lld\n", (long long)getCurrentStateKeyDuration());
+}
+
+int64_t OringDurationTracker::getCurrentStateKeyDuration() const {
+    auto it = mStateKeyDurationMap.find(mEventKey.getStateValuesKey());
+    if (it == mStateKeyDurationMap.end()) {
+        return 0;
+    } else {
+        return it->second.mDuration;
+    }
+}
+
+int64_t OringDurationTracker::getCurrentStateKeyFullBucketDuration() const {
+    auto it = mStateKeyDurationMap.find(mEventKey.getStateValuesKey());
+    if (it == mStateKeyDurationMap.end()) {
+        return 0;
+    } else {
+        return it->second.mDurationFullBucket;
+    }
+}
+
+void OringDurationTracker::updateCurrentStateKey(const int32_t atomId, const FieldValue& newState) {
+    HashableDimensionKey* stateValuesKey = mEventKey.getMutableStateValuesKey();
+    for (size_t i = 0; i < stateValuesKey->getValues().size(); i++) {
+        if (stateValuesKey->getValues()[i].mField.getTag() == atomId) {
+            stateValuesKey->mutableValue(i)->mValue = newState.mValue;
+        }
+    }
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index f44e327..bd8017a 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -28,10 +28,9 @@
 public:
     OringDurationTracker(const ConfigKey& key, const int64_t& id,
                          const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard,
-                         int conditionIndex,
-                         bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum,
-                         int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
-                         bool fullLink,
+                         int conditionIndex, bool nesting, int64_t currentBucketStartNs,
+                         int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs,
+                         bool conditionSliced, bool fullLink,
                          const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
 
     OringDurationTracker(const OringDurationTracker& tracker) = default;
@@ -45,6 +44,9 @@
     void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) override;
     void onConditionChanged(bool condition, const int64_t timestamp) override;
 
+    void onStateChanged(const int64_t timestamp, const int32_t atomId,
+                        const FieldValue& newState) override;
+
     bool flushCurrentBucket(
             const int64_t& eventTimeNs,
             std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
@@ -56,6 +58,12 @@
                                       const int64_t currentTimestamp) const override;
     void dumpStates(FILE* out, bool verbose) const override;
 
+    int64_t getCurrentStateKeyDuration() const override;
+
+    int64_t getCurrentStateKeyFullBucketDuration() const override;
+
+    void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState);
+
 private:
     // We don't need to keep track of individual durations. The information that's needed is:
     // 1) which keys are started. We record the first start time.
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 3810c48..2fcb13b 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -26,7 +26,6 @@
 #include "MetricProducer.h"
 #include "condition/CombinationConditionTracker.h"
 #include "condition/SimpleConditionTracker.h"
-#include "condition/StateConditionTracker.h"
 #include "external/StatsPullerManager.h"
 #include "matchers/CombinationLogMatchingTracker.h"
 #include "matchers/EventMatcherWizard.h"
@@ -283,49 +282,6 @@
     return true;
 }
 
-/**
- * A StateConditionTracker is built from a SimplePredicate which has only "start", and no "stop"
- * or "stop_all". The start must be an atom matcher that matches a state atom. It must
- * have dimension, the dimension must be the state atom's primary fields plus exclusive state
- * field. For example, the StateConditionTracker is used in tracking UidProcessState and ScreenState.
- *
- */
-bool isStateConditionTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) {
-    // 1. must not have "stop". must have "dimension"
-    if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) {
-        auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(
-                simplePredicate.dimensions().field());
-        // 2. must be based on a state atom.
-        if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
-            // 3. dimension must be primary fields + state field IN ORDER
-            size_t expectedDimensionCount = it->second.primaryFields.size() + 1;
-            vector<Matcher> dimensions;
-            translateFieldMatcher(simplePredicate.dimensions(), &dimensions);
-            if (dimensions.size() != expectedDimensionCount) {
-                return false;
-            }
-            // 3.1 check the primary fields first.
-            size_t index = 0;
-            for (const auto& field : it->second.primaryFields) {
-                Matcher matcher = getSimpleMatcher(it->first, field);
-                if (!(matcher == dimensions[index])) {
-                    return false;
-                }
-                primaryKeys->push_back(matcher);
-                index++;
-            }
-            Matcher stateFieldMatcher =
-                    getSimpleMatcher(it->first, it->second.exclusiveField);
-            // 3.2 last dimension should be the exclusive field.
-            if (!(dimensions.back() == stateFieldMatcher)) {
-                return false;
-            }
-            return true;
-        }
-    }
-    return false;
-}  // namespace statsd
-
 bool initConditions(const ConfigKey& key, const StatsdConfig& config,
                     const unordered_map<int64_t, int>& logTrackerMap,
                     unordered_map<int64_t, int>& conditionTrackerMap,
@@ -341,16 +297,8 @@
         int index = allConditionTrackers.size();
         switch (condition.contents_case()) {
             case Predicate::ContentsCase::kSimplePredicate: {
-                vector<Matcher> primaryKeys;
-                if (isStateConditionTracker(condition.simple_predicate(), &primaryKeys)) {
-                    allConditionTrackers.push_back(new StateConditionTracker(key, condition.id(), index,
-                                                                    condition.simple_predicate(),
-                                                                    logTrackerMap, primaryKeys));
-                } else {
-                    allConditionTrackers.push_back(new SimpleConditionTracker(
-                            key, condition.id(), index, condition.simple_predicate(),
-                            logTrackerMap));
-                }
+                allConditionTrackers.push_back(new SimpleConditionTracker(
+                        key, condition.id(), index, condition.simple_predicate(), logTrackerMap));
                 break;
             }
             case Predicate::ContentsCase::kCombination: {
@@ -564,6 +512,33 @@
             }
         }
 
+        std::vector<int> slicedStateAtoms;
+        unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+        if (metric.slice_by_state_size() > 0) {
+            if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
+                ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
+                return false;
+            }
+            if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+                return false;
+            }
+        } else {
+            if (metric.state_link_size() > 0) {
+                ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
+                return false;
+            }
+        }
+
+        // Check that all metric state links are a subset of dimensions_in_what fields.
+        std::vector<Matcher> dimensionsInWhat;
+        translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+        for (const auto& stateLink : metric.state_link()) {
+            if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+                return false;
+            }
+        }
+
         unordered_map<int, shared_ptr<Activation>> eventActivationMap;
         unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
         bool success = handleMetricActivation(config, metric.id(), metricIndex,
@@ -575,7 +550,8 @@
         sp<MetricProducer> durationMetric = new DurationMetricProducer(
                 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
                 trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs,
-                currentTimeNs, eventActivationMap, eventDeactivationMap);
+                currentTimeNs, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+                stateGroupMap);
 
         allMetricProducers.push_back(durationMetric);
     }
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index a8ccc62..6af7a9a 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -132,8 +132,6 @@
                       vector<int>& metricsWithActivation,
                       std::set<int64_t>& noReportMetricIds);
 
-bool isStateConditionTracker(const SimplePredicate& simplePredicate, std::vector<Matcher>* primaryKeys);
-
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index 1cee4d9..bed836a 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -152,7 +152,6 @@
                 mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, &data);
                 VLOG("pulled %zu atoms with id %d", data.size(), pullInfo.mPullerMatcher.atom_id());
 
-                // TODO(b/150969574): Don't write to a pipe while holding a lock.
                 if (!writePulledAtomsLocked(data, pullInfo.mPullerMatcher)) {
                     mSubscriptionInfo->mClientAlive = false;
                     mSubscriptionShouldEnd.notify_one();
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index c45274e..ed98f50 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -103,12 +103,14 @@
 message DurationMetricData {
   optional DimensionsValue dimensions_in_what = 1;
 
-  optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+  repeated StateValue slice_by_state = 6;
 
   repeated DurationBucketInfo bucket_info = 3;
 
   repeated DimensionsValue dimension_leaf_values_in_what = 4;
 
+  optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+
   repeated DimensionsValue dimension_leaf_values_in_condition = 5 [deprecated = true];
 }
 
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 83d9484..c7407bd 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -227,8 +227,12 @@
 
   optional int64 condition = 3;
 
+  repeated int64 slice_by_state = 9;
+
   repeated MetricConditionLink links = 4;
 
+  repeated MetricStateLink state_link = 10;
+
   enum AggregationType {
     SUM = 1;
 
@@ -238,9 +242,9 @@
 
   optional FieldMatcher dimensions_in_what = 6;
 
-  optional FieldMatcher dimensions_in_condition = 8 [deprecated = true];
-
   optional TimeUnit bucket = 7;
+
+  optional FieldMatcher dimensions_in_condition = 8 [deprecated = true];
 }
 
 message GaugeMetric {
diff --git a/cmds/statsd/tests/HashableDimensionKey_test.cpp b/cmds/statsd/tests/HashableDimensionKey_test.cpp
new file mode 100644
index 0000000..29adcd0
--- /dev/null
+++ b/cmds/statsd/tests/HashableDimensionKey_test.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "src/HashableDimensionKey.h"
+
+#include <gtest/gtest.h>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "statsd_test_util.h"
+
+#ifdef __ANDROID__
+
+using android::util::ProtoReader;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Test that #containsLinkedStateValues returns false when the whatKey is
+ * smaller than the primaryKey.
+ */
+TEST(HashableDimensionKeyTest, TestContainsLinkedStateValues_WhatKeyTooSmall) {
+    std::vector<Metric2State> mMetric2StateLinks;
+
+    int32_t uid1 = 1000;
+    HashableDimensionKey whatKey = DEFAULT_DIMENSION_KEY;
+    HashableDimensionKey primaryKey;
+    getUidProcessKey(uid1, &primaryKey);
+
+    EXPECT_FALSE(containsLinkedStateValues(whatKey, primaryKey, mMetric2StateLinks,
+                                           UID_PROCESS_STATE_ATOM_ID));
+}
+
+/**
+ * Test that #containsLinkedStateValues returns false when the linked values
+ * are not equal.
+ */
+TEST(HashableDimensionKeyTest, TestContainsLinkedStateValues_UnequalLinkedValues) {
+    int stateAtomId = UID_PROCESS_STATE_ATOM_ID;
+
+    FieldMatcher whatMatcher;
+    whatMatcher.set_field(util::OVERLAY_STATE_CHANGED);
+    FieldMatcher* child11 = whatMatcher.add_child();
+    child11->set_field(1);
+
+    FieldMatcher stateMatcher;
+    stateMatcher.set_field(stateAtomId);
+    FieldMatcher* child21 = stateMatcher.add_child();
+    child21->set_field(1);
+
+    std::vector<Metric2State> mMetric2StateLinks;
+    Metric2State ms;
+    ms.stateAtomId = stateAtomId;
+    translateFieldMatcher(whatMatcher, &ms.metricFields);
+    translateFieldMatcher(stateMatcher, &ms.stateFields);
+    mMetric2StateLinks.push_back(ms);
+
+    int32_t uid1 = 1000;
+    int32_t uid2 = 1001;
+    HashableDimensionKey whatKey;
+    getOverlayKey(uid2, "package", &whatKey);
+    HashableDimensionKey primaryKey;
+    getUidProcessKey(uid1, &primaryKey);
+
+    EXPECT_FALSE(containsLinkedStateValues(whatKey, primaryKey, mMetric2StateLinks, stateAtomId));
+}
+
+/**
+ * Test that #containsLinkedStateValues returns false when there is no link
+ * between the key values.
+ */
+TEST(HashableDimensionKeyTest, TestContainsLinkedStateValues_MissingMetric2StateLinks) {
+    int stateAtomId = UID_PROCESS_STATE_ATOM_ID;
+
+    std::vector<Metric2State> mMetric2StateLinks;
+
+    int32_t uid1 = 1000;
+    HashableDimensionKey whatKey;
+    getOverlayKey(uid1, "package", &whatKey);
+    HashableDimensionKey primaryKey;
+    getUidProcessKey(uid1, &primaryKey);
+
+    EXPECT_FALSE(containsLinkedStateValues(whatKey, primaryKey, mMetric2StateLinks, stateAtomId));
+}
+
+/**
+ * Test that #containsLinkedStateValues returns true when the key values are
+ * linked and equal.
+ */
+TEST(HashableDimensionKeyTest, TestContainsLinkedStateValues_AllConditionsMet) {
+    int stateAtomId = UID_PROCESS_STATE_ATOM_ID;
+
+    FieldMatcher whatMatcher;
+    whatMatcher.set_field(util::OVERLAY_STATE_CHANGED);
+    FieldMatcher* child11 = whatMatcher.add_child();
+    child11->set_field(1);
+
+    FieldMatcher stateMatcher;
+    stateMatcher.set_field(stateAtomId);
+    FieldMatcher* child21 = stateMatcher.add_child();
+    child21->set_field(1);
+
+    std::vector<Metric2State> mMetric2StateLinks;
+    Metric2State ms;
+    ms.stateAtomId = stateAtomId;
+    translateFieldMatcher(whatMatcher, &ms.metricFields);
+    translateFieldMatcher(stateMatcher, &ms.stateFields);
+    mMetric2StateLinks.push_back(ms);
+
+    int32_t uid1 = 1000;
+    HashableDimensionKey whatKey;
+    getOverlayKey(uid1, "package", &whatKey);
+    HashableDimensionKey primaryKey;
+    getUidProcessKey(uid1, &primaryKey);
+
+    EXPECT_TRUE(containsLinkedStateValues(whatKey, primaryKey, mMetric2StateLinks, stateAtomId));
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 7458cbf..bb4578d 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -13,12 +13,13 @@
 // limitations under the License.
 
 #include "src/logd/LogEvent.h"
+
 #include <gtest/gtest.h>
-#include <log/log_event_list.h>
+
 #include "frameworks/base/cmds/statsd/src/atoms.pb.h"
 #include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
-#include <stats_event.h>
-
+#include "log/log_event_list.h"
+#include "stats_event.h"
 
 #ifdef __ANDROID__
 
@@ -31,6 +32,8 @@
 using util::ProtoOutputStream;
 using util::ProtoReader;
 
+namespace {
+
 Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
     Field f(tag, (int32_t*)pos.data(), depth);
 
@@ -42,6 +45,38 @@
     return f;
 }
 
+void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
+                                         bool annotationValue) {
+    AStatsEvent* statsEvent = AStatsEvent_obtain();
+    AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
+    AStatsEvent_writeInt32(statsEvent, 10);
+    AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
+    AStatsEvent_build(statsEvent);
+
+    size_t size;
+    uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+    EXPECT_TRUE(logEvent->parseBuffer(buf, size));
+
+    AStatsEvent_release(statsEvent);
+}
+
+void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
+                                        int annotationValue) {
+    AStatsEvent* statsEvent = AStatsEvent_obtain();
+    AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
+    AStatsEvent_writeInt32(statsEvent, 10);
+    AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
+    AStatsEvent_build(statsEvent);
+
+    size_t size;
+    uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+    EXPECT_TRUE(logEvent->parseBuffer(buf, size));
+
+    AStatsEvent_release(statsEvent);
+}
+
+}  // anonymous namespace
+
 TEST(LogEventTest, TestPrimitiveParsing) {
     AStatsEvent* event = AStatsEvent_obtain();
     AStatsEvent_setAtomId(event, 100);
@@ -85,13 +120,12 @@
     const FieldValue& boolItem = values[3];
     expectedField = getField(100, {4, 1, 1}, 0, {true, false, false});
     EXPECT_EQ(expectedField, boolItem.mField);
-    EXPECT_EQ(Type::INT, boolItem.mValue.getType()); // FieldValue does not support boolean type
+    EXPECT_EQ(Type::INT, boolItem.mValue.getType());  // FieldValue does not support boolean type
     EXPECT_EQ(1, boolItem.mValue.int_value);
 
     AStatsEvent_release(event);
 }
 
-
 TEST(LogEventTest, TestStringAndByteArrayParsing) {
     AStatsEvent* event = AStatsEvent_obtain();
     AStatsEvent_setAtomId(event, 100);
@@ -103,7 +137,7 @@
     size_t size;
     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
 
-    LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+    LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
 
     EXPECT_EQ(100, logEvent.GetTagId());
@@ -139,7 +173,7 @@
     size_t size;
     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
 
-    LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+    LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
 
     EXPECT_EQ(100, logEvent.GetTagId());
@@ -168,7 +202,7 @@
     size_t size;
     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
 
-    LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+    LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
 
     EXPECT_EQ(100, logEvent.GetTagId());
@@ -204,7 +238,7 @@
     size_t size;
     uint8_t* buf = AStatsEvent_getBuffer(event, &size);
 
-    LogEvent logEvent(/*uid=*/ 1000, /*pid=*/ 1001);
+    LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
     EXPECT_TRUE(logEvent.parseBuffer(buf, size));
 
     EXPECT_EQ(100, logEvent.GetTagId());
@@ -212,7 +246,7 @@
     EXPECT_EQ(1001, logEvent.GetPid());
 
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(4, values.size()); // 2 per attribution node
+    EXPECT_EQ(4, values.size());  // 2 per attribution node
 
     // Check first attribution node
     const FieldValue& uid1Item = values[0];
@@ -243,6 +277,84 @@
     AStatsEvent_release(event);
 }
 
+TEST(LogEventTest, TestAnnotationIdIsUid) {
+    LogEvent event(/*uid=*/0, /*pid=*/0);
+    createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
+
+    const vector<FieldValue>& values = event.getValues();
+    EXPECT_EQ(values.size(), 1);
+    EXPECT_EQ(event.getUidFieldIndex(), 0);
+}
+
+TEST(LogEventTest, TestAnnotationIdStateNested) {
+    LogEvent event(/*uid=*/0, /*pid=*/0);
+    createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_STATE_NESTED, true);
+
+    const vector<FieldValue>& values = event.getValues();
+    EXPECT_EQ(values.size(), 1);
+    EXPECT_TRUE(values[0].mAnnotations.isNested());
+}
+
+TEST(LogEventTest, TestPrimaryFieldAnnotation) {
+    LogEvent event(/*uid=*/0, /*pid=*/0);
+    createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true);
+
+    const vector<FieldValue>& values = event.getValues();
+    EXPECT_EQ(values.size(), 1);
+    EXPECT_TRUE(values[0].mAnnotations.isPrimaryField());
+}
+
+TEST(LogEventTest, TestExclusiveStateAnnotation) {
+    LogEvent event(/*uid=*/0, /*pid=*/0);
+    createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
+
+    const vector<FieldValue>& values = event.getValues();
+    EXPECT_EQ(values.size(), 1);
+    EXPECT_TRUE(values[0].mAnnotations.isExclusiveState());
+}
+
+TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
+    // Event has 10 ints and then an attribution chain
+    int numInts = 10;
+    int firstUidInChainIndex = numInts;
+    string tag1 = "tag1";
+    string tag2 = "tag2";
+    uint32_t uids[] = {1001, 1002};
+    const char* tags[] = {tag1.c_str(), tag2.c_str()};
+
+    // Construct AStatsEvent
+    AStatsEvent* statsEvent = AStatsEvent_obtain();
+    AStatsEvent_setAtomId(statsEvent, 100);
+    for (int i = 0; i < numInts; i++) {
+        AStatsEvent_writeInt32(statsEvent, 10);
+    }
+    AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
+    AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
+    AStatsEvent_build(statsEvent);
+
+    // Construct LogEvent
+    size_t size;
+    uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+    LogEvent logEvent(/*uid=*/0, /*pid=*/0);
+    EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+    AStatsEvent_release(statsEvent);
+
+    // Check annotation
+    const vector<FieldValue>& values = logEvent.getValues();
+    EXPECT_EQ(values.size(), numInts + 4);
+    EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField());
+}
+
+TEST(LogEventTest, TestResetStateAnnotation) {
+    int32_t resetState = 10;
+    LogEvent event(/*uid=*/0, /*pid=*/0);
+    createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState);
+
+    const vector<FieldValue>& values = event.getValues();
+    EXPECT_EQ(values.size(), 1);
+    EXPECT_EQ(values[0].mAnnotations.getResetState(), resetState);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/condition/StateConditionTracker_test.cpp b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
deleted file mode 100644
index 86b50ae8..0000000
--- a/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
+++ /dev/null
@@ -1,113 +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 "src/condition/StateConditionTracker.h"
-#include "tests/statsd_test_util.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <stdio.h>
-#include <numeric>
-#include <vector>
-
-using std::map;
-using std::unordered_map;
-using std::vector;
-
-#ifdef __ANDROID__
-namespace android {
-namespace os {
-namespace statsd {
-
-const int kUidProcTag = 27;
-
-SimplePredicate getUidProcStatePredicate() {
-    SimplePredicate simplePredicate;
-    simplePredicate.set_start(StringToId("UidProcState"));
-
-    simplePredicate.mutable_dimensions()->set_field(kUidProcTag);
-    simplePredicate.mutable_dimensions()->add_child()->set_field(1);
-    simplePredicate.mutable_dimensions()->add_child()->set_field(2);
-
-    simplePredicate.set_count_nesting(false);
-    return simplePredicate;
-}
-
-// TODO(b/149590301): Update these tests to use new socket schema.
-//void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
-//    event->write(uid);
-//    event->write(state);
-//    event->init();
-//}
-//
-//TEST(StateConditionTrackerTest, TestStateChange) {
-//    int uid1 = 111;
-//    int uid2 = 222;
-//
-//    int state1 = 1001;
-//    int state2 = 1002;
-//    unordered_map<int64_t, int> trackerNameIndexMap;
-//    trackerNameIndexMap[StringToId("UidProcState")] = 0;
-//    vector<Matcher> primaryFields;
-//    primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
-//    StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
-//                         trackerNameIndexMap, primaryFields);
-//
-//    LogEvent event(kUidProcTag, 0 /*timestamp*/);
-//    makeUidProcStateEvent(uid1, state1, &event);
-//
-//    vector<MatchingState> matcherState;
-//    matcherState.push_back(MatchingState::kMatched);
-//    vector<sp<ConditionTracker>> allPredicates;
-//    vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
-//    vector<bool> changedCache(1, false);
-//
-//    tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
-//    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
-//    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
-//    EXPECT_TRUE(changedCache[0]);
-//
-//    changedCache[0] = false;
-//    conditionCache[0] = ConditionState::kNotEvaluated;
-//    tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
-//    EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
-//    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
-//    EXPECT_FALSE(changedCache[0]);
-//
-//    LogEvent event2(kUidProcTag, 0 /*timestamp*/);
-//    makeUidProcStateEvent(uid1, state2, &event2);
-//
-//    changedCache[0] = false;
-//    conditionCache[0] = ConditionState::kNotEvaluated;
-//    tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
-//    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
-//    EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
-//    EXPECT_TRUE(changedCache[0]);
-//
-//    LogEvent event3(kUidProcTag, 0 /*timestamp*/);
-//    makeUidProcStateEvent(uid2, state1, &event3);
-//    changedCache[0] = false;
-//    conditionCache[0] = ConditionState::kNotEvaluated;
-//    tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
-//    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
-//    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
-//    EXPECT_TRUE(changedCache[0]);
-//}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
-#else
-GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index ae2a0f5..2659944 100644
--- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -14,12 +14,13 @@
 
 #include <gtest/gtest.h>
 
+#include <vector>
+
 #include "src/StatsLogProcessor.h"
+#include "src/state/StateTracker.h"
 #include "src/stats_log_util.h"
 #include "tests/statsd_test_util.h"
 
-#include <vector>
-
 namespace android {
 namespace os {
 namespace statsd {
@@ -101,7 +102,7 @@
             reports.reports(0).metrics(0).duration_metrics();
     EXPECT_EQ(1, durationMetrics.data_size());
 
-    auto data = durationMetrics.data(0);
+    DurationMetricData data = durationMetrics.data(0);
     EXPECT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -183,7 +184,7 @@
             reports.reports(0).metrics(0).duration_metrics();
     EXPECT_EQ(1, durationMetrics.data_size());
 
-    auto data = durationMetrics.data(0);
+    DurationMetricData data = durationMetrics.data(0);
     EXPECT_EQ(1, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
@@ -353,7 +354,7 @@
             reports.reports(0).metrics(0).duration_metrics();
     EXPECT_EQ(1, durationMetrics.data_size());
 
-    auto data = durationMetrics.data(0);
+    DurationMetricData data = durationMetrics.data(0);
     EXPECT_EQ(1, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
@@ -434,7 +435,7 @@
     EXPECT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
 
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
 
     // Validate bucket info.
     EXPECT_EQ(1, data.bucket_info_size());
@@ -533,7 +534,7 @@
     EXPECT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
 
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, appUid);
@@ -691,7 +692,7 @@
     EXPECT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
 
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, appUid);
@@ -709,6 +710,734 @@
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
 }
 
+TEST(DurationMetricE2eTest, TestWithSlicedState) {
+    // Initialize config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
+    *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
+
+    auto batterySaverModePredicate = CreateBatterySaverModePredicate();
+    *config.add_predicate() = batterySaverModePredicate;
+
+    auto screenState = CreateScreenState();
+    *config.add_state() = screenState;
+
+    // Create duration metric that slices by screen state.
+    auto durationMetric = config.add_duration_metric();
+    durationMetric->set_id(StringToId("DurationBatterySaverModeSliceScreen"));
+    durationMetric->set_what(batterySaverModePredicate.id());
+    durationMetric->add_slice_by_state(screenState.id());
+    durationMetric->set_aggregation_type(DurationMetric::SUM);
+    durationMetric->set_bucket(FIVE_MINUTES);
+
+    // Initialize StatsLogProcessor.
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    EXPECT_TRUE(metricsManager->isActive());
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+
+    // Check that StateTrackers were initialized correctly.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+    /*
+               bucket #1                      bucket #2
+    |     1     2     3     4     5     6     7     8     9     10 (minutes)
+    |-----------------------------|-----------------------------|--
+        ON              OFF     ON                                  (BatterySaverMode)
+      |          |                   |                              (ScreenIsOnEvent)
+           |                  |                                     (ScreenIsOffEvent)
+              |                                                     (ScreenDozeEvent)
+    */
+    // Initialize log events.
+    std::vector<std::unique_ptr<LogEvent>> events;
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 10 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:20
+    events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 50 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:00
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 80 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 1:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 120 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));                         // 2:10
+    events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 250 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));                       // 4:20
+    events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
+
+    // Bucket boundary.
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 310 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 5:20
+
+    // Send log events to StatsLogProcessor.
+    for (auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+
+    // Check dump report.
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 360 * NS_PER_SEC,
+                            true /* include current partial bucket */, true, ADB_DUMP, FAST,
+                            &buffer);  // 6:10
+    EXPECT_GT(buffer.size(), 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStringInReport(&reports);
+    backfillStartEndTimestamp(&reports);
+
+    EXPECT_EQ(1, reports.reports_size());
+    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+    EXPECT_EQ(3, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(1);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(2);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState) {
+    // Initialize config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
+    *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
+    *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
+    *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
+
+    auto batterySaverModePredicate = CreateBatterySaverModePredicate();
+    *config.add_predicate() = batterySaverModePredicate;
+
+    auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
+    *config.add_predicate() = deviceUnpluggedPredicate;
+
+    auto screenState = CreateScreenState();
+    *config.add_state() = screenState;
+
+    // Create duration metric that has a condition and slices by screen state.
+    auto durationMetric = config.add_duration_metric();
+    durationMetric->set_id(StringToId("DurationBatterySaverModeOnBatterySliceScreen"));
+    durationMetric->set_what(batterySaverModePredicate.id());
+    durationMetric->set_condition(deviceUnpluggedPredicate.id());
+    durationMetric->add_slice_by_state(screenState.id());
+    durationMetric->set_aggregation_type(DurationMetric::SUM);
+    durationMetric->set_bucket(FIVE_MINUTES);
+
+    // Initialize StatsLogProcessor.
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    EXPECT_TRUE(metricsManager->isActive());
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+
+    // Check that StateTrackers were initialized correctly.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+    /*
+               bucket #1                      bucket #2
+    |       1       2       3       4       5     6     7     8  (minutes)
+    |---------------------------------------|------------------
+         ON                              OFF    ON             (BatterySaverMode)
+                  T            F    T                          (DeviceUnpluggedPredicate)
+             |          |              |                       (ScreenIsOnEvent)
+                |           |                       |          (ScreenIsOffEvent)
+                                |                              (ScreenDozeEvent)
+    */
+    // Initialize log events.
+    std::vector<std::unique_ptr<LogEvent>> events;
+    events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 60 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 1:10
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 80 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:30
+    events.push_back(
+            CreateBatteryStateChangedEvent(bucketStartTimeNs + 110 * NS_PER_SEC,
+                                           BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE));  // 2:00
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 145 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:35
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 170 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 3:00
+    events.push_back(
+            CreateBatteryStateChangedEvent(bucketStartTimeNs + 180 * NS_PER_SEC,
+                                           BatteryPluggedStateEnum::BATTERY_PLUGGED_USB));  // 3:10
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 200 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 3:30
+    events.push_back(
+            CreateBatteryStateChangedEvent(bucketStartTimeNs + 230 * NS_PER_SEC,
+                                           BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE));  // 4:00
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 260 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));                         // 4:30
+    events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
+
+    // Bucket boundary.
+    events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 320 * NS_PER_SEC));  // 5:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 380 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 6:30
+
+    // Send log events to StatsLogProcessor.
+    for (auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+
+    // Check dump report.
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 410 * NS_PER_SEC,
+                            true /* include current partial bucket */, true, ADB_DUMP, FAST,
+                            &buffer);
+    EXPECT_GT(buffer.size(), 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStringInReport(&reports);
+    backfillStartEndTimestamp(&reports);
+
+    EXPECT_EQ(1, reports.reports_size());
+    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+    EXPECT_EQ(3, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(2);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(60 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(1);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestWithSlicedStateMapped) {
+    // Initialize config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    *config.add_atom_matcher() = CreateBatterySaverModeStartAtomMatcher();
+    *config.add_atom_matcher() = CreateBatterySaverModeStopAtomMatcher();
+
+    auto batterySaverModePredicate = CreateBatterySaverModePredicate();
+    *config.add_predicate() = batterySaverModePredicate;
+
+    auto screenStateWithMap = CreateScreenStateWithOnOffMap();
+    *config.add_state() = screenStateWithMap;
+
+    // Create duration metric that slices by mapped screen state.
+    auto durationMetric = config.add_duration_metric();
+    durationMetric->set_id(StringToId("DurationBatterySaverModeSliceScreenMapped"));
+    durationMetric->set_what(batterySaverModePredicate.id());
+    durationMetric->add_slice_by_state(screenStateWithMap.id());
+    durationMetric->set_aggregation_type(DurationMetric::SUM);
+    durationMetric->set_bucket(FIVE_MINUTES);
+
+    // Initialize StatsLogProcessor.
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    EXPECT_TRUE(metricsManager->isActive());
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+
+    // Check that StateTrackers were initialized correctly.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+    /*
+               bucket #1                      bucket #2
+    |     1     2     3     4     5     6     7     8     9     10 (minutes)
+    |-----------------------------|-----------------------------|--
+        ON              OFF     ON                                  (BatterySaverMode)
+     ---------------------------------------------------------SCREEN_OFF events
+           |                  |                                  (ScreenStateOffEvent = 1)
+              |                                                  (ScreenStateDozeEvent = 3)
+                                                |                (ScreenStateDozeSuspendEvent = 4)
+     ---------------------------------------------------------SCREEN_ON events
+      |          |                   |                           (ScreenStateOnEvent = 2)
+                      |                                          (ScreenStateVrEvent = 5)
+                                            |                    (ScreenStateOnSuspendEvent = 6)
+    */
+    // Initialize log events.
+    std::vector<std::unique_ptr<LogEvent>> events;
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 10 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));                       // 0:20
+    events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 70 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));  // 1:20
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 100 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 1:50
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 120 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 2:10
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 170 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_VR));                         // 3:00
+    events.push_back(CreateBatterySaverOffEvent(bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 250 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_OFF));                       // 4:20
+    events.push_back(CreateBatterySaverOnEvent(bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
+
+    // Bucket boundary 5:10.
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 320 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON));  // 5:30
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 390 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND));  // 6:40
+    events.push_back(CreateScreenStateChangedEvent(
+            bucketStartTimeNs + 430 * NS_PER_SEC,
+            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND));  // 7:20
+    // Send log events to StatsLogProcessor.
+    for (auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+
+    // Check dump report.
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 490 * NS_PER_SEC,
+                            true /* include current partial bucket */, true, ADB_DUMP, FAST,
+                            &buffer);
+    EXPECT_GT(buffer.size(), 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStringInReport(&reports);
+    backfillStartEndTimestamp(&reports);
+
+    EXPECT_EQ(1, reports.reports_size());
+    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+    EXPECT_EQ(2, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(130 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(1);
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(80 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+}
+
+TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat) {
+    // Initialize config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+
+    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+    *config.add_predicate() = holdingWakelockPredicate;
+
+    auto uidProcessState = CreateUidProcessState();
+    *config.add_state() = uidProcessState;
+
+    // Create duration metric that slices by uid process state.
+    auto durationMetric = config.add_duration_metric();
+    durationMetric->set_id(StringToId("DurationHoldingWakelockSliceUidProcessState"));
+    durationMetric->set_what(holdingWakelockPredicate.id());
+    durationMetric->add_slice_by_state(uidProcessState.id());
+    durationMetric->set_aggregation_type(DurationMetric::SUM);
+    durationMetric->set_bucket(FIVE_MINUTES);
+
+    // The state has only one primary field (uid).
+    auto stateLink = durationMetric->add_state_link();
+    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+    *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+    auto fieldsInState = stateLink->mutable_fields_in_state();
+    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+
+    // Initialize StatsLogProcessor.
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    // This config is rejected because the dimension in what fields are not a superset of the sliced
+    // state primary fields.
+    EXPECT_EQ(processor->mMetricsManagers.size(), 0);
+}
+
+TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset) {
+    // Initialize config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+
+    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+    *config.add_predicate() = holdingWakelockPredicate;
+
+    auto uidProcessState = CreateUidProcessState();
+    *config.add_state() = uidProcessState;
+
+    // Create duration metric that slices by uid process state.
+    auto durationMetric = config.add_duration_metric();
+    durationMetric->set_id(StringToId("DurationPartialWakelockPerTagUidSliceProcessState"));
+    durationMetric->set_what(holdingWakelockPredicate.id());
+    durationMetric->add_slice_by_state(uidProcessState.id());
+    durationMetric->set_aggregation_type(DurationMetric::SUM);
+    durationMetric->set_bucket(FIVE_MINUTES);
+
+    // The metric is dimensioning by first uid of attribution node and tag.
+    *durationMetric->mutable_dimensions_in_what() = CreateAttributionUidAndOtherDimensions(
+            util::WAKELOCK_STATE_CHANGED, {Position::FIRST}, {3 /* tag */});
+    // The state has only one primary field (uid).
+    auto stateLink = durationMetric->add_state_link();
+    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+    *fieldsInWhat = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+    auto fieldsInState = stateLink->mutable_fields_in_state();
+    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+
+    // Initialize StatsLogProcessor.
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    EXPECT_TRUE(metricsManager->isActive());
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+
+    // Check that StateTrackers were initialized correctly.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+    // Initialize log events.
+    int appUid1 = 1001;
+    int appUid2 = 1002;
+    std::vector<int> attributionUids1 = {appUid1};
+    std::vector<string> attributionTags1 = {"App1"};
+
+    std::vector<int> attributionUids2 = {appUid2};
+    std::vector<string> attributionTags2 = {"App2"};
+
+    std::vector<std::unique_ptr<LogEvent>> events;
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 10 * NS_PER_SEC, appUid1,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND));  // 0:20
+    events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
+                                                attributionUids1, attributionTags1,
+                                                "wakelock1"));  // 0:30
+    events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 25 * NS_PER_SEC,
+                                                attributionUids1, attributionTags1,
+                                                "wakelock2"));  // 0:35
+    events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 30 * NS_PER_SEC,
+                                                attributionUids2, attributionTags2,
+                                                "wakelock1"));  // 0:40
+    events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 35 * NS_PER_SEC,
+                                                attributionUids2, attributionTags2,
+                                                "wakelock2"));  // 0:45
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 50 * NS_PER_SEC, appUid2,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 1:00
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 60 * NS_PER_SEC, appUid1,
+            android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND));  // 1:10
+    events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 100 * NS_PER_SEC,
+                                                attributionUids2, attributionTags2,
+                                                "wakelock1"));  // 1:50
+    events.push_back(CreateUidProcessStateChangedEvent(
+            bucketStartTimeNs + 120 * NS_PER_SEC, appUid2,
+            android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE));  // 2:10
+    events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 200 * NS_PER_SEC,
+                                                attributionUids1, attributionTags1,
+                                                "wakelock2"));  // 3:30
+
+    // Send log events to StatsLogProcessor.
+    for (auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+
+    // Check dump report.
+    vector<uint8_t> buffer;
+    ConfigMetricsReportList reports;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 320 * NS_PER_SEC,
+                            true /* include current partial bucket */, true, ADB_DUMP, FAST,
+                            &buffer);
+    EXPECT_GT(buffer.size(), 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStringInReport(&reports);
+    backfillStartEndTimestamp(&reports);
+
+    EXPECT_EQ(1, reports.reports_size());
+    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+    EXPECT_EQ(9, reports.reports(0).metrics(0).duration_metrics().data_size());
+
+    DurationMetricData data = reports.reports(0).metrics(0).duration_metrics().data(0);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
+                                                  "wakelock2");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(35 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(1);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
+                                                  "wakelock2");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(140 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(2);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
+                                                  "wakelock1");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(3);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
+                                                  "wakelock1");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(240 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(4);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
+                                                  "wakelock1");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(5);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
+                                                  "wakelock2");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(180 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(20 * NS_PER_SEC, data.bucket_info(1).duration_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(330 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(6);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
+                                                  "wakelock2");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(15 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(7);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
+                                                  "wakelock1");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = reports.reports(0).metrics(0).duration_metrics().data(8);
+    ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
+                                                  "wakelock2");
+    EXPECT_EQ(1, data.slice_by_state_size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
+    EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
+}
+
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 100220b..d2f0f57 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -62,9 +62,8 @@
     int64_t bucketNum = 0;
 
     int64_t metricId = 1;
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1,
-                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               false, false, {});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     tracker.noteStart(key1, true, bucketStartTimeNs, ConditionKey());
     // Event starts again. This would not change anything as it already starts.
@@ -97,9 +96,8 @@
     int64_t bucketNum = 0;
 
     int64_t metricId = 1;
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1,
-                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               false, false, {});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     tracker.noteStart(key1, true, bucketStartTimeNs + 1, ConditionKey());
 
@@ -132,9 +130,8 @@
     int64_t bucketNum = 0;
 
     int64_t metricId = 1;
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1,
-                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               false, false, {});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, false, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     // The event starts.
     tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
@@ -172,9 +169,8 @@
     int64_t bucketNum = 0;
 
     int64_t metricId = 1;
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1,
-                               true, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               false, false, {});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, true, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     // 2 starts
     tracker.noteStart(DEFAULT_DIMENSION_KEY, true, bucketStartTimeNs + 1, ConditionKey());
@@ -218,9 +214,8 @@
     int64_t eventStopTimeNs = conditionStops2 + 8 * NS_PER_SEC;
 
     int64_t metricId = 1;
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                               false, bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, true,
-                               false, {});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs,
+                               0, bucketStartTimeNs, bucketSizeNs, true, false, {});
     EXPECT_TRUE(tracker.mAnomalyTrackers.empty());
 
     tracker.noteStart(key1, false, eventStartTimeNs, conditionKey1);
@@ -267,9 +262,9 @@
     sp<AlarmMonitor> alarmMonitor;
     sp<DurationAnomalyTracker> anomalyTracker =
         new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               true, false, {anomalyTracker});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, true, false,
+                               {anomalyTracker});
 
     tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1);
     sp<const InternalAlarm> alarm = anomalyTracker->mAlarms.begin()->second;
@@ -326,9 +321,9 @@
     sp<AlarmMonitor> alarmMonitor;
     sp<DurationAnomalyTracker> anomalyTracker =
         new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               true, false, {anomalyTracker});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, true, false,
+                               {anomalyTracker});
 
     tracker.noteStart(key1, false, eventStartTimeNs, conditionKey1);
     tracker.noteConditionChanged(key1, true, conditionStarts1);
@@ -408,9 +403,9 @@
     sp<AlarmMonitor> alarmMonitor;
     sp<DurationAnomalyTracker> anomalyTracker =
         new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                               false, bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
-                               true, false, {anomalyTracker});
+    MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false, bucketStartTimeNs,
+                               bucketNum, bucketStartTimeNs, bucketSizeNs, true, false,
+                               {anomalyTracker});
 
     tracker.noteStart(key1, true, eventStartTimeNs1, conditionKey1);
     tracker.noteStart(key2, true, eventStartTimeNs2, conditionKey2);
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 1cd7bdb..39d3919 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -61,9 +61,9 @@
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
     int64_t durationTimeNs = 2 * 1000;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, false, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
+                                 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                                 false, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
@@ -92,9 +92,8 @@
     int64_t bucketNum = 0;
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, false, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
+                                 bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 10, ConditionKey());  // overlapping wl
@@ -124,9 +123,8 @@
     int64_t bucketNum = 0;
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, false, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
+                                 bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     tracker.noteStart(kEventKey2, true, eventStartTimeNs + 10, ConditionKey());  // overlapping wl
@@ -154,9 +152,8 @@
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
     int64_t durationTimeNs = 2 * 1000;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, false, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
+                                 bucketNum, bucketStartTimeNs, bucketSizeNs, false, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     EXPECT_EQ((long long)eventStartTimeNs, tracker.mLastStartTime);
@@ -198,9 +195,9 @@
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
     int64_t durationTimeNs = 2 * 1000;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, true, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
+                                 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                                 true, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
 
@@ -237,9 +234,9 @@
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
     int64_t durationTimeNs = 2 * 1000;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, true, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, false,
+                                 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                                 true, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
     // condition to false; record duration 5n
@@ -275,9 +272,8 @@
     int64_t bucketNum = 0;
     int64_t eventStartTimeNs = bucketStartTimeNs + 1;
 
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, true, false, {});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
+                                 bucketNum, bucketStartTimeNs, bucketSizeNs, true, false, {});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2, key1);
@@ -316,9 +312,9 @@
     sp<AlarmMonitor> alarmMonitor;
     sp<DurationAnomalyTracker> anomalyTracker =
         new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, true, false, {anomalyTracker});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true, bucketStartTimeNs,
+                                 bucketNum, bucketStartTimeNs, bucketSizeNs, true, false,
+                                 {anomalyTracker});
 
     // Nothing in the past bucket.
     tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
@@ -422,9 +418,8 @@
             sp<AlarmMonitor> alarmMonitor;
             sp<DurationAnomalyTracker> anomalyTracker =
                 new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-            OringDurationTracker tracker(kConfigKey, metricId, DEFAULT_METRIC_DIMENSION_KEY,
-                                         wizard, 1,
-                                         true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
+            OringDurationTracker tracker(kConfigKey, metricId, DEFAULT_METRIC_DIMENSION_KEY, wizard,
+                                         1, true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
                                          bucketSizeNs, true, false, {anomalyTracker});
 
             int64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
@@ -481,15 +476,15 @@
     sp<AlarmMonitor> alarmMonitor;
     sp<DurationAnomalyTracker> anomalyTracker =
         new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true /*nesting*/, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
-                                 bucketSizeNs, false, false, {anomalyTracker});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/,
+                                 bucketStartTimeNs, bucketNum, bucketStartTimeNs, bucketSizeNs,
+                                 false, false, {anomalyTracker});
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs, ConditionKey());
     tracker.noteStop(kEventKey1, eventStartTimeNs + 10, false);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
     EXPECT_TRUE(tracker.mStarted.empty());
-    EXPECT_EQ(10LL, tracker.mDuration); // 10ns
+    EXPECT_EQ(10LL, tracker.mStateKeyDurationMap[DEFAULT_DIMENSION_KEY].mDuration);  // 10ns
 
     EXPECT_EQ(0u, tracker.mStarted.size());
 
@@ -530,11 +525,11 @@
     sp<AlarmMonitor> alarmMonitor;
     sp<DurationAnomalyTracker> anomalyTracker =
         new DurationAnomalyTracker(alert, kConfigKey, alarmMonitor);
-    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1,
-                                 true /*nesting*/, bucketStartTimeNs, 0, bucketStartTimeNs,
-                                 bucketSizeNs, false, false, {anomalyTracker});
+    OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, true /*nesting*/,
+                                 bucketStartTimeNs, 0, bucketStartTimeNs, bucketSizeNs, false,
+                                 false, {anomalyTracker});
 
-    tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey); // start key1
+    tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey);  // start key1
     EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
     sp<const InternalAlarm> alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(55ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
@@ -544,13 +539,13 @@
     EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
 
-    tracker.noteStart(kEventKey1, true, 22 * NS_PER_SEC, conkey); // start key1 again
+    tracker.noteStart(kEventKey1, true, 22 * NS_PER_SEC, conkey);  // start key1 again
     EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
 
-    tracker.noteStart(kEventKey2, true, 32 * NS_PER_SEC, conkey); // start key2
+    tracker.noteStart(kEventKey2, true, 32 * NS_PER_SEC, conkey);  // start key2
     EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index a0e0095..a5b8e1c 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -105,63 +105,6 @@
 }
 // END: build event functions.
 
-// START: get primary key functions
-void getUidProcessKey(int uid, HashableDimensionKey* key) {
-    int pos1[] = {1, 0, 0};
-    Field field1(27 /* atom id */, pos1, 0 /* depth */);
-    Value value1((int32_t)uid);
-
-    key->addValue(FieldValue(field1, value1));
-}
-
-void getOverlayKey(int uid, string packageName, HashableDimensionKey* key) {
-    int pos1[] = {1, 0, 0};
-    int pos2[] = {2, 0, 0};
-
-    Field field1(59 /* atom id */, pos1, 0 /* depth */);
-    Field field2(59 /* atom id */, pos2, 0 /* depth */);
-
-    Value value1((int32_t)uid);
-    Value value2(packageName);
-
-    key->addValue(FieldValue(field1, value1));
-    key->addValue(FieldValue(field2, value2));
-}
-
-void getPartialWakelockKey(int uid, const std::string& tag, HashableDimensionKey* key) {
-    int pos1[] = {1, 1, 1};
-    int pos3[] = {2, 0, 0};
-    int pos4[] = {3, 0, 0};
-
-    Field field1(10 /* atom id */, pos1, 2 /* depth */);
-
-    Field field3(10 /* atom id */, pos3, 0 /* depth */);
-    Field field4(10 /* atom id */, pos4, 0 /* depth */);
-
-    Value value1((int32_t)uid);
-    Value value3((int32_t)1 /*partial*/);
-    Value value4(tag);
-
-    key->addValue(FieldValue(field1, value1));
-    key->addValue(FieldValue(field3, value3));
-    key->addValue(FieldValue(field4, value4));
-}
-
-void getPartialWakelockKey(int uid, HashableDimensionKey* key) {
-    int pos1[] = {1, 1, 1};
-    int pos3[] = {2, 0, 0};
-
-    Field field1(10 /* atom id */, pos1, 2 /* depth */);
-    Field field3(10 /* atom id */, pos3, 0 /* depth */);
-
-    Value value1((int32_t)uid);
-    Value value3((int32_t)1 /*partial*/);
-
-    key->addValue(FieldValue(field1, value1));
-    key->addValue(FieldValue(field3, value3));
-}
-// END: get primary key functions
-
 TEST(StateListenerTest, TestStateListenerWeakPointer) {
     sp<TestStateListener> listener = new TestStateListener();
     wp<TestStateListener> wListener = listener;
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 8c8836b..7d765d3 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -135,6 +135,27 @@
         "BatterySaverModeStop", BatterySaverModeStateChanged::OFF);
 }
 
+AtomMatcher CreateBatteryStateChangedAtomMatcher(const string& name,
+                                                 BatteryPluggedStateEnum state) {
+    AtomMatcher atom_matcher;
+    atom_matcher.set_id(StringToId(name));
+    auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
+    simple_atom_matcher->set_atom_id(util::PLUGGED_STATE_CHANGED);
+    auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
+    field_value_matcher->set_field(1);  // State field.
+    field_value_matcher->set_eq_int(state);
+    return atom_matcher;
+}
+
+AtomMatcher CreateBatteryStateNoneMatcher() {
+    return CreateBatteryStateChangedAtomMatcher("BatteryPluggedNone",
+                                                BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE);
+}
+
+AtomMatcher CreateBatteryStateUsbMatcher() {
+    return CreateBatteryStateChangedAtomMatcher("BatteryPluggedUsb",
+                                                BatteryPluggedStateEnum::BATTERY_PLUGGED_USB);
+}
 
 AtomMatcher CreateScreenStateChangedAtomMatcher(
     const string& name, android::view::DisplayStateEnum state) {
@@ -234,6 +255,14 @@
     return predicate;
 }
 
+Predicate CreateDeviceUnpluggedPredicate() {
+    Predicate predicate;
+    predicate.set_id(StringToId("DeviceUnplugged"));
+    predicate.mutable_simple_predicate()->set_start(StringToId("BatteryPluggedNone"));
+    predicate.mutable_simple_predicate()->set_stop(StringToId("BatteryPluggedUsb"));
+    return predicate;
+}
+
 Predicate CreateScreenIsOnPredicate() {
     Predicate predicate;
     predicate.set_id(StringToId("ScreenIsOn"));
@@ -410,6 +439,74 @@
     return dimensions;
 }
 
+FieldMatcher CreateAttributionUidAndOtherDimensions(const int atomId,
+                                                    const std::vector<Position>& positions,
+                                                    const std::vector<int>& fields) {
+    FieldMatcher dimensions = CreateAttributionUidDimensions(atomId, positions);
+
+    for (const int field : fields) {
+        dimensions.add_child()->set_field(field);
+    }
+    return dimensions;
+}
+
+// START: get primary key functions
+void getUidProcessKey(int uid, HashableDimensionKey* key) {
+    int pos1[] = {1, 0, 0};
+    Field field1(27 /* atom id */, pos1, 0 /* depth */);
+    Value value1((int32_t)uid);
+
+    key->addValue(FieldValue(field1, value1));
+}
+
+void getOverlayKey(int uid, string packageName, HashableDimensionKey* key) {
+    int pos1[] = {1, 0, 0};
+    int pos2[] = {2, 0, 0};
+
+    Field field1(59 /* atom id */, pos1, 0 /* depth */);
+    Field field2(59 /* atom id */, pos2, 0 /* depth */);
+
+    Value value1((int32_t)uid);
+    Value value2(packageName);
+
+    key->addValue(FieldValue(field1, value1));
+    key->addValue(FieldValue(field2, value2));
+}
+
+void getPartialWakelockKey(int uid, const std::string& tag, HashableDimensionKey* key) {
+    int pos1[] = {1, 1, 1};
+    int pos3[] = {2, 0, 0};
+    int pos4[] = {3, 0, 0};
+
+    Field field1(10 /* atom id */, pos1, 2 /* depth */);
+
+    Field field3(10 /* atom id */, pos3, 0 /* depth */);
+    Field field4(10 /* atom id */, pos4, 0 /* depth */);
+
+    Value value1((int32_t)uid);
+    Value value3((int32_t)1 /*partial*/);
+    Value value4(tag);
+
+    key->addValue(FieldValue(field1, value1));
+    key->addValue(FieldValue(field3, value3));
+    key->addValue(FieldValue(field4, value4));
+}
+
+void getPartialWakelockKey(int uid, HashableDimensionKey* key) {
+    int pos1[] = {1, 1, 1};
+    int pos3[] = {2, 0, 0};
+
+    Field field1(10 /* atom id */, pos1, 2 /* depth */);
+    Field field3(10 /* atom id */, pos3, 0 /* depth */);
+
+    Value value1((int32_t)uid);
+    Value value3((int32_t)1 /*partial*/);
+
+    key->addValue(FieldValue(field1, value1));
+    key->addValue(FieldValue(field3, value3));
+}
+// END: get primary key functions
+
 shared_ptr<LogEvent> CreateTwoValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
                                             int32_t value2) {
     AStatsEvent* statsEvent = AStatsEvent_obtain();
@@ -595,6 +692,23 @@
     return logEvent;
 }
 
+std::unique_ptr<LogEvent> CreateBatteryStateChangedEvent(const uint64_t timestampNs, const BatteryPluggedStateEnum state) {
+    AStatsEvent* statsEvent = AStatsEvent_obtain();
+    AStatsEvent_setAtomId(statsEvent, util::PLUGGED_STATE_CHANGED);
+    AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
+
+    AStatsEvent_writeInt32(statsEvent, state);
+    AStatsEvent_build(statsEvent);
+
+    size_t size;
+    uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+
+    std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
+    logEvent->parseBuffer(buf, size);
+    AStatsEvent_release(statsEvent);
+    return logEvent;
+}
+
 std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(uint64_t timestampNs, int level) {
     AStatsEvent* statsEvent = AStatsEvent_obtain();
     AStatsEvent_setAtomId(statsEvent, util::SCREEN_BRIGHTNESS_CHANGED);
@@ -946,13 +1060,6 @@
     return processor;
 }
 
-AttributionNodeInternal CreateAttribution(const int& uid, const string& tag) {
-    AttributionNodeInternal attribution;
-    attribution.set_uid(uid);
-    attribution.set_tag(tag);
-    return attribution;
-}
-
 void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events) {
   std::sort(events->begin(), events->end(),
             [](const std::unique_ptr<LogEvent>& a, const std::unique_ptr<LogEvent>& b) {
@@ -964,6 +1071,22 @@
     return static_cast<int64_t>(std::hash<std::string>()(str));
 }
 
+void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
+                                                   const int uid, const string& tag) {
+    EXPECT_EQ(value.field(), atomId);
+    EXPECT_EQ(value.value_tuple().dimensions_value_size(), 2);
+    // Attribution field.
+    EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
+    // Uid field.
+    EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 1);
+    EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).field(), 1);
+    EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).value_int(),
+              uid);
+    // Tag field.
+    EXPECT_EQ(value.value_tuple().dimensions_value(1).field(), 3);
+    EXPECT_EQ(value.value_tuple().dimensions_value(1).value_str(), tag);
+}
+
 void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid) {
     EXPECT_EQ(value.field(), atomId);
     EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 7c01755..f24705a 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -68,6 +68,12 @@
 // Create AtomMatcher proto for stopping battery save mode.
 AtomMatcher CreateBatterySaverModeStopAtomMatcher();
 
+// Create AtomMatcher proto for battery state none mode.
+AtomMatcher CreateBatteryStateNoneMatcher();
+
+// Create AtomMatcher proto for battery state usb mode.
+AtomMatcher CreateBatteryStateUsbMatcher();
+
 // Create AtomMatcher proto for process state changed.
 AtomMatcher CreateUidProcessStateChangedAtomMatcher();
 
@@ -110,6 +116,9 @@
 // Create Predicate proto for battery saver mode.
 Predicate CreateBatterySaverModePredicate();
 
+// Create Predicate proto for device unplogged mode.
+Predicate CreateDeviceUnpluggedPredicate();
+
 // Create Predicate proto for holding wakelock.
 Predicate CreateHoldingWakelockPredicate();
 
@@ -164,6 +173,22 @@
 FieldMatcher CreateAttributionUidDimensions(const int atomId,
                                             const std::vector<Position>& positions);
 
+FieldMatcher CreateAttributionUidAndOtherDimensions(const int atomId,
+                                                    const std::vector<Position>& positions,
+                                                    const std::vector<int>& fields);
+
+// START: get primary key functions
+// These functions take in atom field information and create FieldValues which are stored in the
+// given HashableDimensionKey.
+void getUidProcessKey(int uid, HashableDimensionKey* key);
+
+void getOverlayKey(int uid, string packageName, HashableDimensionKey* key);
+
+void getPartialWakelockKey(int uid, const std::string& tag, HashableDimensionKey* key);
+
+void getPartialWakelockKey(int uid, HashableDimensionKey* key);
+// END: get primary key functions
+
 shared_ptr<LogEvent> CreateTwoValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
                                             int32_t value2);
 
@@ -213,6 +238,9 @@
 // Create log event when battery saver stops.
 std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs);
 
+// Create log event when battery state changes.
+std::unique_ptr<LogEvent> CreateBatteryStateChangedEvent(const uint64_t timestampNs, const BatteryPluggedStateEnum state);
+
 // Create log event for app moving to background.
 std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid);
 
@@ -263,9 +291,6 @@
                                                          const bool usingAlertWindow,
                                                          const OverlayStateChanged::State state);
 
-// Helper function to create an AttributionNodeInternal proto.
-AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
-
 // Create a statsd log event processor upon the start time in seconds, config and key.
 sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
                                               const StatsdConfig& config, const ConfigKey& key,
@@ -277,6 +302,8 @@
 
 int64_t StringToId(const string& str);
 
+void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
+                                                   const int uid, const string& tag);
 void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
 void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid);
 void ValidateAttributionUidAndTagDimension(
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
index a381f9c..2909048 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
@@ -17,16 +17,23 @@
 
 import com.android.os.StatsLog.ConfigMetricsReportList;
 
+import com.google.common.io.Files;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Formatter;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Utilities for local use of statsd.
@@ -80,7 +87,8 @@
      * @throws InterruptedException
      */
     public static ConfigMetricsReportList getReportList(long configId, boolean clearData,
-            boolean useShellUid, Logger logger) throws IOException, InterruptedException {
+            boolean useShellUid, Logger logger, String deviceSerial)
+            throws IOException, InterruptedException {
         try {
             File outputFile = File.createTempFile("statsdret", ".bin");
             outputFile.deleteOnExit();
@@ -88,6 +96,8 @@
                     outputFile,
                     logger,
                     "adb",
+                    "-s",
+                    deviceSerial,
                     "shell",
                     CMD_DUMP_REPORT,
                     useShellUid ? SHELL_UID : "",
@@ -117,12 +127,14 @@
      * @throws IOException
      * @throws InterruptedException
      */
-    public static void logAppBreadcrumb(int label, int state, Logger logger)
+    public static void logAppBreadcrumb(int label, int state, Logger logger, String deviceSerial)
             throws IOException, InterruptedException {
         runCommand(
                 null,
                 logger,
                 "adb",
+                "-s",
+                deviceSerial,
                 "shell",
                 CMD_LOG_APP_BREADCRUMB,
                 String.valueOf(label),
@@ -145,13 +157,14 @@
      * Algorithm: true if (sdk >= minSdk) || (sdk == minSdk-1 && codeName.startsWith(minCodeName))
      * If all else fails, assume it will work (letting future commands deal with any errors).
      */
-    public static boolean isAcceptableStatsd(Logger logger, int minSdk, String minCodename) {
+    public static boolean isAcceptableStatsd(Logger logger, int minSdk, String minCodename,
+            String deviceSerial) {
         BufferedReader in = null;
         try {
             File outFileSdk = File.createTempFile("shelltools_sdk", "tmp");
             outFileSdk.deleteOnExit();
             runCommand(outFileSdk, logger,
-                    "adb", "shell", "getprop", "ro.build.version.sdk");
+                    "adb", "-s", deviceSerial, "shell", "getprop", "ro.build.version.sdk");
             in = new BufferedReader(new InputStreamReader(new FileInputStream(outFileSdk)));
             // If NullPointerException/NumberFormatException/etc., just catch and return true.
             int sdk = Integer.parseInt(in.readLine().trim());
@@ -162,7 +175,7 @@
                 File outFileCode = File.createTempFile("shelltools_codename", "tmp");
                 outFileCode.deleteOnExit();
                 runCommand(outFileCode, logger,
-                        "adb", "shell", "getprop", "ro.build.version.codename");
+                        "adb", "-s", deviceSerial, "shell", "getprop", "ro.build.version.codename");
                 in = new BufferedReader(new InputStreamReader(new FileInputStream(outFileCode)));
                 return in.readLine().startsWith(minCodename);
             } else {
@@ -190,4 +203,30 @@
             return record.getMessage() + "\n";
         }
     }
+
+    /**
+     * Parse the result of "adb devices" to return the list of connected devices.
+     * @param logger Logger to log error messages
+     * @return List of the serial numbers of the connected devices.
+     */
+    public static List<String> getDeviceSerials(Logger logger) {
+        try {
+            ArrayList<String> devices = new ArrayList<>();
+            File outFile = File.createTempFile("device_serial", "tmp");
+            outFile.deleteOnExit();
+            Utils.runCommand(outFile, logger, "adb", "devices");
+            List<String> outputLines = Files.readLines(outFile, Charset.defaultCharset());
+            Pattern regex = Pattern.compile("^(.*)\tdevice$");
+            for (String line : outputLines) {
+                Matcher m = regex.matcher(line);
+                if (m.find()) {
+                    devices.add(m.group(1));
+                }
+            }
+            return devices;
+        } catch (Exception ex) {
+            logger.log(Level.SEVERE, "Failed to list connected devices: " + ex.getMessage());
+        }
+        return null;
+    }
 }
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java
index 2eb4660..7db5141 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/localdrive/LocalDrive.java
@@ -26,6 +26,8 @@
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
@@ -49,7 +51,7 @@
     public static final String HELP_STRING =
         "Usage:\n\n" +
 
-        "statsd_localdrive upload CONFIG_FILE [CONFIG_ID] [--binary]\n" +
+        "statsd_localdrive [-s DEVICE_SERIAL] upload CONFIG_FILE [CONFIG_ID] [--binary]\n" +
         "  Uploads the given statsd config file (in binary or human-readable-text format).\n" +
         "  If a config with this id already exists, removes it first.\n" +
         "    CONFIG_FILE    Location of config file on host.\n" +
@@ -59,12 +61,12 @@
         // Similar to: adb shell cmd stats config update SHELL_UID CONFIG_ID
         "\n" +
 
-        "statsd_localdrive update CONFIG_FILE [CONFIG_ID] [--binary]\n" +
+        "statsd_localdrive [-s DEVICE_SERIAL] update CONFIG_FILE [CONFIG_ID] [--binary]\n" +
         "  Same as upload, but does not remove the old config first (if it already exists).\n" +
         // Similar to: adb shell cmd stats config update SHELL_UID CONFIG_ID
         "\n" +
 
-        "statsd_localdrive get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]\n" +
+        "statsd_localdrive [-s DEVICE_SERIAL] get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]\n" +
         "  Prints the output statslog data (in binary or human-readable-text format).\n" +
         "    CONFIG_ID      Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" +
         "    --binary       Output should be in binary, instead of default human-readable text.\n" +
@@ -75,13 +77,13 @@
         //                                                      --include_current_bucket --proto
         "\n" +
 
-        "statsd_localdrive remove [CONFIG_ID]\n" +
+        "statsd_localdrive [-s DEVICE_SERIAL] remove [CONFIG_ID]\n" +
         "  Removes the config.\n" +
         "    CONFIG_ID      Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" +
         // Equivalent to: adb shell cmd stats config remove SHELL_UID CONFIG_ID
         "\n" +
 
-        "statsd_localdrive clear [CONFIG_ID]\n" +
+        "statsd_localdrive [-s DEVICE_SERIAL] clear [CONFIG_ID]\n" +
         "  Clears the data associated with the config.\n" +
         "    CONFIG_ID      Long ID of the config. If absent, uses " + DEFAULT_CONFIG_ID + ".\n" +
         // Similar to: adb shell cmd stats dump-report SHELL_UID CONFIG_ID
@@ -94,29 +96,59 @@
     /** Usage: make statsd_localdrive && statsd_localdrive */
     public static void main(String[] args) {
         Utils.setUpLogger(sLogger, DEBUG);
+        if (args.length == 0) {
+            printHelp();
+            return;
+        }
 
-        if (!Utils.isAcceptableStatsd(sLogger, MIN_SDK, MIN_CODENAME)) {
+        int remainingArgsLength = args.length;
+        String deviceSerial = null;
+        if (args[0].equals("-s")) {
+            if (args.length == 1) {
+                printHelp();
+            }
+            deviceSerial = args[1];
+            remainingArgsLength -= 2;
+        }
+
+        List<String> connectedDevices = Utils.getDeviceSerials(sLogger);
+        if (connectedDevices == null || connectedDevices.size() == 0) {
+            sLogger.log(Level.SEVERE, "No device connected.");
+            return;
+        }
+        if (connectedDevices.size() == 1 && deviceSerial == null) {
+            deviceSerial = connectedDevices.get(0);
+        }
+
+        if (deviceSerial == null) {
+            sLogger.log(Level.SEVERE, "More than one devices connected. Please specify"
+                    + " with -s DEVICE_SERIAL");
+            return;
+        }
+
+        if (!Utils.isAcceptableStatsd(sLogger, MIN_SDK, MIN_CODENAME, deviceSerial)) {
             sLogger.severe("LocalDrive only works with statsd versions for Android "
                     + MIN_CODENAME + " or higher.");
             return;
         }
 
-        if (args.length > 0) {
-            switch (args[0]) {
+        int idx = args.length - remainingArgsLength;
+        if (remainingArgsLength > 0) {
+            switch (args[idx]) {
                 case "clear":
-                    cmdClear(args);
+                    cmdClear(args, idx, deviceSerial);
                     return;
                 case "get-data":
-                    cmdGetData(args);
+                    cmdGetData(args, idx, deviceSerial);
                     return;
                 case "remove":
-                    cmdRemove(args);
+                    cmdRemove(args, idx);
                     return;
                 case "update":
-                    cmdUpdate(args);
+                    cmdUpdate(args, idx, deviceSerial);
                     return;
                 case "upload":
-                    cmdUpload(args);
+                    cmdUpload(args, idx, deviceSerial);
                     return;
             }
         }
@@ -128,17 +160,18 @@
     }
 
     // upload CONFIG_FILE [CONFIG_ID] [--binary]
-    private static boolean cmdUpload(String[] args) {
-        return updateConfig(args, true);
+    private static boolean cmdUpload(String[] args, int idx, String deviceSerial) {
+        return updateConfig(args, idx, true, deviceSerial);
     }
 
     // update CONFIG_FILE [CONFIG_ID] [--binary]
-    private static boolean cmdUpdate(String[] args) {
-        return updateConfig(args, false);
+    private static boolean cmdUpdate(String[] args, int idx, String deviceSerial) {
+        return updateConfig(args, idx, false, deviceSerial);
     }
 
-    private static boolean updateConfig(String[] args, boolean removeOldConfig) {
-        int argCount = args.length - 1; // Used up one for upload/update.
+    private static boolean updateConfig(String[] args, int idx, boolean removeOldConfig,
+            String deviceSerial) {
+        int argCount = args.length - 1 - idx; // Used up one for upload/update.
 
         // Get CONFIG_FILE
         if (argCount < 1) {
@@ -146,7 +179,7 @@
             printHelp();
             return false;
         }
-        final String origConfigLocation = args[1];
+        final String origConfigLocation = args[idx + 1];
         if (!new File(origConfigLocation).exists()) {
             sLogger.severe("Error - Cannot find the provided config file: " + origConfigLocation);
             return false;
@@ -154,13 +187,13 @@
         argCount--;
 
         // Get --binary
-        boolean binary = contains(args, 2, BINARY_FLAG);
+        boolean binary = contains(args, idx + 2, BINARY_FLAG);
         if (binary) argCount --;
 
         // Get CONFIG_ID
         long configId;
         try {
-            configId = getConfigId(argCount < 1, args, 2);
+            configId = getConfigId(argCount < 1, args, idx + 2);
         } catch (NumberFormatException e) {
             sLogger.severe("Invalid config id provided.");
             printHelp();
@@ -174,7 +207,8 @@
             try {
                 Utils.runCommand(null, sLogger, "adb", "shell", Utils.CMD_REMOVE_CONFIG,
                         Utils.SHELL_UID, String.valueOf(configId));
-                Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger);
+                Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger,
+                        deviceSerial);
             } catch (InterruptedException | IOException e) {
                 sLogger.severe("Failed to remove config: " + e.getMessage());
                 return false;
@@ -218,19 +252,19 @@
     }
 
     // get-data [CONFIG_ID] [--clear] [--binary] [--no-uid-map]
-    private static boolean cmdGetData(String[] args) {
-        boolean binary = contains(args, 1, BINARY_FLAG);
-        boolean noUidMap = contains(args, 1, NO_UID_MAP_FLAG);
-        boolean clearData = contains(args, 1, CLEAR_DATA);
+    private static boolean cmdGetData(String[] args, int idx, String deviceSerial) {
+        boolean binary = contains(args, idx + 1, BINARY_FLAG);
+        boolean noUidMap = contains(args, idx + 1, NO_UID_MAP_FLAG);
+        boolean clearData = contains(args, idx + 1, CLEAR_DATA);
 
         // Get CONFIG_ID
-        int argCount = args.length - 1; // Used up one for get-data.
+        int argCount = args.length - 1 - idx; // Used up one for get-data.
         if (binary) argCount--;
         if (noUidMap) argCount--;
         if (clearData) argCount--;
         long configId;
         try {
-            configId = getConfigId(argCount < 1, args, 1);
+            configId = getConfigId(argCount < 1, args, idx + 1);
         } catch (NumberFormatException e) {
             sLogger.severe("Invalid config id provided.");
             printHelp();
@@ -243,7 +277,8 @@
         // Even if the args request no modifications, we still parse it to make sure it's valid.
         ConfigMetricsReportList reportList;
         try {
-            reportList = Utils.getReportList(configId, clearData, true /* SHELL_UID */, sLogger);
+            reportList = Utils.getReportList(configId, clearData, true /* SHELL_UID */, sLogger,
+                    deviceSerial);
         } catch (IOException | InterruptedException e) {
             sLogger.severe("Failed to get report list: " + e.getMessage());
             return false;
@@ -274,11 +309,11 @@
     }
 
     // clear [CONFIG_ID]
-    private static boolean cmdClear(String[] args) {
+    private static boolean cmdClear(String[] args, int idx, String deviceSerial) {
         // Get CONFIG_ID
         long configId;
         try {
-            configId = getConfigId(false, args, 1);
+            configId = getConfigId(false, args, idx + 1);
         } catch (NumberFormatException e) {
             sLogger.severe("Invalid config id provided.");
             printHelp();
@@ -287,7 +322,8 @@
         sLogger.fine(String.format("cmdClear with %d", configId));
 
         try {
-            Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger);
+            Utils.getReportList(configId, true /* clearData */, true /* SHELL_UID */, sLogger,
+                    deviceSerial);
         } catch (IOException | InterruptedException e) {
             sLogger.severe("Failed to get report list: " + e.getMessage());
             return false;
@@ -296,11 +332,11 @@
     }
 
     // remove [CONFIG_ID]
-    private static boolean cmdRemove(String[] args) {
+    private static boolean cmdRemove(String[] args, int idx) {
         // Get CONFIG_ID
         long configId;
         try {
-            configId = getConfigId(false, args, 1);
+            configId = getConfigId(false, args, idx + 1);
         } catch (NumberFormatException e) {
             sLogger.severe("Invalid config id provided.");
             printHelp();
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index 75518a3..d5da0b4 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -37,6 +37,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -67,10 +68,12 @@
     };
     private static final String[] DEFAULT_PULL_SOURCES = {
             "AID_SYSTEM",
+            "AID_RADIO"
     };
     private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName());
 
     private String mAdditionalAllowedPackage;
+    private String mDeviceSerial;
     private final Set<Long> mTrackedMetrics = new HashSet<>();
 
     public static void main(String[] args) {
@@ -81,15 +84,41 @@
 
         if (args.length < 1) {
             LOGGER.log(Level.SEVERE, "Usage: ./test_drive [-p additional_allowed_package] "
+                    + "[-s DEVICE_SERIAL_NUMBER]"
                     + "<atomId1> <atomId2> ... <atomIdN>");
             return;
         }
 
-        if (args.length >= 3 && args[0].equals("-p")) {
-            testDrive.mAdditionalAllowedPackage = args[1];
+        List<String> connectedDevices = Utils.getDeviceSerials(LOGGER);
+        if (connectedDevices == null || connectedDevices.size() == 0) {
+            LOGGER.log(Level.SEVERE, "No device connected.");
+            return;
         }
 
-        for (int i = testDrive.mAdditionalAllowedPackage == null ? 0 : 2; i < args.length; i++) {
+        int arg_index = 0;
+        while (arg_index < args.length) {
+            String arg = args[arg_index];
+            if (arg.equals("-p")) {
+                testDrive.mAdditionalAllowedPackage = args[++arg_index];
+            } else if (arg.equals("-s")) {
+                testDrive.mDeviceSerial = args[++arg_index];
+            } else {
+                break;
+            }
+            arg_index++;
+        }
+
+        if (connectedDevices.size() == 1 && testDrive.mDeviceSerial == null) {
+            testDrive.mDeviceSerial = connectedDevices.get(0);
+        }
+
+        if (testDrive.mDeviceSerial == null) {
+            LOGGER.log(Level.SEVERE, "More than one devices connected. Please specify"
+                    + " with -s DEVICE_SERIAL");
+            return;
+        }
+
+        for (int i = arg_index; i < args.length; i++) {
             try {
                 int atomId = Integer.valueOf(args[i]);
                 if (Atom.getDescriptor().findFieldByNumber(atomId) == null) {
@@ -109,7 +138,7 @@
                 LOGGER.log(Level.SEVERE, "Failed to create valid config.");
                 return;
             }
-            remoteConfigPath = testDrive.pushConfig(config);
+            remoteConfigPath = testDrive.pushConfig(config, testDrive.mDeviceSerial);
             LOGGER.info("Pushed the following config to statsd:");
             LOGGER.info(config.toString());
             if (!hasPulledAtom(trackedAtoms)) {
@@ -120,17 +149,18 @@
             } else {
                 LOGGER.info("Now wait for 1.5 minutes ...");
                 Thread.sleep(15_000);
-                Utils.logAppBreadcrumb(0, 0, LOGGER);
+                Utils.logAppBreadcrumb(0, 0, LOGGER, testDrive.mDeviceSerial);
                 Thread.sleep(75_000);
             }
             testDrive.dumpMetrics();
         } catch (Exception e) {
             LOGGER.log(Level.SEVERE, "Failed to test drive: " + e.getMessage(), e);
         } finally {
-            testDrive.removeConfig();
+            testDrive.removeConfig(testDrive.mDeviceSerial);
             if (remoteConfigPath != null) {
                 try {
-                    Utils.runCommand(null, LOGGER, "adb", "shell", "rm", remoteConfigPath);
+                    Utils.runCommand(null, LOGGER,
+                            "adb", "-s", testDrive.mDeviceSerial, "shell", "rm", remoteConfigPath);
                 } catch (Exception e) {
                     LOGGER.log(Level.WARNING,
                             "Unable to remove remote config file: " + remoteConfigPath, e);
@@ -140,7 +170,8 @@
     }
 
     private void dumpMetrics() throws Exception {
-        ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER);
+        ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER,
+                mDeviceSerial);
         // We may get multiple reports. Take the last one.
         ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1);
         for (StatsLogReport statsLog : report.getMetricsList()) {
@@ -216,22 +247,24 @@
         return atomMatcherBuilder.build();
     }
 
-    private static String pushConfig(StatsdConfig config) throws IOException, InterruptedException {
+    private static String pushConfig(StatsdConfig config, String deviceSerial)
+            throws IOException, InterruptedException {
         File configFile = File.createTempFile("statsdconfig", ".config");
         configFile.deleteOnExit();
         Files.write(config.toByteArray(), configFile);
         String remotePath = "/data/local/tmp/" + configFile.getName();
-        Utils.runCommand(null, LOGGER, "adb", "push", configFile.getAbsolutePath(), remotePath);
-        Utils.runCommand(null, LOGGER,
-                "adb", "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG,
+        Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial,
+                "push", configFile.getAbsolutePath(), remotePath);
+        Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial,
+                "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG,
                 String.valueOf(CONFIG_ID));
         return remotePath;
     }
 
-    private static void removeConfig() {
+    private static void removeConfig(String deviceSerial) {
         try {
-            Utils.runCommand(null, LOGGER,
-                    "adb", "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID));
+            Utils.runCommand(null, LOGGER, "adb", "-s", deviceSerial,
+                    "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID));
         } catch (Exception e) {
             LOGGER.log(Level.SEVERE, "Failed to remove config: " + e.getMessage());
         }
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index f3759fd..67334f5 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -47,7 +47,6 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.KeyEvent;
-import android.view.SurfaceControl;
 import android.view.SurfaceView;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -1820,6 +1819,13 @@
 
     /**
      * Returns a list of system actions available in the system right now.
+     * <p>
+     * System actions that correspond to the global action constants will have matching action IDs.
+     * For example, an with id {@link #GLOBAL_ACTION_BACK} will perform the back action.
+     * </p>
+     * <p>
+     * These actions should be called by {@link #performGlobalAction}.
+     * </p>
      *
      * @return A list of available system actions.
      */
@@ -1981,8 +1987,6 @@
      * to declare the capability to take screenshot by setting the
      * {@link android.R.styleable#AccessibilityService_canTakeScreenshot}
      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
-     * This API only will support {@link Display#DEFAULT_DISPLAY} until {@link SurfaceControl}
-     * supports non-default displays.
      * </p>
      *
      * @param displayId The logic display id, must be {@link Display#DEFAULT_DISPLAY} for
@@ -1990,18 +1994,11 @@
      * @param executor Executor on which to run the callback.
      * @param callback The callback invoked when taking screenshot has succeeded or failed.
      *                 See {@link TakeScreenshotCallback} for details.
-     *
-     * @throws IllegalArgumentException if displayId is not {@link Display#DEFAULT_DISPLAY}.
      */
     public void takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor,
             @NonNull TakeScreenshotCallback callback) {
         Preconditions.checkNotNull(executor, "executor cannot be null");
         Preconditions.checkNotNull(callback, "callback cannot be null");
-
-        if (displayId != Display.DEFAULT_DISPLAY) {
-            throw new IllegalArgumentException("DisplayId isn't the default display");
-        }
-
         final IAccessibilityServiceConnection connection =
                 AccessibilityInteractionClient.getInstance().getConnection(
                         mConnectionId);
diff --git a/core/java/android/annotation/NonNull.java b/core/java/android/annotation/NonNull.java
index a95bf3b..c5aff9d 100644
--- a/core/java/android/annotation/NonNull.java
+++ b/core/java/android/annotation/NonNull.java
@@ -30,8 +30,8 @@
  * <p>
  * This is a marker annotation and it has no specific attributes.
  *
- * @paramDoc This value must never be {@code null}.
- * @returnDoc This value will never be {@code null}.
+ * @paramDoc This value cannot be {@code null}.
+ * @returnDoc This value cannot be {@code null}.
  * @hide
  */
 @Retention(SOURCE)
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2531c89..b6d519a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -73,8 +73,8 @@
 import android.util.DisplayMetrics;
 import android.util.Singleton;
 import android.util.Size;
-import android.window.WindowContainerToken;
 import android.view.Surface;
+import android.window.WindowContainerToken;
 
 import com.android.internal.app.LocalePicker;
 import com.android.internal.app.procstats.ProcessStats;
@@ -3632,7 +3632,8 @@
      * Set custom state data for this process. It will be included in the record of
      * {@link ApplicationExitInfo} on the death of the current calling process; the new process
      * of the app can retrieve this state data by calling
-     * {@link ApplicationExitInfo#getProcessStateSummary} on the record returned by
+     * {@link android.app.ApplicationExitInfo#getProcessStateSummary()
+     * ApplicationExitInfo.getProcessStateSummary()} on the record returned by
      * {@link #getHistoricalProcessExitReasons}.
      *
      * <p> This would be useful for the calling app to save its stateful data: if it's
@@ -3657,7 +3658,7 @@
         }
     }
 
-    /*
+    /**
      * @return Whether or not the low memory kill will be reported in
      * {@link #getHistoricalProcessExitReasons}.
      *
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 0ecc003..cfe0aff 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -90,7 +90,8 @@
      * {@link #REASON_SIGNALED} and {@link #getStatus} will return
      * the value {@link android.system.OsConstants#SIGKILL}.
      *
-     * Application should use {@link ActivityManager#isLowMemoryKillReportSupported} to check
+     * Application should use {@link android.app.ActivityManager#isLowMemoryKillReportSupported()
+     * ActivityManager.isLowMemoryKillReportSupported()} to check
      * if the device supports reporting {@link #REASON_LOW_MEMORY} or not.
      * </p>
      */
@@ -523,7 +524,7 @@
         return mReason;
     }
 
-    /*
+    /**
      * The exit status argument of exit() if the application calls it, or the signal
      * number if the application is signaled.
      */
@@ -538,7 +539,7 @@
         return mImportance;
     }
 
-    /*
+    /**
      * Last proportional set size of the memory that the process had used in kB.
      *
      * <p class="note">Note: This is the value from last sampling on the process,
@@ -562,7 +563,7 @@
 
     /**
      * The timestamp of the process's death, in milliseconds since the epoch,
-     * as returned by {@link System#currentTimeMillis System.currentTimeMillis()}.
+     * as returned by {@link java.lang.System#currentTimeMillis() System.currentTimeMillis()}.
      */
     public @CurrentTimeMillisLong long getTimestamp() {
         return mTimestamp;
@@ -586,8 +587,9 @@
     }
 
     /**
-     * Return the state data set by calling {@link ActivityManager#setProcessStateSummary}
-     * from the process before its death.
+     * Return the state data set by calling
+     * {@link android.app.ActivityManager#setProcessStateSummary(byte[])
+     * ActivityManager.setProcessStateSummary(byte[])} from the process before its death.
      *
      * @return The process-customized data
      * @see ActivityManager#setProcessStateSummary(byte[])
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a1ec27b..f883b60 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1610,7 +1610,10 @@
 
     @Override
     public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
-        Drawable badge = getProfileIconForDensity(user,
+        if (!hasUserBadge(user.getIdentifier())) {
+            return null;
+        }
+        Drawable badge = getDrawableForDensity(
                 getUserManager().getUserBadgeNoBackgroundResId(user.getIdentifier()), density);
         if (badge != null) {
             badge.setTint(getUserBadgeColor(user));
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index e476993..b7ceb6a 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -299,7 +299,6 @@
             in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
 
     void suppressResizeConfigChanges(boolean suppress);
-    void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
     boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
     boolean isInMultiWindowMode(in IBinder token);
     boolean isInPictureInPictureMode(in IBinder token);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f461a17..7a59349 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7158,7 +7158,8 @@
             CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
                     ? super.mBigContentTitle
                     : mConversationTitle;
-            if (!TextUtils.isEmpty(conversationTitle) && !hasOnlyWhiteSpaceSenders()) {
+            if (mConversationType == CONVERSATION_TYPE_LEGACY
+                    && !TextUtils.isEmpty(conversationTitle) && !hasOnlyWhiteSpaceSenders()) {
                 return conversationTitle;
             }
             return null;
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index eaee060..7a18b81 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -19,6 +19,7 @@
 import static android.content.Context.DISPLAY_SERVICE;
 import static android.content.Context.WINDOW_SERVICE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -191,12 +192,16 @@
         mDisplay = display;
         mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE);
 
+        final int windowType =
+                (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION
+                        : TYPE_PRESENTATION;
+
         final Window w = getWindow();
         final WindowManager.LayoutParams attr = w.getAttributes();
         attr.token = mToken;
         w.setAttributes(attr);
         w.setGravity(Gravity.FILL);
-        w.setType(TYPE_PRESENTATION);
+        w.setType(windowType);
         setCanceledOnTouchOutside(false);
     }
 
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index dc8269f..b96b54a 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -34,6 +34,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -306,7 +307,8 @@
  * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java
  *      bind}
  */
-public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
+public abstract class Service extends ContextWrapper implements ComponentCallbacks2,
+        ContentCaptureManager.ContentCaptureClient {
     private static final String TAG = "Service";
 
     /**
@@ -817,6 +819,14 @@
         writer.println("nothing to dump");
     }
 
+    @Override
+    protected void attachBaseContext(Context newBase) {
+        super.attachBaseContext(newBase);
+        if (newBase != null) {
+            newBase.setContentCaptureOptions(getContentCaptureOptions());
+        }
+    }
+
     // ------------------ Internal API ------------------
     
     /**
@@ -835,6 +845,8 @@
         mActivityManager = (IActivityManager)activityManager;
         mStartCompatibility = getApplicationInfo().targetSdkVersion
                 < Build.VERSION_CODES.ECLAIR;
+
+        setContentCaptureOptions(application.getContentCaptureOptions());
     }
 
     /**
@@ -849,6 +861,18 @@
         return mClassName;
     }
 
+    /** @hide */
+    @Override
+    public final ContentCaptureManager.ContentCaptureClient getContentCaptureClient() {
+        return this;
+    }
+
+    /** @hide */
+    @Override
+    public final ComponentName contentCaptureClientGetComponentName() {
+        return new ComponentName(this, mClassName);
+    }
+
     // set by the thread after the constructor and before onCreate(Bundle icicle) is called.
     @UnsupportedAppUsage
     private ActivityThread mThread = null;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 054e5e0..91a8572 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -186,6 +186,7 @@
 import android.telephony.TelephonyRegistryManager;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Slog;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.WindowManager;
@@ -222,6 +223,9 @@
 public final class SystemServiceRegistry {
     private static final String TAG = "SystemServiceRegistry";
 
+    /** @hide */
+    public static boolean sEnableServiceNotFoundWtf = false;
+
     // Service registry information.
     // This information is never changed once static initialization has completed.
     private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =
@@ -1364,8 +1368,30 @@
      * @hide
      */
     public static Object getSystemService(ContextImpl ctx, String name) {
-        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
-        return fetcher != null ? fetcher.getService(ctx) : null;
+        if (name == null) {
+            return null;
+        }
+        final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
+        if (fetcher == null) {
+            if (sEnableServiceNotFoundWtf) {
+                Slog.wtf(TAG, "Unknown manager requested: " + name);
+            }
+            return null;
+        }
+
+        final Object ret = fetcher.getService(ctx);
+        if (sEnableServiceNotFoundWtf && ret == null) {
+            // Some services do return null in certain situations, so don't do WTF for them.
+            switch (name) {
+                case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
+                case Context.APP_PREDICTION_SERVICE:
+                case Context.INCREMENTAL_SERVICE:
+                    return null;
+            }
+            Slog.wtf(TAG, "Manager wrapper not available: " + name);
+            return null;
+        }
+        return ret;
     }
 
     /**
@@ -1373,7 +1399,15 @@
      * @hide
      */
     public static String getSystemServiceName(Class<?> serviceClass) {
-        return SYSTEM_SERVICE_NAMES.get(serviceClass);
+        if (serviceClass == null) {
+            return null;
+        }
+        final String serviceName = SYSTEM_SERVICE_NAMES.get(serviceClass);
+        if (sEnableServiceNotFoundWtf && serviceName == null) {
+            // This should be a caller bug.
+            Slog.wtf(TAG, "Unknown manager requested: " + serviceClass.getCanonicalName());
+        }
+        return serviceName;
     }
 
     /**
@@ -1683,7 +1717,9 @@
                         try {
                             cache.wait();
                         } catch (InterruptedException e) {
-                            Log.w(TAG, "getService() interrupted");
+                            // This shouldn't normally happen, but if someone interrupts the
+                            // thread, it will.
+                            Slog.wtf(TAG, "getService() interrupted");
                             Thread.currentThread().interrupt();
                             return null;
                         }
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 7b45b72..ab86860 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -44,7 +44,7 @@
             "name": "CtsWindowManagerDeviceTestCases",
             "options": [
                 {
-                    "include-filter": "android.server.wm.ToastTest"
+                    "include-filter": "android.server.wm.ToastWindowTest"
                 }
             ],
             "file_patterns": ["INotificationManager\\.aidl"]
diff --git a/core/java/android/app/admin/DevicePolicyKeyguardService.java b/core/java/android/app/admin/DevicePolicyKeyguardService.java
index 5b7e387..db833ec 100644
--- a/core/java/android/app/admin/DevicePolicyKeyguardService.java
+++ b/core/java/android/app/admin/DevicePolicyKeyguardService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
@@ -28,14 +29,16 @@
 /**
  * Client interface for providing the SystemUI with secondary lockscreen information.
  *
- * <p>An implementation must be provided by the Profile Owner when
- * {@link DevicePolicyManager#setSecondaryLockscreenEnabled} is set to true and the service must be
- * declared in the manifest as handling the action
+ * <p>An implementation must be provided by the default configured supervision app that is set as
+ * Profile Owner or Device Owner when {@link DevicePolicyManager#setSecondaryLockscreenEnabled} is
+ * set to true and the service must be declared in the manifest as handling the action
  * {@link DevicePolicyManager#ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE}, otherwise the keyguard
  * will fail to bind to the service and continue to unlock.
  *
  * @see DevicePolicyManager#setSecondaryLockscreenEnabled
+ * @hide
  */
+@SystemApi
 public class DevicePolicyKeyguardService extends Service {
     private static final String TAG = "DevicePolicyKeyguardService";
     private IKeyguardCallback mCallback;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 10309a9..faf9ec6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2395,9 +2395,11 @@
     public static final int MAX_PASSWORD_LENGTH = 16;
 
     /**
-     * Service Action: Service implemented by a device owner or profile owner to provide a
-     * secondary lockscreen.
+     * Service Action: Service implemented by a device owner or profile owner supervision app to
+     * provide a secondary lockscreen.
+     * @hide
      */
+    @SystemApi
     public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE =
             "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
 
@@ -7001,6 +7003,22 @@
     }
 
     /**
+     * Returns the configured supervision app if it exists and is the device owner or policy owner.
+     * @hide
+     */
+    public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(
+            @NonNull UserHandle user) {
+        if (mService != null) {
+            try {
+                return mService.getProfileOwnerOrDeviceOwnerSupervisionComponent(user);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return null;
+    }
+
+    /**
      * @hide
      * @return the human readable name of the organisation associated with this DPM or {@code null}
      *         if one is not set.
@@ -8637,11 +8655,16 @@
      * <p>Relevant interactions on the secondary lockscreen should be communicated back to the
      * keyguard via {@link IKeyguardCallback}, such as when the screen is ready to be dismissed.
      *
+     * <p>This API, and associated APIs, can only be called by the default supervision app when it
+     * is set as the device owner or profile owner.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param enabled Whether or not the lockscreen needs to be shown.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      * @see #isSecondaryLockscreenEnabled
+     * @hide
      **/
+    @SystemApi
     public void setSecondaryLockscreenEnabled(@NonNull ComponentName admin, boolean enabled) {
         throwIfParentInstance("setSecondaryLockscreenEnabled");
         if (mService != null) {
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 80fa871..41f04f7 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -176,19 +176,31 @@
      * for cross-profile communication, via {@link
      * DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)}.</li>
      * <li>The default package names that are allowed to request user consent for cross-profile
-     * communication without being explicitly enabled by the admin , via {@link
-     * DevicePolicyManager#setDefaultCrossProfilePackages(ComponentName, UserHandle, Set)}.</li>
+     * communication without being explicitly enabled by the admin, via
+     * {@link com.android.internal.R.array#cross_profile_apps} and
+     * {@link com.android.internal.R.array#vendor_cross_profile_apps}.</li>
      * </ul>
      *
      * @return the combined set of whitelisted package names set via
      * {@link DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)} and
-     * {@link DevicePolicyManager#setDefaultCrossProfilePackages(ComponentName, UserHandle, Set)}
+     * {@link com.android.internal.R.array#cross_profile_apps} and
+     * {@link com.android.internal.R.array#vendor_cross_profile_apps}
      *
      * @hide
      */
     public abstract List<String> getAllCrossProfilePackages();
 
     /**
+     * Returns the default package names set by the OEM that are allowed to request user consent for
+     * cross-profile communication without being explicitly enabled by the admin, via
+     * {@link com.android.internal.R.array#cross_profile_apps} and
+     * {@link com.android.internal.R.array#vendor_cross_profile_apps}.
+     *
+     * @hide
+     */
+    public abstract List<String> getDefaultCrossProfilePackages();
+
+    /**
      * Sends the {@code intent} to the packages with cross profile capabilities.
      *
      * <p>This means the application must have the {@code crossProfile} property and the
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index fc1eb0a..591a3f6 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -155,6 +155,7 @@
     boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
     ComponentName getProfileOwnerAsUser(int userHandle);
     ComponentName getProfileOwner(int userHandle);
+    ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(in UserHandle userHandle);
     String getProfileOwnerName(int userHandle);
     void setProfileEnabled(in ComponentName who);
     void setProfileName(in ComponentName who, String profileName);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f216db6..fc48e7f 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -979,17 +979,14 @@
                 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) {
                 @Override
                 protected Integer recompute(Void query) {
+                    // This function must be called while holding the
+                    // mServiceLock, and with mService not null. The public
+                    // getState() method makes this guarantee.
                     try {
-                        mServiceLock.readLock().lock();
-                        if (mService != null) {
-                            return mService.getState();
-                        }
+                        return mService.getState();
                     } catch (RemoteException e) {
-                        Log.e(TAG, "", e);
-                    } finally {
-                        mServiceLock.readLock().unlock();
+                        throw e.rethrowFromSystemServer();
                     }
-                    return BluetoothAdapter.STATE_OFF;
                 }
             };
 
@@ -1016,7 +1013,24 @@
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     @AdapterState
     public int getState() {
-        int state = mBluetoothGetStateCache.query(null);
+        int state = BluetoothAdapter.STATE_OFF;
+
+        try {
+            mServiceLock.readLock().lock();
+            // The test for mService must either be outside the cache, or
+            // the cache must be invalidated when mService changes.
+            if (mService != null) {
+                state = mBluetoothGetStateCache.query(null);
+            }
+        } catch (RuntimeException e) {
+            if (e.getCause() instanceof RemoteException) {
+                Log.e(TAG, "", e.getCause());
+            } else {
+                throw e;
+            }
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
 
         // Consider all internal states as OFF
         if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 7578ede..144a07e 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -435,6 +435,9 @@
      * <p>This differs from {@link #canConfigureInteractAcrossProfiles(String)} since it will
      * not return {@code false} if the app is not whitelisted or not installed in the other profile.
      *
+     * <p>Note that platform-signed apps that are automatically granted the permission and are not
+     * whitelisted by the OEM will not be included in this list.
+     *
      * @hide
      */
     public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
diff --git a/core/java/android/content/pm/FileSystemControlParcel.aidl b/core/java/android/content/pm/FileSystemControlParcel.aidl
index f00feae..92df16c 100644
--- a/core/java/android/content/pm/FileSystemControlParcel.aidl
+++ b/core/java/android/content/pm/FileSystemControlParcel.aidl
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.content.pm.IPackageInstallerSessionFileSystemConnector;
+import android.os.incremental.IIncrementalServiceConnector;
 import android.os.incremental.IncrementalFileSystemControlParcel;
 
 /**
@@ -26,6 +27,8 @@
 parcelable FileSystemControlParcel {
     // Incremental FS control descriptors.
     @nullable IncrementalFileSystemControlParcel incremental;
+    // Incremental FS service.
+    @nullable IIncrementalServiceConnector service;
     // Callback-based installation connector.
     @nullable IPackageInstallerSessionFileSystemConnector callback;
 }
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 27c9cfc..aa29040 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -25,6 +25,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IOnAppsChangedListener;
 import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutQueryWrapper;
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IShortcutChangeCallback;
 import android.content.pm.PackageInstaller;
@@ -67,9 +68,8 @@
     LauncherApps.AppUsageLimit getAppUsageLimit(String callingPackage, String packageName,
             in UserHandle user);
 
-    ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
-            in List shortcutIds, in List<LocusId> locusIds, in ComponentName componentName,
-            int flags, in UserHandle user);
+    ParceledListSlice getShortcuts(String callingPackage, in ShortcutQueryWrapper query,
+            in UserHandle user);
     void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
             in UserHandle user);
     boolean startShortcut(String callingPackage, String packageName, String featureId, String id,
@@ -93,9 +93,8 @@
             in IPackageInstallerCallback callback);
     ParceledListSlice getAllSessions(String callingPackage);
 
-    void registerShortcutChangeCallback(String callingPackage, long changedSince,
-            String packageName, in List shortcutIds, in List<LocusId> locusIds,
-            in ComponentName componentName, int flags, in IShortcutChangeCallback callback);
+    void registerShortcutChangeCallback(String callingPackage, in ShortcutQueryWrapper query,
+	    in IShortcutChangeCallback callback);
     void unregisterShortcutChangeCallback(String callingPackage,
             in IShortcutChangeCallback callback);
 
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 5bad055..8bebaff 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -306,6 +306,35 @@
     void setHomeActivity(in ComponentName className, int userId);
 
     /**
+     * Overrides the label and icon of the component specified by the component name. The component
+     * must belong to the calling app.
+     *
+     * These changes will be reset on the next boot and whenever the package is updated.
+     *
+     * Only the app defined as com.android.internal.R.config_overrideComponentUiPackage is allowed
+     * to call this.
+     *
+     * @param componentName The component name to override the label/icon of.
+     * @param nonLocalizedLabel The label to be displayed.
+     * @param icon The icon to be displayed.
+     * @param userId The user id.
+     */
+    void overrideLabelAndIcon(in ComponentName componentName, String nonLocalizedLabel,
+            int icon, int userId);
+
+    /**
+     * Restores the label and icon of the activity specified by the component name if either has
+     * been overridden. The component must belong to the calling app.
+     *
+     * Only the app defined as com.android.internal.R.config_overrideComponentUiPackage is allowed
+     * to call this.
+     *
+     * @param componentName The component name.
+     * @param userId The user id.
+     */
+    void restoreLabelAndIcon(in ComponentName componentName, int userId);
+
+    /**
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
     @UnsupportedAppUsage
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 6c161fc..87dc0a1 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -1046,8 +1046,7 @@
             // changed callback, but that only returns shortcuts with the "key" information, so
             // that won't return disabled message.
             return maybeUpdateDisabledMessage(mService.getShortcuts(mContext.getPackageName(),
-                    query.mChangedSince, query.mPackage, query.mShortcutIds, query.mLocusIds,
-                    query.mActivity, query.mQueryFlags, user)
+                    new ShortcutQueryWrapper(query), user)
                     .getList());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1826,8 +1825,7 @@
             mShortcutChangeCallbacks.put(callback, new Pair<>(executor, proxy));
             try {
                 mService.registerShortcutChangeCallback(mContext.getPackageName(),
-                        query.mChangedSince, query.mPackage, query.mShortcutIds, query.mLocusIds,
-                        query.mActivity, query.mQueryFlags, proxy);
+                        new ShortcutQueryWrapper(query), proxy);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f48d78a..9a2e07e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1542,6 +1542,14 @@
      */
     public static final int INSTALL_FAILED_PROCESS_NOT_DEFINED = -122;
 
+    /**
+     * Installation parse return code: system is in a minimal boot state, and the parser only
+     * allows the package with {@code coreApp} manifest attribute to be a valid application.
+     *
+     * @hide
+     */
+    public static final int INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED = -123;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DELETE_" }, value = {
             DELETE_KEEP_DATA,
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 61b1553..327d1b8 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -27,18 +27,24 @@
 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
 import android.content.pm.parsing.component.ParsedMainComponent;
 import android.os.BaseBundle;
 import android.os.Debug;
 import android.os.PersistableBundle;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DebugUtils;
+import android.util.Pair;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -84,6 +90,9 @@
     private ArrayMap<String, String[]> sharedLibraryOverlayPaths; // Lib name to overlay paths
     private String[] cachedOverlayPaths;
 
+    @Nullable
+    private ArrayMap<ComponentName, Pair<String, Integer>> componentLabelIconOverrideMap;
+
     @UnsupportedAppUsage
     public PackageUserState() {
         installed = true;
@@ -123,6 +132,9 @@
             sharedLibraryOverlayPaths = new ArrayMap<>(o.sharedLibraryOverlayPaths);
         }
         harmfulAppWarning = o.harmfulAppWarning;
+        if (o.componentLabelIconOverrideMap != null) {
+            this.componentLabelIconOverrideMap = new ArrayMap<>(o.componentLabelIconOverrideMap);
+        }
     }
 
     public String[] getOverlayPaths() {
@@ -147,6 +159,65 @@
     }
 
     /**
+     * Overrides the non-localized label and icon of a component.
+     *
+     * @return true if the label or icon was changed.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public boolean overrideLabelAndIcon(@NonNull ComponentName component,
+            @Nullable String nonLocalizedLabel, @Nullable Integer icon) {
+        String existingLabel = null;
+        Integer existingIcon = null;
+
+        if (componentLabelIconOverrideMap != null) {
+            Pair<String, Integer> pair = componentLabelIconOverrideMap.get(component);
+            if (pair != null) {
+                existingLabel = pair.first;
+                existingIcon = pair.second;
+            }
+        }
+
+        boolean changed = !TextUtils.equals(existingLabel, nonLocalizedLabel)
+                || !Objects.equals(existingIcon, icon);
+
+        if (changed) {
+            if (nonLocalizedLabel == null && icon == null) {
+                componentLabelIconOverrideMap.remove(component);
+                if (componentLabelIconOverrideMap.isEmpty()) {
+                    componentLabelIconOverrideMap = null;
+                }
+            } else {
+                if (componentLabelIconOverrideMap == null) {
+                    componentLabelIconOverrideMap = new ArrayMap<>(1);
+                }
+
+                componentLabelIconOverrideMap.put(component, Pair.create(nonLocalizedLabel, icon));
+            }
+        }
+
+        return changed;
+    }
+
+    /**
+     * Clears all values previously set by {@link #overrideLabelAndIcon(ComponentName,
+     * String, Integer)}.
+     *
+     * This is done when the package is updated as the components and resource IDs may have changed.
+     */
+    public void resetOverrideComponentLabelIcon() {
+        componentLabelIconOverrideMap = null;
+    }
+
+    @Nullable
+    public Pair<String, Integer> getOverrideLabelIconForComponent(ComponentName componentName) {
+        if (ArrayUtils.isEmpty(componentLabelIconOverrideMap)) {
+            return null;
+        }
+
+        return componentLabelIconOverrideMap.get(componentName);
+    }
+
+    /**
      * Test if this package is installed.
      */
     public boolean isAvailable(int flags) {
diff --git a/core/java/android/content/pm/ShortcutQueryWrapper.aidl b/core/java/android/content/pm/ShortcutQueryWrapper.aidl
new file mode 100644
index 0000000..d02600a
--- /dev/null
+++ b/core/java/android/content/pm/ShortcutQueryWrapper.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable ShortcutQueryWrapper;
+
diff --git a/core/java/android/content/pm/ShortcutQueryWrapper.java b/core/java/android/content/pm/ShortcutQueryWrapper.java
new file mode 100644
index 0000000..c613441
--- /dev/null
+++ b/core/java/android/content/pm/ShortcutQueryWrapper.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.LocusId;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide
+ */
+@DataClass(genParcelable = true, genToString = true)
+public final class ShortcutQueryWrapper extends LauncherApps.ShortcutQuery implements Parcelable {
+
+    public ShortcutQueryWrapper(LauncherApps.ShortcutQuery query) {
+        this();
+        mChangedSince = query.mChangedSince;
+        mPackage = query.mPackage;
+        mLocusIds = query.mLocusIds;
+        mShortcutIds = query.mShortcutIds;
+        mActivity = query.mActivity;
+        mQueryFlags = query.mQueryFlags;
+    }
+
+    public long getChangedSince() {
+        return mChangedSince;
+    }
+
+    @Nullable
+    public String getPackage() {
+        return mPackage;
+    }
+
+    @Nullable
+    public List<LocusId> getLocusIds() {
+        return mLocusIds;
+    }
+
+    @Nullable
+    public List<String> getShortcutIds() {
+        return mShortcutIds;
+    }
+
+    @Nullable
+    public ComponentName getActivity() {
+        return mActivity;
+    }
+
+    public int getQueryFlags() {
+        return mQueryFlags;
+    }
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/ShortcutQueryWrapper.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    public ShortcutQueryWrapper() {
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "ShortcutQueryWrapper { " +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mPackage != null) flg |= 0x2;
+        if (mShortcutIds != null) flg |= 0x4;
+        if (mLocusIds != null) flg |= 0x8;
+        if (mActivity != null) flg |= 0x10;
+        dest.writeByte(flg);
+        dest.writeLong(mChangedSince);
+        if (mPackage != null) dest.writeString(mPackage);
+        if (mShortcutIds != null) dest.writeStringList(mShortcutIds);
+        if (mLocusIds != null) dest.writeParcelableList(mLocusIds, flags);
+        if (mActivity != null) dest.writeTypedObject(mActivity, flags);
+        dest.writeInt(mQueryFlags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ ShortcutQueryWrapper(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        long changedSince = in.readLong();
+        String pkg = (flg & 0x2) == 0 ? null : in.readString();
+        List<String> shortcutIds = null;
+        if ((flg & 0x4) != 0) {
+            shortcutIds = new ArrayList<>();
+            in.readStringList(shortcutIds);
+        }
+        List<LocusId> locusIds = null;
+        if ((flg & 0x8) != 0) {
+            locusIds = new ArrayList<>();
+            in.readParcelableList(locusIds, LocusId.class.getClassLoader());
+        }
+        ComponentName activity = (flg & 0x10) == 0 ? null
+                : (ComponentName) in.readTypedObject(ComponentName.CREATOR);
+        int queryFlags = in.readInt();
+
+        this.mChangedSince = changedSince;
+        this.mPackage = pkg;
+        this.mShortcutIds = shortcutIds;
+        this.mLocusIds = locusIds;
+        this.mActivity = activity;
+        this.mQueryFlags = queryFlags;
+        com.android.internal.util.AnnotationValidations.validate(
+                QueryFlags.class, null, mQueryFlags);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ShortcutQueryWrapper> CREATOR
+            = new Parcelable.Creator<ShortcutQueryWrapper>() {
+        @Override
+        public ShortcutQueryWrapper[] newArray(int size) {
+            return new ShortcutQueryWrapper[size];
+        }
+
+        @Override
+        public ShortcutQueryWrapper createFromParcel(@NonNull Parcel in) {
+            return new ShortcutQueryWrapper(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1582049937960L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/content/pm/ShortcutQueryWrapper.java",
+            inputSignatures = "public  long getChangedSince()\npublic @android.annotation.Nullable java.lang.String getPackage()\npublic @android.annotation.Nullable java.util.List<android.content.LocusId> getLocusIds()\npublic @android.annotation.Nullable java.util.List<java.lang.String> getShortcutIds()\npublic @android.annotation.Nullable android.content.ComponentName getActivity()\npublic  int getQueryFlags()\nclass ShortcutQueryWrapper extends android.content.pm.LauncherApps.ShortcutQuery implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 435c70a..eee91ce 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -109,4 +109,8 @@
      */
     public abstract String getShortcutIconUri(int launcherUserId, @NonNull String launcherPackage,
             @NonNull String packageName, @NonNull String shortcutId, int userId);
+
+    public abstract boolean isSharingShortcut(int callingUserId, @NonNull String callingPackage,
+            @NonNull String packageName, @NonNull String shortcutId, int userId,
+            @NonNull IntentFilter filter);
 }
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 894ad55..be1817d 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -322,7 +322,12 @@
     private String className;
     private int compatibleWidthLimitDp;
     private int descriptionRes;
-    private boolean enabled;
+
+    // Usually there's code to set this to true during parsing, but it's possible to install an APK
+    // targeting <R that doesn't contain an <application> tag. That code would be skipped and never
+    // assign this, so initialize this to true for those cases.
+    private boolean enabled = true;
+
     private boolean crossProfile;
     private int fullBackupContent;
     private int iconRes;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 12328cf..c94d428 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -22,6 +22,7 @@
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
 import static android.os.Build.VERSION_CODES.DONUT;
 import static android.os.Build.VERSION_CODES.O;
@@ -229,7 +230,8 @@
         final PackageParser.PackageLite lite = ApkLiteParseUtils.parseClusterPackageLite(packageDir,
                 0);
         if (mOnlyCoreApps && !lite.coreApp) {
-            return input.error("Not a coreApp: " + packageDir);
+            return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
+                    "Not a coreApp: " + packageDir);
         }
 
         // Build the split dependency tree.
@@ -291,7 +293,8 @@
         final PackageParser.PackageLite lite = ApkLiteParseUtils.parseMonolithicPackageLite(apkFile,
                 flags);
         if (mOnlyCoreApps && !lite.coreApp) {
-            return input.error("Not a coreApp: " + apkFile);
+            return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
+                    "Not a coreApp: " + apkFile);
         }
 
         final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d6a9f69..c399bc7 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -40,6 +40,7 @@
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
 import android.annotation.XmlRes;
+import android.app.Application;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
@@ -58,9 +59,11 @@
 import android.util.LongSparseArray;
 import android.util.Pools.SynchronizedPool;
 import android.util.TypedValue;
+import android.view.Display;
 import android.view.DisplayAdjustments;
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -101,6 +104,12 @@
  * (such as for different languages and screen sizes). This is an important aspect of developing
  * Android applications that are compatible on different types of devices.</p>
  *
+ * <p>After {@link Build.VERSION_CODES#R}, {@link Resources} must be obtained by
+ * {@link android.app.Activity} or {@link android.content.Context} created with
+ * {@link android.content.Context#createWindowContext(int, Bundle)}.
+ * {@link Application#getResources()} may report wrong values in multi-window or on secondary
+ * displays.
+ *
  * <p>For more information about using resources, see the documentation about <a
  * href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p>
  */
@@ -2024,10 +2033,20 @@
     }
 
     /**
-     * Return the current display metrics that are in effect for this resource 
-     * object.  The returned object should be treated as read-only.
-     * 
-     * @return The resource's current display metrics. 
+     * Return the current display metrics that are in effect for this resource
+     * object. The returned object should be treated as read-only.
+     *
+     * <p>Note that the reported value may be different than the window this application is
+     * interested in.</p>
+     *
+     * <p>Best practices are to obtain metrics from {@link WindowManager#getCurrentWindowMetrics()}
+     * for window bounds, {@link Display#getRealMetrics(DisplayMetrics)} for display bounds and
+     * obtain density from {@link Configuration#densityDpi}. The value obtained from this API may be
+     * wrong if the {@link Resources} is from the context which is different than the window is
+     * attached such as {@link Application#getResources()}.
+     * <p/>
+     *
+     * @return The resource's current display metrics.
      */
     public DisplayMetrics getDisplayMetrics() {
         return mResourcesImpl.getDisplayMetrics();
diff --git a/core/java/android/content/res/TEST_MAPPING b/core/java/android/content/res/TEST_MAPPING
index daf9a14..9ebc996 100644
--- a/core/java/android/content/res/TEST_MAPPING
+++ b/core/java/android/content/res/TEST_MAPPING
@@ -1,7 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "FrameworksResourceLoaderTests"
+      "name": "CtsResourcesLoaderTests"
     }
   ]
 }
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 65f45d8..ea5cc7f 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -634,17 +634,39 @@
     public VirtualDisplay createVirtualDisplay(@NonNull String name,
             int width, int height, int densityDpi, @Nullable Surface surface, int flags,
             @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
-        return createVirtualDisplay(null /* projection */, name, width, height, densityDpi, surface,
-                flags, callback, handler, null /* uniqueId */);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+                height, densityDpi);
+        builder.setFlags(flags);
+        if (surface != null) {
+            builder.setSurface(surface);
+        }
+        return createVirtualDisplay(null /* projection */, builder.build(), callback, handler);
     }
 
+    // TODO : Remove this hidden API after remove all callers. (Refer to MultiDisplayService)
     /** @hide */
     public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
             @NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface,
             int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
             @Nullable String uniqueId) {
-        return mGlobal.createVirtualDisplay(mContext, projection,
-                name, width, height, densityDpi, surface, flags, callback, handler, uniqueId);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+                height, densityDpi);
+        builder.setFlags(flags);
+        if (uniqueId != null) {
+            builder.setUniqueId(uniqueId);
+        }
+        if (surface != null) {
+            builder.setSurface(surface);
+        }
+        return createVirtualDisplay(projection, builder.build(), callback, handler);
+    }
+
+    /** @hide */
+    public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
+            @NonNull VirtualDisplayConfig virtualDisplayConfig,
+            @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+        return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback,
+                handler);
     }
 
     /**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 526db85..4d645e6 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -451,35 +451,26 @@
         }
     }
 
-    public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
-            String name, int width, int height, int densityDpi, Surface surface, int flags,
-            VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
-        if (TextUtils.isEmpty(name)) {
-            throw new IllegalArgumentException("name must be non-null and non-empty");
-        }
-        if (width <= 0 || height <= 0 || densityDpi <= 0) {
-            throw new IllegalArgumentException("width, height, and densityDpi must be "
-                    + "greater than 0");
-        }
-
+    public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection,
+            @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback,
+            Handler handler) {
         VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
         IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
         int displayId;
         try {
-            displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
-                    context.getPackageName(), name, width, height, densityDpi, surface, flags,
-                    uniqueId);
+            displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper,
+                    projectionToken, context.getPackageName());
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
         if (displayId < 0) {
-            Log.e(TAG, "Could not create virtual display: " + name);
+            Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName());
             return null;
         }
         Display display = getRealDisplay(displayId);
         if (display == null) {
             Log.wtf(TAG, "Could not obtain display info for newly created "
-                    + "virtual display: " + name);
+                    + "virtual display: " + virtualDisplayConfig.getName());
             try {
                 mDm.releaseVirtualDisplay(callbackWrapper);
             } catch (RemoteException ex) {
@@ -487,7 +478,8 @@
             }
             return null;
         }
-        return new VirtualDisplay(this, display, callbackWrapper, surface);
+        return new VirtualDisplay(this, display, callbackWrapper,
+                virtualDisplayConfig.getSurface());
     }
 
     public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index ea2b9e7..462110f 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -17,6 +17,7 @@
 package android.hardware.display;
 
 import android.annotation.Nullable;
+import android.graphics.Point;
 import android.hardware.SensorManager;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -72,6 +73,15 @@
     public abstract SurfaceControl.ScreenshotGraphicBuffer screenshot(int displayId);
 
     /**
+     * Take a screenshot without secure layer of the specified display and return a buffer.
+     *
+     * @param displayId The display id to take the screenshot of.
+     * @return The buffer or null if we have failed.
+     */
+    public abstract SurfaceControl.ScreenshotGraphicBuffer screenshotWithoutSecureLayer(
+            int displayId);
+
+    /**
      * Returns information about the specified logical display.
      *
      * @param displayId The logical display id.
@@ -81,6 +91,16 @@
     public abstract DisplayInfo getDisplayInfo(int displayId);
 
     /**
+     * Returns the position of the display's projection.
+     *
+     * @param displayId The logical display id.
+     * @return The x, y coordinates of the display, or null if the display does not exist. The
+     * return object must be treated as immutable.
+     */
+    @Nullable
+    public abstract Point getDisplayPosition(int displayId);
+
+    /**
      * Registers a display transaction listener to provide the client a chance to
      * update its surfaces within the same transaction as any display layout updates.
      *
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index d22188e..c697106 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -22,6 +22,7 @@
 import android.hardware.display.Curve;
 import android.hardware.display.IDisplayManagerCallback;
 import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
 import android.hardware.display.WifiDisplay;
 import android.hardware.display.WifiDisplayStatus;
 import android.media.projection.IMediaProjection;
@@ -71,9 +72,9 @@
 
     // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
     // MediaProjection token for certain combinations of flags.
-    int createVirtualDisplay(in IVirtualDisplayCallback callback,
-            in IMediaProjection projectionToken, String packageName, String name,
-            int width, int height, int densityDpi, in Surface surface, int flags, String uniqueId);
+    int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig,
+            in IVirtualDisplayCallback callback, in IMediaProjection projectionToken,
+            String packageName);
 
     // No permissions required, but must be same Uid as the creator.
     void resizeVirtualDisplay(in IVirtualDisplayCallback token,
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.aidl b/core/java/android/hardware/display/VirtualDisplayConfig.aidl
new file mode 100644
index 0000000..c28f1df
--- /dev/null
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+parcelable VirtualDisplayConfig;
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
new file mode 100644
index 0000000..10e1c7c
--- /dev/null
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.projection.MediaProjection;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Surface;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Holds configuration used to create {@link VirtualDisplay} instances. See
+ * {@link MediaProjection#createVirtualDisplay(VirtualDisplayConfig, VirtualDisplay.Callback, Handler)}.
+ *
+ * @hide
+ */
+@DataClass(genParcelable = true, genAidl = true, genBuilder = true)
+public final class VirtualDisplayConfig implements Parcelable {
+    /**
+     * The name of the virtual display, must be non-empty.
+     */
+    @NonNull
+    private String mName;
+
+    /**
+     * The width of the virtual display in pixels. Must be greater than 0.
+     */
+    @IntRange(from = 1)
+    private int mWidth;
+
+    /**
+     * The height of the virtual display in pixels. Must be greater than 0.
+     */
+    @IntRange(from = 1)
+    private int mHeight;
+
+    /**
+     * The density of the virtual display in dpi. Must be greater than 0.
+     */
+    @IntRange(from = 1)
+    private int mDensityDpi;
+
+    /**
+     * A combination of virtual display flags.
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+     * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+     */
+    private int mFlags = 0;
+
+    /**
+     * The surface to which the content of the virtual display should be rendered, or null if
+     * there is none initially.
+     */
+    @Nullable
+    private Surface mSurface = null;
+
+    /**
+     * The unique identifier for the display. Shouldn't be displayed to the user.
+     * @hide
+     */
+    @Nullable
+    private String mUniqueId = null;
+
+    /**
+     * The id of the display that the virtual display should mirror, or
+     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+     */
+    private int mDisplayIdToMirror = DEFAULT_DISPLAY;
+
+
+
+    // Code below generated by codegen v1.0.15.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ VirtualDisplayConfig(
+            @NonNull String name,
+            @IntRange(from = 1) int width,
+            @IntRange(from = 1) int height,
+            @IntRange(from = 1) int densityDpi,
+            int flags,
+            @Nullable Surface surface,
+            @Nullable String uniqueId,
+            int displayIdToMirror) {
+        this.mName = name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mName);
+        this.mWidth = width;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mWidth,
+                "from", 1);
+        this.mHeight = height;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mHeight,
+                "from", 1);
+        this.mDensityDpi = densityDpi;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mDensityDpi,
+                "from", 1);
+        this.mFlags = flags;
+        this.mSurface = surface;
+        this.mUniqueId = uniqueId;
+        this.mDisplayIdToMirror = displayIdToMirror;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The name of the virtual display, must be non-empty.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getName() {
+        return mName;
+    }
+
+    /**
+     * The width of the virtual display in pixels. Must be greater than 0.
+     */
+    @DataClass.Generated.Member
+    public @IntRange(from = 1) int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * The height of the virtual display in pixels. Must be greater than 0.
+     */
+    @DataClass.Generated.Member
+    public @IntRange(from = 1) int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * The density of the virtual display in dpi. Must be greater than 0.
+     */
+    @DataClass.Generated.Member
+    public @IntRange(from = 1) int getDensityDpi() {
+        return mDensityDpi;
+    }
+
+    /**
+     * A combination of virtual display flags.
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
+     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+     * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+     */
+    @DataClass.Generated.Member
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * The surface to which the content of the virtual display should be rendered, or null if
+     * there is none initially.
+     */
+    @DataClass.Generated.Member
+    public @Nullable Surface getSurface() {
+        return mSurface;
+    }
+
+    /**
+     * The unique identifier for the display. Shouldn't be displayed to the user.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getUniqueId() {
+        return mUniqueId;
+    }
+
+    /**
+     * The id of the display that the virtual display should mirror, or
+     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+     */
+    @DataClass.Generated.Member
+    public int getDisplayIdToMirror() {
+        return mDisplayIdToMirror;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        int flg = 0;
+        if (mSurface != null) flg |= 0x20;
+        if (mUniqueId != null) flg |= 0x40;
+        dest.writeInt(flg);
+        dest.writeString(mName);
+        dest.writeInt(mWidth);
+        dest.writeInt(mHeight);
+        dest.writeInt(mDensityDpi);
+        dest.writeInt(mFlags);
+        if (mSurface != null) dest.writeTypedObject(mSurface, flags);
+        if (mUniqueId != null) dest.writeString(mUniqueId);
+        dest.writeInt(mDisplayIdToMirror);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ VirtualDisplayConfig(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        int flg = in.readInt();
+        String name = in.readString();
+        int width = in.readInt();
+        int height = in.readInt();
+        int densityDpi = in.readInt();
+        int flags = in.readInt();
+        Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
+        String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
+        int displayIdToMirror = in.readInt();
+
+        this.mName = name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mName);
+        this.mWidth = width;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mWidth,
+                "from", 1);
+        this.mHeight = height;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mHeight,
+                "from", 1);
+        this.mDensityDpi = densityDpi;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mDensityDpi,
+                "from", 1);
+        this.mFlags = flags;
+        this.mSurface = surface;
+        this.mUniqueId = uniqueId;
+        this.mDisplayIdToMirror = displayIdToMirror;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<VirtualDisplayConfig> CREATOR
+            = new Parcelable.Creator<VirtualDisplayConfig>() {
+        @Override
+        public VirtualDisplayConfig[] newArray(int size) {
+            return new VirtualDisplayConfig[size];
+        }
+
+        @Override
+        public VirtualDisplayConfig createFromParcel(@NonNull Parcel in) {
+            return new VirtualDisplayConfig(in);
+        }
+    };
+
+    /**
+     * A builder for {@link VirtualDisplayConfig}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull String mName;
+        private @IntRange(from = 1) int mWidth;
+        private @IntRange(from = 1) int mHeight;
+        private @IntRange(from = 1) int mDensityDpi;
+        private int mFlags;
+        private @Nullable Surface mSurface;
+        private @Nullable String mUniqueId;
+        private int mDisplayIdToMirror;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param name
+         *   The name of the virtual display, must be non-empty.
+         * @param width
+         *   The width of the virtual display in pixels. Must be greater than 0.
+         * @param height
+         *   The height of the virtual display in pixels. Must be greater than 0.
+         * @param densityDpi
+         *   The density of the virtual display in dpi. Must be greater than 0.
+         */
+        public Builder(
+                @NonNull String name,
+                @IntRange(from = 1) int width,
+                @IntRange(from = 1) int height,
+                @IntRange(from = 1) int densityDpi) {
+            mName = name;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mName);
+            mWidth = width;
+            com.android.internal.util.AnnotationValidations.validate(
+                    IntRange.class, null, mWidth,
+                    "from", 1);
+            mHeight = height;
+            com.android.internal.util.AnnotationValidations.validate(
+                    IntRange.class, null, mHeight,
+                    "from", 1);
+            mDensityDpi = densityDpi;
+            com.android.internal.util.AnnotationValidations.validate(
+                    IntRange.class, null, mDensityDpi,
+                    "from", 1);
+        }
+
+        /**
+         * The name of the virtual display, must be non-empty.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setName(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mName = value;
+            return this;
+        }
+
+        /**
+         * The width of the virtual display in pixels. Must be greater than 0.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setWidth(@IntRange(from = 1) int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mWidth = value;
+            return this;
+        }
+
+        /**
+         * The height of the virtual display in pixels. Must be greater than 0.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setHeight(@IntRange(from = 1) int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mHeight = value;
+            return this;
+        }
+
+        /**
+         * The density of the virtual display in dpi. Must be greater than 0.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setDensityDpi(@IntRange(from = 1) int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mDensityDpi = value;
+            return this;
+        }
+
+        /**
+         * A combination of virtual display flags.
+         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
+         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
+         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+         * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setFlags(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mFlags = value;
+            return this;
+        }
+
+        /**
+         * The surface to which the content of the virtual display should be rendered, or null if
+         * there is none initially.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setSurface(@NonNull Surface value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mSurface = value;
+            return this;
+        }
+
+        /**
+         * The unique identifier for the display. Shouldn't be displayed to the user.
+         *
+         * @hide
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setUniqueId(@NonNull String value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40;
+            mUniqueId = value;
+            return this;
+        }
+
+        /**
+         * The id of the display that the virtual display should mirror, or
+         * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setDisplayIdToMirror(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x80;
+            mDisplayIdToMirror = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull VirtualDisplayConfig build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x100; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x10) == 0) {
+                mFlags = 0;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
+                mSurface = null;
+            }
+            if ((mBuilderFieldsSet & 0x40) == 0) {
+                mUniqueId = null;
+            }
+            if ((mBuilderFieldsSet & 0x80) == 0) {
+                mDisplayIdToMirror = DEFAULT_DISPLAY;
+            }
+            VirtualDisplayConfig o = new VirtualDisplayConfig(
+                    mName,
+                    mWidth,
+                    mHeight,
+                    mDensityDpi,
+                    mFlags,
+                    mSurface,
+                    mUniqueId,
+                    mDisplayIdToMirror);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x100) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1585179350902L,
+            codegenVersion = "1.0.15",
+            sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
+            inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange(from=1L) int mWidth\nprivate @android.annotation.IntRange(from=1L) int mHeight\nprivate @android.annotation.IntRange(from=1L) int mDensityDpi\nprivate  int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate  int mDisplayIdToMirror\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index b52b437..a298c85 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.BinderThread;
 import android.annotation.MainThread;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -37,6 +38,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.CancellationGroup;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
@@ -52,7 +54,6 @@
 import java.lang.ref.WeakReference;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Implements the internal IInputMethod interface to convert incoming calls
@@ -90,12 +91,13 @@
      *
      * <p>This field must be set and cleared only from the binder thread(s), where the system
      * guarantees that {@link #bindInput(InputBinding)},
-     * {@link #startInput(IBinder, IInputContext, int, EditorInfo, boolean)}, and
+     * {@link #startInput(IBinder, IInputContext, int, EditorInfo, boolean, boolean)}, and
      * {@link #unbindInput()} are called with the same order as the original calls
      * in {@link com.android.server.inputmethod.InputMethodManagerService}.
      * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p>
      */
-    AtomicBoolean mIsUnbindIssued = null;
+    @Nullable
+    CancellationGroup mCancellationGroup = null;
 
     // NOTE: we should have a cache of these.
     static final class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback {
@@ -187,11 +189,11 @@
                 final IBinder startInputToken = (IBinder) args.arg1;
                 final IInputContext inputContext = (IInputContext) args.arg2;
                 final EditorInfo info = (EditorInfo) args.arg3;
-                final AtomicBoolean isUnbindIssued = (AtomicBoolean) args.arg4;
+                final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
                 SomeArgs moreArgs = (SomeArgs) args.arg5;
                 final InputConnection ic = inputContext != null
                         ? new InputConnectionWrapper(
-                                mTarget, inputContext, moreArgs.argi3, isUnbindIssued)
+                                mTarget, inputContext, moreArgs.argi3, cancellationGroup)
                         : null;
                 info.makeCompatible(mTargetSdkVersion);
                 inputMethod.dispatchStartInputWithToken(
@@ -295,15 +297,15 @@
     @BinderThread
     @Override
     public void bindInput(InputBinding binding) {
-        if (mIsUnbindIssued != null) {
+        if (mCancellationGroup != null) {
             Log.e(TAG, "bindInput must be paired with unbindInput.");
         }
-        mIsUnbindIssued = new AtomicBoolean();
+        mCancellationGroup = new CancellationGroup();
         // This IInputContext is guaranteed to implement all the methods.
         final int missingMethodFlags = 0;
         InputConnection ic = new InputConnectionWrapper(mTarget,
                 IInputContext.Stub.asInterface(binding.getConnectionToken()), missingMethodFlags,
-                mIsUnbindIssued);
+                mCancellationGroup);
         InputBinding nu = new InputBinding(ic, binding);
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
     }
@@ -311,10 +313,10 @@
     @BinderThread
     @Override
     public void unbindInput() {
-        if (mIsUnbindIssued != null) {
+        if (mCancellationGroup != null) {
             // Signal the flag then forget it.
-            mIsUnbindIssued.set(true);
-            mIsUnbindIssued = null;
+            mCancellationGroup.cancelAll();
+            mCancellationGroup = null;
         } else {
             Log.e(TAG, "unbindInput must be paired with bindInput.");
         }
@@ -326,16 +328,16 @@
     public void startInput(IBinder startInputToken, IInputContext inputContext,
             @InputConnectionInspector.MissingMethodFlags final int missingMethods,
             EditorInfo attribute, boolean restarting, boolean shouldPreRenderIme) {
-        if (mIsUnbindIssued == null) {
+        if (mCancellationGroup == null) {
             Log.e(TAG, "startInput must be called after bindInput.");
-            mIsUnbindIssued = new AtomicBoolean();
+            mCancellationGroup = new CancellationGroup();
         }
         SomeArgs args = SomeArgs.obtain();
         args.argi1 = restarting ? 1 : 0;
         args.argi2 = shouldPreRenderIme ? 1 : 0;
         args.argi3 = missingMethods;
-        mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOO(
-                DO_START_INPUT, startInputToken, inputContext, attribute, mIsUnbindIssued, args));
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOO(DO_START_INPUT, startInputToken,
+                inputContext, attribute, mCancellationGroup, args));
     }
 
     @BinderThread
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java
index ef138a0..dbb669b 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java
@@ -39,6 +39,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IMultiClientInputMethodSession;
+import com.android.internal.inputmethod.CancellationGroup;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.view.IInputContext;
@@ -46,7 +47,6 @@
 import com.android.internal.view.InputConnectionWrapper;
 
 import java.lang.ref.WeakReference;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Re-dispatches all the incoming per-client events to the specified {@link Looper} thread.
@@ -80,19 +80,19 @@
     @Nullable
     InputEventReceiver mInputEventReceiver;
 
-    private final AtomicBoolean mFinished = new AtomicBoolean(false);
+    private final CancellationGroup mCancellationGroup = new CancellationGroup();
 
     IInputMethodSession.Stub createIInputMethodSession() {
         synchronized (mSessionLock) {
             return new InputMethodSessionImpl(
-                    mSessionLock, mCallbackImpl, mHandler, mFinished);
+                    mSessionLock, mCallbackImpl, mHandler, mCancellationGroup);
         }
     }
 
     IMultiClientInputMethodSession.Stub createIMultiClientInputMethodSession() {
         synchronized (mSessionLock) {
             return new MultiClientInputMethodSessionImpl(
-                    mSessionLock, mCallbackImpl, mHandler, mFinished);
+                    mSessionLock, mCallbackImpl, mHandler, mCancellationGroup);
         }
     }
 
@@ -105,7 +105,7 @@
             mHandler = new Handler(looper, null, true);
             mReadChannel = readChannel;
             mInputEventReceiver = new ImeInputEventReceiver(mReadChannel, mHandler.getLooper(),
-                    mFinished, mDispatcherState, mCallbackImpl.mOriginalCallback);
+                    mCancellationGroup, mDispatcherState, mCallbackImpl.mOriginalCallback);
         }
     }
 
@@ -139,16 +139,17 @@
     }
 
     private static final class ImeInputEventReceiver extends InputEventReceiver {
-        private final AtomicBoolean mFinished;
+        private final CancellationGroup mCancellationGroupOnFinishSession;
         private final KeyEvent.DispatcherState mDispatcherState;
         private final MultiClientInputMethodServiceDelegate.ClientCallback mClientCallback;
         private final KeyEventCallbackAdaptor mKeyEventCallbackAdaptor;
 
-        ImeInputEventReceiver(InputChannel readChannel, Looper looper, AtomicBoolean finished,
+        ImeInputEventReceiver(InputChannel readChannel, Looper looper,
+                CancellationGroup cancellationGroupOnFinishSession,
                 KeyEvent.DispatcherState dispatcherState,
                 MultiClientInputMethodServiceDelegate.ClientCallback callback) {
             super(readChannel, looper);
-            mFinished = finished;
+            mCancellationGroupOnFinishSession = cancellationGroupOnFinishSession;
             mDispatcherState = dispatcherState;
             mClientCallback = callback;
             mKeyEventCallbackAdaptor = new KeyEventCallbackAdaptor(callback);
@@ -156,7 +157,7 @@
 
         @Override
         public void onInputEvent(InputEvent event) {
-            if (mFinished.get()) {
+            if (mCancellationGroupOnFinishSession.isCanceled()) {
                 // The session has been finished.
                 finishInputEvent(event, false);
                 return;
@@ -187,14 +188,14 @@
         private CallbackImpl mCallbackImpl;
         @GuardedBy("mSessionLock")
         private Handler mHandler;
-        private final AtomicBoolean mSessionFinished;
+        private final CancellationGroup mCancellationGroupOnFinishSession;
 
         InputMethodSessionImpl(Object lock, CallbackImpl callback, Handler handler,
-                AtomicBoolean sessionFinished) {
+                CancellationGroup cancellationGroupOnFinishSession) {
             mSessionLock = lock;
             mCallbackImpl = callback;
             mHandler = handler;
-            mSessionFinished = sessionFinished;
+            mCancellationGroupOnFinishSession = cancellationGroupOnFinishSession;
         }
 
         @Override
@@ -272,7 +273,7 @@
                 if (mCallbackImpl == null || mHandler == null) {
                     return;
                 }
-                mSessionFinished.set(true);
+                mCancellationGroupOnFinishSession.cancelAll();
                 mHandler.sendMessage(PooledLambda.obtainMessage(
                         CallbackImpl::finishSession, mCallbackImpl));
                 mCallbackImpl = null;
@@ -311,14 +312,14 @@
         private CallbackImpl mCallbackImpl;
         @GuardedBy("mSessionLock")
         private Handler mHandler;
-        private final AtomicBoolean mSessionFinished;
+        private final CancellationGroup mCancellationGroupOnFinishSession;
 
         MultiClientInputMethodSessionImpl(Object lock, CallbackImpl callback,
-                Handler handler, AtomicBoolean sessionFinished) {
+                Handler handler, CancellationGroup cancellationGroupOnFinishSession) {
             mSessionLock = lock;
             mCallbackImpl = callback;
             mHandler = handler;
-            mSessionFinished = sessionFinished;
+            mCancellationGroupOnFinishSession = cancellationGroupOnFinishSession;
         }
 
         @Override
@@ -335,7 +336,7 @@
                         new WeakReference<>(null);
                 args.arg1 = (inputContext == null) ? null
                         : new InputConnectionWrapper(fakeIMS, inputContext, missingMethods,
-                                mSessionFinished);
+                                mCancellationGroupOnFinishSession);
                 args.arg2 = editorInfo;
                 args.argi1 = controlFlags;
                 args.argi2 = softInputMode;
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 7ff954b..651494d 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -1074,6 +1074,21 @@
     }
 
     /**
+     * Returns true if this link has an IPv4 unreachable default route.
+     *
+     * @return {@code true} if there is an IPv4 unreachable default route, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIpv4UnreachableDefaultRoute() {
+        for (RouteInfo r : mRoutes) {
+            if (r.isIPv4UnreachableDefault()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * For backward compatibility.
      * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
      * just yet.
@@ -1102,6 +1117,21 @@
     }
 
     /**
+     * Returns true if this link has an IPv6 unreachable default route.
+     *
+     * @return {@code true} if there is an IPv6 unreachable default route, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIpv6UnreachableDefaultRoute() {
+        for (RouteInfo r : mRoutes) {
+            if (r.isIPv6UnreachableDefault()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * For backward compatibility.
      * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
      * just yet.
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index fe90a84..e9bcefe 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -556,12 +556,12 @@
     @NonNull
     public Network register() {
         if (VDBG) log("Registering NetworkAgent");
-        final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
-                .getSystemService(Context.CONNECTIVITY_SERVICE);
         synchronized (mRegisterLock) {
             if (mNetwork != null) {
                 throw new IllegalStateException("Agent already registered");
             }
+            final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
+                    .getSystemService(Context.CONNECTIVITY_SERVICE);
             mNetwork = cm.registerNetworkAgent(new Messenger(mHandler),
                     new NetworkInfo(mInitialConfiguration.info),
                     mInitialConfiguration.properties, mInitialConfiguration.capabilities,
@@ -624,7 +624,9 @@
             throw new UnsupportedOperationException(
                     "Legacy agents can't call markConnected.");
         }
-        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+        // |reason| cannot be used by the non-legacy agents
+        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */,
+                mNetworkInfo.getExtraInfo());
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
     }
 
@@ -638,7 +640,9 @@
         if (mIsLegacy) {
             throw new UnsupportedOperationException("Legacy agents can't call unregister.");
         }
-        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+        // When unregistering an agent nobody should use the extrainfo (or reason) any more.
+        mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */,
+                null /* extraInfo */);
         queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
     }
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 9ff7ebe..73c6b3d 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -169,6 +169,7 @@
             NET_CAPABILITY_OEM_PAID,
             NET_CAPABILITY_MCX,
             NET_CAPABILITY_PARTIAL_CONNECTIVITY,
+            NET_CAPABILITY_TEMPORARILY_NOT_METERED,
     })
     public @interface NetCapability { }
 
@@ -336,8 +337,16 @@
     @SystemApi
     public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24;
 
+    /**
+     * This capability will be set for networks that are generally metered, but are currently
+     * unmetered, e.g., because the user is in a particular area. This capability can be changed at
+     * any time. When it is removed, applications are responsible for stopping any data transfer
+     * that should not occur on a metered network.
+     */
+    public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PARTIAL_CONNECTIVITY;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TEMPORARILY_NOT_METERED;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -353,7 +362,8 @@
             | (1 << NET_CAPABILITY_FOREGROUND)
             | (1 << NET_CAPABILITY_NOT_CONGESTED)
             | (1 << NET_CAPABILITY_NOT_SUSPENDED)
-            | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+            | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY
+            | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED));
 
     /**
      * Network capabilities that are not allowed in NetworkRequests. This exists because the
@@ -424,6 +434,7 @@
      */
     private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES =
             (1 << NET_CAPABILITY_NOT_METERED)
+            | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED)
             | (1 << NET_CAPABILITY_NOT_RESTRICTED)
             | (1 << NET_CAPABILITY_NOT_VPN)
             | (1 << NET_CAPABILITY_NOT_ROAMING)
@@ -1864,6 +1875,7 @@
             case NET_CAPABILITY_OEM_PAID:             return "OEM_PAID";
             case NET_CAPABILITY_MCX:                  return "MCX";
             case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY";
+            case NET_CAPABILITY_TEMPORARILY_NOT_METERED:    return "TEMPORARILY_NOT_METERED";
             default:                                  return Integer.toString(capability);
         }
     }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 9c1fb41..b7fb280 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -1195,18 +1195,24 @@
 
     /**
      * Remove all rows that match one of specified UIDs.
+     * This mutates the original structure in place.
      * @hide
      */
     public void removeUids(int[] uids) {
-        int nextOutputEntry = 0;
-        for (int i = 0; i < size; i++) {
-            if (!ArrayUtils.contains(uids, uid[i])) {
-                maybeCopyEntry(nextOutputEntry, i);
-                nextOutputEntry++;
-            }
-        }
+        filter(e -> !ArrayUtils.contains(uids, e.uid));
+    }
 
-        size = nextOutputEntry;
+    /**
+     * Remove all rows that match one of specified UIDs.
+     * @return the result object.
+     * @hide
+     */
+    @NonNull
+    public NetworkStats removeEmptyEntries() {
+        final NetworkStats ret = this.clone();
+        ret.filter(e -> e.rxBytes != 0 || e.rxPackets != 0 || e.txBytes != 0 || e.txPackets != 0
+                || e.operations != 0);
+        return ret;
     }
 
     /**
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index dbdaa4c..e550f85 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -426,6 +426,16 @@
     }
 
     /**
+     * Indicates if this route is an unreachable default route.
+     *
+     * @return {@code true} if it's an unreachable route with prefix length of 0.
+     * @hide
+     */
+    private boolean isUnreachableDefaultRoute() {
+        return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0;
+    }
+
+    /**
      * Indicates if this route is an IPv4 default route.
      * @hide
      */
@@ -434,6 +444,14 @@
     }
 
     /**
+     * Indicates if this route is an IPv4 unreachable default route.
+     * @hide
+     */
+    public boolean isIPv4UnreachableDefault() {
+        return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
+    }
+
+    /**
      * Indicates if this route is an IPv6 default route.
      * @hide
      */
@@ -442,6 +460,14 @@
     }
 
     /**
+     * Indicates if this route is an IPv6 unreachable default route.
+     * @hide
+     */
+    public boolean isIPv6UnreachableDefault() {
+        return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
+    }
+
+    /**
      * Indicates if this route is a host route (ie, matches only a single host address).
      *
      * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 20e5f24..683993f 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -251,6 +251,11 @@
                     }
                 }
             }
+            // For gathering this debug output, we're making synchronous binder calls
+            // out of system_server to all processes hosting binder objects it holds a reference to;
+            // since some of those processes might be frozen, we don't want to block here
+            // forever. Disable the freezer.
+            Process.enableFreezer(false);
             for (WeakReference<BinderProxy> weakRef : proxiesToQuery) {
                 BinderProxy bp = weakRef.get();
                 String key;
@@ -273,6 +278,7 @@
                     counts.put(key, i + 1);
                 }
             }
+            Process.enableFreezer(true);
             Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
                     new Map.Entry[counts.size()]);
 
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index ae65f1d..5f8c4f5 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -1268,6 +1268,7 @@
     public static boolean isExternalStorageLegacy(@NonNull File path) {
         final Context context = AppGlobals.getInitialApplication();
         final int uid = context.getApplicationInfo().uid;
+        // Isolated processes and Instant apps are never allowed to be in scoped storage
         if (Process.isIsolated(uid)) {
             return false;
         }
@@ -1277,8 +1278,6 @@
             return false;
         }
 
-        // TODO(b/150672994): Compat flags do not override instant app and isolated process's
-        //  behavior.
         boolean defaultScopedStorage = Compatibility.isChangeEnabled(DEFAULT_SCOPED_STORAGE);
         boolean forceEnableScopedStorage = Compatibility.isChangeEnabled(
                 FORCE_ENABLE_SCOPED_STORAGE);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index cdc0019..b8e1aa8 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -32,6 +32,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.service.dreams.Sandman;
+import android.sysprop.InitProperties;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
@@ -1487,7 +1488,7 @@
      */
     // TODO(b/138605180): add link to documentation once it's ready.
     public boolean isRebootingUserspaceSupported() {
-        return SystemProperties.getBoolean("ro.init.userspace_reboot.is_supported", false);
+        return InitProperties.is_userspace_reboot_supported().orElse(false);
     }
 
     /**
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 51f01ca..653a559 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -102,9 +102,9 @@
      *
      * This method must only be called by the window manager.
      *
-     * @param brightness The overridden brightness, or -1 to disable the override.
+     * @param brightness The overridden brightness, or Float.NaN to disable the override.
      */
-    public abstract void setScreenBrightnessOverrideFromWindowManager(int brightness);
+    public abstract void setScreenBrightnessOverrideFromWindowManager(float brightness);
 
     /**
      * Used by the window manager to override the user activity timeout based on the
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b7b3c4f..5d2c9d1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -607,6 +607,9 @@
      *                             started.
      * @param pkgDataInfoMap Map from related package names to private data directory
      *                       volume UUID and inode number.
+     * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
+     *                       volume UUID and inode number.
+     * @param bindMountAppsData whether zygote needs to mount CE and DE data.
      * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
@@ -631,13 +634,17 @@
                                            @Nullable long[] disabledCompatChanges,
                                            @Nullable Map<String, Pair<String, Long>>
                                                    pkgDataInfoMap,
+                                           @Nullable Map<String, Pair<String, Long>>
+                                                   whitelistedDataInfoMap,
+                                           boolean bindMountAppsData,
                                            boolean bindMountAppStorageDirs,
                                            @Nullable String[] zygoteArgs) {
         return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
                     zygotePolicyFlags, isTopApp, disabledCompatChanges,
-                    pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
+                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
+                    bindMountAppStorageDirs, zygoteArgs);
     }
 
     /** @hide */
@@ -661,7 +668,8 @@
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
                     /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
-                disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs);
+                disabledCompatChanges, /* pkgDataInfoMap */ null,
+                /* whitelistedDataInfoMap */ null, false, false, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 5f3f14f..a4c99c0 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -333,6 +333,9 @@
      *                             started.
      * @param pkgDataInfoMap Map from related package names to private data directory
      *                       volume UUID and inode number.
+     * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
+     *                       volume UUID and inode number.
+     * @param bindMountAppsData whether zygote needs to mount CE and DE data.
      * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
      *
      * @param zygoteArgs Additional arguments to supply to the Zygote process.
@@ -355,6 +358,9 @@
                                                   @Nullable long[] disabledCompatChanges,
                                                   @Nullable Map<String, Pair<String, Long>>
                                                           pkgDataInfoMap,
+                                                  @Nullable Map<String, Pair<String, Long>>
+                                                          whitelistedDataInfoMap,
+                                                  boolean bindMountAppsData,
                                                   boolean bindMountAppStorageDirs,
                                                   @Nullable String[] zygoteArgs) {
         // TODO (chriswailes): Is there a better place to check this value?
@@ -367,7 +373,8 @@
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                     packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
-                    pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
+                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
+                    bindMountAppStorageDirs, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -608,6 +615,9 @@
      * @param disabledCompatChanges a list of disabled compat changes for the process being started.
      * @param pkgDataInfoMap Map from related package names to private data directory volume UUID
      *                       and inode number.
+     * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
+     *                       volume UUID and inode number.
+     * @param bindMountAppsData whether zygote needs to mount CE and DE data.
      * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
@@ -631,6 +641,9 @@
                                                       @Nullable long[] disabledCompatChanges,
                                                       @Nullable Map<String, Pair<String, Long>>
                                                               pkgDataInfoMap,
+                                                      @Nullable Map<String, Pair<String, Long>>
+                                                              whitelistedDataInfoMap,
+                                                      boolean bindMountAppsData,
                                                       boolean bindMountAppStorageDirs,
                                                       @Nullable String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
@@ -728,11 +741,33 @@
             }
             argsForZygote.add(sb.toString());
         }
+        if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(Zygote.WHITELISTED_DATA_INFO_MAP);
+            sb.append("=");
+            boolean started = false;
+            for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) {
+                if (started) {
+                    sb.append(',');
+                }
+                started = true;
+                sb.append(entry.getKey());
+                sb.append(',');
+                sb.append(entry.getValue().first);
+                sb.append(',');
+                sb.append(entry.getValue().second);
+            }
+            argsForZygote.add(sb.toString());
+        }
 
         if (bindMountAppStorageDirs) {
             argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
         }
 
+        if (bindMountAppsData) {
+            argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
+        }
+
         if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
             StringBuilder sb = new StringBuilder();
             sb.append("--disabled-compat-changes=");
@@ -1291,6 +1326,7 @@
                     true /* startChildZygote */, null /* packageName */,
                     ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
                     null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
+                    null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
                     /* bindMountAppStorageDirs */ false, extraArgs);
 
         } catch (ZygoteStartFailedEx ex) {
diff --git a/core/java/android/os/incremental/IIncrementalServiceConnector.aidl b/core/java/android/os/incremental/IIncrementalServiceConnector.aidl
new file mode 100644
index 0000000..5800ecf
--- /dev/null
+++ b/core/java/android/os/incremental/IIncrementalServiceConnector.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.incremental;
+
+/** @hide */
+interface IIncrementalServiceConnector {
+    /**
+     * Changes storage params. Returns 0 on success, and -errno on failure.
+     * Use enableReadLogs to switch pages read logs reporting on and off.
+     * Returns 0 on success, and - errno on failure: permission check or remount.
+     */
+    int setStorageParams(boolean enableReadLogs);
+}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index fb81d67..e86aa62 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -266,6 +266,13 @@
     public static final String NAMESPACE_SCHEDULER = "scheduler";
 
     /**
+     * Namespace for settings statistics features.
+     *
+     * @hide
+     */
+    public static final String NAMESPACE_SETTINGS_STATS = "settings_stats";
+
+    /**
      * Namespace for storage-related features.
      *
      * @deprecated Replace storage namespace with storage_native_boot.
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 327bca2..2e00c0c 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -1274,6 +1274,8 @@
 
             out.putParcelable(DocumentsContract.EXTRA_RESULT, path);
         } else if (METHOD_GET_DOCUMENT_METADATA.equals(method)) {
+            enforceReadPermissionInner(documentUri, getCallingPackage(),
+                    getCallingAttributionTag(), null);
             return getDocumentMetadata(documentId);
         } else {
             throw new UnsupportedOperationException("Method not supported " + method);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e2d0c49..920302c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13757,6 +13757,16 @@
                 "show_notification_channel_warnings";
 
         /**
+         * When enabled, requires all notifications in the conversation section to be backed
+         * by a long-lived sharing shortcut
+         *
+         * The value 1 - require a shortcut, 0 - do not require a shortcut
+         * @hide
+         */
+        public static final String REQUIRE_SHORTCUTS_FOR_CONVERSATIONS =
+                "require_shortcuts_for_conversations";
+
+        /**
          * Whether cell is enabled/disabled
          * @hide
          */
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 1beeb65..21b83c6 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -17,8 +17,6 @@
 package android.service.notification;
 
 import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
-import static android.util.FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ;
-import static android.util.FeatureFlagUtils.isEnabled;
 
 import android.annotation.NonNull;
 import android.app.Notification;
@@ -33,6 +31,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.text.TextUtils;
 
 import com.android.internal.logging.InstanceId;
@@ -477,9 +476,10 @@
      */
     public String getShortcutId(Context context) {
         String conversationId = getNotification().getShortcutId();
-        if (isEnabled(context,  NOTIF_CONVO_BYPASS_SHORTCUT_REQ)
-                && getNotification().getNotificationStyle() == Notification.MessagingStyle.class
-                && TextUtils.isEmpty(conversationId)) {
+        if (TextUtils.isEmpty(conversationId)
+                && (Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0) == 0)
+                && getNotification().getNotificationStyle() == Notification.MessagingStyle.class) {
             conversationId = getId() + getTag() + PLACEHOLDER_CONVERSATION_ID;
         }
         return conversationId;
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f531e12..f944dd7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -55,6 +55,7 @@
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.MotionEvent;
 import android.view.SurfaceControl;
@@ -190,6 +191,7 @@
                 new DisplayCutout.ParcelableWrapper();
         DisplayCutout mDispatchedDisplayCutout = DisplayCutout.NO_CUTOUT;
         final InsetsState mInsetsState = new InsetsState();
+        final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
         final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
         private final Point mSurfaceSize = new Point();
 
@@ -878,7 +880,7 @@
                         if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
                                 mDisplay.getDisplayId(), mWinFrame, mContentInsets, mStableInsets,
                                 mDisplayCutout, inputChannel,
-                                mInsetsState) < 0) {
+                                mInsetsState, mTempControls) < 0) {
                             Log.w(TAG, "Failed to add window while updating wallpaper surface.");
                             return;
                         }
@@ -903,7 +905,7 @@
                             View.VISIBLE, 0, -1, mWinFrame, mContentInsets,
                             mVisibleInsets, mStableInsets, mBackdropFrame,
                             mDisplayCutout, mMergedConfiguration, mSurfaceControl,
-                            mInsetsState, mSurfaceSize, mTmpSurfaceControl);
+                            mInsetsState, mTempControls, mSurfaceSize, mTmpSurfaceControl);
                     if (mSurfaceControl.isValid()) {
                         mSurfaceHolder.mSurface.copyFrom(mSurfaceControl);
                         mSurfaceControl.release();
diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
index 9950143..b1647fe 100644
--- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java
+++ b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
@@ -21,7 +21,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -64,6 +66,7 @@
  * </pre>
  * @hide
  */
+@TestApi
 @SystemApi
 public abstract class ExplicitHealthCheckService extends Service {
 
@@ -159,6 +162,15 @@
     }
 
     /**
+     * Sets {@link RemoteCallback}, for testing purpose.
+     *
+     * @hide
+     */
+    @TestApi
+    public void setCallback(@Nullable RemoteCallback callback) {
+        mCallback = callback;
+    }
+    /**
      * Implementors should call this to notify the system when explicit health check passes
      * for {@code packageName};
      */
@@ -183,6 +195,7 @@
      *
      * @hide
      */
+    @TestApi
     @SystemApi
     public static final class PackageConfig implements Parcelable {
         private static final long DEFAULT_HEALTH_CHECK_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(1);
@@ -263,7 +276,7 @@
         }
 
         @Override
-        public void writeToParcel(Parcel parcel, int flags) {
+        public void writeToParcel(@SuppressLint({"MissingNullability"}) Parcel parcel, int flags) {
             parcel.writeString(mPackageName);
             parcel.writeLong(mHealthCheckTimeoutMillis);
         }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index faa5cf5..cd20b35 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -42,8 +42,6 @@
     public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
     public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
     public static final String SETTINGS_FUSE_FLAG = "settings_fuse";
-    public static final String NOTIF_CONVO_BYPASS_SHORTCUT_REQ =
-            "settings_notif_convo_bypass_shortcut_req";
     /** @hide */
     public static final String SETTINGS_DO_NOT_RESTORE_PRESERVED =
             "settings_do_not_restore_preserved";
@@ -66,7 +64,6 @@
         DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "true");
         DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "false");
         DEFAULT_FLAGS.put("settings_conditionals", "false");
-        DEFAULT_FLAGS.put(NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
         // This flags guards a feature introduced in R and will be removed in the next release
         // (b/148367230).
         DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true");
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 4b3afba..e8d3459 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -335,7 +335,17 @@
 
     /** @hide Just for debugging; not internationalized. */
     public static String formatUptime(long time) {
-        final long diff = time - SystemClock.uptimeMillis();
+        return formatTime(time, SystemClock.uptimeMillis());
+    }
+
+    /** @hide Just for debugging; not internationalized. */
+    public static String formatRealtime(long time) {
+        return formatTime(time, SystemClock.elapsedRealtime());
+    }
+
+    /** @hide Just for debugging; not internationalized. */
+    public static String formatTime(long time, long referenceTime) {
+        long diff = time - referenceTime;
         if (diff > 0) {
             return time + " (in " + diff + " ms)";
         }
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0ccb1e0..4469fdb 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -253,12 +253,14 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public static final int TYPE_UNKNOWN = 0;
 
     /**
      * Display type: Physical display connected through an internal port.
      * @hide
      */
+    @TestApi
     public static final int TYPE_INTERNAL = 1;
 
     /**
@@ -266,6 +268,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public static final int TYPE_EXTERNAL = 2;
 
     /**
@@ -273,12 +276,14 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public static final int TYPE_WIFI = 3;
 
     /**
      * Display type: Overlay display.
      * @hide
      */
+    @TestApi
     public static final int TYPE_OVERLAY = 4;
 
     /**
@@ -286,6 +291,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public static final int TYPE_VIRTUAL = 5;
 
     /**
@@ -569,6 +575,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     public int getType() {
         return mType;
     }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 45e51f7..81bfcb0 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -29,6 +29,7 @@
 import android.view.IWindowId;
 import android.view.MotionEvent;
 import android.view.WindowManager;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -46,7 +47,7 @@
             in int viewVisibility, in int layerStackId, out Rect outFrame,
             out Rect outContentInsets, out Rect outStableInsets,
             out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
-            out InsetsState insetsState);
+            out InsetsState insetsState, out InsetsSourceControl[] activeControls);
     int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, in int layerStackId, out Rect outContentInsets,
             out Rect outStableInsets, out InsetsState insetsState);
@@ -106,8 +107,8 @@
             out Rect outBackdropFrame,
             out DisplayCutout.ParcelableWrapper displayCutout,
             out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
-            out InsetsState insetsState, out Point outSurfaceSize,
-            out SurfaceControl outBlastSurfaceControl);
+            out InsetsState insetsState, out InsetsSourceControl[] activeControls,
+            out Point outSurfaceSize, out SurfaceControl outBlastSurfaceControl);
 
     /*
      * Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index 6784cf7..dbbe4b6 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -170,10 +170,15 @@
         }
         if (DEBUG) Log.d(TAG, "onViewFocusChanged, view=" + view + ", mServedView=" + mServedView);
 
+        // We don't need to track the next served view when the view lost focus here because:
+        // 1) The current view focus may be cleared temporary when in touch mode, closing input
+        //    at this moment isn't the right way.
+        // 2) We only care about the served view change when it focused, since changing input
+        //    connection when the focus target changed is reasonable.
+        // 3) Setting the next served view as null when no more served view should be handled in
+        //    other special events (e.g. view detached from window or the window dismissed).
         if (hasFocus) {
             mNextServedView = view;
-        } else if (view == mServedView) {
-            mNextServedView = null;
         }
         mViewRootImpl.dispatchCheckFocus();
     }
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 35286ba..2461e96 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import static android.view.InsetsController.ANIMATION_TYPE_USER;
 import static android.view.InsetsController.AnimationType;
 import static android.view.InsetsState.ITYPE_IME;
 
@@ -104,13 +103,9 @@
     void hide(boolean animationFinished, @AnimationType int animationType) {
         super.hide();
 
-        if (!animationFinished) {
-            if (animationType == ANIMATION_TYPE_USER) {
-                // if controlWindowInsetsAnimation is hiding keyboard.
-                notifyHidden();
-            }
-        } else {
+        if (animationFinished) {
             // remove IME surface as IME has finished hide animation.
+            notifyHidden();
             removeSurface();
         }
     }
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
index 4227f78..74c1869 100644
--- a/core/java/android/view/InsetsAnimationControlCallbacks.java
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -40,8 +40,10 @@
 
     /**
      * Schedule the apply by posting the animation callback.
+     *
+     * @param runner The runner that requested applying insets
      */
-    void scheduleApplyChangeInsets();
+    void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner);
 
     /**
      * Finish the final steps after the animation.
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index ef6a9b2..05abc60 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -156,7 +156,7 @@
         mPendingFraction = sanitize(fraction);
         mPendingInsets = sanitize(insets);
         mPendingAlpha = sanitize(alpha);
-        mController.scheduleApplyChangeInsets();
+        mController.scheduleApplyChangeInsets(this);
     }
 
     @VisibleForTesting
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 40ffa7ef..9dfdd06 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -54,7 +54,7 @@
         }
 
         @Override
-        public void scheduleApplyChangeInsets() {
+        public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
             mControl.applyChangeInsets(mState);
         }
 
@@ -91,7 +91,7 @@
             @AnimationType int animationType, Handler mainThreadHandler) {
         mMainThreadHandler = mainThreadHandler;
         mOuterCallbacks = controller;
-        mControl = new InsetsAnimationControlImpl(copyControls(controls), frame, state, listener,
+        mControl = new InsetsAnimationControlImpl(controls, frame, state, listener,
                 types, mCallbacks, durationMs, interpolator, animationType);
         InsetsAnimationThread.getHandler().post(() -> listener.onReady(mControl, types));
     }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 8eb9b5f..43c7bed 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -18,6 +18,7 @@
 
 import static android.view.InsetsState.ITYPE_CAPTION_BAR;
 import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsState.toInternalType;
 import static android.view.InsetsState.toPublicType;
 import static android.view.WindowInsets.Type.all;
 import static android.view.WindowInsets.Type.ime;
@@ -471,7 +472,7 @@
         if (!localStateChanged && mLastDispachedState.equals(state)) {
             return false;
         }
-        mState.set(state);
+        updateState(state);
         mLastDispachedState.set(state, true /* copySources */);
         applyLocalVisibilityOverride();
         if (localStateChanged) {
@@ -480,11 +481,25 @@
         if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
             sendStateToWindowManager();
         }
+        return true;
+    }
+
+    private void updateState(InsetsState newState) {
+        mState.setDisplayFrame(newState.getDisplayFrame());
+        for (int i = newState.getSourcesCount() - 1; i >= 0; i--) {
+            InsetsSource source = newState.sourceAt(i);
+            getSourceConsumer(source.getType()).updateSource(source);
+        }
+        for (int i = mState.getSourcesCount() - 1; i >= 0; i--) {
+            InsetsSource source = mState.sourceAt(i);
+            if (newState.peekSource(source.getType()) == null) {
+                mState.removeSource(source.getType());
+            }
+        }
         if (mCaptionInsetsHeight != 0) {
             mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
                     mFrame.right, mFrame.top + mCaptionInsetsHeight));
         }
-        return true;
     }
 
     private boolean captionInsetsUnchanged() {
@@ -879,8 +894,15 @@
             control.cancel();
         }
         for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
-            if (mRunningAnimations.get(i).runner == control) {
+            RunningAnimation runningAnimation = mRunningAnimations.get(i);
+            if (runningAnimation.runner == control) {
                 mRunningAnimations.remove(i);
+                ArraySet<Integer> types = toInternalType(control.getTypes());
+                for (int j = types.size() - 1; j >= 0; j--) {
+                    if (getSourceConsumer(types.valueAt(j)).notifyAnimationFinished()) {
+                        mViewRoot.notifyInsetsChanged();
+                    }
+                }
                 break;
             }
         }
@@ -1076,8 +1098,8 @@
 
     @VisibleForTesting
     @Override
-    public void scheduleApplyChangeInsets() {
-        if (mStartingAnimation) {
+    public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
+        if (mStartingAnimation || runner.getAnimationType() == ANIMATION_TYPE_USER) {
             mAnimCallback.run();
             mAnimCallbackScheduled = false;
             return;
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 83ff8fa..6cb9374 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -16,11 +16,13 @@
 
 package android.view;
 
+import static android.view.InsetsController.ANIMATION_TYPE_NONE;
 import static android.view.InsetsController.AnimationType;
 import static android.view.InsetsState.toPublicType;
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.graphics.Rect;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowInsets.Type.InsetsType;
@@ -64,6 +66,8 @@
     private final Supplier<Transaction> mTransactionSupplier;
     private @Nullable InsetsSourceControl mSourceControl;
     private boolean mHasWindowFocus;
+    private Rect mPendingFrame;
+    private Rect mPendingVisibleFrame;
 
     public InsetsSourceConsumer(@InternalInsetsType int type, InsetsState state,
             Supplier<Transaction> transactionSupplier, InsetsController controller) {
@@ -87,6 +91,8 @@
         if (mSourceControl == control) {
             return;
         }
+        SurfaceControl oldLeash = mSourceControl != null ? mSourceControl.getLeash() : null;
+
         final InsetsSourceControl lastControl = mSourceControl;
         mSourceControl = control;
 
@@ -112,12 +118,18 @@
                 // However make sure that the leash visibility is still up to date.
                 if (applyLocalVisibilityOverride()) {
                     mController.notifyVisibilityChanged();
+                }
+
+                // If we have a new leash, make sure visibility is up-to-date, even though we
+                // didn't want to run an animation above.
+                SurfaceControl newLeash = mSourceControl.getLeash();
+                if (oldLeash == null || newLeash == null || !oldLeash.isSameSurface(newLeash)) {
                     applyHiddenToControl();
                 }
             }
         }
         if (lastControl != null) {
-            lastControl.release(mController::releaseSurfaceControlFromRt);
+            lastControl.release(SurfaceControl::release);
         }
     }
 
@@ -215,6 +227,38 @@
         // no-op for types that always return ShowResult#SHOW_IMMEDIATELY.
     }
 
+    void updateSource(InsetsSource newSource) {
+        InsetsSource source = mState.peekSource(mType);
+        if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE
+                || source.getFrame().equals(newSource.getFrame())) {
+            mState.addSource(newSource);
+            return;
+        }
+
+        // Frame is changing while animating. Keep note of the new frame but keep existing frame
+        // until animaition is finished.
+        newSource = new InsetsSource(newSource);
+        mPendingFrame = new Rect(newSource.getFrame());
+        mPendingVisibleFrame = newSource.getVisibleFrame() != null
+                ? new Rect(newSource.getVisibleFrame())
+                : null;
+        newSource.setFrame(source.getFrame());
+        newSource.setVisibleFrame(source.getVisibleFrame());
+        mState.addSource(newSource);
+    }
+
+    boolean notifyAnimationFinished() {
+        if (mPendingFrame != null) {
+            InsetsSource source = mState.getSource(mType);
+            source.setFrame(mPendingFrame);
+            source.setVisibleFrame(mPendingVisibleFrame);
+            mPendingFrame = null;
+            mPendingVisibleFrame = null;
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Sets requested visibility from the client, regardless of whether we are able to control it at
      * the moment.
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index f3ec65f..e001b66 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -44,8 +44,7 @@
     public InsetsSourceControl(InsetsSourceControl other) {
         mType = other.mType;
         if (other.mLeash != null) {
-            mLeash = new SurfaceControl();
-            mLeash.copyFrom(other.mLeash);
+            mLeash = new SurfaceControl(other.mLeash);
         } else {
             mLeash = null;
         }
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index c515466..9896aa4 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -172,6 +172,10 @@
         for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
             InsetsSource source = mSources.get(type);
             if (source == null) {
+                int index = indexOf(toPublicType(type));
+                if (typeInsetsMap[index] == null) {
+                    typeInsetsMap[index] = Insets.NONE;
+                }
                 continue;
             }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index a37c1cb..ab65e3a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -32,6 +32,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.ColorSpace;
@@ -215,6 +216,10 @@
 
     private static native void nativeSetFrameRate(
             long transactionObj, long nativeObject, float frameRate, int compatibility);
+    private static native long nativeGetHandle(long nativeObject);
+
+    private static native long nativeAcquireFrameRateFlexibilityToken();
+    private static native void nativeReleaseFrameRateFlexibilityToken(long token);
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
@@ -222,6 +227,7 @@
      * @hide
      */
     public long mNativeObject;
+    private long mNativeHandle;
 
     // TODO: Move this to native.
     private final Object mSizeLock = new Object();
@@ -424,12 +430,13 @@
             mCloseGuard.open("release");
         }
         mNativeObject = nativeObject;
+        mNativeHandle = mNativeObject != 0 ? nativeGetHandle(nativeObject) : 0;
     }
 
     /**
      * @hide
      */
-    public void copyFrom(SurfaceControl other) {
+    public void copyFrom(@NonNull SurfaceControl other) {
         mName = other.mName;
         mWidth = other.mWidth;
         mHeight = other.mHeight;
@@ -849,23 +856,19 @@
             throw new OutOfResourcesException(
                     "Couldn't allocate SurfaceControl native object");
         }
-
+        mNativeHandle = nativeGetHandle(mNativeObject);
         mCloseGuard.open("release");
     }
 
-    /** This is a transfer constructor, useful for transferring a live SurfaceControl native
-     * object to another Java wrapper which could have some different behavior, e.g.
-     * event logging.
+    /**
+     * Copy constructor. Creates a new native object pointing to the same surface as {@code other}.
+     *
+     * @param other The object to copy the surface from.
      * @hide
      */
-    public SurfaceControl(SurfaceControl other) {
-        mName = other.mName;
-        mWidth = other.mWidth;
-        mHeight = other.mHeight;
-        mNativeObject = other.mNativeObject;
-        other.mCloseGuard.close();
-        other.mNativeObject = 0;
-        mCloseGuard.open("release");
+    @TestApi
+    public SurfaceControl(@NonNull SurfaceControl other) {
+        copyFrom(other);
     }
 
     private SurfaceControl(Parcel in) {
@@ -917,6 +920,18 @@
     }
 
     /**
+     * Checks whether two {@link SurfaceControl} objects represent the same surface.
+     *
+     * @param other The other object to check
+     * @return {@code true} if these two {@link SurfaceControl} objects represent the same surface.
+     * @hide
+     */
+    @TestApi
+    public boolean isSameSurface(@NonNull SurfaceControl other) {
+        return other.mNativeHandle == mNativeHandle;
+    }
+
+    /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
      * android.view.SurfaceControlProto}.
      *
@@ -973,6 +988,7 @@
         if (mNativeObject != 0) {
             nativeRelease(mNativeObject);
             mNativeObject = 0;
+            mNativeHandle = 0;
             mCloseGuard.close();
         }
     }
@@ -2868,4 +2884,24 @@
             }
         }
     }
+
+    /**
+     * Acquire a frame rate flexibility token, which allows surface flinger to freely switch display
+     * frame rates. This is used by CTS tests to put the device in a consistent state. See
+     * ISurfaceComposer::acquireFrameRateFlexibilityToken().
+     * @hide
+     */
+    @TestApi
+    public static long acquireFrameRateFlexibilityToken() {
+        return nativeAcquireFrameRateFlexibilityToken();
+    }
+
+    /**
+     * Release a frame rate flexibility token.
+     * @hide
+     */
+    @TestApi
+    public static void releaseFrameRateFlexibilityToken(long token) {
+        nativeReleaseFrameRateFlexibilityToken(token);
+    }
 }
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index fe70ff7..174165c 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -124,8 +124,14 @@
     /** @hide */
     public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
             @NonNull WindowlessWindowManager wwm) {
+        this(c, d, wwm, false /* useSfChoreographer */);
+    }
+
+    /** @hide */
+    public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
+            @NonNull WindowlessWindowManager wwm, boolean useSfChoreographer) {
         mWm = wwm;
-        mViewRoot = new ViewRootImpl(c, d, mWm);
+        mViewRoot = new ViewRootImpl(c, d, mWm, useSfChoreographer);
         mViewRoot.forceDisableBLAST();
         mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index c89e0c9..b677ccd 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1037,7 +1037,7 @@
                             mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                                     mSurfaceHeight);
                         }
-                    } else if ((layoutSizeChanged || positionChanged) &&
+                    } else if ((layoutSizeChanged || positionChanged || visibleChanged) &&
                             viewRoot.useBLAST()) {
                         viewRoot.setUseBLASTSyncTransaction();
                     }
@@ -1241,7 +1241,7 @@
     private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
             Rect position, long frameNumber) {
         final ViewRootImpl viewRoot = getViewRootImpl();
-        if (frameNumber > 0 && viewRoot != null && !viewRoot.useBLAST()) {
+        if (frameNumber > 0 && viewRoot != null && !viewRoot.isDrawingToBLASTTransaction()) {
             t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(),
                     frameNumber);
         }
@@ -1258,7 +1258,7 @@
 
     private void setParentSpaceRectangle(Rect position, long frameNumber) {
         final ViewRootImpl viewRoot = getViewRootImpl();
-        final boolean useBLAST = viewRoot.useBLAST();
+        final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction();
         final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() :
             mRtTransaction;
 
@@ -1319,7 +1319,7 @@
         @Override
         public void positionLost(long frameNumber) {
             final ViewRootImpl viewRoot = getViewRootImpl();
-            boolean useBLAST = viewRoot != null && viewRoot.useBLAST();
+            boolean useBLAST = viewRoot != null && viewRoot.isDrawingToBLASTTransaction();
             if (DEBUG) {
                 Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
                         System.identityHashCode(this), frameNumber));
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 51304dc..750b1ed 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -21,6 +21,7 @@
 import static android.view.InputDevice.SOURCE_CLASS_NONE;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.LAST_TYPE;
 import static android.view.View.PFLAG_DRAW_ANIMATION;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -130,6 +131,7 @@
 import android.view.Window.OnContentApplyWindowInsetsListener;
 import android.view.WindowInsets.Type;
 import android.view.WindowInsets.Type.InsetsType;
+import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -448,7 +450,7 @@
     InputQueue mInputQueue;
     @UnsupportedAppUsage
     FallbackEventHandler mFallbackEventHandler;
-    Choreographer mChoreographer;
+    final Choreographer mChoreographer;
 
     // used in relayout to get SurfaceControl size
     // for BLAST adapter surface setup
@@ -557,7 +559,8 @@
     final DisplayCutout.ParcelableWrapper mPendingDisplayCutout =
             new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
     boolean mPendingAlwaysConsumeSystemBars;
-    private InsetsState mTempInsets = new InsetsState();
+    private final InsetsState mTempInsets = new InsetsState();
+    private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[LAST_TYPE + 1];
     final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
             = new ViewTreeObserver.InternalInsetsInfo();
 
@@ -691,11 +694,18 @@
     private SurfaceControl.Transaction mRtBLASTSyncTransaction = new SurfaceControl.Transaction();
 
     private String mTag = TAG;
+
     public ViewRootImpl(Context context, Display display) {
-        this(context, display, WindowManagerGlobal.getWindowSession());
+        this(context, display, WindowManagerGlobal.getWindowSession(),
+                false /* useSfChoreographer */);
     }
 
     public ViewRootImpl(Context context, Display display, IWindowSession session) {
+        this(context, display, session, false /* useSfChoreographer */);
+    }
+
+    public ViewRootImpl(Context context, Display display, IWindowSession session,
+            boolean useSfChoreographer) {
         mContext = context;
         mWindowSession = session;
         mDisplay = display;
@@ -731,7 +741,8 @@
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
         mFallbackEventHandler = new PhoneFallbackEventHandler(context);
-        mChoreographer = Choreographer.getInstance();
+        mChoreographer = useSfChoreographer
+                ? Choreographer.getSfInstance() : Choreographer.getInstance();
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
         mInsetsController = new InsetsController(this);
 
@@ -994,7 +1005,7 @@
                             getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
                             mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                             mAttachInfo.mDisplayCutout, inputChannel,
-                            mTempInsets);
+                            mTempInsets, mTempControls);
                     setFrame(mTmpFrame);
                 } catch (RemoteException e) {
                     mAdded = false;
@@ -1019,6 +1030,7 @@
                         (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS) != 0;
                 mPendingAlwaysConsumeSystemBars = mAttachInfo.mAlwaysConsumeSystemBars;
                 mInsetsController.onStateChanged(mTempInsets);
+                mInsetsController.onControlsChanged(mTempControls);
                 if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
                 if (res < WindowManagerGlobal.ADD_OKAY) {
                     mAttachInfo.mRootView = null;
@@ -1412,6 +1424,10 @@
                         | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
             }
 
+            if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) {
+                requestFitSystemWindows();
+            }
+
             mWindowAttributesChanged = true;
             scheduleTraversals();
         }
@@ -1742,17 +1758,18 @@
                 || !mBlastSurfaceControl.isValid()) {
             return null;
         }
+
+        Surface ret = null;
         if (mBlastBufferQueue == null) {
             mBlastBufferQueue = new BLASTBufferQueue(
                 mBlastSurfaceControl, width, height);
+            // We only return the Surface the first time, as otherwise
+            // it hasn't changed and there is no need to update.
+            ret = mBlastBufferQueue.getSurface();
         }
         mBlastBufferQueue.update(mBlastSurfaceControl, width, height);
 
-        mTransaction.show(mBlastSurfaceControl)
-            .reparent(mBlastSurfaceControl, mSurfaceControl)
-            .apply();
-
-        return mBlastBufferQueue.getSurface();
+        return ret;
     }
 
     private void setBoundsLayerCrop() {
@@ -7342,13 +7359,19 @@
                 insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                 mTmpFrame, mTmpRect, mTmpRect, mTmpRect, mPendingBackDropFrame,
                 mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
-                mSurfaceSize, mBlastSurfaceControl);
+                mTempControls, mSurfaceSize, mBlastSurfaceControl);
         if (mSurfaceControl.isValid()) {
             if (!mUseBLASTAdapter) {
                 mSurface.copyFrom(mSurfaceControl);
             } else {
-                mSurface.transferFrom(getOrCreateBLASTSurface(mSurfaceSize.x,
-                        mSurfaceSize.y));
+                final Surface blastSurface = getOrCreateBLASTSurface(mSurfaceSize.x,
+                    mSurfaceSize.y);
+                // If blastSurface == null that means it hasn't changed since the last time we
+                // called. In this situation, avoid calling transferFrom as we would then
+                // inc the generation ID and cause EGL resources to be recreated.
+                if (blastSurface != null) {
+                    mSurface.transferFrom(blastSurface);
+                }
             }
         } else {
             destroySurface();
@@ -7366,6 +7389,7 @@
         }
         setFrame(mTmpFrame);
         mInsetsController.onStateChanged(mTempInsets);
+        mInsetsController.onControlsChanged(mTempControls);
         return relayoutResult;
     }
 
@@ -9590,4 +9614,12 @@
     boolean useBLAST() {
         return mUseBLASTAdapter;
     }
+
+    /**
+     * Returns true if we are about to or currently processing a draw directed
+     * in to a BLAST transaction.
+     */
+    boolean isDrawingToBLASTTransaction() {
+        return mNextReportConsumeBLAST;
+    }
 }
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 9b2a6cb..ca3dd04 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -818,12 +818,13 @@
      * @return A modified copy of this WindowInsets
      * @deprecated Consuming of different parts individually of a {@link WindowInsets} instance is
      * deprecated, since {@link WindowInsets} contains many different insets. Use {@link #CONSUMED}
-     * instead to stop dispatching insets.
+     * instead to stop dispatching insets. On {@link android.os.Build.VERSION_CODES#R R}, this
+     * method has no effect.
      */
     @Deprecated
     @NonNull
     public WindowInsets consumeStableInsets() {
-        return consumeSystemWindowInsets();
+        return this;
     }
 
     /**
@@ -835,12 +836,24 @@
 
     @Override
     public String toString() {
-        return "WindowInsets{systemWindowInsets=" + getSystemWindowInsets()
-                + " stableInsets=" + getStableInsets()
-                + " sysGestureInsets=" + getSystemGestureInsets()
-                + (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "")
-                + (isRound() ? " round" : "")
-                + "}";
+        StringBuilder result = new StringBuilder("WindowInsets{\n    ");
+        for (int i = 0; i < SIZE; i++) {
+            Insets insets = mTypeInsetsMap[i];
+            Insets maxInsets = mTypeMaxInsetsMap[i];
+            boolean visible = mTypeVisibilityMap[i];
+            if (!Insets.NONE.equals(insets) || !Insets.NONE.equals(maxInsets) || visible) {
+                result.append(Type.toString(1 << i)).append("=").append(insets)
+                        .append(" max=").append(maxInsets)
+                        .append(" vis=").append(visible)
+                        .append("\n    ");
+            }
+        }
+
+        result.append(mDisplayCutout != null ? "cutout=" + mDisplayCutout : "");
+        result.append("\n    ");
+        result.append(isRound() ? "round" : "");
+        result.append("}");
+        return result.toString();
     }
 
     /**
@@ -1309,6 +1322,32 @@
             }
         }
 
+        static String toString(@InsetsType int type) {
+            switch (type) {
+                case STATUS_BARS:
+                    return "statusBars";
+                case NAVIGATION_BARS:
+                    return "navigationBars";
+                case CAPTION_BAR:
+                    return "captionBar";
+                case IME:
+                    return "ime";
+                case SYSTEM_GESTURES:
+                    return "systemGestures";
+                case MANDATORY_SYSTEM_GESTURES:
+                    return "mandatorySystemGestures";
+                case TAPPABLE_ELEMENT:
+                    return "tappableElement";
+                case DISPLAY_CUTOUT:
+                    return "displayCutout";
+                case WINDOW_DECOR:
+                    return "windowDecor";
+                default:
+                    throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
+                            + " type=" + type);
+            }
+        }
+
         private Type() {
         }
 
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 561ee60..316a5f2 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -36,7 +36,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 
 import java.util.List;
@@ -70,8 +69,7 @@
 public final class WindowManagerImpl implements WindowManager {
     @UnsupportedAppUsage
     private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
-    @VisibleForTesting
-    public final Context mContext;
+    private final Context mContext;
     private final Window mParentWindow;
 
     private IBinder mDefaultToken;
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 144f8e3..39ed401 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -104,7 +104,7 @@
             int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
             Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
-            InsetsState outInsetsState) {
+            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
                 .setParent(mRootSurface)
                 .setFormat(attrs.format)
@@ -179,7 +179,8 @@
             Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
+            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
+            SurfaceControl outBLASTSurfaceControl) {
         final State state;
         synchronized (this) {
             state = mStateForWindow.get(window.asBinder());
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index dc87453..6a10925 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -1275,7 +1275,14 @@
 
     /**
      * Register the provided {@link RemoteAction} with the given actionId
-     *
+     * <p>
+     * To perform established system actions, an accessibility service uses the GLOBAL_ACTION
+     * constants in {@link android.accessibilityservice.AccessibilityService}. To provide a
+     * customized implementation for one of these actions, the id of the registered system action
+     * must match that of the corresponding GLOBAL_ACTION constant. For example, to register a
+     * Back action, {@code actionId} must be
+     * {@link android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK}
+     * </p>
      * @param action The remote action to be registered with the given actionId as system action.
      * @param actionId The id uniquely identify the system action.
      * @hide
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 6aa288d..af896fc 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -30,6 +30,7 @@
 
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Preconditions;
+import com.android.internal.widget.InlinePresentationStyleUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -113,6 +114,10 @@
         mHostInputToken = hostInputToken;
     }
 
+    private boolean extrasEquals(@NonNull Bundle extras) {
+        return InlinePresentationStyleUtils.bundleEquals(mExtras, extras);
+    }
+
     // TODO(b/149609075): remove once IBinder parcelling is natively supported
     private void parcelHostInputToken(@NonNull Parcel parcel, int flags) {
         parcel.writeStrongBinder(mHostInputToken);
@@ -331,7 +336,7 @@
                 && java.util.Objects.equals(mInlinePresentationSpecs, that.mInlinePresentationSpecs)
                 && java.util.Objects.equals(mHostPackageName, that.mHostPackageName)
                 && java.util.Objects.equals(mSupportedLocales, that.mSupportedLocales)
-                && java.util.Objects.equals(mExtras, that.mExtras)
+                && extrasEquals(that.mExtras)
                 && java.util.Objects.equals(mHostInputToken, that.mHostInputToken)
                 && mHostDisplayId == that.mHostDisplayId;
     }
@@ -603,10 +608,10 @@
     }
 
     @DataClass.Generated(
-            time = 1585691147541L,
+            time = 1585768018462L,
             codegenVersion = "1.0.15",
             sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
-            inputSignatures = "public static final  int SUGGESTION_COUNT_UNLIMITED\nprivate final  int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate  int mHostDisplayId\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs()\npublic  void setHostInputToken(android.os.IBinder)\nprivate  void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic  void setHostDisplayId(int)\nprivate  void onConstructed()\nprivate static  int defaultMaxSuggestionCount()\nprivate static  java.lang.String defaultHostPackageName()\nprivate static  android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.view.inputmethod.InlineSuggestionsRequest.Builder addPresentationSpecs(android.view.inline.InlinePresentationSpec)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "public static final  int SUGGESTION_COUNT_UNLIMITED\nprivate final  int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate  int mHostDisplayId\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs()\npublic  void setHostInputToken(android.os.IBinder)\nprivate  boolean extrasEquals(android.os.Bundle)\nprivate  void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic  void setHostDisplayId(int)\nprivate  void onConstructed()\nprivate static  int defaultMaxSuggestionCount()\nprivate static  java.lang.String defaultHostPackageName()\nprivate static  android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.view.inputmethod.InlineSuggestionsRequest.Builder addPresentationSpecs(android.view.inline.InlinePresentationSpec)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract  android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 71ccb59..849488d 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -22,6 +22,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -484,21 +485,21 @@
         super.onInitializeAccessibilityNodeInfo(info);
         if (this.getOrientation() == HORIZONTAL) {
             info.setCollectionInfo(AccessibilityNodeInfo.CollectionInfo.obtain(1,
-                    getVisibleChildCount(), false,
+                    getVisibleChildWithTextCount(), false,
                     AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_SINGLE));
         } else {
             info.setCollectionInfo(
-                    AccessibilityNodeInfo.CollectionInfo.obtain(getVisibleChildCount(),
+                    AccessibilityNodeInfo.CollectionInfo.obtain(getVisibleChildWithTextCount(),
                     1, false,
                     AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_SINGLE));
         }
     }
 
-    private int getVisibleChildCount() {
+    private int getVisibleChildWithTextCount() {
         int count = 0;
         for (int i = 0; i < getChildCount(); i++) {
             if (this.getChildAt(i) instanceof RadioButton) {
-                if (((RadioButton) this.getChildAt(i)).getVisibility() == VISIBLE) {
+                if (isVisibleWithText((RadioButton) this.getChildAt(i))) {
                     count++;
                 }
             }
@@ -513,15 +514,19 @@
         int index = 0;
         for (int i = 0; i < getChildCount(); i++) {
             if (this.getChildAt(i) instanceof RadioButton) {
-                RadioButton radioButton = (RadioButton) this.getChildAt(i);
-                if (radioButton == child) {
+                RadioButton button = (RadioButton) this.getChildAt(i);
+                if (button == child) {
                     return index;
                 }
-                if (radioButton.getVisibility() == VISIBLE) {
+                if (isVisibleWithText(button)) {
                     index++;
                 }
             }
         }
         return -1;
     }
+
+    private boolean isVisibleWithText(RadioButton button) {
+        return button.getVisibility() == VISIBLE && !TextUtils.isEmpty(button.getText());
+    }
 }
\ No newline at end of file
diff --git a/core/java/android/widget/TEST_MAPPING b/core/java/android/widget/TEST_MAPPING
index d0b8dbc..f089f48 100644
--- a/core/java/android/widget/TEST_MAPPING
+++ b/core/java/android/widget/TEST_MAPPING
@@ -13,7 +13,7 @@
       "name": "CtsWindowManagerDeviceTestCases",
       "options": [
         {
-          "include-filter": "android.server.wm.ToastTest"
+          "include-filter": "android.server.wm.ToastWindowTest"
         }
       ],
       "file_patterns": ["Toast\\.java"]
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 4f14539..fb96210 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -43,7 +43,7 @@
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -117,7 +117,6 @@
     private final Binder mToken;
     private final Context mContext;
     private final Handler mHandler;
-    private final ToastPresenter mPresenter;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     final TN mTN;
     @UnsupportedAppUsage
@@ -165,8 +164,8 @@
         looper = getLooper(looper);
         mHandler = new Handler(looper);
         mCallbacks = new ArrayList<>();
-        mPresenter = new ToastPresenter(context, AccessibilityManager.getInstance(context));
-        mTN = new TN(mPresenter, context.getPackageName(), mToken, mCallbacks, looper);
+        mTN = new TN(context, context.getPackageName(), mToken,
+                mCallbacks, looper);
         mTN.mY = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.toast_y_offset);
         mTN.mGravity = context.getResources().getInteger(
@@ -496,7 +495,7 @@
             return result;
         } else {
             Toast result = new Toast(context, looper);
-            View v = result.mPresenter.getTextToastView(text);
+            View v = ToastPresenter.getTextToastView(context, text);
             result.mNextView = v;
             result.mDuration = duration;
 
@@ -565,13 +564,14 @@
         if (sService != null) {
             return sService;
         }
-        sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
+        sService = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
         return sService;
     }
 
     private static class TN extends ITransientNotification.Stub {
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
-        private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
+        private final WindowManager.LayoutParams mParams;
 
         private static final int SHOW = 0;
         private static final int HIDE = 1;
@@ -608,9 +608,13 @@
          * The parameter {@code callbacks} is not copied and is accessed with itself as its own
          * lock.
          */
-        TN(ToastPresenter presenter, String packageName, Binder token, List<Callback> callbacks,
+        TN(Context context, String packageName, Binder token, List<Callback> callbacks,
                 @Nullable Looper looper) {
-            mPresenter = presenter;
+            IAccessibilityManager accessibilityManager = IAccessibilityManager.Stub.asInterface(
+                    ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
+            mPresenter = new ToastPresenter(context, accessibilityManager, getService(),
+                    packageName);
+            mParams = mPresenter.getLayoutParams();
             mPackageName = packageName;
             mToken = token;
             mCallbacks = callbacks;
@@ -645,8 +649,6 @@
                     }
                 }
             };
-
-            presenter.startLayoutParams(mParams, packageName);
         }
 
         private List<Callback> getCallbacks() {
@@ -691,31 +693,9 @@
                 // remove the old view if necessary
                 handleHide();
                 mView = mNextView;
-                Context context = mView.getContext().getApplicationContext();
-                if (context == null) {
-                    context = mView.getContext();
-                }
-                mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-                mPresenter.adjustLayoutParams(mParams, windowToken, mDuration, mGravity, mX, mY,
-                        mHorizontalMargin, mVerticalMargin);
-                if (mView.getParent() != null) {
-                    if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
-                    mWM.removeView(mView);
-                }
-                if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
-                // Since the notification manager service cancels the token right
-                // after it notifies us to cancel the toast there is an inherent
-                // race and we may attempt to add a window after the token has been
-                // invalidated. Let us hedge against that.
-                try {
-                    mWM.addView(mView, mParams);
-                    mPresenter.trySendAccessibilityEvent(mView, mPackageName);
-                    for (Callback callback : getCallbacks()) {
-                        callback.onToastShown();
-                    }
-                } catch (WindowManager.BadTokenException e) {
-                    /* ignore */
-                }
+                mPresenter.show(mView, mToken, windowToken, mDuration, mGravity, mX, mY,
+                        mHorizontalMargin, mVerticalMargin,
+                        new CallbackBinder(getCallbacks(), mHandler));
             }
         }
 
@@ -723,25 +703,9 @@
         public void handleHide() {
             if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
             if (mView != null) {
-                // note: checking parent() just to make sure the view has
-                // been added...  i have seen cases where we get here when
-                // the view isn't yet added, so let's try not to crash.
-                if (mView.getParent() != null) {
-                    if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
-                    mWM.removeViewImmediate(mView);
-                }
-
-
-                // Now that we've removed the view it's safe for the server to release
-                // the resources.
-                try {
-                    getService().finishToken(mPackageName, mToken);
-                } catch (RemoteException e) {
-                }
-
-                for (Callback callback : getCallbacks()) {
-                    callback.onToastHidden();
-                }
+                checkState(mView == mPresenter.getView(),
+                        "Trying to hide toast view different than the last one displayed");
+                mPresenter.hide(new CallbackBinder(getCallbacks(), mHandler));
                 mView = null;
             }
         }
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 0447b6b..2679c69 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -16,19 +16,29 @@
 
 package android.widget;
 
+import static com.android.internal.util.Preconditions.checkState;
+
+import android.annotation.Nullable;
+import android.app.INotificationManager;
+import android.app.ITransientNotificationCallback;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
 /**
@@ -37,41 +47,104 @@
  * @hide
  */
 public class ToastPresenter {
+    private static final String TAG = "ToastPresenter";
+    private static final String WINDOW_TITLE = "Toast";
     private static final long SHORT_DURATION_TIMEOUT = 4000;
     private static final long LONG_DURATION_TIMEOUT = 7000;
 
+    @VisibleForTesting
+    public static final int TEXT_TOAST_LAYOUT = R.layout.transient_notification;
+
+    /**
+     * Returns the default text toast view for message {@code text}.
+     */
+    public static View getTextToastView(Context context, CharSequence text) {
+        View view = LayoutInflater.from(context).inflate(TEXT_TOAST_LAYOUT, null);
+        TextView textView = view.findViewById(com.android.internal.R.id.message);
+        textView.setText(text);
+        return view;
+    }
+
     private final Context mContext;
     private final Resources mResources;
+    private final WindowManager mWindowManager;
     private final AccessibilityManager mAccessibilityManager;
+    private final INotificationManager mNotificationManager;
+    private final String mPackageName;
+    private final WindowManager.LayoutParams mParams;
+    @Nullable private View mView;
+    @Nullable private IBinder mToken;
 
-    public ToastPresenter(Context context, AccessibilityManager accessibilityManager) {
+    public ToastPresenter(Context context, IAccessibilityManager accessibilityManager,
+            INotificationManager notificationManager, String packageName) {
         mContext = context;
         mResources = context.getResources();
-        mAccessibilityManager = accessibilityManager;
+        mWindowManager = context.getSystemService(WindowManager.class);
+        mNotificationManager = notificationManager;
+        mPackageName = packageName;
+
+        // We obtain AccessibilityManager manually via its constructor instead of using method
+        // AccessibilityManager.getInstance() for 2 reasons:
+        //   1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
+        //   2. getInstance() caches the instance for the process even if we pass a different
+        //      context to it. This is problematic for multi-user because callers can pass a context
+        //      created via Context.createContextAsUser().
+        mAccessibilityManager = new AccessibilityManager(context, accessibilityManager,
+                UserHandle.getCallingUserId());
+
+        mParams = createLayoutParams();
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public WindowManager.LayoutParams getLayoutParams() {
+        return mParams;
     }
 
     /**
-     * Initializes {@code params} with default values for toasts.
+     * Returns the {@link View} being shown at the moment or {@code null} if no toast is being
+     * displayed.
      */
-    public void startLayoutParams(WindowManager.LayoutParams params, String packageName) {
+    @Nullable
+    public View getView() {
+        return mView;
+    }
+
+    /**
+     * Returns the {@link IBinder} token used to display the toast or {@code null} if there is no
+     * toast being shown at the moment.
+     */
+    @Nullable
+    public IBinder getToken() {
+        return mToken;
+    }
+
+    /**
+     * Creates {@link WindowManager.LayoutParams} with default values for toasts.
+     */
+    private WindowManager.LayoutParams createLayoutParams() {
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
         params.height = WindowManager.LayoutParams.WRAP_CONTENT;
         params.width = WindowManager.LayoutParams.WRAP_CONTENT;
         params.format = PixelFormat.TRANSLUCENT;
         params.windowAnimations = R.style.Animation_Toast;
         params.type = WindowManager.LayoutParams.TYPE_TOAST;
         params.setFitInsetsIgnoringVisibility(true);
-        params.setTitle("Toast");
+        params.setTitle(WINDOW_TITLE);
         params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-        setShowForAllUsersIfApplicable(params, packageName);
+        setShowForAllUsersIfApplicable(params, mPackageName);
+        return params;
     }
 
     /**
      * Customizes {@code params} according to other parameters, ready to be passed to {@link
      * WindowManager#addView(View, ViewGroup.LayoutParams)}.
      */
-    public void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken,
+    private void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken,
             int duration, int gravity, int xOffset, int yOffset, float horizontalMargin,
             float verticalMargin) {
         Configuration config = mResources.getConfiguration();
@@ -97,7 +170,7 @@
      * Sets {@link WindowManager.LayoutParams#SYSTEM_FLAG_SHOW_FOR_ALL_USERS} flag if {@code
      * packageName} is a cross-user package.
      *
-     * Implementation note:
+     * <p>Implementation note:
      *     This code is safe to be executed in SystemUI and the app's process:
      *         <li>SystemUI: It's running on a trusted domain so apps can't tamper with it. SystemUI
      *             has the permission INTERNAL_SYSTEM_WINDOW needed by the flag, so SystemUI can add
@@ -120,14 +193,66 @@
     }
 
     /**
-     * Returns the default text toast view for message {@code text}.
+     * Shows the toast in {@code view} with the parameters passed and callback {@code callback}.
      */
-    public View getTextToastView(CharSequence text) {
-        View view = LayoutInflater.from(mContext).inflate(
-                R.layout.transient_notification, null);
-        TextView textView = view.findViewById(com.android.internal.R.id.message);
-        textView.setText(text);
-        return view;
+    public void show(View view, IBinder token, IBinder windowToken, int duration, int gravity,
+            int xOffset, int yOffset, float horizontalMargin, float verticalMargin,
+            @Nullable ITransientNotificationCallback callback) {
+        checkState(mView == null, "Only one toast at a time is allowed, call hide() first.");
+        mView = view;
+        mToken = token;
+
+        adjustLayoutParams(mParams, windowToken, duration, gravity, xOffset, yOffset,
+                horizontalMargin, verticalMargin);
+        if (mView.getParent() != null) {
+            mWindowManager.removeView(mView);
+        }
+        try {
+            mWindowManager.addView(mView, mParams);
+        } catch (WindowManager.BadTokenException e) {
+            // Since the notification manager service cancels the token right after it notifies us
+            // to cancel the toast there is an inherent race and we may attempt to add a window
+            // after the token has been invalidated. Let us hedge against that.
+            Log.w(TAG, "Error while attempting to show toast from " + mPackageName, e);
+            return;
+        }
+        trySendAccessibilityEvent(mView, mPackageName);
+        if (callback != null) {
+            try {
+                callback.onToastShown();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling back " + mPackageName + " to notify onToastShow()", e);
+            }
+        }
+    }
+
+    /**
+     * Hides toast that was shown using {@link #show(View, IBinder, IBinder, int,
+     * int, int, int, float, float, ITransientNotificationCallback)}.
+     *
+     * <p>This method has to be called on the same thread on which {@link #show(View, IBinder,
+     * IBinder, int, int, int, int, float, float, ITransientNotificationCallback)} was called.
+     */
+    public void hide(@Nullable ITransientNotificationCallback callback) {
+        checkState(mView != null, "No toast to hide.");
+
+        if (mView.getParent() != null) {
+            mWindowManager.removeViewImmediate(mView);
+        }
+        try {
+            mNotificationManager.finishToken(mPackageName, mToken);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error finishing toast window token from package " + mPackageName, e);
+        }
+        if (callback != null) {
+            try {
+                callback.onToastHidden();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling back " + mPackageName + " to notify onToastHide()", e);
+            }
+        }
+        mView = null;
+        mToken = null;
     }
 
     /**
diff --git a/core/java/android/widget/inline/InlinePresentationSpec.java b/core/java/android/widget/inline/InlinePresentationSpec.java
index 00eb3ce..5635857 100644
--- a/core/java/android/widget/inline/InlinePresentationSpec.java
+++ b/core/java/android/widget/inline/InlinePresentationSpec.java
@@ -23,6 +23,7 @@
 import android.util.Size;
 
 import com.android.internal.util.DataClass;
+import com.android.internal.widget.InlinePresentationStyleUtils;
 
 /**
  * This class represents the presentation specification by which an inline suggestion
@@ -52,6 +53,10 @@
         return Bundle.EMPTY;
     }
 
+    private boolean styleEquals(@NonNull Bundle style) {
+        return InlinePresentationStyleUtils.bundleEquals(mStyle, style);
+    }
+
     /** @hide */
     @DataClass.Suppress({"setMaxSize", "setMinSize"})
     abstract static class BaseBuilder {
@@ -143,7 +148,7 @@
         return true
                 && java.util.Objects.equals(mMinSize, that.mMinSize)
                 && java.util.Objects.equals(mMaxSize, that.mMaxSize)
-                && java.util.Objects.equals(mStyle, that.mStyle);
+                && styleEquals(that.mStyle);
     }
 
     @Override
@@ -280,10 +285,10 @@
     }
 
     @DataClass.Generated(
-            time = 1585605466300L,
+            time = 1585768046898L,
             codegenVersion = "1.0.15",
             sourceFile = "frameworks/base/core/java/android/widget/inline/InlinePresentationSpec.java",
-            inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.NonNull android.os.Bundle mStyle\nprivate static @android.annotation.NonNull android.os.Bundle defaultStyle()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.NonNull android.os.Bundle mStyle\nprivate static @android.annotation.NonNull android.os.Bundle defaultStyle()\nprivate  boolean styleEquals(android.os.Bundle)\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index 9fc0da8..d43333e 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -55,6 +55,7 @@
     private static final String TAG = "AbstractMultiProfilePagerAdapter";
     static final int PROFILE_PERSONAL = 0;
     static final int PROFILE_WORK = 1;
+
     @IntDef({PROFILE_PERSONAL, PROFILE_WORK})
     @interface Profile {}
 
@@ -365,7 +366,7 @@
         UserHandle listUserHandle = listAdapter.getUserHandle();
         if (!listUserHandle.equals(mWorkProfileUserHandle)
                 || !mInjector.isQuietModeEnabled(mWorkProfileUserHandle)
-                || !hasResolvedAppsInWorkProfile(listAdapter)) {
+                || listAdapter.getCount() == 0) {
             return false;
         }
         DevicePolicyEventLogger
@@ -382,20 +383,6 @@
         return true;
     }
 
-    /**
-     * Returns {@code true} if there is at least one app resolved in the work profile,
-     * regardless of whether the work profile is enabled or not.
-     */
-    private boolean hasResolvedAppsInWorkProfile(ResolverListAdapter listAdapter) {
-        List<ResolverActivity.ResolvedComponentInfo> userStateIndependentWorkResolvers =
-                listAdapter.mResolverListController.getUserStateIndependentResolversAsUser(
-                        listAdapter.getIntents(), mWorkProfileUserHandle);
-        return userStateIndependentWorkResolvers.stream()
-                .anyMatch(resolvedComponentInfo ->
-                        resolvedComponentInfo.getResolveInfoAt(0).targetUserId
-                                == UserHandle.USER_CURRENT);
-    }
-
     private void maybeShowNoAppsAvailableEmptyState(ResolverListAdapter listAdapter) {
         UserHandle listUserHandle = listAdapter.getUserHandle();
         if (mWorkProfileUserHandle != null
@@ -529,6 +516,13 @@
         return false;
     }
 
+    boolean shouldShowEmptyStateScreen(ResolverListAdapter listAdapter) {
+        int count = listAdapter.getUnfilteredCount();
+        return (count == 0 && listAdapter.getPlaceholderCount() == 0)
+                || (listAdapter.getUserHandle().equals(mWorkProfileUserHandle)
+                    && isQuietModeEnabled(mWorkProfileUserHandle));
+    }
+
     protected class ProfileDescriptor {
         final ViewGroup rootView;
         private final ViewGroup mEmptyStateView;
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 553721d7..be43e82 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -286,6 +286,7 @@
         if (mTitleView != null) {
             mTitleView.setText(title);
         }
+        mWindow.setTitle(title);
     }
 
     /**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index dca682e..c82ab6c 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -124,6 +124,7 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.GridLayoutManager;
 import com.android.internal.widget.RecyclerView;
 import com.android.internal.widget.ResolverDrawerLayout;
@@ -178,7 +179,7 @@
     private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = true;
     // TODO(b/123088566) Share these in a better way.
     private static final String APP_PREDICTION_SHARE_UI_SURFACE = "share";
-    public static final String LAUNCH_LOCATON_DIRECT_SHARE = "direct_share";
+    public static final String LAUNCH_LOCATION_DIRECT_SHARE = "direct_share";
     private static final int APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
     public static final String APP_PREDICTION_INTENT_FILTER_KEY = "intent_filter";
 
@@ -194,6 +195,14 @@
     public static final int TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER = 2;
     public static final int TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE = 3;
 
+    public static final int SELECTION_TYPE_SERVICE = 1;
+    public static final int SELECTION_TYPE_APP = 2;
+    public static final int SELECTION_TYPE_STANDARD = 3;
+    public static final int SELECTION_TYPE_COPY = 4;
+
+    // statsd logger wrapper
+    protected ChooserActivityLogger mChooserActivityLogger;
+
     private static final boolean USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS = true;
 
     @IntDef(flag = false, prefix = { "TARGET_TYPE_" }, value = {
@@ -226,7 +235,7 @@
     private boolean mAppendDirectShareEnabled = DeviceConfig.getBoolean(
             DeviceConfig.NAMESPACE_SYSTEMUI,
             SystemUiDeviceConfigFlags.APPEND_DIRECT_SHARE_ENABLED,
-            false);
+            true);
 
     private Bundle mReplacementExtras;
     private IntentSender mChosenComponentSender;
@@ -270,9 +279,9 @@
 
     // Starting at 1 since 0 is considered "undefined" for some of the database transformations
     // of tron logs.
-    private static final int CONTENT_PREVIEW_IMAGE = 1;
-    private static final int CONTENT_PREVIEW_FILE = 2;
-    private static final int CONTENT_PREVIEW_TEXT = 3;
+    protected static final int CONTENT_PREVIEW_IMAGE = 1;
+    protected static final int CONTENT_PREVIEW_FILE = 2;
+    protected static final int CONTENT_PREVIEW_TEXT = 3;
     protected MetricsLogger mMetricsLogger;
 
     private ContentPreviewCoordinator mPreviewCoord;
@@ -500,6 +509,9 @@
 
                 case CHOOSER_TARGET_SERVICE_WATCHDOG_MAX_TIMEOUT:
                     mMinTimeoutPassed = true;
+                    if (!mServiceConnections.isEmpty()) {
+                        getChooserActivityLogger().logSharesheetDirectLoadTimeout();
+                    }
                     unbindRemainingServices();
                     maybeStopServiceRequestTimer();
                     break;
@@ -533,6 +545,7 @@
                     logDirectShareTargetReceived(
                             MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER);
                     sendVoiceChoicesIfNeeded();
+                    getChooserActivityLogger().logSharesheetDirectLoadComplete();
                     break;
 
                 default:
@@ -544,6 +557,7 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         final long intentReceivedTime = System.currentTimeMillis();
+        getChooserActivityLogger().logSharesheetTriggered();
         // This is the only place this value is being set. Effectively final.
         mIsAppPredictorComponentAvailable = isAppPredictionServiceAvailable();
 
@@ -707,6 +721,8 @@
                                 incrementNumSheetExpansions();
                                 mWrittenOnce = true;
                             }
+                            getChooserActivityLogger()
+                                    .logSharesheetExpansionChanged(isCollapsed);
                         }
                     });
         }
@@ -715,6 +731,16 @@
             Log.d(TAG, "System Time Cost is " + systemCost);
         }
 
+        getChooserActivityLogger().logShareStarted(
+                FrameworkStatsLog.SHARESHEET_STARTED,
+                getReferrerPackageName(),
+                target.getType(),
+                initialIntents == null ? 0 : initialIntents.length,
+                mCallerChooserTargets == null ? 0 : mCallerChooserTargets.length,
+                isWorkProfile(),
+                findPreferredContentPreview(getTargetIntent(), getContentResolver()),
+                target.getAction()
+        );
         mDirectShareShortcutInfoCache = new HashMap<>();
     }
 
@@ -969,6 +995,10 @@
             LogMaker targetLogMaker = new LogMaker(
                     MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET).setSubtype(1);
             getMetricsLogger().write(targetLogMaker);
+            getChooserActivityLogger().logShareTargetSelected(
+                    SELECTION_TYPE_COPY,
+                    "",
+                    -1);
 
             finish();
         }
@@ -1644,18 +1674,33 @@
                     if (mCallerChooserTargets != null) {
                         numCallerProvided = mCallerChooserTargets.length;
                     }
+                    getChooserActivityLogger().logShareTargetSelected(
+                            SELECTION_TYPE_SERVICE,
+                            targetInfo.getResolveInfo().activityInfo.processName,
+                            value
+                    );
                     break;
                 case ChooserListAdapter.TARGET_CALLER:
                 case ChooserListAdapter.TARGET_STANDARD:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
                     value -= currentListAdapter.getSelectableServiceTargetCount();
                     numCallerProvided = currentListAdapter.getCallerTargetCount();
+                    getChooserActivityLogger().logShareTargetSelected(
+                            SELECTION_TYPE_APP,
+                            targetInfo.getResolveInfo().activityInfo.processName,
+                            value
+                    );
                     break;
                 case ChooserListAdapter.TARGET_STANDARD_AZ:
                     // A-Z targets are unranked standard targets; we use -1 to mark that they
                     // are from the alphabetical pool.
                     value = -1;
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
+                    getChooserActivityLogger().logShareTargetSelected(
+                            SELECTION_TYPE_STANDARD,
+                            targetInfo.getResolveInfo().activityInfo.processName,
+                            value
+                    );
                     break;
             }
 
@@ -2131,7 +2176,7 @@
         if (appTarget != null) {
             directShareAppPredictor.notifyAppTargetEvent(
                     new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
-                        .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
+                        .setLaunchLocation(LAUNCH_LOCATION_DIRECT_SHARE)
                         .build());
         }
     }
@@ -2290,6 +2335,13 @@
         return mMetricsLogger;
     }
 
+    protected ChooserActivityLogger getChooserActivityLogger() {
+        if (mChooserActivityLogger == null) {
+            mChooserActivityLogger = new ChooserActivityLoggerImpl();
+        }
+        return mChooserActivityLogger;
+    }
+
     public class ChooserListController extends ResolverListController {
         public ChooserListController(Context context,
                 PackageManager pm,
@@ -2601,6 +2653,7 @@
 
         // don't support direct share on low ram devices
         if (ActivityManager.isLowRamDeviceStatic()) {
+            getChooserActivityLogger().logSharesheetAppLoadComplete();
             return;
         }
 
@@ -2619,6 +2672,8 @@
 
             queryTargetServices(chooserListAdapter);
         }
+
+        getChooserActivityLogger().logSharesheetAppLoadComplete();
     }
 
     private void setupScrollListener() {
@@ -3777,4 +3832,9 @@
             canvas.drawRoundRect(x, y, width, height, mRadius, mRadius, mRoundRectPaint);
         }
     }
+
+    @Override
+    protected void maybeLogProfileChange() {
+        getChooserActivityLogger().logShareheetProfileChanged();
+    }
 }
diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java
new file mode 100644
index 0000000..088973c
--- /dev/null
+++ b/core/java/com/android/internal/app/ChooserActivityLogger.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app;
+
+import android.content.Intent;
+import android.provider.MediaStore;
+
+import com.android.internal.logging.InstanceId;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.util.FrameworkStatsLog;
+
+/**
+ * Interface for writing Sharesheet atoms to statsd log.
+ * @hide
+ */
+public interface ChooserActivityLogger {
+    /** Logs a UiEventReported event for the system sharesheet completing initial start-up. */
+    void logShareStarted(int eventId, String packageName, String mimeType, int appProvidedDirect,
+            int appProvidedApp, boolean isWorkprofile, int previewType, String intent);
+
+    /** Logs a UiEventReported event for the system sharesheet when the user selects a target. */
+    void logShareTargetSelected(int targetType, String packageName, int positionPicked);
+
+    /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */
+    default void logSharesheetTriggered() {
+        log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId());
+    }
+
+    /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */
+    default void logSharesheetAppLoadComplete() {
+        log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId());
+    }
+
+    /**
+     * Logs a UiEventReported event for the system sharesheet completing loading service targets.
+     */
+    default void logSharesheetDirectLoadComplete() {
+        log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId());
+    }
+
+    /**
+     * Logs a UiEventReported event for the system sharesheet timing out loading service targets.
+     */
+    default void logSharesheetDirectLoadTimeout() {
+        log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId());
+    }
+
+    /**
+     * Logs a UiEventReported event for the system sharesheet switching
+     * between work and main profile.
+     */
+    default void logShareheetProfileChanged() {
+        log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId());
+    }
+
+    /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */
+    default void logSharesheetExpansionChanged(boolean isCollapsed) {
+        log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED :
+                SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId());
+    }
+
+    /**
+     * Logs a UiEventReported event for a given share activity
+     * @param event
+     * @param instanceId
+     */
+    void log(UiEventLogger.UiEventEnum event, InstanceId instanceId);
+
+    /**
+     *
+     * @return
+     */
+    InstanceId getInstanceId();
+
+    /**
+     * The UiEvent enums that this class can log.
+     */
+    enum SharesheetStartedEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "Basic system Sharesheet has started and is visible.")
+        SHARE_STARTED(228);
+
+        private final int mId;
+        SharesheetStartedEvent(int id) {
+            mId = id;
+        }
+        @Override
+        public int getId() {
+            return mId;
+        }
+    }
+
+    /**
+     * The UiEvent enums that this class can log.
+     */
+    enum SharesheetTargetSelectedEvent implements UiEventLogger.UiEventEnum {
+        INVALID(0),
+        @UiEvent(doc = "User selected a service target.")
+        SHARESHEET_SERVICE_TARGET_SELECTED(232),
+        @UiEvent(doc = "User selected an app target.")
+        SHARESHEET_APP_TARGET_SELECTED(233),
+        @UiEvent(doc = "User selected a standard target.")
+        SHARESHEET_STANDARD_TARGET_SELECTED(234),
+        @UiEvent(doc = "User selected the copy target.")
+        SHARESHEET_COPY_TARGET_SELECTED(235);
+
+        private final int mId;
+        SharesheetTargetSelectedEvent(int id) {
+            mId = id;
+        }
+        @Override public int getId() {
+            return mId;
+        }
+
+        public static SharesheetTargetSelectedEvent fromTargetType(int targetType) {
+            switch(targetType) {
+                case ChooserActivity.SELECTION_TYPE_SERVICE:
+                    return SHARESHEET_SERVICE_TARGET_SELECTED;
+                case ChooserActivity.SELECTION_TYPE_APP:
+                    return SHARESHEET_APP_TARGET_SELECTED;
+                case ChooserActivity.SELECTION_TYPE_STANDARD:
+                    return SHARESHEET_STANDARD_TARGET_SELECTED;
+                case ChooserActivity.SELECTION_TYPE_COPY:
+                    return SHARESHEET_COPY_TARGET_SELECTED;
+                default:
+                    return INVALID;
+            }
+        }
+    }
+
+    /**
+     * The UiEvent enums that this class can log.
+     */
+    enum SharesheetStandardEvent implements UiEventLogger.UiEventEnum {
+        INVALID(0),
+        @UiEvent(doc = "User clicked share.")
+        SHARESHEET_TRIGGERED(227),
+        @UiEvent(doc = "User changed from work to personal profile or vice versa.")
+        SHARESHEET_PROFILE_CHANGED(229),
+        @UiEvent(doc = "User expanded target list.")
+        SHARESHEET_EXPANDED(230),
+        @UiEvent(doc = "User collapsed target list.")
+        SHARESHEET_COLLAPSED(231),
+        @UiEvent(doc = "Sharesheet app targets is fully populated.")
+        SHARESHEET_APP_LOAD_COMPLETE(322),
+        @UiEvent(doc = "Sharesheet direct targets is fully populated.")
+        SHARESHEET_DIRECT_LOAD_COMPLETE(323),
+        @UiEvent(doc = "Sharesheet direct targets timed out.")
+        SHARESHEET_DIRECT_LOAD_TIMEOUT(324);
+
+        private final int mId;
+        SharesheetStandardEvent(int id) {
+            mId = id;
+        }
+        @Override public int getId() {
+            return mId;
+        }
+    }
+
+    /**
+     * Returns the enum used in sharesheet started atom to indicate what preview type was used.
+     */
+    default int typeFromPreviewInt(int previewType) {
+        switch(previewType) {
+            case ChooserActivity.CONTENT_PREVIEW_IMAGE:
+                return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_IMAGE;
+            case ChooserActivity.CONTENT_PREVIEW_FILE:
+                return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE;
+            case ChooserActivity.CONTENT_PREVIEW_TEXT:
+            default:
+                return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_TEXT;
+        }
+    }
+
+    /**
+     * Returns the enum used in sharesheet started atom to indicate what intent triggers the
+     * ChooserActivity.
+     */
+    default int typeFromIntentString(String intent) {
+        if (intent == null) {
+            return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT;
+        }
+        switch (intent) {
+            case Intent.ACTION_VIEW:
+                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_VIEW;
+            case Intent.ACTION_EDIT:
+                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_EDIT;
+            case Intent.ACTION_SEND:
+                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND;
+            case Intent.ACTION_SENDTO:
+                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO;
+            case Intent.ACTION_SEND_MULTIPLE:
+                return FrameworkStatsLog
+                        .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND_MULTIPLE;
+            case MediaStore.ACTION_IMAGE_CAPTURE:
+                return FrameworkStatsLog
+                        .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_IMAGE_CAPTURE;
+            case Intent.ACTION_MAIN:
+                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_MAIN;
+            default:
+                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java b/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java
new file mode 100644
index 0000000..48bdba3
--- /dev/null
+++ b/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app;
+
+import com.android.internal.logging.InstanceId;
+import com.android.internal.logging.InstanceIdSequence;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
+import com.android.internal.util.FrameworkStatsLog;
+
+/**
+ * Standard implementation of ChooserActivityLogger interface.
+ * @hide
+ */
+public class ChooserActivityLoggerImpl implements ChooserActivityLogger {
+    private static final int SHARESHEET_INSTANCE_ID_MAX = (1 << 13);
+
+    private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
+    // A small per-notification ID, used for statsd logging.
+    private InstanceId mInstanceId;
+    private static InstanceIdSequence sInstanceIdSequence;
+
+    @Override
+    public void logShareStarted(int eventId, String packageName, String mimeType,
+            int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType,
+            String intent) {
+        FrameworkStatsLog.write(FrameworkStatsLog.SHARESHEET_STARTED,
+                /* event_id = 1 */ SharesheetStartedEvent.SHARE_STARTED.getId(),
+                /* package_name = 2 */ packageName,
+                /* instance_id = 3 */ getInstanceId().getId(),
+                /* mime_type = 4 */ mimeType,
+                /* num_app_provided_direct_targets = 5 */ appProvidedDirect,
+                /* num_app_provided_app_targets = 6 */ appProvidedApp,
+                /* is_workprofile = 7 */ isWorkprofile,
+                /* previewType = 8 */ typeFromPreviewInt(previewType),
+                /* intentType = 9 */ typeFromIntentString(intent));
+    }
+
+    @Override
+    public void logShareTargetSelected(int targetType, String packageName, int positionPicked) {
+        FrameworkStatsLog.write(FrameworkStatsLog.RANKING_SELECTED,
+                /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(),
+                /* package_name = 2 */ packageName,
+                /* instance_id = 3 */ getInstanceId().getId(),
+                /* position_picked = 4 */ positionPicked);
+    }
+
+    @Override
+    public void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) {
+        mUiEventLogger.logWithInstanceId(
+                event,
+                0,
+                null,
+                instanceId);
+    }
+
+    @Override
+    public InstanceId getInstanceId() {
+        if (mInstanceId == null) {
+            if (sInstanceIdSequence == null) {
+                sInstanceIdSequence = new InstanceIdSequence(SHARESHEET_INSTANCE_ID_MAX);
+            }
+            mInstanceId = sInstanceIdSequence.newInstanceId();
+        }
+        return mInstanceId;
+    }
+
+}
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index 0ea855a..0d90bbf 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -64,7 +64,7 @@
     private boolean mAppendDirectShareEnabled = DeviceConfig.getBoolean(
             DeviceConfig.NAMESPACE_SYSTEMUI,
             SystemUiDeviceConfigFlags.APPEND_DIRECT_SHARE_ENABLED,
-            false);
+            true);
 
     private boolean mEnableStackedApps = true;
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index f088ab3..fc3f20f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -994,7 +994,7 @@
         if (isAutolaunching() || maybeAutolaunchActivity()) {
             return;
         }
-        if (isResolverListEmpty(listAdapter)) {
+        if (mMultiProfilePagerAdapter.shouldShowEmptyStateScreen(listAdapter)) {
             mMultiProfilePagerAdapter.showEmptyResolverListEmptyState(listAdapter);
         } else {
             mMultiProfilePagerAdapter.showListView(listAdapter);
@@ -1578,6 +1578,7 @@
                 viewPager.setCurrentItem(1);
             }
             setupViewVisibilities();
+            maybeLogProfileChange();
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS)
                     .setInt(viewPager.getCurrentItem())
@@ -1640,16 +1641,11 @@
 
     private void setupViewVisibilities() {
         ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
-        if (!isResolverListEmpty(activeListAdapter)) {
+        if (!mMultiProfilePagerAdapter.shouldShowEmptyStateScreen(activeListAdapter)) {
             addUseDifferentAppLabelIfNecessary(activeListAdapter);
         }
     }
 
-    private boolean isResolverListEmpty(ResolverListAdapter listAdapter) {
-        int count = listAdapter.getUnfilteredCount();
-        return count == 0 && listAdapter.getPlaceholderCount() == 0;
-    }
-
     /**
      * Add a label to signify that the user can pick a different app.
      * @param adapter The adapter used to provide data to item views.
@@ -1998,4 +1994,6 @@
             }
         }
     }
+
+    protected void maybeLogProfileChange() {}
 }
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 3f897a5..033ac72 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -121,23 +121,13 @@
             List<Intent> intents,
             UserHandle userHandle) {
         int baseFlags = PackageManager.MATCH_DEFAULT_ONLY
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                 | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
                 | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
         return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
     }
 
-    /**
-     * Returns a list of resolved intents which is user state-independent. This means it will
-     * return the same results regardless of whether the {@code userHandle} user is disabled or not.
-     */
-    public List<ResolverActivity.ResolvedComponentInfo> getUserStateIndependentResolversAsUser(
-            List<Intent> intents,
-            UserHandle userHandle) {
-        int baseFlags = PackageManager.MATCH_DIRECT_BOOT_AWARE
-                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
-        return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
-    }
-
     private List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUserInternal(
             List<Intent> intents,
             UserHandle userHandle,
diff --git a/core/java/com/android/internal/inputmethod/CancellationGroup.java b/core/java/com/android/internal/inputmethod/CancellationGroup.java
new file mode 100644
index 0000000..09c9d12
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/CancellationGroup.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A utility class, which works as both a factory class of completable objects and a cancellation
+ * signal to cancel all the completable objects created by this object.
+ */
+public final class CancellationGroup {
+    private final Object mLock = new Object();
+
+    /**
+     * List of {@link CountDownLatch}, which can be used to propagate {@link #cancelAll()} to
+     * completable objects.
+     *
+     * <p>This will be lazily instantiated to avoid unnecessary object allocations.</p>
+     */
+    @Nullable
+    @GuardedBy("mLock")
+    private ArrayList<CountDownLatch> mLatchList = null;
+
+    @GuardedBy("mLock")
+    private boolean mCanceled = false;
+
+    /**
+     * An inner class to consolidate completable object types supported by
+     * {@link CancellationGroup}.
+     */
+    public static final class Completable {
+
+        /**
+         * Not intended to be instantiated.
+         */
+        private Completable() {
+        }
+
+        /**
+         * Base class of all the completable types supported by {@link CancellationGroup}.
+         */
+        protected static class ValueBase {
+            /**
+             * {@link CountDownLatch} to be signaled to unblock {@link #await(int, TimeUnit)}.
+             */
+            private final CountDownLatch mLatch = new CountDownLatch(1);
+
+            /**
+             * {@link CancellationGroup} to which this completable object belongs.
+             */
+            @NonNull
+            private final CancellationGroup mParentGroup;
+
+            /**
+             * Lock {@link Object} to guard complete operations within this class.
+             */
+            protected final Object mValueLock = new Object();
+
+            /**
+             * {@code true} after {@link #onComplete()} gets called.
+             */
+            @GuardedBy("mValueLock")
+            protected boolean mHasValue = false;
+
+            /**
+             * Base constructor.
+             *
+             * @param parentGroup {@link CancellationGroup} to which this completable object
+             *                    belongs.
+             */
+            protected ValueBase(@NonNull CancellationGroup parentGroup) {
+                mParentGroup = parentGroup;
+            }
+
+            /**
+             * @return {@link true} if {@link #onComplete()} gets called already.
+             */
+            @AnyThread
+            public boolean hasValue() {
+                synchronized (mValueLock) {
+                    return mHasValue;
+                }
+            }
+
+            /**
+             * Called by subclasses to signale {@link #mLatch}.
+             */
+            @AnyThread
+            protected void onComplete() {
+                mLatch.countDown();
+            }
+
+            /**
+             * Blocks the calling thread until at least one of the following conditions is met.
+             *
+             * <p>
+             *     <ol>
+             *         <li>This object becomes ready to return the value.</li>
+             *         <li>{@link CancellationGroup#cancelAll()} gets called.</li>
+             *         <li>The given timeout period has passed.</li>
+             *     </ol>
+             * </p>
+             *
+             * <p>The caller can distinguish the case 1 and case 2 by calling {@link #hasValue()}.
+             * Note that the return value of {@link #hasValue()} can change from {@code false} to
+             * {@code true} at any time, even after this methods finishes with returning
+             * {@code true}.</p>
+             *
+             * @param timeout length of the timeout.
+             * @param timeUnit unit of {@code timeout}.
+             * @return {@code false} if and only if the given timeout period has passed. Otherwise
+             *         {@code true}.
+             */
+            @AnyThread
+            public boolean await(int timeout, @NonNull TimeUnit timeUnit) {
+                if (!mParentGroup.registerLatch(mLatch)) {
+                    // Already canceled when this method gets called.
+                    return false;
+                }
+                try {
+                    return mLatch.await(timeout, timeUnit);
+                } catch (InterruptedException e) {
+                    return true;
+                } finally {
+                    mParentGroup.unregisterLatch(mLatch);
+                }
+            }
+        }
+
+        /**
+         * Completable object of integer primitive.
+         */
+        public static final class Int extends ValueBase {
+            @GuardedBy("mValueLock")
+            private int mValue = 0;
+
+            private Int(@NonNull CancellationGroup factory) {
+                super(factory);
+            }
+
+            /**
+             * Notify when a value is set to this completable object.
+             *
+             * @param value value to be set.
+             */
+            @AnyThread
+            void onComplete(int value) {
+                synchronized (mValueLock) {
+                    if (mHasValue) {
+                        throw new UnsupportedOperationException(
+                                "onComplete() cannot be called multiple times");
+                    }
+                    mValue = value;
+                    mHasValue = true;
+                }
+                onComplete();
+            }
+
+            /**
+             * @return value associated with this object.
+             * @throws UnsupportedOperationException when called while {@link #hasValue()} returns
+             *                                       {@code false}.
+             */
+            @AnyThread
+            public int getValue() {
+                synchronized (mValueLock) {
+                    if (!mHasValue) {
+                        throw new UnsupportedOperationException(
+                                "getValue() is allowed only if hasValue() returns true");
+                    }
+                    return mValue;
+                }
+            }
+        }
+
+        /**
+         * Base class of completable object types.
+         *
+         * @param <T> type associated with this completable object.
+         */
+        public static class Values<T> extends ValueBase {
+            @GuardedBy("mValueLock")
+            @Nullable
+            private T mValue = null;
+
+            protected Values(@NonNull CancellationGroup factory) {
+                super(factory);
+            }
+
+            /**
+             * Notify when a value is set to this completable value object.
+             *
+             * @param value value to be set.
+             */
+            @AnyThread
+            void onComplete(@Nullable T value) {
+                synchronized (mValueLock) {
+                    if (mHasValue) {
+                        throw new UnsupportedOperationException(
+                                "onComplete() cannot be called multiple times");
+                    }
+                    mValue = value;
+                    mHasValue = true;
+                }
+                onComplete();
+            }
+
+            /**
+             * @return value associated with this object.
+             * @throws UnsupportedOperationException when called while {@link #hasValue()} returns
+             *                                       {@code false}.
+             */
+            @AnyThread
+            @Nullable
+            public T getValue() {
+                synchronized (mValueLock) {
+                    if (!mHasValue) {
+                        throw new UnsupportedOperationException(
+                                "getValue() is allowed only if hasValue() returns true");
+                    }
+                    return mValue;
+                }
+            }
+        }
+
+        /**
+         * Completable object of {@link java.lang.CharSequence}.
+         */
+        public static final class CharSequence extends Values<java.lang.CharSequence> {
+            private CharSequence(@NonNull CancellationGroup factory) {
+                super(factory);
+            }
+        }
+
+        /**
+         * Completable object of {@link android.view.inputmethod.ExtractedText}.
+         */
+        public static final class ExtractedText
+                extends Values<android.view.inputmethod.ExtractedText> {
+            private ExtractedText(@NonNull CancellationGroup factory) {
+                super(factory);
+            }
+        }
+    }
+
+    /**
+     * @return an instance of {@link Completable.Int} that is associated with this
+     *         {@link CancellationGroup}.
+     */
+    @AnyThread
+    public Completable.Int createCompletableInt() {
+        return new Completable.Int(this);
+    }
+
+    /**
+     * @return an instance of {@link Completable.CharSequence} that is associated with this
+     *         {@link CancellationGroup}.
+     */
+    @AnyThread
+    public Completable.CharSequence createCompletableCharSequence() {
+        return new Completable.CharSequence(this);
+    }
+
+    /**
+     * @return an instance of {@link Completable.ExtractedText} that is associated with this
+     *         {@link CancellationGroup}.
+     */
+    @AnyThread
+    public Completable.ExtractedText createCompletableExtractedText() {
+        return new Completable.ExtractedText(this);
+    }
+
+    @AnyThread
+    private boolean registerLatch(@NonNull CountDownLatch latch) {
+        synchronized (mLock) {
+            if (mCanceled) {
+                return false;
+            }
+            if (mLatchList == null) {
+                // Set the initial capacity to 1 with an assumption that usually there is up to 1
+                // on-going operation.
+                mLatchList = new ArrayList<>(1);
+            }
+            mLatchList.add(latch);
+            return true;
+        }
+    }
+
+    @AnyThread
+    private void unregisterLatch(@NonNull CountDownLatch latch) {
+        synchronized (mLock) {
+            if (mLatchList != null) {
+                mLatchList.remove(latch);
+            }
+        }
+    }
+
+    /**
+     * Cancel all the completable objects created from this {@link CancellationGroup}.
+     *
+     * <p>Secondary calls will be silently ignored.</p>
+     */
+    @AnyThread
+    public void cancelAll() {
+        synchronized (mLock) {
+            if (!mCanceled) {
+                mCanceled = true;
+                if (mLatchList != null) {
+                    mLatchList.forEach(CountDownLatch::countDown);
+                    mLatchList.clear();
+                    mLatchList = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * @return {@code true} if {@link #cancelAll()} is already called. {@code false} otherwise.
+     */
+    @AnyThread
+    public boolean isCanceled() {
+        synchronized (mLock) {
+            return mCanceled;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl b/core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl
new file mode 100644
index 0000000..da56fd0
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inputmethod;
+
+oneway interface ICharSequenceResultCallback {
+    void onResult(in CharSequence result);
+}
diff --git a/core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl b/core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl
new file mode 100644
index 0000000..b603f6a
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inputmethod;
+
+import android.view.inputmethod.ExtractedText;
+
+oneway interface IExtractedTextResultCallback {
+    void onResult(in ExtractedText result);
+}
diff --git a/core/java/com/android/internal/inputmethod/IIntResultCallback.aidl b/core/java/com/android/internal/inputmethod/IIntResultCallback.aidl
new file mode 100644
index 0000000..bc5ed0d
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IIntResultCallback.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inputmethod;
+
+oneway interface IIntResultCallback {
+    void onResult(int result);
+}
diff --git a/core/java/com/android/internal/inputmethod/ResultCallbacks.java b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
new file mode 100644
index 0000000..44a8a83
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.BinderThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Defines a set of factory methods to create {@link android.os.IBinder}-based callbacks that are
+ * associated with completable objects defined in {@link CancellationGroup.Completable}.
+ */
+public final class ResultCallbacks {
+
+    /**
+     * Not intended to be instantiated.
+     */
+    private ResultCallbacks() {
+    }
+
+    @AnyThread
+    @Nullable
+    private static <T> T unwrap(@NonNull AtomicReference<WeakReference<T>> atomicRef) {
+        final WeakReference<T> ref = atomicRef.getAndSet(null);
+        if (ref == null) {
+            // Double-call is guaranteed to be ignored here.
+            return null;
+        }
+        final T value = ref.get();
+        ref.clear();
+        return value;
+    }
+
+    /**
+     * Creates {@link IIntResultCallback.Stub} that is to set
+     * {@link CancellationGroup.Completable.Int} when receiving the result.
+     *
+     * @param value {@link CancellationGroup.Completable.Int} to be set when receiving the result.
+     * @return {@link IIntResultCallback.Stub} that can be passed as a binder IPC parameter.
+     */
+    @AnyThread
+    public static IIntResultCallback.Stub of(@NonNull CancellationGroup.Completable.Int value) {
+        final AtomicReference<WeakReference<CancellationGroup.Completable.Int>>
+                atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+        return new IIntResultCallback.Stub() {
+            @BinderThread
+            @Override
+            public void onResult(int result) {
+                final CancellationGroup.Completable.Int value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onComplete(result);
+            }
+        };
+    }
+
+    /**
+     * Creates {@link ICharSequenceResultCallback.Stub} that is to set
+     * {@link CancellationGroup.Completable.CharSequence} when receiving the result.
+     *
+     * @param value {@link CancellationGroup.Completable.CharSequence} to be set when receiving the
+     *              result.
+     * @return {@link ICharSequenceResultCallback.Stub} that can be passed as a binder IPC
+     *         parameter.
+     */
+    @AnyThread
+    public static ICharSequenceResultCallback.Stub of(
+            @NonNull CancellationGroup.Completable.CharSequence value) {
+        final AtomicReference<WeakReference<CancellationGroup.Completable.CharSequence>> atomicRef =
+                new AtomicReference<>(new WeakReference<>(value));
+
+        return new ICharSequenceResultCallback.Stub() {
+            @BinderThread
+            @Override
+            public void onResult(CharSequence result) {
+                final CancellationGroup.Completable.CharSequence value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onComplete(result);
+            }
+        };
+    }
+
+    /**
+     * Creates {@link IExtractedTextResultCallback.Stub} that is to set
+     * {@link CancellationGroup.Completable.ExtractedText} when receiving the result.
+     *
+     * @param value {@link CancellationGroup.Completable.ExtractedText} to be set when receiving the
+     *              result.
+     * @return {@link IExtractedTextResultCallback.Stub} that can be passed as a binder IPC
+     *         parameter.
+     */
+    @AnyThread
+    public static IExtractedTextResultCallback.Stub of(
+            @NonNull CancellationGroup.Completable.ExtractedText value) {
+        final AtomicReference<WeakReference<CancellationGroup.Completable.ExtractedText>>
+                atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+        return new IExtractedTextResultCallback.Stub() {
+            @BinderThread
+            @Override
+            public void onResult(android.view.inputmethod.ExtractedText result) {
+                final CancellationGroup.Completable.ExtractedText value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onComplete(result);
+            }
+        };
+    }
+}
diff --git a/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
index 91ba0df..180ab08 100644
--- a/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
+++ b/core/java/com/android/internal/logging/testing/UiEventLoggerFake.java
@@ -85,7 +85,7 @@
     }
 
     @Override
-    public void logWithInstanceId(UiEventLogger.UiEventEnum event, int uid, String packageName,
+    public void logWithInstanceId(UiEventEnum event, int uid, String packageName,
             InstanceId instance) {
         final int eventId = event.getId();
         if (eventId > 0) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index ff03f1a..505a05e 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -205,9 +205,15 @@
     /** List of packages with the same uid, and its app data info: volume uuid and inode. */
     public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
 
+    /** List of whitelisted packages and its app data info: volume uuid and inode. */
+    public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map";
+
     /** Bind mount app storage dirs to lower fs not via fuse */
     public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";
 
+    /** Bind mount app storage dirs to lower fs not via fuse */
+    public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
+
     /**
      * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
      * in the abstract socket namespace. This socket name is what the new child zygote
@@ -313,6 +319,8 @@
      * @param isTopApp true if the process is for top (high priority) application.
      * @param pkgDataInfoList A list that stores related packages and its app data
      * info: volume uuid and inode.
+     * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
+     * @param bindMountAppDataDirs  True if the zygote needs to mount data dirs.
      * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
      *
      * @return 0 if this is the child, pid of the child
@@ -321,13 +329,15 @@
     static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
-            boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
+            boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
+            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
         ZygoteHooks.preFork();
 
         int pid = nativeForkAndSpecialize(
                 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                 fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
-                pkgDataInfoList, bindMountAppStorageDirs);
+                pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
+                bindMountAppStorageDirs);
         if (pid == 0) {
             // Note that this event ends at the end of handleChildProc,
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -344,6 +354,7 @@
             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
             int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
             String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
+            String[] whitelistedDataInfoList, boolean bindMountAppDataDirs,
             boolean bindMountAppStorageDirs);
 
     /**
@@ -371,15 +382,19 @@
      * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
      * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
      * app_b_ce_inode, ...];
+     * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
+     * @param bindMountAppDataDirs  True if the zygote needs to mount data dirs.
      * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
      */
     private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName,
             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
-            String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
+            String[] pkgDataInfoList, String[] whitelistedDataInfoList,
+            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
         nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
                 niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
-                pkgDataInfoList, bindMountAppStorageDirs);
+                pkgDataInfoList, whitelistedDataInfoList,
+                bindMountAppDataDirs, bindMountAppStorageDirs);
 
         // Note that this event ends at the end of handleChildProc.
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -399,7 +414,8 @@
     private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
-            String[] pkgDataInfoList, boolean bindMountAppStorageDirs);
+            String[] pkgDataInfoList, String[] whitelistedDataInfoList,
+            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
 
     /**
      * Called to do any initialization before starting an application.
@@ -724,7 +740,8 @@
                                  args.mRuntimeFlags, rlimits, args.mMountExternal,
                                  args.mSeInfo, args.mNiceName, args.mStartChildZygote,
                                  args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
-                                 args.mPkgDataInfoList, args.mBindMountAppStorageDirs);
+                                 args.mPkgDataInfoList, args.mWhitelistedDataInfoList,
+                                 args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
 
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
@@ -1060,4 +1077,11 @@
      */
     @FastNative
     public static native int nativeParseSigChld(byte[] in, int length, int[] out);
+
+    /**
+     * Returns whether the kernel supports tagged pointers. Present in the
+     * Android Common Kernel from 4.14 and up. By default, you should prefer
+     * fully-feature Memory Tagging, rather than the static Tagged Pointers.
+     */
+    public static native boolean nativeSupportsTaggedPointers();
 }
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 1a63765..94c1f71 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -227,11 +227,22 @@
     String[] mPkgDataInfoList;
 
     /**
+     * A list that stores all whitelisted app data info: volume uuid and inode.
+     * Null if it does need to do app data isolation.
+     */
+    String[] mWhitelistedDataInfoList;
+
+    /**
      * @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS
      */
     boolean mBindMountAppStorageDirs;
 
     /**
+     * @see Zygote#BIND_MOUNT_APP_DATA_DIRS
+     */
+    boolean mBindMountAppDataDirs;
+
+    /**
      * Constructs instance and parses args
      *
      * @param args zygote command-line args
@@ -452,8 +463,12 @@
                 }
             } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
                 mPkgDataInfoList = getAssignmentList(arg);
+            } else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) {
+                mWhitelistedDataInfoList = getAssignmentList(arg);
             } else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) {
                 mBindMountAppStorageDirs = true;
+            } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
+                mBindMountAppDataDirs = true;
             } else {
                 break;
             }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index bc8dfd4..e6a3029 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,7 +258,8 @@
                 parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                 parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                 parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
-                parsedArgs.mPkgDataInfoList, parsedArgs.mBindMountAppStorageDirs);
+                parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
+                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
 
         try {
             if (pid == 0) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ec1f516..c2b13c9 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -757,9 +757,11 @@
             Zygote.applyDebuggerSystemProperty(parsedArgs);
             Zygote.applyInvokeWithSystemProperty(parsedArgs);
 
-            /* Enable pointer tagging in the system server unconditionally. Hardware support for
-             * this is present in all ARMv8 CPUs; this flag has no effect on other platforms. */
-            parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+            if (Zygote.nativeSupportsTaggedPointers()) {
+                /* Enable pointer tagging in the system server. Hardware support for this is present
+                 * in all ARMv8 CPUs. */
+                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+            }
 
             /* Enable gwp-asan on the system server with a small probability. This is the same
              * policy as applied to native processes and system apps. */
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index f007768..99b4b5f 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -41,17 +41,17 @@
 public class DecorContext extends ContextThemeWrapper {
     private PhoneWindow mPhoneWindow;
     private WindowManager mWindowManager;
-    private Resources mResources;
+    private Resources mActivityResources;
     private ContentCaptureManager mContentCaptureManager;
 
-    private WeakReference<Context> mContext;
+    private WeakReference<Context> mActivityContext;
 
     // TODO(b/149928768): Non-activity context can be passed.
     @VisibleForTesting
-    public DecorContext(Context baseContext, Context context) {
-        super(baseContext.createDisplayContext(context.getDisplayNoVerify()), null);
-        mContext = new WeakReference<>(context);
-        mResources = context.getResources();
+    public DecorContext(Context context, Context activityContext) {
+        super(context.createDisplayContext(activityContext.getDisplayNoVerify()), null);
+        mActivityContext = new WeakReference<>(activityContext);
+        mActivityResources = activityContext.getResources();
     }
 
     void setPhoneWindow(PhoneWindow phoneWindow) {
@@ -61,56 +61,58 @@
 
     @Override
     public Object getSystemService(String name) {
-        final Context context = mContext.get();
         if (Context.WINDOW_SERVICE.equals(name)) {
-            if (context != null && mWindowManager == null) {
-                WindowManagerImpl wm = (WindowManagerImpl) context.getSystemService(name);
+            if (mWindowManager == null) {
+                WindowManagerImpl wm =
+                        (WindowManagerImpl) super.getSystemService(Context.WINDOW_SERVICE);
                 mWindowManager = wm.createLocalWindowManager(mPhoneWindow);
             }
             return mWindowManager;
         }
         if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) {
-            if (context != null && mContentCaptureManager == null) {
-                mContentCaptureManager = (ContentCaptureManager) context.getSystemService(name);
+            if (mContentCaptureManager == null) {
+                Context activityContext = mActivityContext.get();
+                if (activityContext != null) {
+                    mContentCaptureManager = (ContentCaptureManager) activityContext
+                            .getSystemService(name);
+                }
             }
             return mContentCaptureManager;
         }
-        // LayoutInflater and WallpaperManagerService should also be obtained from context
-        // instead of application context.
-        return (context != null) ? context.getSystemService(name) : super.getSystemService(name);
+        return super.getSystemService(name);
     }
 
     @Override
     public Resources getResources() {
-        Context context = mContext.get();
+        Context activityContext = mActivityContext.get();
         // Attempt to update the local cached Resources from the activity context. If the activity
         // is no longer around, return the old cached values.
-        if (context != null) {
-            mResources = context.getResources();
+        if (activityContext != null) {
+            mActivityResources = activityContext.getResources();
         }
 
-        return mResources;
+        return mActivityResources;
     }
 
     @Override
     public AssetManager getAssets() {
-        return mResources.getAssets();
+        return mActivityResources.getAssets();
     }
 
     @Override
     public AutofillOptions getAutofillOptions() {
-        Context context = mContext.get();
-        if (context != null) {
-            return context.getAutofillOptions();
+        Context activityContext = mActivityContext.get();
+        if (activityContext != null) {
+            return activityContext.getAutofillOptions();
         }
         return null;
     }
 
     @Override
     public ContentCaptureOptions getContentCaptureOptions() {
-        Context context = mContext.get();
-        if (context != null) {
-            return context.getContentCaptureOptions();
+        Context activityContext = mActivityContext.get();
+        if (activityContext != null) {
+            return activityContext.getContentCaptureOptions();
         }
         return null;
     }
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 2779be6..575a532 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -69,6 +69,7 @@
     private final ArrayList<SnapTarget> mTargets = new ArrayList<>();
     private final Rect mInsets = new Rect();
     private final int mSnapMode;
+    private final boolean mFreeSnapMode;
     private final int mMinimalSizeResizableTask;
     private final int mTaskHeightInMinimizedMode;
     private final float mFixedRatio;
@@ -125,6 +126,8 @@
         mInsets.set(insets);
         mSnapMode = isMinimizedMode ? SNAP_MODE_MINIMIZED :
                 res.getInteger(com.android.internal.R.integer.config_dockedStackDividerSnapMode);
+        mFreeSnapMode = res.getBoolean(
+                com.android.internal.R.bool.config_dockedStackDividerFreeSnapMode);
         mFixedRatio = res.getFraction(
                 com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
         mMinimalSizeResizableTask = res.getDimensionPixelSize(
@@ -247,7 +250,20 @@
         }
     }
 
+    private boolean shouldApplyFreeSnapMode(int position) {
+        if (!mFreeSnapMode) {
+            return false;
+        }
+        if (!isFirstSplitTargetAvailable() || !isLastSplitTargetAvailable()) {
+            return false;
+        }
+        return mFirstSplitTarget.position < position && position < mLastSplitTarget.position;
+    }
+
     private SnapTarget snap(int position, boolean hardDismiss) {
+        if (shouldApplyFreeSnapMode(position)) {
+            return new SnapTarget(position, position, SnapTarget.FLAG_NONE);
+        }
         int minIndex = -1;
         float minDistance = Float.MAX_VALUE;
         int size = mTargets.size();
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 5b79b18..38f5f32 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -204,8 +204,8 @@
     /**
      * Displays a text toast.
      */
-    void showToast(String packageName, IBinder token, CharSequence text, IBinder windowToken,
-            int duration, @nullable ITransientNotificationCallback callback);
+    void showToast(int uid, String packageName, IBinder token, CharSequence text,
+            IBinder windowToken, int duration, @nullable ITransientNotificationCallback callback);
 
     /**
      * Cancels toast with token {@code token} in {@code packageName}.
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 6278d4a3..9257c6d 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -29,6 +29,7 @@
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
+import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputConnectionInspector;
@@ -36,6 +37,9 @@
 import android.view.inputmethod.InputContentInfo;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.ICharSequenceResultCallback;
+import com.android.internal.inputmethod.IExtractedTextResultCallback;
+import com.android.internal.inputmethod.IIntResultCallback;
 import com.android.internal.os.SomeArgs;
 
 public abstract class IInputConnectionWrapper extends IInputContext.Stub {
@@ -111,28 +115,31 @@
 
     abstract protected boolean isActive();
 
-    public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback));
-    }
-    
-    public void getTextBeforeCursor(int length, int flags, int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageIISC(DO_GET_TEXT_BEFORE_CURSOR, length, flags, seq, callback));
+    public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
+        dispatchMessage(mH.obtainMessage(DO_GET_TEXT_AFTER_CURSOR, length, flags, callback));
     }
 
-    public void getSelectedText(int flags, int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageISC(DO_GET_SELECTED_TEXT, flags, seq, callback));
+    public void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback) {
+        dispatchMessage(mH.obtainMessage(DO_GET_TEXT_BEFORE_CURSOR, length, flags, callback));
     }
 
-    public void getCursorCapsMode(int reqModes, int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageISC(DO_GET_CURSOR_CAPS_MODE, reqModes, seq, callback));
+    public void getSelectedText(int flags, ICharSequenceResultCallback callback) {
+        dispatchMessage(mH.obtainMessage(DO_GET_SELECTED_TEXT, flags, 0 /* unused */, callback));
     }
 
-    public void getExtractedText(ExtractedTextRequest request,
-            int flags, int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageIOSC(DO_GET_EXTRACTED_TEXT, flags,
-                request, seq, callback));
+    public void getCursorCapsMode(int reqModes, IIntResultCallback callback) {
+        dispatchMessage(
+                mH.obtainMessage(DO_GET_CURSOR_CAPS_MODE, reqModes, 0 /* unused */, callback));
     }
-    
+
+    public void getExtractedText(ExtractedTextRequest request, int flags,
+            IExtractedTextResultCallback callback) {
+        final SomeArgs args = SomeArgs.obtain();
+        args.arg1 = request;
+        args.arg2 = callback;
+        dispatchMessage(mH.obtainMessage(DO_GET_EXTRACTED_TEXT, flags, 0 /* unused */, args));
+    }
+
     public void commitText(CharSequence text, int newCursorPosition) {
         dispatchMessage(obtainMessageIO(DO_COMMIT_TEXT, newCursorPosition, text));
     }
@@ -199,10 +206,9 @@
         dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
     }
 
-    public void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
-            IInputContextCallback callback) {
-        dispatchMessage(obtainMessageISC(DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO, cursorUpdateMode,
-                seq, callback));
+    public void requestUpdateCursorAnchorInfo(int cursorUpdateMode, IIntResultCallback callback) {
+        dispatchMessage(mH.obtainMessage(DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO, cursorUpdateMode,
+                0 /* unused */, callback));
     }
 
     public void closeConnection() {
@@ -210,9 +216,12 @@
     }
 
     public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts,
-            int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageIOOSC(DO_COMMIT_CONTENT, flags, inputContentInfo, opts, seq,
-                callback));
+            IIntResultCallback callback) {
+        final SomeArgs args = SomeArgs.obtain();
+        args.arg1 = inputContentInfo;
+        args.arg2 = opts;
+        args.arg3 = callback;
+        dispatchMessage(mH.obtainMessage(DO_COMMIT_CONTENT, flags, 0 /* unused */, args));
     }
 
     void dispatchMessage(Message msg) {
@@ -231,100 +240,97 @@
     void executeMessage(Message msg) {
         switch (msg.what) {
             case DO_GET_TEXT_AFTER_CURSOR: {
-                SomeArgs args = (SomeArgs)msg.obj;
+                final ICharSequenceResultCallback callback = (ICharSequenceResultCallback) msg.obj;
+                final InputConnection ic = getInputConnection();
+                final CharSequence result;
+                if (ic == null || !isActive()) {
+                    Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
+                    result = null;
+                } else {
+                    result = ic.getTextAfterCursor(msg.arg1, msg.arg2);
+                }
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
-                    if (ic == null || !isActive()) {
-                        Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
-                        callback.setTextAfterCursor(null, callbackSeq);
-                        return;
-                    }
-                    callback.setTextAfterCursor(ic.getTextAfterCursor(
-                            msg.arg1, msg.arg2), callbackSeq);
+                    callback.onResult(result);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling setTextAfterCursor", e);
-                } finally {
-                    args.recycle();
+                    Log.w(TAG, "Failed to return the result to getTextAfterCursor()."
+                            + " result=" + result, e);
                 }
                 return;
             }
             case DO_GET_TEXT_BEFORE_CURSOR: {
-                SomeArgs args = (SomeArgs)msg.obj;
+                final ICharSequenceResultCallback callback = (ICharSequenceResultCallback) msg.obj;
+                final InputConnection ic = getInputConnection();
+                final CharSequence result;
+                if (ic == null || !isActive()) {
+                    Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
+                    result = null;
+                } else {
+                    result = ic.getTextBeforeCursor(msg.arg1, msg.arg2);
+                }
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
-                    if (ic == null || !isActive()) {
-                        Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
-                        callback.setTextBeforeCursor(null, callbackSeq);
-                        return;
-                    }
-                    callback.setTextBeforeCursor(ic.getTextBeforeCursor(
-                            msg.arg1, msg.arg2), callbackSeq);
+                    callback.onResult(result);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling setTextBeforeCursor", e);
-                } finally {
-                    args.recycle();
+                    Log.w(TAG, "Failed to return the result to getTextBeforeCursor()."
+                            + " result=" + result, e);
                 }
                 return;
             }
             case DO_GET_SELECTED_TEXT: {
-                SomeArgs args = (SomeArgs)msg.obj;
+                final ICharSequenceResultCallback callback = (ICharSequenceResultCallback) msg.obj;
+                final InputConnection ic = getInputConnection();
+                final CharSequence result;
+                if (ic == null || !isActive()) {
+                    Log.w(TAG, "getSelectedText on inactive InputConnection");
+                    result = null;
+                } else {
+                    result = ic.getSelectedText(msg.arg1);
+                }
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
-                    if (ic == null || !isActive()) {
-                        Log.w(TAG, "getSelectedText on inactive InputConnection");
-                        callback.setSelectedText(null, callbackSeq);
-                        return;
-                    }
-                    callback.setSelectedText(ic.getSelectedText(
-                            msg.arg1), callbackSeq);
+                    callback.onResult(result);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling setSelectedText", e);
-                } finally {
-                    args.recycle();
+                    Log.w(TAG, "Failed to return the result to getSelectedText()."
+                            + " result=" + result, e);
                 }
                 return;
             }
             case DO_GET_CURSOR_CAPS_MODE: {
-                SomeArgs args = (SomeArgs)msg.obj;
+                final IIntResultCallback callback = (IIntResultCallback) msg.obj;
+                final InputConnection ic = getInputConnection();
+                final int result;
+                if (ic == null || !isActive()) {
+                    Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
+                    result = 0;
+                } else {
+                    result = ic.getCursorCapsMode(msg.arg1);
+                }
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
-                    if (ic == null || !isActive()) {
-                        Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
-                        callback.setCursorCapsMode(0, callbackSeq);
-                        return;
-                    }
-                    callback.setCursorCapsMode(ic.getCursorCapsMode(msg.arg1),
-                            callbackSeq);
+                    callback.onResult(result);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling setCursorCapsMode", e);
-                } finally {
-                    args.recycle();
+                    Log.w(TAG, "Failed to return the result to getCursorCapsMode()."
+                            + " result=" + result, e);
                 }
                 return;
             }
             case DO_GET_EXTRACTED_TEXT: {
-                SomeArgs args = (SomeArgs)msg.obj;
+                final SomeArgs args = (SomeArgs) msg.obj;
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
+                    final ExtractedTextRequest request = (ExtractedTextRequest) args.arg1;
+                    final IExtractedTextResultCallback callback =
+                            (IExtractedTextResultCallback) args.arg2;
+                    final InputConnection ic = getInputConnection();
+                    final ExtractedText result;
                     if (ic == null || !isActive()) {
                         Log.w(TAG, "getExtractedText on inactive InputConnection");
-                        callback.setExtractedText(null, callbackSeq);
-                        return;
+                        result = null;
+                    } else {
+                        result = ic.getExtractedText(request, msg.arg1);
                     }
-                    callback.setExtractedText(ic.getExtractedText(
-                            (ExtractedTextRequest)args.arg1, msg.arg1), callbackSeq);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling setExtractedText", e);
+                    try {
+                        callback.onResult(result);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to return the result to getExtractedText()."
+                                + " result=" + result, e);
+                    }
                 } finally {
                     args.recycle();
                 }
@@ -494,22 +500,20 @@
                 return;
             }
             case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
-                SomeArgs args = (SomeArgs)msg.obj;
+                final IIntResultCallback callback = (IIntResultCallback) msg.obj;
+                final InputConnection ic = getInputConnection();
+                final boolean result;
+                if (ic == null || !isActive()) {
+                    Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
+                    result = false;
+                } else {
+                    result = ic.requestCursorUpdates(msg.arg1);
+                }
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
-                    if (ic == null || !isActive()) {
-                        Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
-                        callback.setRequestUpdateCursorAnchorInfoResult(false, callbackSeq);
-                        return;
-                    }
-                    callback.setRequestUpdateCursorAnchorInfoResult(
-                            ic.requestCursorUpdates(msg.arg1), callbackSeq);
+                    callback.onResult(result ? 1 : 0);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
-                } finally {
-                    args.recycle();
+                    Log.w(TAG, "Failed to return the result to requestCursorUpdates()."
+                            + " result=" + result, e);
                 }
                 return;
             }
@@ -547,26 +551,28 @@
                 final int flags = msg.arg1;
                 SomeArgs args = (SomeArgs) msg.obj;
                 try {
-                    final IInputContextCallback callback = (IInputContextCallback) args.arg6;
-                    final int callbackSeq = args.argi6;
-                    InputConnection ic = getInputConnection();
+                    final IIntResultCallback callback = (IIntResultCallback) args.arg3;
+                    final InputConnection ic = getInputConnection();
+                    final boolean result;
                     if (ic == null || !isActive()) {
                         Log.w(TAG, "commitContent on inactive InputConnection");
-                        callback.setCommitContentResult(false, callbackSeq);
-                        return;
+                        result = false;
+                    } else {
+                        final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
+                        if (inputContentInfo == null || !inputContentInfo.validate()) {
+                            Log.w(TAG, "commitContent with invalid inputContentInfo="
+                                    + inputContentInfo);
+                            result = false;
+                        } else {
+                            result = ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
+                        }
                     }
-                    final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
-                    if (inputContentInfo == null || !inputContentInfo.validate()) {
-                        Log.w(TAG, "commitContent with invalid inputContentInfo="
-                                + inputContentInfo);
-                        callback.setCommitContentResult(false, callbackSeq);
-                        return;
+                    try {
+                        callback.onResult(result ? 1 : 0);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to return the result to commitContent()."
+                                + " result=" + result, e);
                     }
-                    final boolean result =
-                            ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
-                    callback.setCommitContentResult(result, callbackSeq);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling commitContent", e);
                 } finally {
                     args.recycle();
                 }
@@ -588,40 +594,6 @@
         return mH.obtainMessage(what, 0, 0, arg1);
     }
 
-    Message obtainMessageISC(int what, int arg1, int callbackSeq, IInputContextCallback callback) {
-        final SomeArgs args = SomeArgs.obtain();
-        args.arg6 = callback;
-        args.argi6 = callbackSeq;
-        return mH.obtainMessage(what, arg1, 0, args);
-    }
-
-    Message obtainMessageIISC(int what, int arg1, int arg2, int callbackSeq,
-            IInputContextCallback callback) {
-        final SomeArgs args = SomeArgs.obtain();
-        args.arg6 = callback;
-        args.argi6 = callbackSeq;
-        return mH.obtainMessage(what, arg1, arg2, args);
-    }
-
-    Message obtainMessageIOOSC(int what, int arg1, Object objArg1, Object objArg2, int callbackSeq,
-            IInputContextCallback callback) {
-        final SomeArgs args = SomeArgs.obtain();
-        args.arg1 = objArg1;
-        args.arg2 = objArg2;
-        args.arg6 = callback;
-        args.argi6 = callbackSeq;
-        return mH.obtainMessage(what, arg1, 0, args);
-    }
-
-    Message obtainMessageIOSC(int what, int arg1, Object arg2, int callbackSeq,
-            IInputContextCallback callback) {
-        final SomeArgs args = SomeArgs.obtain();
-        args.arg1 = arg2;
-        args.arg6 = callback;
-        args.argi6 = callbackSeq;
-        return mH.obtainMessage(what, arg1, 0, args);
-    }
-
     Message obtainMessageIO(int what, int arg1, Object arg2) {
         return mH.obtainMessage(what, arg1, 0, arg2);
     }
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index c227991..86f1293 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -23,7 +23,9 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputContentInfo;
 
-import com.android.internal.view.IInputContextCallback;
+import com.android.internal.inputmethod.ICharSequenceResultCallback;
+import com.android.internal.inputmethod.IExtractedTextResultCallback;
+import com.android.internal.inputmethod.IIntResultCallback;
 
 /**
  * Interface from an input method to the application, allowing it to perform
@@ -31,14 +33,14 @@
  * {@hide}
  */
  oneway interface IInputContext {
-    void getTextBeforeCursor(int length, int flags, int seq, IInputContextCallback callback); 
+    void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback);
 
-    void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback);
-    
-    void getCursorCapsMode(int reqModes, int seq, IInputContextCallback callback);
-    
-    void getExtractedText(in ExtractedTextRequest request, int flags, int seq,
-            IInputContextCallback callback);
+    void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback);
+
+    void getCursorCapsMode(int reqModes, IIntResultCallback callback);
+
+    void getExtractedText(in ExtractedTextRequest request, int flags,
+            IExtractedTextResultCallback callback);
 
     void deleteSurroundingText(int beforeLength, int afterLength);
     void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength);
@@ -71,11 +73,10 @@
 
     void setComposingRegion(int start, int end);
 
-    void getSelectedText(int flags, int seq, IInputContextCallback callback);
+    void getSelectedText(int flags, ICharSequenceResultCallback callback);
 
-    void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
-            IInputContextCallback callback);
+    void requestUpdateCursorAnchorInfo(int cursorUpdateMode, IIntResultCallback callback);
 
-    void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, int sec,
-            IInputContextCallback callback);
+    void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts,
+            IIntResultCallback callback);
 }
diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl
deleted file mode 100644
index 0f40a83..0000000
--- a/core/java/com/android/internal/view/IInputContextCallback.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.view.inputmethod.ExtractedText;
-
-/**
- * {@hide}
- */
-oneway interface IInputContextCallback {
-    void setTextBeforeCursor(CharSequence textBeforeCursor, int seq);
-    void setTextAfterCursor(CharSequence textAfterCursor, int seq);
-    void setCursorCapsMode(int capsMode, int seq);
-    void setExtractedText(in ExtractedText extractedText, int seq);
-    void setSelectedText(CharSequence selectedText, int seq);
-    void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq);
-    void setCommitContentResult(boolean result, int seq);
-}
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index a41048c..0bf5234 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -17,14 +17,12 @@
 package com.android.internal.view;
 
 import android.annotation.AnyThread;
-import android.annotation.BinderThread;
 import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
+import android.annotation.Nullable;
 import android.inputmethodservice.AbstractInputMethodService;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
@@ -36,10 +34,15 @@
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputContentInfo;
 
+import com.android.internal.inputmethod.CancellationGroup;
+import com.android.internal.inputmethod.ResultCallbacks;
+
 import java.lang.ref.WeakReference;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.TimeUnit;
 
 public class InputConnectionWrapper implements InputConnection {
+    private static final String TAG = "InputConnectionWrapper";
+
     private static final int MAX_WAIT_TIME_MILLIS = 2000;
     private final IInputContext mIInputContext;
     @NonNull
@@ -49,257 +52,94 @@
     private final int mMissingMethods;
 
     /**
-     * {@code true} if the system already decided to take away IME focus from the target app. This
-     * can be signaled even when the corresponding signal is in the task queue and
-     * {@link InputMethodService#onUnbindInput()} is not yet called back on the UI thread.
+     * Signaled when the system decided to take away IME focus from the target app.
+     *
+     * <p>This is expected to be signaled immediately when the IME process receives
+     * {@link IInputMethod#unbindInput()}.</p>
      */
     @NonNull
-    private final AtomicBoolean mIsUnbindIssued;
-
-    static class InputContextCallback extends IInputContextCallback.Stub {
-        private static final String TAG = "InputConnectionWrapper.ICC";
-        public int mSeq;
-        public boolean mHaveValue;
-        public CharSequence mTextBeforeCursor;
-        public CharSequence mTextAfterCursor;
-        public CharSequence mSelectedText;
-        public ExtractedText mExtractedText;
-        public int mCursorCapsMode;
-        public boolean mRequestUpdateCursorAnchorInfoResult;
-        public boolean mCommitContentResult;
-
-        // A 'pool' of one InputContextCallback.  Each ICW request will attempt to gain
-        // exclusive access to this object.
-        private static InputContextCallback sInstance = new InputContextCallback();
-        private static int sSequenceNumber = 1;
-        
-        /**
-         * Returns an InputContextCallback object that is guaranteed not to be in use by
-         * any other thread.  The returned object's 'have value' flag is cleared and its expected
-         * sequence number is set to a new integer.  We use a sequence number so that replies that
-         * occur after a timeout has expired are not interpreted as replies to a later request.
-         */
-        @UnsupportedAppUsage
-        @AnyThread
-        private static InputContextCallback getInstance() {
-            synchronized (InputContextCallback.class) {
-                // Return sInstance if it's non-null, otherwise construct a new callback
-                InputContextCallback callback;
-                if (sInstance != null) {
-                    callback = sInstance;
-                    sInstance = null;
-                    
-                    // Reset the callback
-                    callback.mHaveValue = false;
-                } else {
-                    callback = new InputContextCallback();
-                }
-                
-                // Set the sequence number
-                callback.mSeq = sSequenceNumber++;
-                return callback;
-            }
-        }
-        
-        /**
-         * Makes the given InputContextCallback available for use in the future.
-         */
-        @UnsupportedAppUsage
-        @AnyThread
-        private void dispose() {
-            synchronized (InputContextCallback.class) {
-                // If sInstance is non-null, just let this object be garbage-collected
-                if (sInstance == null) {
-                    // Allow any objects being held to be gc'ed
-                    mTextAfterCursor = null;
-                    mTextBeforeCursor = null;
-                    mExtractedText = null;
-                    sInstance = this;
-                }
-            }
-        }
-
-        @BinderThread
-        public void setTextBeforeCursor(CharSequence textBeforeCursor, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mTextBeforeCursor = textBeforeCursor;
-                    mHaveValue = true;
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setTextBeforeCursor, ignoring.");
-                }
-            }
-        }
-
-        @BinderThread
-        public void setTextAfterCursor(CharSequence textAfterCursor, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mTextAfterCursor = textAfterCursor;
-                    mHaveValue = true;
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setTextAfterCursor, ignoring.");
-                }
-            }
-        }
-
-        @BinderThread
-        public void setSelectedText(CharSequence selectedText, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mSelectedText = selectedText;
-                    mHaveValue = true;
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setSelectedText, ignoring.");
-                }
-            }
-        }
-
-        @BinderThread
-        public void setCursorCapsMode(int capsMode, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mCursorCapsMode = capsMode; 
-                    mHaveValue = true;  
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setCursorCapsMode, ignoring.");
-                }
-            }
-        }
-
-        @BinderThread
-        public void setExtractedText(ExtractedText extractedText, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mExtractedText = extractedText;
-                    mHaveValue = true;
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setExtractedText, ignoring.");
-                }
-            }
-        }
-
-        @BinderThread
-        public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mRequestUpdateCursorAnchorInfoResult = result;
-                    mHaveValue = true;
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setCursorAnchorInfoRequestResult, ignoring.");
-                }
-            }
-        }
-
-        @BinderThread
-        public void setCommitContentResult(boolean result, int seq) {
-            synchronized (this) {
-                if (seq == mSeq) {
-                    mCommitContentResult = result;
-                    mHaveValue = true;
-                    notifyAll();
-                } else {
-                    Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setCommitContentResult, ignoring.");
-                }
-            }
-        }
-
-        /**
-         * Waits for a result for up to {@link #MAX_WAIT_TIME_MILLIS} milliseconds.
-         * 
-         * <p>The caller must be synchronized on this callback object.
-         */
-        @AnyThread
-        void waitForResultLocked() {
-            long startTime = SystemClock.uptimeMillis();
-            long endTime = startTime + MAX_WAIT_TIME_MILLIS;
-
-            while (!mHaveValue) {
-                long remainingTime = endTime - SystemClock.uptimeMillis();
-                if (remainingTime <= 0) {
-                    Log.w(TAG, "Timed out waiting on IInputContextCallback");
-                    return;
-                }
-                try {
-                    wait(remainingTime);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-    }
+    private final CancellationGroup mCancellationGroup;
 
     public InputConnectionWrapper(
             @NonNull WeakReference<AbstractInputMethodService> inputMethodService,
-            IInputContext inputContext, @MissingMethodFlags final int missingMethods,
-            @NonNull AtomicBoolean isUnbindIssued) {
+            IInputContext inputContext, @MissingMethodFlags int missingMethods,
+            @NonNull CancellationGroup cancellationGroup) {
         mInputMethodService = inputMethodService;
         mIInputContext = inputContext;
         mMissingMethods = missingMethods;
-        mIsUnbindIssued = isUnbindIssued;
+        mCancellationGroup = cancellationGroup;
+    }
+
+    @AnyThread
+    private static void logInternal(@Nullable String methodName, boolean timedOut,
+            @Nullable Object defaultValue) {
+        if (timedOut) {
+            Log.w(TAG, methodName + " didn't respond in " + MAX_WAIT_TIME_MILLIS + " msec."
+                    + " Returning default: " + defaultValue);
+        } else {
+            Log.w(TAG, methodName + " was canceled before complete. Returning default: "
+                    + defaultValue);
+        }
+    }
+
+    @AnyThread
+    private static int getResultOrZero(@NonNull CancellationGroup.Completable.Int value,
+             @NonNull String methodName) {
+        final boolean timedOut = value.await(MAX_WAIT_TIME_MILLIS,  TimeUnit.MILLISECONDS);
+        if (value.hasValue()) {
+            return value.getValue();
+        }
+        logInternal(methodName, timedOut, 0);
+        return 0;
+    }
+
+    @AnyThread
+    @Nullable
+    private static <T> T getResultOrNull(@NonNull CancellationGroup.Completable.Values<T> value,
+            @NonNull String methodName) {
+        final boolean timedOut = value.await(MAX_WAIT_TIME_MILLIS,  TimeUnit.MILLISECONDS);
+        if (value.hasValue()) {
+            return value.getValue();
+        }
+        logInternal(methodName, timedOut, null);
+        return null;
     }
 
     @AnyThread
     public CharSequence getTextAfterCursor(int length, int flags) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return null;
         }
 
-        CharSequence value = null;
+        final CancellationGroup.Completable.CharSequence value =
+                mCancellationGroup.createCompletableCharSequence();
         try {
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.getTextAfterCursor(length, flags, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    value = callback.mTextAfterCursor;
-                }
-            }
-            callback.dispose();
+            mIInputContext.getTextAfterCursor(length, flags, ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return null;
         }
-        return value;
+        return getResultOrNull(value, "getTextAfterCursor()");
     }
 
     @AnyThread
     public CharSequence getTextBeforeCursor(int length, int flags) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return null;
         }
 
-        CharSequence value = null;
+        final CancellationGroup.Completable.CharSequence value =
+                mCancellationGroup.createCompletableCharSequence();
         try {
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.getTextBeforeCursor(length, flags, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    value = callback.mTextBeforeCursor;
-                }
-            }
-            callback.dispose();
+            mIInputContext.getTextBeforeCursor(length, flags, ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return null;
         }
-        return value;
+        return getResultOrNull(value, "getTextBeforeCursor()");
     }
 
     @AnyThread
     public CharSequence getSelectedText(int flags) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return null;
         }
 
@@ -307,67 +147,46 @@
             // This method is not implemented.
             return null;
         }
-        CharSequence value = null;
+        final CancellationGroup.Completable.CharSequence value =
+                mCancellationGroup.createCompletableCharSequence();
         try {
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.getSelectedText(flags, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    value = callback.mSelectedText;
-                }
-            }
-            callback.dispose();
+            mIInputContext.getSelectedText(flags, ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return null;
         }
-        return value;
+        return getResultOrNull(value, "getSelectedText()");
     }
 
     @AnyThread
     public int getCursorCapsMode(int reqModes) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return 0;
         }
 
-        int value = 0;
+        final CancellationGroup.Completable.Int value =
+                mCancellationGroup.createCompletableInt();
         try {
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.getCursorCapsMode(reqModes, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    value = callback.mCursorCapsMode;
-                }
-            }
-            callback.dispose();
+            mIInputContext.getCursorCapsMode(reqModes, ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return 0;
         }
-        return value;
+        return getResultOrZero(value, "getCursorCapsMode()");
     }
 
     @AnyThread
     public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return null;
         }
 
-        ExtractedText value = null;
+        final CancellationGroup.Completable.ExtractedText value =
+                mCancellationGroup.createCompletableExtractedText();
         try {
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.getExtractedText(request, flags, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    value = callback.mExtractedText;
-                }
-            }
-            callback.dispose();
+            mIInputContext.getExtractedText(request, flags, ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return null;
         }
-        return value;
+        return getResultOrNull(value, "getExtractedText()");
     }
 
     @AnyThread
@@ -563,29 +382,22 @@
 
     @AnyThread
     public boolean requestCursorUpdates(int cursorUpdateMode) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return false;
         }
 
-        boolean result = false;
         if (isMethodMissing(MissingMethodFlags.REQUEST_CURSOR_UPDATES)) {
             // This method is not implemented.
             return false;
         }
+        final CancellationGroup.Completable.Int value = mCancellationGroup.createCompletableInt();
         try {
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    result = callback.mRequestUpdateCursorAnchorInfoResult;
-                }
-            }
-            callback.dispose();
+            mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode,
+                    ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return false;
         }
-        return result;
+        return getResultOrZero(value, "requestUpdateCursorAnchorInfo()") != 0;
     }
 
     @AnyThread
@@ -601,38 +413,31 @@
 
     @AnyThread
     public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
-        if (mIsUnbindIssued.get()) {
+        if (mCancellationGroup.isCanceled()) {
             return false;
         }
 
-        boolean result = false;
         if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
             // This method is not implemented.
             return false;
         }
-        try {
-            if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
-                final AbstractInputMethodService inputMethodService = mInputMethodService.get();
-                if (inputMethodService == null) {
-                    // This basically should not happen, because it's the the caller of this method.
-                    return false;
-                }
-                inputMethodService.exposeContent(inputContentInfo, this);
-            }
 
-            InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
-            synchronized (callback) {
-                callback.waitForResultLocked();
-                if (callback.mHaveValue) {
-                    result = callback.mCommitContentResult;
-                }
+        if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
+            final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+            if (inputMethodService == null) {
+                // This basically should not happen, because it's the caller of this method.
+                return false;
             }
-            callback.dispose();
+            inputMethodService.exposeContent(inputContentInfo, this);
+        }
+
+        final CancellationGroup.Completable.Int value = mCancellationGroup.createCompletableInt();
+        try {
+            mIInputContext.commitContent(inputContentInfo, flags, opts, ResultCallbacks.of(value));
         } catch (RemoteException e) {
             return false;
         }
-        return result;
+        return getResultOrZero(value, "commitContent()") != 0;
     }
 
     @AnyThread
diff --git a/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java b/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java
deleted file mode 100644
index 924b3f7..0000000
--- a/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java
+++ /dev/null
@@ -1,94 +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.internal.view;
-
-import android.os.Handler;
-import android.os.Message;
-import android.view.Choreographer;
-import android.view.Display;
-
-/**
- * Utility class to schedule things at vsync-sf instead of vsync-app
- * @hide
- */
-public class SurfaceFlingerVsyncChoreographer {
-
-    private static final long ONE_MS_IN_NS = 1000000;
-    private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
-
-    private final Handler mHandler;
-    private final Choreographer mChoreographer;
-
-    /**
-     * The offset between vsync-app and vsync-surfaceflinger. See
-     * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
-     */
-    private long mSurfaceFlingerOffsetMs;
-
-    public SurfaceFlingerVsyncChoreographer(Handler handler, Display display,
-            Choreographer choreographer) {
-        mHandler = handler;
-        mChoreographer = choreographer;
-        mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(display);
-    }
-
-    public long getSurfaceFlingerOffsetMs() {
-        return mSurfaceFlingerOffsetMs;
-    }
-
-    /**
-     * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
-     * is a couple of milliseconds before vsync-sf, a touch or animation event that causes a surface
-     * flinger transaction are sometimes processed before the vsync-sf tick, and sometimes after,
-     * which leads to jank. Figure out this difference here and then post all the touch/animation
-     * events to start being processed at vsync-sf.
-     *
-     * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
-     */
-    private long calculateAppSurfaceFlingerVsyncOffsetMs(Display display) {
-
-        // Calculate vsync offset from SurfaceFlinger.
-        // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
-        long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
-        long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
-        return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
-    }
-
-    public void scheduleAtSfVsync(Runnable r) {
-        final long delay = calculateDelay();
-        if (delay <= 0) {
-            r.run();
-        } else {
-            mHandler.postDelayed(r, delay);
-        }
-    }
-
-    public void scheduleAtSfVsync(Handler h, Message m) {
-        final long delay = calculateDelay();
-        if (delay <= 0) {
-            h.handleMessage(m);
-        } else {
-            m.setAsynchronous(true);
-            h.sendMessageDelayed(m, delay);
-        }
-    }
-
-    private long calculateDelay() {
-        final long sinceFrameStart = System.nanoTime() - mChoreographer.getLastFrameTimeNanos();
-        return mSurfaceFlingerOffsetMs - sinceFrameStart / 1000000;
-    }
-}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index ab68c44..2668420 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -40,7 +40,6 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.Gravity;
@@ -121,6 +120,7 @@
     private CachingIconView mConversationIconBadgeBg;
     private Icon mLargeIcon;
     private View mExpandButtonContainer;
+    private View mExpandButtonInnerContainer;
     private ViewGroup mExpandButtonAndContentContainer;
     private NotificationExpandButton mExpandButton;
     private MessagingLinearLayout mImageMessageContainer;
@@ -242,6 +242,7 @@
         mConversationHeader = findViewById(R.id.conversation_header);
         mContentContainer = findViewById(R.id.notification_action_list_margin_target);
         mExpandButtonAndContentContainer = findViewById(R.id.expand_button_and_content_container);
+        mExpandButtonInnerContainer = findViewById(R.id.expand_button_inner_container);
         mExpandButton = findViewById(R.id.expand_button);
         mExpandButtonExpandedTopMargin = getResources().getDimensionPixelSize(
                 R.dimen.conversation_expand_button_top_margin_expanded);
@@ -331,7 +332,8 @@
     @RemotableViewMethod
     public void setIsImportantConversation(boolean isImportantConversation) {
         mImportantConversation = isImportantConversation;
-        mImportanceRingView.setVisibility(isImportantConversation ? VISIBLE : GONE);
+        mImportanceRingView.setVisibility(isImportantConversation
+                && mIcon.getVisibility() != GONE ? VISIBLE : GONE);
     }
 
     public boolean isImportantConversation() {
@@ -384,14 +386,17 @@
 
     /** @hide */
     public void setUnreadCount(int unreadCount) {
-        mUnreadBadge.setVisibility(mIsCollapsed && unreadCount > 1 ? VISIBLE : GONE);
-        CharSequence text = unreadCount >= 100
-                ? getResources().getString(R.string.unread_convo_overflow, 99)
-                : String.format(Locale.getDefault(), "%d", unreadCount);
-        mUnreadBadge.setText(text);
-        mUnreadBadge.setBackgroundTintList(ColorStateList.valueOf(mLayoutColor));
-        boolean needDarkText = ColorUtils.calculateLuminance(mLayoutColor) > 0.5f;
-        mUnreadBadge.setTextColor(needDarkText ? Color.BLACK : Color.WHITE);
+        boolean visible = mIsCollapsed && unreadCount > 1;
+        mUnreadBadge.setVisibility(visible ? VISIBLE : GONE);
+        if (visible) {
+            CharSequence text = unreadCount >= 100
+                    ? getResources().getString(R.string.unread_convo_overflow, 99)
+                    : String.format(Locale.getDefault(), "%d", unreadCount);
+            mUnreadBadge.setText(text);
+            mUnreadBadge.setBackgroundTintList(ColorStateList.valueOf(mLayoutColor));
+            boolean needDarkText = ColorUtils.calculateLuminance(mLayoutColor) > 0.5f;
+            mUnreadBadge.setTextColor(needDarkText ? Color.BLACK : Color.WHITE);
+        }
     }
 
     private void addRemoteInputHistoryToMessages(
@@ -534,37 +539,26 @@
     }
 
     private void updateImageMessages() {
-        boolean displayExternalImage = false;
-        ArraySet<View> newMessages = new ArraySet<>();
-        if (mIsCollapsed) {
+        View newMessage = null;
+        if (mIsCollapsed && mGroups.size() > 0) {
 
-            // When collapsed, we're displaying all image messages in a dedicated container
-            // on the right of the layout instead of inline. Let's add all isolated images there
-            int imageIndex = 0;
-            for (int i = 0; i < mGroups.size(); i++) {
-                MessagingGroup messagingGroup = mGroups.get(i);
-                MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
-                if (isolatedMessage != null) {
-                    newMessages.add(isolatedMessage.getView());
-                    displayExternalImage = true;
-                    if (imageIndex
-                            != mImageMessageContainer.indexOfChild(isolatedMessage.getView())) {
-                        mImageMessageContainer.removeView(isolatedMessage.getView());
-                        mImageMessageContainer.addView(isolatedMessage.getView(), imageIndex);
-                    }
-                    imageIndex++;
-                }
+            // When collapsed, we're displaying the image message in a dedicated container
+            // on the right of the layout instead of inline. Let's add the isolated image there
+            MessagingGroup messagingGroup = mGroups.get(mGroups.size() -1);
+            MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
+            if (isolatedMessage != null) {
+                newMessage = isolatedMessage.getView();
             }
         }
         // Remove all messages that don't belong into the image layout
-        for (int i = 0; i < mImageMessageContainer.getChildCount(); i++) {
-            View child = mImageMessageContainer.getChildAt(i);
-            if (!newMessages.contains(child)) {
-                mImageMessageContainer.removeView(child);
-                i--;
+        View previousMessage = mImageMessageContainer.getChildAt(0);
+        if (previousMessage != newMessage) {
+            mImageMessageContainer.removeView(previousMessage);
+            if (newMessage != null) {
+                mImageMessageContainer.addView(newMessage);
             }
         }
-        mImageMessageContainer.setVisibility(displayExternalImage ? VISIBLE : GONE);
+        mImageMessageContainer.setVisibility(newMessage != null ? VISIBLE : GONE);
     }
 
     private void bindFacePile() {
@@ -1168,7 +1162,7 @@
         layoutParams.topMargin = topMargin;
         mExpandButton.setLayoutParams(layoutParams);
 
-        mExpandButtonContainer.setContentDescription(mContext.getText(contentDescriptionId));
+        mExpandButtonInnerContainer.setContentDescription(mContext.getText(contentDescriptionId));
     }
 
     private void updateContentEndPaddings() {
@@ -1212,7 +1206,7 @@
         mExpandable = expandable;
         if (expandable) {
             mExpandButtonContainer.setVisibility(VISIBLE);
-            mExpandButtonContainer.setOnClickListener(onClickListener);
+            mExpandButtonInnerContainer.setOnClickListener(onClickListener);
         } else {
             // TODO: handle content paddings to end of layout
             mExpandButtonContainer.setVisibility(GONE);
diff --git a/core/java/com/android/internal/widget/InlinePresentationStyleUtils.java b/core/java/com/android/internal/widget/InlinePresentationStyleUtils.java
new file mode 100644
index 0000000..264c8bd
--- /dev/null
+++ b/core/java/com/android/internal/widget/InlinePresentationStyleUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Utility methods relating to inline presentation UI.
+ */
+public final class InlinePresentationStyleUtils {
+
+    /**
+     * Returns true if the two bundles are deeply equal.
+     *
+     * Each input bundle may represent a UI style in the
+     * {@link android.widget.inline.InlinePresentationSpec} or the extra
+     * request info in the {@link android.view.inputmethod.InlineSuggestionsRequest}
+     *
+     * Note: this method should not be called in the framework process for security reasons.
+     */
+    public static boolean bundleEquals(@NonNull Bundle bundle1, @NonNull Bundle bundle2) {
+        if (bundle1 == bundle2) {
+            return true;
+        }
+        if (bundle1 == null || bundle2 == null) {
+            return false;
+        }
+        if (bundle1.size() != bundle2.size()) {
+            return false;
+        }
+        Set<String> keys = bundle1.keySet();
+        for (String key : keys) {
+            Object value1 = bundle1.get(key);
+            Object value2 = bundle2.get(key);
+            if (value1 instanceof Bundle && value2 instanceof Bundle
+                    && !bundleEquals((Bundle) value1, (Bundle) value2)) {
+                return false;
+            } else if (!Objects.equals(value1, value2)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Private ctor to avoid constructing the class.
+     */
+    private InlinePresentationStyleUtils() {
+    }
+}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index d40924b..21ca948 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -229,6 +229,7 @@
     private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
 
     private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
+    private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
 
     /**
      * Map of system pre-defined, uniquely named actors; keys are namespace,
@@ -394,6 +395,10 @@
         return mRollbackWhitelistedPackages;
     }
 
+    public Set<String> getWhitelistedStagedInstallers() {
+        return mWhitelistedStagedInstallers;
+    }
+
     public ArraySet<String> getAppDataIsolationWhitelistedApps() {
         return mAppDataIsolationWhitelistedApps;
     }
@@ -1137,6 +1142,20 @@
                         }
                         XmlUtils.skipCurrentTag(parser);
                     } break;
+                    case "whitelisted-staged-installer": {
+                        if (allowAppConfigs) {
+                            String pkgname = parser.getAttributeValue(null, "package");
+                            if (pkgname == null) {
+                                Slog.w(TAG, "<" + name + "> without package in " + permFile
+                                        + " at " + parser.getPositionDescription());
+                            } else {
+                                mWhitelistedStagedInstallers.add(pkgname);
+                            }
+                        } else {
+                            logNotAllowedInPartition(name, permFile, parser);
+                        }
+                        XmlUtils.skipCurrentTag(parser);
+                    } break;
                     default: {
                         Slog.w(TAG, "Tag " + name + " is unknown in "
                                 + permFile + " at " + parser.getPositionDescription());
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 0c74387..7c32ca6 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -696,7 +696,7 @@
         return -1;
     }
 
-    return si.totalram;
+    return static_cast<jlong>(si.totalram) * si.mem_unit;
 }
 
 /*
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index b2ca0a7..1cfa12d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -29,11 +29,13 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_view_Surface.h>
 #include <android_runtime/android_view_SurfaceSession.h>
+#include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
+#include <private/gui/ComposerService.h>
 #include <stdio.h>
 #include <system/graphics.h>
 #include <ui/ConfigStoreTypes.h>
@@ -624,6 +626,23 @@
     transaction->setFrameRate(ctrl, frameRate, static_cast<int8_t>(compatibility));
 }
 
+static jlong nativeAcquireFrameRateFlexibilityToken(JNIEnv* env, jclass clazz) {
+    sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+    sp<IBinder> token;
+    status_t result = composer->acquireFrameRateFlexibilityToken(&token);
+    if (result < 0) {
+        ALOGE("Failed acquiring frame rate flexibility token: %s (%d)", strerror(-result), result);
+        return 0;
+    }
+    token->incStrong((void*)nativeAcquireFrameRateFlexibilityToken);
+    return reinterpret_cast<jlong>(token.get());
+}
+
+static void nativeReleaseFrameRateFlexibilityToken(JNIEnv* env, jclass clazz, jlong tokenLong) {
+    sp<IBinder> token(reinterpret_cast<IBinder*>(tokenLong));
+    token->decStrong((void*)nativeAcquireFrameRateFlexibilityToken);
+}
+
 static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) {
     const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
     jlongArray array = env->NewLongArray(displayIds.size());
@@ -1411,6 +1430,12 @@
 
     client->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
 }
+
+static jlong nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    SurfaceControl *surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    return reinterpret_cast<jlong>(surfaceControl->getHandle().get());
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1474,6 +1499,10 @@
             (void*)nativeSetShadowRadius },
     {"nativeSetFrameRate", "(JJFI)V",
             (void*)nativeSetFrameRate },
+    {"nativeAcquireFrameRateFlexibilityToken", "()J",
+            (void*)nativeAcquireFrameRateFlexibilityToken },
+    {"nativeReleaseFrameRateFlexibilityToken", "(J)V",
+            (void*)nativeReleaseFrameRateFlexibilityToken },
     {"nativeGetPhysicalDisplayIds", "()[J",
             (void*)nativeGetPhysicalDisplayIds },
     {"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;",
@@ -1583,6 +1612,8 @@
             (void*)nativeMirrorSurface },
     {"nativeSetGlobalShadowSettings", "([F[FFFF)V",
             (void*)nativeSetGlobalShadowSettings },
+    {"nativeGetHandle", "(J)J",
+            (void*)nativeGetHandle },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index ea3c0fa..4b30359 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -110,7 +110,6 @@
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 using android::base::GetBoolProperty;
-using android::base::GetProperty;
 
 #define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
                               append(StringPrintf(__VA_ARGS__))
@@ -170,18 +169,6 @@
 
 static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751;
 
-/**
- * Property to control if app data isolation is enabled.
- */
-static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
-    "persist.zygote.app_data_isolation";
-
-/**
- * Property to enable app data isolation for sdcard obb or data in vold.
- */
-static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
-    "persist.sys.vold_app_data_isolation_enabled";
-
 static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
 static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
 
@@ -1319,20 +1306,13 @@
  * be decrypted after storage is decrypted.
  *
  */
-static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
-    uid_t uid, const char* process_name, jstring managed_nice_name,
-    fail_fn_t fail_fn) {
+static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
+    uid_t uid, const char* process_name,
+    jstring managed_nice_name, fail_fn_t fail_fn) {
 
   const userid_t userId = multiuser_get_user_id(uid);
 
-  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
-
-  int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
-  // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
-  if ((size % 3) != 0) {
-    fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
-  }
-  ensureInAppMountNamespace(fail_fn);
+  int size = merged_data_info_list.size();
 
   // Mount tmpfs on all possible data directories, so app no longer see the original apps data.
   char internalCePath[PATH_MAX];
@@ -1377,14 +1357,10 @@
   bool legacySymlinkCreated = false;
 
   for (int i = 0; i < size; i += 3) {
-    jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
-    std::string packageName = extract_fn(package_str).value();
+    std::string const & packageName = merged_data_info_list[i];
+    std::string const & volUuid  = merged_data_info_list[i + 1];
+    std::string const & inode = merged_data_info_list[i + 2];
 
-    jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1));
-    std::string volUuid = extract_fn(vol_str).value();
-
-    jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2));
-    std::string inode = extract_fn(inode_str).value();
     std::string::size_type sz;
     long long ceDataInode = std::stoll(inode, &sz);
 
@@ -1482,6 +1458,48 @@
   freecon(dataDataContext);
 }
 
+static void insertPackagesToMergedList(JNIEnv* env,
+  std::vector<std::string>& merged_data_info_list,
+  jobjectArray data_info_list, const char* process_name,
+  jstring managed_nice_name, fail_fn_t fail_fn) {
+
+  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+
+  int size = (data_info_list != nullptr) ? env->GetArrayLength(data_info_list) : 0;
+  // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
+  if ((size % 3) != 0) {
+    fail_fn(CREATE_ERROR("Wrong data_info_list size %d", size));
+  }
+
+  for (int i = 0; i < size; i += 3) {
+    jstring package_str = (jstring) (env->GetObjectArrayElement(data_info_list, i));
+    std::string packageName = extract_fn(package_str).value();
+    merged_data_info_list.push_back(packageName);
+
+    jstring vol_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 1));
+    std::string volUuid = extract_fn(vol_str).value();
+    merged_data_info_list.push_back(volUuid);
+
+    jstring inode_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 2));
+    std::string inode = extract_fn(inode_str).value();
+    merged_data_info_list.push_back(inode);
+  }
+}
+
+static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
+    jobjectArray whitelisted_data_info_list, uid_t uid, const char* process_name,
+    jstring managed_nice_name, fail_fn_t fail_fn) {
+
+  ensureInAppMountNamespace(fail_fn);
+  std::vector<std::string> merged_data_info_list;
+  insertPackagesToMergedList(env, merged_data_info_list, pkg_data_info_list,
+          process_name, managed_nice_name, fail_fn);
+  insertPackagesToMergedList(env, merged_data_info_list, whitelisted_data_info_list,
+          process_name, managed_nice_name, fail_fn);
+
+  isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn);
+}
+
 /**
  * Like isolateAppData(), isolate jit profile directories, so apps don't see what
  * other apps are installed by reading content inside /data/misc/profiles/cur.
@@ -1594,7 +1612,9 @@
                              jstring managed_nice_name, bool is_system_server,
                              bool is_child_zygote, jstring managed_instruction_set,
                              jstring managed_app_data_dir, bool is_top_app,
-                             jobjectArray pkg_data_info_list, bool mount_storage_dirs) {
+                             jobjectArray pkg_data_info_list,
+                             jobjectArray whitelisted_data_info_list,
+                             bool mount_data_dirs, bool mount_storage_dirs) {
   const char* process_name = is_system_server ? "system_server" : "zygote";
   auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
   auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1628,9 +1648,9 @@
   // give a null in same_uid_pkgs and private_volumes so they don't need app data isolation.
   // Isolated process / webview / app zygote should be gated by SELinux and file permission
   // so they can't even traverse CE / DE directories.
-  if (pkg_data_info_list != nullptr
-      && GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
-    isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
+  if (mount_data_dirs) {
+    isolateAppData(env, pkg_data_info_list, whitelisted_data_info_list,
+            uid, process_name, managed_nice_name, fail_fn);
     isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
   }
   if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) {
@@ -2003,7 +2023,8 @@
         jint mount_external, jstring se_info, jstring nice_name,
         jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
         jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
-        jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
+        jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
+        jboolean mount_data_dirs, jboolean mount_storage_dirs) {
     jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
     if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -2041,6 +2062,8 @@
                        mount_external, se_info, nice_name, false,
                        is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                        is_top_app == JNI_TRUE, pkg_data_info_list,
+                       whitelisted_data_info_list,
+                       mount_data_dirs == JNI_TRUE,
                        mount_storage_dirs == JNI_TRUE);
     }
     return pid;
@@ -2076,7 +2099,8 @@
                        permitted_capabilities, effective_capabilities,
                        MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                        false, nullptr, nullptr, /* is_top_app= */ false,
-                       /* pkg_data_info_list */ nullptr, false);
+                       /* pkg_data_info_list */ nullptr,
+                       /* whitelisted_data_info_list */ nullptr, false, false);
   } else if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -2206,15 +2230,16 @@
     jint runtime_flags, jobjectArray rlimits,
     jint mount_external, jstring se_info, jstring nice_name,
     jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
-    jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
+    jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
+    jboolean mount_data_dirs, jboolean mount_storage_dirs) {
   jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
   SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                    capabilities, capabilities,
                    mount_external, se_info, nice_name, false,
                    is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
-                   is_top_app == JNI_TRUE, pkg_data_info_list,
-                   mount_storage_dirs == JNI_TRUE);
+                   is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list,
+                   mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
 }
 
 /**
@@ -2405,10 +2430,19 @@
     return -1;
 }
 
+static jboolean com_android_internal_os_Zygote_nativeSupportsTaggedPointers(JNIEnv* env, jclass) {
+#ifdef __aarch64__
+  int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+  return res >= 0 && res & PR_TAGGED_ADDR_ENABLE;
+#else
+  return false;
+#endif
+}
+
 static const JNINativeMethod gMethods[] = {
         {"nativeForkAndSpecialize",
          "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
-         "String;Z[Ljava/lang/String;Z)I",
+         "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
          (void*)com_android_internal_os_Zygote_nativeForkAndSpecialize},
         {"nativeForkSystemServer", "(II[II[[IJJ)I",
          (void*)com_android_internal_os_Zygote_nativeForkSystemServer},
@@ -2421,7 +2455,7 @@
         {"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap},
         {"nativeSpecializeAppProcess",
          "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
-         "String;Z[Ljava/lang/String;Z)V",
+         "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
          (void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
         {"nativeInitNativeState", "(Z)V",
          (void*)com_android_internal_os_Zygote_nativeInitNativeState},
@@ -2440,6 +2474,8 @@
          (void*)com_android_internal_os_Zygote_nativeBoostUsapPriority},
         {"nativeParseSigChld", "([BI[I)I",
          (void*)com_android_internal_os_Zygote_nativeParseSigChld},
+        {"nativeSupportsTaggedPointers", "()Z",
+         (void*)com_android_internal_os_Zygote_nativeSupportsTaggedPointers},
 };
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index ab57e3d..6321651 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2669,4 +2669,9 @@
     // Open: Settings > Sound > Do Not Disturb > Apps > <Choose App>
     // OS: R
     DND_APPS_BYPASSING = 1840;
+
+    // OPEN: Settings > Battery > Advanced battery option
+    // CATEGORY: SETTINGS
+    // OS: R
+    FUELGAUGE_ADVANCED_BATTERY_OPTION = 1842;
 }
diff --git a/core/proto/android/stats/dnsresolver/dns_resolver.proto b/core/proto/android/stats/dnsresolver/dns_resolver.proto
index 76f8f0f..61b9b25 100644
--- a/core/proto/android/stats/dnsresolver/dns_resolver.proto
+++ b/core/proto/android/stats/dnsresolver/dns_resolver.proto
@@ -62,6 +62,13 @@
     NS_R_NOTAUTH = 9;   // Not authoritative for zone
     NS_R_NOTZONE = 10;  // Zone of record different from zone section
     NS_R_MAX = 11;
+    // Define rcode=12~15(UNASSIGNED) in rcode enum type.
+    // Some DNS Servers might return undefined code to devices.
+    // Without the enum definition, that would be noise for our dashboard.
+    NS_R_UNASSIGNED12 = 12; // Unassigned
+    NS_R_UNASSIGNED13 = 13; // Unassigned
+    NS_R_UNASSIGNED14 = 14; // Unassigned
+    NS_R_UNASSIGNED15 = 15; // Unassigned
     // The following are EDNS extended rcodes
     NS_R_BADVERS = 16;
     // The following are TSIG errors
@@ -170,12 +177,22 @@
     NT_BLUETOOTH = 3;
     // Indicates this network uses an Ethernet transport.
     NT_ETHERNET = 4;
-    // Indicates this network uses a VPN transport.
-    NT_VPN = 5;
+    // Indicates this network uses a VPN transport, now deprecated.
+    NT_VPN = 5 [deprecated=true];
     // Indicates this network uses a Wi-Fi Aware transport.
     NT_WIFI_AWARE = 6;
     // Indicates this network uses a LoWPAN transport.
     NT_LOWPAN = 7;
+    // Indicates this network uses a Cellular+VPN transport.
+    NT_CELLULAR_VPN = 8;
+    // Indicates this network uses a Wi-Fi+VPN transport.
+    NT_WIFI_VPN = 9;
+    // Indicates this network uses a Bluetooth+VPN transport.
+    NT_BLUETOOTH_VPN = 10;
+    // Indicates this network uses an Ethernet+VPN transport.
+    NT_ETHERNET_VPN = 11;
+    // Indicates this network uses a Wi-Fi+Cellular+VPN transport.
+    NT_WIFI_CELLULAR_VPN = 12;
 }
 
 enum CacheStatus{
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ad0f247..451363f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4712,12 +4712,6 @@
     <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows preempting sound trigger recognitions for the sake of capturing audio on
-         implementations which do not support running both concurrently.
-         @hide -->
-    <permission android:name="android.permission.PREEMPT_SOUND_TRIGGER"
-                android:protectionLevel="signature|privileged" />
-
     <!-- Must be required by system/priv apps implementing sound trigger detection services
          @hide
          @SystemApi -->
diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml
index b9ca292..e986b18 100644
--- a/core/res/res/layout/notification_template_material_conversation.xml
+++ b/core/res/res/layout/notification_template_material_conversation.xml
@@ -245,6 +245,7 @@
                     android:id="@+id/notification_messaging"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
+                    android:minHeight="@dimen/notification_text_size"
                     android:spacing="@dimen/notification_messaging_spacing"
                     android:clipToPadding="false"
                     android:clipChildren="false"
@@ -263,53 +264,65 @@
         <include layout="@layout/notification_material_action_list" />
     </com.android.internal.widget.RemeasuringLinearLayout>
 
-    <!--This is dynamically placed between here and at the end of the layout-->
-    <LinearLayout
+    <!--This is dynamically placed between here and at the end of the layout. It starts here since
+        only FrameLayout layout params have gravity-->
+    <FrameLayout
         android:id="@+id/expand_button_container"
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/conversation_expand_button_size"
+        android:layout_height="match_parent"
         android:layout_gravity="end|top"
-        android:paddingStart="16dp"
-        android:orientation="horizontal"
-        android:paddingEnd="@dimen/notification_content_margin_end"
-        android:clipToPadding="false"
         android:clipChildren="false"
-        >
-        <!-- Images -->
-        <com.android.internal.widget.MessagingLinearLayout
-            android:id="@+id/conversation_image_message_container"
-            android:forceHasOverlappingRendering="false"
-            android:layout_width="40dp"
-            android:layout_height="40dp"
-            android:layout_marginEnd="11dp"
-            android:spacing="0dp"
-            android:layout_gravity="center"
+        android:clipToPadding="false">
+        <!--This layout makes sure that we can nicely center the expand content in the
+            collapsed layout while the parent makes sure that we're never laid out bigger
+            than the messaging content.-->
+        <LinearLayout
+            android:id="@+id/expand_button_inner_container"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/conversation_expand_button_size"
+            android:paddingStart="16dp"
+            android:orientation="horizontal"
+            android:layout_gravity="end|top"
+            android:paddingEnd="@dimen/notification_content_margin_end"
             android:clipToPadding="false"
             android:clipChildren="false"
-            />
-        <!-- Unread Count -->
-        <TextView
-            android:id="@+id/conversation_unread_count"
-            android:layout_width="33sp"
-            android:layout_height="wrap_content"
-            android:layout_marginEnd="11dp"
-            android:layout_gravity="center"
-            android:gravity="center"
-            android:padding="2dp"
-            android:visibility="gone"
-            android:textAppearance="@style/TextAppearance.DeviceDefault.Notification"
-            android:textColor="#FFFFFF"
-            android:textSize="12sp"
-            android:background="@drawable/conversation_unread_bg"
-        />
-        <com.android.internal.widget.NotificationExpandButton
-            android:id="@+id/expand_button"
-            android:layout_width="@dimen/notification_header_expand_icon_size"
-            android:layout_height="@dimen/notification_header_expand_icon_size"
-            android:layout_gravity="center"
-            android:drawable="@drawable/ic_expand_notification"
-            android:clickable="false"
-            android:importantForAccessibility="no"
-        />
-    </LinearLayout>
+            >
+            <!-- Images -->
+            <com.android.internal.widget.MessagingLinearLayout
+                android:id="@+id/conversation_image_message_container"
+                android:forceHasOverlappingRendering="false"
+                android:layout_width="40dp"
+                android:layout_height="40dp"
+                android:layout_marginEnd="11dp"
+                android:spacing="0dp"
+                android:layout_gravity="center"
+                android:clipToPadding="false"
+                android:clipChildren="false"
+                />
+            <!-- Unread Count -->
+            <TextView
+                android:id="@+id/conversation_unread_count"
+                android:layout_width="33sp"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="11dp"
+                android:layout_gravity="center"
+                android:gravity="center"
+                android:padding="2dp"
+                android:visibility="gone"
+                android:textAppearance="@style/TextAppearance.DeviceDefault.Notification"
+                android:textColor="#FFFFFF"
+                android:textSize="12sp"
+                android:background="@drawable/conversation_unread_bg"
+                />
+            <com.android.internal.widget.NotificationExpandButton
+                android:id="@+id/expand_button"
+                android:layout_width="@dimen/notification_header_expand_icon_size"
+                android:layout_height="@dimen/notification_header_expand_icon_size"
+                android:layout_gravity="center"
+                android:drawable="@drawable/ic_expand_notification"
+                android:clickable="false"
+                android:importantForAccessibility="no"
+                />
+        </LinearLayout>
+    </FrameLayout>
 </com.android.internal.widget.ConversationLayout>
diff --git a/core/res/res/layout/resolver_empty_states.xml b/core/res/res/layout/resolver_empty_states.xml
index c7e1a21..5890bed 100644
--- a/core/res/res/layout/resolver_empty_states.xml
+++ b/core/res/res/layout/resolver_empty_states.xml
@@ -19,61 +19,66 @@
     android:id="@+id/resolver_empty_state"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical"
     android:gravity="center_horizontal"
     android:visibility="gone"
-    android:paddingTop="48dp"
     android:paddingStart="24dp"
     android:paddingEnd="24dp">
-    <ImageView
-        android:id="@+id/resolver_empty_state_icon"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
-        android:layout_centerHorizontal="true" />
-    <TextView
-        android:id="@+id/resolver_empty_state_title"
-        android:layout_below="@+id/resolver_empty_state_icon"
-        android:layout_marginTop="8dp"
-        android:layout_width="wrap_content"
+    <RelativeLayout
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:fontFamily="@string/config_headlineFontFamilyMedium"
-        android:textColor="@color/resolver_empty_state_text"
-        android:textSize="14sp"
-        android:layout_centerHorizontal="true" />
-    <TextView
-        android:id="@+id/resolver_empty_state_subtitle"
-        android:layout_below="@+id/resolver_empty_state_title"
-        android:layout_marginTop="4dp"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="@color/resolver_empty_state_text"
-        android:textSize="12sp"
-        android:gravity="center_horizontal"
-        android:layout_centerHorizontal="true" />
-    <Button
-        android:id="@+id/resolver_empty_state_button"
-        android:layout_below="@+id/resolver_empty_state_subtitle"
-        android:layout_marginTop="16dp"
-        android:text="@string/resolver_switch_on_work"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:fontFamily="@string/config_headlineFontFamilyMedium"
-        android:textSize="14sp"
-        android:textColor="?attr/colorAccent"
-        android:layout_centerHorizontal="true"
-        android:background="@drawable/resolver_turn_on_work_button_ripple_background"/>
-    <ProgressBar
-        android:id="@+id/resolver_empty_state_progress"
-        style="@style/Widget.Material.Light.ProgressBar"
-        android:visibility="gone"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:indeterminate="true"
-        android:layout_alignTop="@+id/resolver_empty_state_icon"
-        android:layout_alignBottom="@+id/resolver_empty_state_button"
-        android:layout_centerHorizontal="true"
-        android:layout_below="@+id/resolver_empty_state_subtitle"
-        android:indeterminateTint="?attr/colorAccent"/>
+        android:paddingTop="48dp"
+        android:paddingBottom="48dp"
+        android:gravity="center_horizontal">
+        <ImageView
+            android:id="@+id/resolver_empty_state_icon"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_centerHorizontal="true" />
+        <TextView
+            android:id="@+id/resolver_empty_state_title"
+            android:layout_below="@+id/resolver_empty_state_icon"
+            android:layout_marginTop="8dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@string/config_headlineFontFamilyMedium"
+            android:textColor="@color/resolver_empty_state_text"
+            android:textSize="14sp"
+            android:layout_centerHorizontal="true" />
+        <TextView
+            android:id="@+id/resolver_empty_state_subtitle"
+            android:layout_below="@+id/resolver_empty_state_title"
+            android:layout_marginTop="4dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/resolver_empty_state_text"
+            android:textSize="12sp"
+            android:gravity="center_horizontal"
+            android:layout_centerHorizontal="true" />
+        <Button
+            android:id="@+id/resolver_empty_state_button"
+            android:layout_below="@+id/resolver_empty_state_subtitle"
+            android:layout_marginTop="16dp"
+            android:text="@string/resolver_switch_on_work"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@string/config_headlineFontFamilyMedium"
+            android:textSize="14sp"
+            android:textColor="?attr/colorAccent"
+            android:layout_centerHorizontal="true"
+            android:background="@drawable/resolver_turn_on_work_button_ripple_background"/>
+        <ProgressBar
+            android:id="@+id/resolver_empty_state_progress"
+            style="@style/Widget.Material.Light.ProgressBar"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:indeterminate="true"
+            android:layout_alignTop="@+id/resolver_empty_state_icon"
+            android:layout_alignBottom="@+id/resolver_empty_state_button"
+            android:layout_centerHorizontal="true"
+            android:layout_below="@+id/resolver_empty_state_subtitle"
+            android:indeterminateTint="?attr/colorAccent"/>
+    </RelativeLayout>
     <TextView android:id="@+id/empty"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index e078384..8facd8a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Gesprek"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Groepsgesprek"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Persoonlik"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Werk"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persoonlike aansig"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b3c8b7a..37fd965 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>፦"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"ውይይት"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"የቡድን ውይይት"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"የግል"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ሥራ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"የግል እይታ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a6db03a..4715823 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -218,7 +218,7 @@
     <string name="power_dialog" product="default" msgid="1107775420270203046">"خيارات الهاتف"</string>
     <string name="silent_mode" msgid="8796112363642579333">"وضع صامت"</string>
     <string name="turn_on_radio" msgid="2961717788170634233">"تفعيل اللاسلكي"</string>
-    <string name="turn_off_radio" msgid="7222573978109933360">"إيقاف تفعيل الشبكة اللاسلكية"</string>
+    <string name="turn_off_radio" msgid="7222573978109933360">"إيقاف الشبكة اللاسلكية"</string>
     <string name="screen_lock" msgid="2072642720826409809">"قفل الشاشة"</string>
     <string name="power_off" msgid="4111692782492232778">"إيقاف التشغيل"</string>
     <string name="silent_mode_silent" msgid="5079789070221150912">"إيقاف الرنين"</string>
@@ -231,10 +231,10 @@
     <string name="reboot_to_reset_title" msgid="2226229680017882787">"إعادة الضبط على الإعدادات الأصلية"</string>
     <string name="reboot_to_reset_message" msgid="3347690497972074356">"جارٍ إعادة التشغيل…"</string>
     <string name="shutdown_progress" msgid="5017145516412657345">"جارٍ إيقاف التشغيل..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"سيتم إيقاف تفعيل الجهاز اللوحي."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"سيتم إيقاف الجهاز اللوحي."</string>
     <string name="shutdown_confirm" product="tv" msgid="7975942887313518330">"‏سيتم إيقاف جهاز Android TV."</string>
     <string name="shutdown_confirm" product="watch" msgid="2977299851200240146">"سيتم إيقاف المشاهدة."</string>
-    <string name="shutdown_confirm" product="default" msgid="136816458966692315">"سيتم إيقاف تفعيل هاتفك."</string>
+    <string name="shutdown_confirm" product="default" msgid="136816458966692315">"سيتم إيقاف هاتفك."</string>
     <string name="shutdown_confirm_question" msgid="796151167261608447">"هل تريد إيقاف التشغيل؟"</string>
     <string name="reboot_safemode_title" msgid="5853949122655346734">"إعادة تشغيل في الوضع الآمن"</string>
     <string name="reboot_safemode_confirm" msgid="1658357874737219624">"هل تريد إعادة تشغيل الكمبيوتر في الوضع الآمن؟ سيؤدي ذلك إلى إيقاف جميع تطبيقات الجهات الخارجية التي تم تثبيتها. ستتم استعادتها عند إعادة التشغيل مرة أخرى."</string>
@@ -245,10 +245,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"خيارات الهاتف"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"قفل الشاشة"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"إيقاف التشغيل"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"التشغيل"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"إعادة التشغيل"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"الطوارئ"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"تقرير الأخطاء"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"إنهاء الجلسة"</string>
@@ -452,8 +450,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"التقاط صور وفيديوهات"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"يمكن لهذا التطبيق التقاط صور وتسجيل فيديوهات باستخدام الكاميرا في أي وقت."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"السماح لتطبيق أو خدمة بالوصول إلى كاميرات النظام لالتقاط صور وتسجيل فيديوهات"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"‏إنّ تطبيق النظام هذا، أو التطبيق المزوّد بأذونات مميّزة، يمكنه التقاط صور وتسجيل فيديوهات باستخدام كاميرا النظام في أي وقت. ويجب أن يحصل التطبيق أيضًا على الإذن android.permission.CAMERA."</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"يسمح الإذن لتطبيق أو خدمة بتلقّي استدعاءات عما إذا كانت أجهزة الكاميرات مفتوحة أو مغلقة."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"يمكن أن يتلقّى هذا التطبيق استدعاءات عندما تكون هناك كاميرا مفتوحة (بواسطة هذا التطبيق) أو مغلقة."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"التحكم في الاهتزاز"</string>
@@ -1434,8 +1431,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> غير متوافق"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"هذا الجهاز غير متوافق مع <xliff:g id="NAME">%s</xliff:g> هذا. انقر للإعداد بتنسيق متوافق."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"لا يتوافق هذا الجهاز مع <xliff:g id="NAME">%s</xliff:g>. يمكنك النقر للإعداد بتنسيق متوافق."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"لا يدعم هذا الجهاز <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"تمت إزالة <xliff:g id="NAME">%s</xliff:g> بشكل غير متوقع"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"إخراج الوسائط قبل الإزالة لتجنّب فقدان المحتوى"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"تمت إزالة <xliff:g id="NAME">%s</xliff:g>."</string>
@@ -1711,24 +1707,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"هل تريد رفع مستوى الصوت فوق المستوى الموصى به؟\n\nقد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"هل تريد استخدام اختصار \"سهولة الاستخدام\"؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"عند تفعيل الاختصار، يؤدي الضغط على زرّي التحكّم في مستوى الصوت معًا لمدة 3 ثوانٍ إلى تفعيل إحدى ميزات إمكانية الوصول."</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"هل تريد تفعيل ميزات إمكانية الوصول؟"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"‏يؤدي الضغط مع الاستمرار على كلا مفتاحَي التحكّم في مستوى الصوت لبضع ثوانٍ إلى تفعيل ميزات إمكانية الوصول. قد يؤدي هذا إلى تغيير كيفية عمل جهازك.\n\nالميزات الحالية:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nيمكنك تغيير الميزات المحددة في الإعدادات &gt; أدوات تمكين الوصول."</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"‏هل تريد تفعيل TalkBack؟"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"‏يؤدي الضغط مع الاستمرار لبضع ثوانٍ على كلا مفتاحَي التحكّم في مستوى الصوت إلى تفعيل TalkBack، وهو قارئ شاشة يساعد المكفوفين أو الذين يعانون من ضعف في النظر. تؤدي ميزة TalkBack إلى تغيير كيفية عمل جهازك بالكامل.\n\nيمكنك تغيير هذا الاختصار للعمل مع ميزة أخرى في الإعدادات &gt; أدوات تمكين الوصول."</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"هل تريد تفعيل <xliff:g id="SERVICE">%1$s</xliff:g>؟"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"‏يؤدي الضغط مع الاستمرار لبضع ثوانٍ على كلا مفتاحَي التحكّم في مستوى الصوت إلى تفعيل <xliff:g id="SERVICE">%1$s</xliff:g> وهي إحدى ميزات إمكانية الوصول. يمكن أن يؤدي هذا الإجراء إلى تغيير كيفية عمل جهازك.\n\nيمكنك تغيير هذا الاختصار لاستخدامه مع ميزة أخرى في الإعدادات &gt; أدوات تمكين الوصول."</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"تفعيل"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"عدم التفعيل"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"هل تريد السماح لخدمة <xliff:g id="SERVICE">%1$s</xliff:g> بالتحكّم الكامل في جهازك؟"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"في حال تفعيل <xliff:g id="SERVICE">%1$s</xliff:g>، لن يستخدم جهازك ميزة قفل الشاشة لتحسين ترميز البيانات."</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"إنّ التحكّم الكامل ليس ملائمًا لمعظم التطبيقات، باستثناء التطبيقات المعنية بسهولة الاستخدام."</string>
@@ -1739,10 +1726,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"سماح"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"رفض"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"انقر على ميزة لبدء استخدامها:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"اختيار الميزات التي تريد استخدامها مع زر أدوات تمكين الوصول"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"اختيار الميزات التي تريد استخدامها مع اختصار مفتاح التحكّم في مستوى الصوت"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"تم إيقاف <xliff:g id="SERVICE_NAME">%s</xliff:g>."</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"تعديل الاختصارات"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تم"</string>
@@ -1750,23 +1735,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"عكس الألوان"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"تصحيح الألوان"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"يمكنك اختيار إحدى الميزات لاستخدامها عند النقر على زر أدوات تمكين الوصول:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"يمكنك اختيار إحدى الميزات لاستخدامها مع إيماءة أدوات تمكين الوصول (مرّر سريعًا إلى الأعلى من أسفل الشاشة باستخدام إصبعين):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"يمكنك اختيار إحدى الميزات التالية لاستخدامها مع إيماءة أدوات تمكين الوصول (مرّر سريعًا إلى الأعلى من أسفل الشاشة باستخدام ثلاثة أصابع):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"للتبديل بين الخدمات، يمكنك النقر مع الاستمرار على زر أدوات تمكين الوصول."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"للتبديل بين الخدمات، مرّر سريعًا من أسفل الشاشة إلى أعلاها باستخدام إصبعين مع تثبيتهما."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"للتبديل بين الميزات، مرّر سريعًا من أسفل الشاشة لأعلاها بثلاثة أصابع مع تثبيتها."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"التكبير"</string>
     <string name="user_switched" msgid="7249833311585228097">"المستخدم الحالي <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"جارٍ التبديل إلى <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -2185,8 +2162,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> و<xliff:g id="COUNT_3">%d</xliff:g> ملف</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> وملف (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ليس هناك أشخاص مقترحون للمشاركة معهم"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"قائمة التطبيقات"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"‏لم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"الشاشة الرئيسية"</string>
@@ -2204,6 +2180,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"محادثة"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"محادثة جماعية"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"شخصي"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"عمل"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"عرض المحتوى الشخصي"</string>
@@ -2222,220 +2200,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"لا يمكن لتطبيقات العمل أن تفتح هذا المحتوى."</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"لا يمكن للتطبيقات الشخصية أن تدعم هذا المحتوى."</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"لا يمكن للتطبيقات الشخصية أن تفتح هذا المحتوى."</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"‏رقم التعريف الشخصي لإلغاء قفل شبكة شريحة SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"‏رقم التعريف الشخصي لإلغاء قفل المجموعة الفرعية لشبكة شريحة SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"‏رقم التعريف الشخصي لإلغاء قفل شريحة SIM للشركات"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"‏رقم التعريف الشخصي لإلغاء قفل مقدم خدمة شريحة SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"‏رقم التعريف الشخصي لإلغاء قفل شريحة SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"‏رقم التعريف الشخصي لإلغاء قفل RUIM network1"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"‏رقم التعريف الشخصي لإلغاء قفل RUIM network2"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"‏رقم التعريف الشخصي لإلغاء قفل بطاقة RUIM لبيانات الحزمة ذات المعدل العالي"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"‏رقم التعريف الشخصي لإلغاء قفل بطاقة RUIM للشركات"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"‏رقم التعريف الشخصي لإلغاء قفل مقدم خدمة بطاقة RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"‏رقم التعريف الشخصي لإلغاء قفل بطاقة RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"‏إدخال رمز PUK"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"‏رقم التعريف الشخصي لإلغاء قفل SPN"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"‏رقم التعريف الشخصي لإلغاء قفل SP Equivalent Home PLMN"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"‏رقم التعريف الشخصي لإلغاء قفل ICCID"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"‏رقم التعريف الشخصي لإلغاء قفل IMPI"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"رقم التعريف الشخصي لإلغاء قفل مقدم خدمة المجموعة الفرعية للشبكة"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"‏جارٍ طلب إلغاء قفل شبكة شريحة SIM.…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"‏جارٍ طلب إلغاء قفل المجموعة الفرعية لشبكة شريحة SIM …"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"‏جارٍ طلب إلغاء قفل مقدم خدمة شريحة SIM…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"‏جارٍ طلب إلغاء قفل شريحة SIM للشركات…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"‏جارٍ طلب إلغاء قفل شريحة SIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"‏جارٍ طلب إلغاء قفل RUIM network1…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"‏جارٍ طلب إلغاء قفل RUIM network2…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"‏جارٍ طلب إلغاء قفل بطاقة RUIM لبيانات الحزمة ذات المعدل العالي.…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"‏جارٍ طلب إلغاء قفل مقدم خدمة بطاقة RUIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"‏جارٍ طلب إلغاء قفل بطاقة RUIM للشركات…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"‏جارٍ طلب إلغاء قفل SPN…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"‏جارٍ طلب إلغاء قفل SP Equivalent Home PLMN…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"‏جارٍ طلب إلغاء قفل ICCID.…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"‏جارٍ طلب إلغاء قفل IMPI…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"جارٍ طلب إلغاء قفل مقدم خدمة المجموعة الفرعية للشبكة…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"‏جارٍ طلب إلغاء قفل بطاقة RUIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"‏جارٍ طلب إلغاء القفل باستخدام رمز PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"‏تعذّر طلب إلغاء قفل شبكة شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"‏تعذّر طلب إلغاء قفل المجموعة الفرعية لشبكة شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"‏تعذّر طلب إلغاء قفل مقدم خدمة شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"‏تعذّر طلب إلغاء قفل شريحة SIM للشركات."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"‏تعذّر طلب إلغاء قفل شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"‏تعذّر طلب إلغاء قفل RUIM Network1."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"‏تعذّر طلب إلغاء قفل RUIM network2."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"‏تعذّر طلب إلغاء قفل بطاقة RUIM لبيانات الحزمة ذات المعدل العالي."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"‏تعذّر طلب إلغاء قفل بطاقة RUIM للشركات."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"‏تعذّر طلب إلغاء قفل مقدم خدمة بطاقة RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"‏تعذّر طلب إلغاء قفل بطاقة RUIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"‏تعذّر إلغاء القفل باستخدام رمز PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"‏تعذّر طلب إلغاء قفل SPN."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"‏تعذّر طلب إلغاء قفل SP Equivalent Home PLMN."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"‏تعذّر طلب إلغاء قفل ICCID."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"‏تعذّر طلب إلغاء قفل IMPI."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"تعذّر طلب إلغاء قفل مقدم خدمة المجموعة الفرعية للشبكة."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"‏تم إلغاء قفل شبكة شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"‏تم إلغاء قفل المجموعة الفرعية لشبكة شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"‏تم إلغاء قفل مقدم خدمة شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"‏تم إلغاء قفل شريحة SIM للشركات."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"‏تم إلغاء قفل شريحة SIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"‏تم إلغاء قفل RUIM Network1."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"‏تم إلغاء قفل RUIM network2."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"‏تم إلغاء قفل بطاقة RUIM لبيانات الحزمة ذات المعدل العالي."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"‏تم إلغاء قفل مقدم خدمة بطاقة RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"‏تم إلغاء قفل بطاقة RUIM للشركات بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"‏تم إلغاء قفل بطاقة RUIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"‏تم إلغاء القفل باستخدام رمز PUK بنجاح."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"‏تم إلغاء قفل SPN."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"‏تم إلغاء قفل SP Equivalent Home PLMN."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"‏تم إلغاء قفل ICCID."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"‏تم إلغاء قفل IMPI."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"تم إلغاء قفل مقدم خدمة المجموعة الفرعية للشبكة."</string>
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 7685e4b..c0e070b 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -297,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"আপোনাৰ সম্পৰ্কসূচী চাব পাৰে"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"অৱস্থান"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"এই ডিভাইচৰ অৱস্থান ব্যৱহাৰ কৰিব পাৰে"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"কেলেণ্ডাৰ"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"আপোনাৰ কেলেণ্ডাৰ ব্যৱহাৰ কৰিব পাৰে"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"এছএমএছ"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"এছএমএছ বার্তা পঠিয়াব আৰু চাব পাৰে"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰি"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক ব্যৱহাৰ কৰিব নোৱাৰে। ব্যৱহাৰ কৰিব পৰা ফৰ্মেটত ছেট আপ কৰিবলৈ টিপক।"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"এই ডিভাইচটোৱে <xliff:g id="NAME">%s</xliff:g>ক চলাব নোৱাৰে। চলাব পৰা কোনো ফৰ্মেটত ছেট আপ কৰিবলৈ বাছনি কৰক।"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"এই ডিভাইচটোৱে এই <xliff:g id="NAME">%s</xliff:g>ক সমৰ্থন নকৰে।"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> অপ্ৰত্য়াশিতভাৱে আঁতৰোৱা হ’ল"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"সমল হেৰুওৱাৰ পৰা হাত সাৰিবলৈ আঁতৰোৱাৰ আগতে মিডিয়া বাহিৰ কৰক"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> আঁতৰোৱা হ’ল"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"বাৰ্তালাপ"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"গোটত কৰা বাৰ্তালাপ"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ব্যক্তিগত"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"কৰ্মস্থান"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ব্যক্তিগত ভিউ"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index faeaa65..ec69606 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Dəstəklənməyən <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> bu cihaz tərəfindən dəstəklənmir. Dəstəklənən formatda ayarlamaq üçün tıklayın."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"<xliff:g id="NAME">%s</xliff:g> bu cihaz tərəfindən dəstəklənmir. Dəstəklənən formatda ayarlamaq üçün seçin."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"<xliff:g id="NAME">%s</xliff:g> bu cihaz tərəfindən dəstəklənmir."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> gözlənilmədən çıxarıldı"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Kontenti itirməmək üçün silmədən öncə medianı çıxarın"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> silindi"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Söhbət"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Qrup Söhbəti"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Şəxsi"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"İş"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Şəxsi məzmuna baxış"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index bd11a8f..0636ea9 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1371,8 +1371,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Uređaj <xliff:g id="NAME">%s</xliff:g> nije podržan"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Ovaj uređaj ne podržava ovaj uređaj <xliff:g id="NAME">%s</xliff:g>. Dodirnite da biste podesili podržani format."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Ovaj uređaj ne podržava ovaj medij (<xliff:g id="NAME">%s</xliff:g>). Izaberite da ga podesite u podržanom formatu."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Ovaj uređaj ne podržava: <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Uređaj <xliff:g id="NAME">%s</xliff:g> je neočekivano uklonjen"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Izbacite medijum pre nego što ga uklonite da ne biste izgubili sadržaj"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> je uklonjen/a"</string>
@@ -2079,6 +2078,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Konverzacija"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupna konverzacija"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Lični"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Poslovni"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Lični prikaz"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 2d5d510..133df6c 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1391,8 +1391,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> не падтрымліваецца"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Гэта прылада не падтрымлівае носьбіт <xliff:g id="NAME">%s</xliff:g>. Дакраніцеся, каб наладзіць яго ў фармаце, які падтрымліваецца."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Гэта прылада не падтрымлівае носьбіт <xliff:g id="NAME">%s</xliff:g>. Выберыце, каб наладзіць яго ў фармаце, які падтрымліваецца."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Гэта прылада не падтрымлівае гэты элемент: <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Носьбіт <xliff:g id="NAME">%s</xliff:g> нечакана выняты"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Адключыце носьбіт перад тым, як дастаць яго, каб не страціць змесціва"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Носьбіт (<xliff:g id="NAME">%s</xliff:g>) выняты"</string>
@@ -2113,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Размова"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Групавая размова"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Асабістыя"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Працоўныя"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Прагляд асабістага змесціва"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 7440f20..468b825 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -240,7 +240,7 @@
     <string name="global_action_power_options" msgid="1185286119330160073">"Захранване"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"Рестартиране"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"Спешно обаждане"</string>
-    <string name="global_action_bug_report" msgid="5127867163044170003">"Сигнал за програмна грешка"</string>
+    <string name="global_action_bug_report" msgid="5127867163044170003">"Сигнал за грешка"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"Прекратяване на сесията"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"Екранна снимка"</string>
     <string name="bugreport_title" msgid="8549990811777373050">"Сигнал за грешка"</string>
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Разговор"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Групов разговор"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Лични"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Служебни"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Личен изглед"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 57255f5..a8cc986 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -297,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"আপনার পরিচিতিগুলিতে অ্যাক্সেস"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"লোকেশন"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"এই ডিভাইসের লোকেশন অ্যাক্সেস"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"ক্যালেন্ডার"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"আপনার ক্যালেন্ডারে অ্যাক্সেস"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"এসএমএসগুলি পাঠাতে এবং দেখতে"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> অসমর্থিত"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"এই ডিভাইসটি <xliff:g id="NAME">%s</xliff:g> সমর্থন করে না। কোনো সমর্থিত ফর্ম্যাটে সেট-আপ করতে আলতো চাপুন।"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"এই ডিভাইসটি <xliff:g id="NAME">%s</xliff:g> সমর্থন করে না। কোনো সমর্থিত ফর্ম্যাটে সেট-আপ করতে চাইলে বেছে নিন।"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"এই ডিভাইসে <xliff:g id="NAME">%s</xliff:g> ব্যবহার করা যায় না।"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> অপ্রত্যাশিতভাবে মুছে ফেলা হয়েছে"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"মিডিয়া সরিয়ে নেওয়ার আগে সেটি সিস্টেম থেকে ইজেক্ট করুন, নাহলে কন্টেন্ট সেভ নাও হতে পারে"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> সরানো হয়েছে"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"কথোপকথন"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"গ্রুপ কথোপকথন"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ব্যক্তিগত"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"অফিস"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ব্যক্তিগত ভিউ"</string>
@@ -2104,7 +2105,7 @@
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM Network2 আনলক করতে অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM Hrpd আনলক করতে অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM পরিষেবা প্রদানকারী আনলক করতে অনুরোধ করা হচ্ছে…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"কর্পোরেট RUIM আনলক করতে অনুরোধ করা হচ্ছে…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"কর্পোরেট RUIM করতে অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN আনলক করার অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP Equivalent Home PLMN আনলক করার অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID আনলক করার অনুরোধ করা হচ্ছে…"</string>
@@ -2117,17 +2118,17 @@
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK আনলক করতে অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK আনলক করতে অনুরোধ করা হচ্ছে…"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK আনলক করতে অনুরোধ করা হচ্ছে…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"সিম নেটওয়ার্ক আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"সিম নেটওয়ার্ক সাবসেট আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"সিম পরিষেবা প্রদানকারী আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"কর্পোরেট সিম আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"সিম আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM Network1 আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM Network2 আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"কর্পোরেট RUIM আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM পরিষেবা প্রদানকারী আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"সিম নেটওয়ার্ক আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"সিম নেটওয়ার্ক সাবসেট আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"সিম পরিষেবা প্রদানকারী আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"কর্পোরেট সিম আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"সিম আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM Network1 আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM Network2 আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"কর্পোরেট RUIM আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM পরিষেবা প্রদানকারী আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM আনলক করার অনুরোধ করা যায়নি।"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK আনলক করা যায়নি।"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK আনলক করা যায়নি।"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK আনলক করা যায়নি।"</string>
@@ -2139,11 +2140,11 @@
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK আনলক করা যায়নি।"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK আনলক করা যায়নি।"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK আনলক করা যায়নি।"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"নেটওয়ার্ক সাবসেট পরিষেবা প্রদানকারী আনলক করার অনুরোধ ব্যর্থ হয়েছে।"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI আনলক করার অনুরোধ করা যায়নি।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"নেটওয়ার্ক সাবসেট পরিষেবা প্রদানকারী আনলক করার অনুরোধ করা যায়নি।"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"সিম নেটওয়ার্ক আনলক করা হয়েছে।"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"সিম নেটওয়ার্ক সাবসেট আনলক করা হয়েছে।"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"সিম পরিষেবা প্রদানকারী আনলক করা হয়েছে।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 37739b9..a6aa753 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -2080,6 +2080,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Razgovor"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupni razgovor"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Lično"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Posao"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Prikaz ličnog sadržaja"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index afed753..b3cb436 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1351,7 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> no és compatible"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"El dispositiu no admet la unitat <xliff:g id="NAME">%s</xliff:g>. Toca per configurar-la amb un format compatible."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Aquest dispositiu no admet la unitat següent: <xliff:g id="NAME">%s</xliff:g>. Selecciona-la per configurar-la en un format compatible."</string>
-    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"El dispositiu no admet aquest suport extern: <xliff:g id="NAME">%s</xliff:g>."</string>
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"El dispositiu no admet <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"S\'ha extret <xliff:g id="NAME">%s</xliff:g> de manera inesperada"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Expulsa el suport extern abans d\'extreure\'l per evitar perdre\'n el contingut"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"S\'ha suprimit el suport (<xliff:g id="NAME">%s</xliff:g>)"</string>
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversa de grup"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Feina"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualització personal"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index a77d417..36adc52 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1391,8 +1391,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Úložiště <xliff:g id="NAME">%s</xliff:g> není podporováno"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Úložiště <xliff:g id="NAME">%s</xliff:g> není v tomto zařízení podporováno. Klepnutím zahájíte nastavení v podporovaném formátu."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Úložiště <xliff:g id="NAME">%s</xliff:g> není v tomto zařízení podporováno. Vyberte ho a zahajte nastavení v podporovaném formátu."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Úložiště <xliff:g id="NAME">%s</xliff:g> není v tomto zařízení podporováno."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Úložiště <xliff:g id="NAME">%s</xliff:g> neočekávaně odpojeno"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Před odebráním médium nejprve odpojte, zabráníte tak ztrátě obsahu"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Médium <xliff:g id="NAME">%s</xliff:g> bylo odebráno"</string>
@@ -2113,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Konverzace"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Skupinová konverzace"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Osobní"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Pracovní"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Osobní zobrazení"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 03d969f..6d8a2b4 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Samtale"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Gruppesamtale"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personlig"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Arbejde"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visningen Personligt"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 15d3645..3de322e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -438,7 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"Bilder und Videos aufnehmen"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"Diese App kann mit der Kamera jederzeit Bilder und Videos aufnehmen."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"Einer App oder einem Dienst Zugriff auf Systemkameras erlauben, um Fotos und Videos aufnehmen zu können"</string>
-    <string name="permdesc_systemCamera" msgid="5938360914419175986">"Diese privilegierte System-App kann jederzeit mit einer Systemkamera Bilder und Videos aufnehmen. Die App benötigt auch die Berechtigung \"android.permission.CAMERA\"."</string>
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"Diese privilegierte App oder System-App kann jederzeit mit einer Systemkamera Bilder und Videos aufnehmen. Die App benötigt auch die Berechtigung \"android.permission.CAMERA\"."</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Einer App oder einem Dienst den Empfang von Callbacks erlauben, wenn eine Kamera geöffnet oder geschlossen wird."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"Diese App kann Callbacks empfangen, wenn eine der Kameras des Geräts von einer Anwendung geöffnet oder geschlossen wird."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"Vibrationsalarm steuern"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> nicht unterstützt"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> wird von diesem Gerät nicht unterstützt. Zum Einrichten in einem unterstützten Format tippen."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"<xliff:g id="NAME">%s</xliff:g> wird von diesem Gerät nicht unterstützt. Zur Einrichtung eines unterstützten Formats auswählen."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"<xliff:g id="NAME">%s</xliff:g> wird von diesem Gerät nicht unterstützt."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> wurde unerwartet entfernt"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Lass das Speichergerät vor dem Entfernen auswerfen, damit keine Daten verloren gehen"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> wurde entfernt"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Unterhaltung"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Gruppenunterhaltung"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Privat"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Geschäftlich"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Private Ansicht"</string>
@@ -2063,21 +2064,21 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Diese Inhalte dürfen nicht mit geschäftlichen Apps geöffnet werden"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Diese Inhalte werden von privaten Apps nicht unterstützt"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Diese Inhalte dürfen nicht mit privaten Apps geöffnet werden"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Entsperr-PIN für Netz-SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Entsperr-PIN für Subnetz-SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Entsperr-PIN für Unternehmens-SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"Entsperr-PIN für Mobilfunkanbieter-SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"Entsperr-PIN für netzgebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"Entsperr-PIN für subnetzgebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Entsperr-PIN für unternehmensgebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"Entsperr-PIN für mobilfunkanbietergebundenes Gerät"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"Entsperr-PIN für SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK eingeben"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"Entsperr-PIN für Network1-RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"Entsperr-PIN für Network2-RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"Entsperr-PIN für HRPD-RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Entsperr-PIN für Unternehmens-RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"Entsperr-PIN für Mobilfunkanbieter-RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"Entsperr-PIN für Network1-gebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"Entsperr-PIN für Network2-gebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"Entsperr-PIN für HRPD-Netz-gebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Entsperr-PIN für unternehmensgebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"Entsperr-PIN für mobilfunkanbietergebundenes Gerät"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"Entsperr-PIN für RUIM"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK eingeben"</string>
@@ -2085,49 +2086,49 @@
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK eingeben"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK eingeben"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"Entsperr-PIN für SPN-SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"Entsperr-PIN für SP-Equivalent-Home-PLMN-SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"Entsperr-PIN für SPN-gebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"Entsperr-PIN für SP Equivalent Home PLMN"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"Entsperr-PIN für ICCID"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"Entsperr-PIN für IMPI"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"Entsperr-PIN für Subnetz- und Mobilfunkanbieter-SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"Netz-SIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"Subnetz-SIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"Mobilfunkanbieter-SIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Unternehmens-SIM: Entsperrung wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"Entsperr-PIN für subnetz- und mobilfunkanbietergebundenes Gerät"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"Entsperrung des netzgebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"Entsperrung des subnetzgebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"Entsperrung des mobilfunkanbietergebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Entsperrung des unternehmensgebundenen Geräts wird angefordert…"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"Network1-RUIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"Network2-RUIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"HRPD-RUIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"Mobilfunkanbieter-RUIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Unternehmens-RUIM: Entsperrung wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM-Entsperrung wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"Entsperrung des Network1-gebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"Entsperrung des Network2-gebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"Entsperrung des HRPD-Netz-gebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"Entsperrung des mobilfunkanbietergebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Entsperrung des unternehmensgebundenen Geräts wird angefordert…"</string>
     <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN-SIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP-Equivalent-Home-PLMN: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Subnetz- und Mobilfunkanbieter-SIM: Entsperrung wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM: Entsperrung angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP-Equivalent-Home-PLMN-Entsperrung wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID-Entsperrung wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI-Entsperrung wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Entsperrung des subnetz- und mobilfunkanbietergebundenen Geräts wird angefordert…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM-Entsperrung angefordert…"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"Entsperrung durch PUK-Eingabe wird angefordert…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"Netz-SIM: Entsperrung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"Subnetz-SIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Mobilfunkanbieter-SIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Unternehmens-SIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"Network1-RUIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"Network2-RUIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"HRPD-RUIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Unternehmens-RUIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"Mobilfunkanbieter-RUIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM: Entsperranforderung war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"Entsperranforderung für netzgebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"Entsperranforderung für subnetzgebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Entsperranforderung für mobilfunkanbietergebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Entsperranforderung für unternehmensgebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"Entsperranforderung für SIM war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"Entsperranforderung für Network1-gebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"Entsperranforderung für Network2-gebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"Entsperranforderung für HRPD-Netz-gebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Entsperranforderung für unternehmensgebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"Entsperranforderung für mobilfunkanbietergebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"Entsperranforderung für RUIM war nicht erfolgreich."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"Entsperrung durch PUK-Eingabe war nicht erfolgreich."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"Entsperrung durch PUK-Eingabe war nicht erfolgreich."</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"Entsperrung durch PUK-Eingabe war nicht erfolgreich."</string>
@@ -2139,22 +2140,22 @@
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"Entsperrung durch PUK-Eingabe war nicht erfolgreich."</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"Entsperrung durch PUK-Eingabe war nicht erfolgreich."</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"Entsperrung durch PUK-Eingabe war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN-SIM: Entsperrungsanforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP-Equivalent-Home-PLMN: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI: Entsperrung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Subnetz- und Mobilfunkanbieter-SIM: Entsperranforderung war nicht erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"Subnetz-SIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"Subnetz-SIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"Mobilfunkanbieter-SIM: Entsperranforderung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Unternehmens-SIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"Network1-RUIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"Network2-RUIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"HRPD-RUIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"Mobilfunkanbieter-RUIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Unternehmens-RUIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM: Entsperrung war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"Entsperranforderung für SPN-gebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"Entsperranforderung für SP Equivalent Home PLMN war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"Entsperranforderung für ICCID war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"Entsperranforderung für IMPI war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Entsperranforderung für subnetz- und mobilfunkanbietergebundenes Gerät war nicht erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"Entsperrung des subnetzgebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"Entsperrung des subnetzgebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"Entsperrung des mobilfunkanbietergebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Entsperrung des unternehmensgebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM-Entsperrung war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"Entsperrung des Network1-gebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"Entsperrung des Network2-gebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"Entsperrung des HRPD-Netz-gebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"Entsperrung des mobilfunkanbietergebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Entsperrung des unternehmensgebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM-Entsperrung war erfolgreich."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"Entsperrung durch PUK-Eingabe war erfolgreich."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"Entsperrung durch PUK-Eingabe war erfolgreich."</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"Entsperrung durch PUK-Eingabe war erfolgreich."</string>
@@ -2166,9 +2167,9 @@
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"Entsperrung durch PUK-Eingabe war erfolgreich."</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"Entsperrung durch PUK-Eingabe war erfolgreich."</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"Entsperrung durch PUK-Eingabe war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN-SIM: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP-Equivalent-Home-PLMN: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI: Entsperrung war erfolgreich."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"Subnetz- und Mobilfunkanbieter-SIM: Entsperrung war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"Entsperrung des SPN-gebundenen Geräts war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP-Equivalent-Home-PLMN-Entsperrung war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID-Entsperrung war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI-Entsperrung war erfolgreich."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"Entsperrung des subnetz- und mobilfunkanbietergebundenen Geräts war erfolgreich."</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 2c22a12..57b02f4 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Συνομιλία"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Ομαδική συνομιλία"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Προσωπικό"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Εργασία"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Προσωπική προβολή"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index bcaff2e..ea121ef 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Group conversation"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index dfd80d4..a5bbb41 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Group conversation"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index bcaff2e..ea121ef 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Group conversation"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index bcaff2e..ea121ef 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Group conversation"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Work"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal view"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 96a983e..2777e0e 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SENDER_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎:‎‏‎‎‏‎"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎Conversation‎‏‎‎‏‎"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎Group Conversation‎‏‎‎‏‎"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>‎‏‎‎‏‏‏‎+‎‏‎‎‏‎"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎Personal‎‏‎‎‏‎"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‎Work‎‏‎‎‏‎"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎Personal view‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index f37ac16..366d19d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -438,7 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"tomar fotografías y grabar videos"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"Esta app puede tomar fotos y grabar videos con la cámara en cualquier momento."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"Permitir que una aplicación o un servicio accedan a las cámaras del sistema para tomar fotos y grabar videos"</string>
-    <string name="permdesc_systemCamera" msgid="5938360914419175986">"Esta app con privilegios o del sistema puede tomar fotografías y grabar videos con una cámara del sistema en cualquier momento. También se requiere que la app posea el permiso android.permission.CAMERA."</string>
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"Esta app del sistema o con privilegios puede tomar fotografías y grabar videos con una cámara del sistema en cualquier momento. Para ello, requiere tener el permiso android.permission.CAMERA."</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Permite que una aplicación o un servicio reciba devoluciones de llamada cuando se abren o cierran dispositivos de cámara."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"Esta app puede recibir devoluciones de llamada cuando se cierra o se abre cualquier dispositivo de cámara (y qué aplicación lo hace)."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"controlar la vibración"</string>
@@ -1620,12 +1620,12 @@
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Usar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cuando la combinación de teclas está activada, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"¿Quieres activar las funciones de accesibilidad?"</string>
-    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activan las funciones de accesibilidad. Esto podría cambiar la manera en que funciona tu dispositivo.\n\nFunciones actuales:\n<xliff:g id="SERVICE">%1$s</xliff:g>\npuedes cambiar las funciones seleccionadas en Configuración &gt; Accesibilidad."</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activarán las funciones de accesibilidad. Esto podría cambiar la manera en la que funciona tu dispositivo.\n\nFunciones actuales:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuedes cambiar las funciones seleccionadas en Configuración &gt; Accesibilidad."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
-    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"Cómo activar TalkBack"</string>
-    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activa TalkBack, un lector de pantalla que ayuda a las personas ciegas o con visión reducida. TalkBack cambia por completo la manera en que funciona tu dispositivo.\n\nPuedes cambiar este acceso directo a otra función en Configuración &gt; Accesibilidad."</string>
-    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Cómo activar <xliff:g id="SERVICE">%1$s</xliff:g>"</string>
-    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activa <xliff:g id="SERVICE">%1$s</xliff:g>, un función de accesibilidad. Esto podría cambiar la forma en que funciona tu dispositivo.\n\nPuedes cambiar este acceso directo a otra función en Configuración &gt; Accesibilidad."</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"¿Quieres activar TalkBack?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activará TalkBack, un lector de pantalla que ayuda a las personas ciegas o con visión reducida. TalkBack cambia por completo la manera en la que funciona tu dispositivo.\n\nPuedes cambiar este acceso directo a otra función en Configuración &gt; Accesibilidad."</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"¿Quieres activar <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activará la función de accesibilidad <xliff:g id="SERVICE">%1$s</xliff:g>. Esto podría cambiar la forma en que funciona tu dispositivo.\n\nPuedes cambiar este acceso directo a otra función en Configuración &gt; Accesibilidad."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activar"</string>
     <string name="accessibility_shortcut_off" msgid="3651336255403648739">"No activar"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"¿Deseas permitir que <xliff:g id="SERVICE">%1$s</xliff:g> tenga el control total del dispositivo?"</string>
@@ -1639,7 +1639,7 @@
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Rechazar"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Presiona una función para comenzar a usarla:"</string>
     <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona las funciones a utilizar con el botón de accesibilidad"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona las funciones a utilizar con el acceso directo de la tecla de volumen"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona las funciones a utilizar con la combinación de teclas de volumen"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se desactivó <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Listo"</string>
@@ -1647,15 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar acceso directo"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de color"</string>
-    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Mantuviste presionadas las teclas de volumen. Se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Mantuviste presionadas las teclas de volumen. Se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Al mantener presionadas las teclas de volumen, se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Elige una función para usar cuando pulses el botón accesibilidad:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Elige la función que se usará cuando realices el gesto de accesibilidad (deslizar dos dedos hacia arriba desde la parte inferior de la pantalla):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Elige la función que se usará cuando realices el gesto de accesibilidad (deslizar tres dedos hacia arriba desde la parte inferior de la pantalla):"</string>
-    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Para cambiar entre funciones, mantén pulsado el botón de accesibilidad."</string>
-    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Para cambiar de función, desliza dos dedos hacia arriba y mantenlos pulsados sobre la pantalla."</string>
-    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Para cambiar de función, desliza tres dedos hacia arriba y mantenlos pulsados sobre la pantalla."</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Para cambiar entre funciones, mantén presionado el botón de accesibilidad."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Para cambiar de función, desliza dos dedos hacia arriba y mantén presionada la pantalla."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Para cambiar de función, desliza tres dedos hacia arriba y mantén presionada la pantalla."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliación"</string>
     <string name="user_switched" msgid="7249833311585228097">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="user_switching_message" msgid="1912993630661332336">"Cambiando a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -2026,7 +2026,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> y <xliff:g id="COUNT_3">%d</xliff:g> archivos más</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> y <xliff:g id="COUNT_1">%d</xliff:g> archivo más</item>
     </plurals>
-    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"No hay personas recomendadas para compartir"</string>
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"No hay personas recomendadas con las que compartir"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de apps"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Aunque no se le otorgó permiso de grabación a esta app, puede capturar audio con este dispositivo USB."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Página principal"</string>
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversación"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversación en grupo"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"+<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Trabajo"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vista personal"</string>
@@ -2062,112 +2063,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Las apps de trabajo no pueden abrir este contenido"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Las apps personales no pueden admitir este contenido"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Las apps personales no pueden abrir este contenido"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo de red de tarjeta SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo de subconjunto de redes de tarjeta SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo de tarjeta SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"PIN de desbloqueo de proveedor de servicios de tarjeta SIM"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"PIN de desbloqueo de tarjeta SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN de desbloqueo del dispositivo para la red de tarjeta SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN de desbloqueo del dispositivo para el subconjunto de redes de tarjeta SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN de desbloqueo corporativo del dispositivo para tarjeta SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"PIN de desbloqueo del dispositivo para el proveedor de servicios de tarjeta SIM"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"PIN de desbloqueo del dispositivo para tarjeta SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"Ingresar PUK"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"PIN de desbloqueo de red1 de RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"PIN de desbloqueo del RUIM de network2"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"PIN de desbloqueo de HRPD de RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"PIN de desbloqueo corporativo de RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"PIN de desbloqueo de proveedor de servicios de RUIM"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"PIN de desbloqueo de RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"PIN de desbloqueo del dispositivo para Network1 de RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"PIN de desbloqueo del dispositivo para Network2 de RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"PIN de desbloqueo del dispositivo para la red HRPD"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"PIN de desbloqueo corporativo del dispositivo para RUIM"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"PIN de desbloqueo del dispositivo para el proveedor de servicios de RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"PIN de desbloqueo del dispositivo para RUIM"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"Ingresar PUK"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"Ingresar PUK"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"PIN de desbloqueo de SPN"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"PIN de desbloqueo de PLMN del SP equivalente a la de hogar"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"PIN de desbloqueo de ICCID"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"PIN de desbloqueo de IMPI"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"PIN de desbloqueo de proveedor de servicios de subconjunto de redes"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"Solicitando desbloqueo de red de tarjeta SIM…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"Solicitando desbloqueo de subconjunto de redes de tarjeta SIM…"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"Solicitando desbloqueo de proveedor de servicios de tarjeta SIM…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Solicitando desbloqueo corporativo de tarjeta SIM…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"Solicitando desbloqueo de tarjeta SIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"Solicitando desbloqueo de red1 de RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"Solicitando desbloqueo de red2 de RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"Solicitando desbloqueo de HRPD de RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"Solicitando desbloqueo de proveedor de servicios de RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Solicitando desbloqueo corporativo de RUIM…"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"Solicitando desbloqueo de SPN…"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"Solicitando desbloqueo de PLMN del SP equivalente a la de hogar…"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"Solicitando desbloqueo de ICCID…"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"Solicitando desbloqueo de IMPI…"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Solicitando desbloqueo de proveedor de servicios de subconjunto de redes…"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"Solicitando desbloqueo de RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"Solicitando desbloqueo de PUK…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"Se produjo un error al solicitar el desbloqueo de red de tarjeta SIM."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"Se produjo un error al solicitar el desbloqueo de subconjunto de redes de tarjeta SIM."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Se produjo un error al solicitar el desbloqueo de proveedor de servicios de tarjeta SIM."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Solicitud de desbloqueo corporativo de tarjeta SIM incorrecta."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"Solicitud de desbloqueo de tarjeta SIM incorrecta."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"Se produjo un error al solicitar el desbloqueo de red1 de RUIM."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"Se produjo un error al desbloquear el RUIM de Network2."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"Se produjo un error al solicitar el desbloqueo de HRPD de RUIM."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Se produjo un error al solicitar el desbloqueo corporativo de RUIM."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"Se produjo un error al solicitar el desbloqueo del proveedor de servicios de RUIM."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"Se produjo un error al desbloquear el RUIM."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"Se produjo un error al desbloquear el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"Se produjo un error al solicitar el desbloqueo de SPN incorrecta."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"Se produjo un error al solicitar el desbloqueo de PLMN del SP equivalente a la de hogar."</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"Se produjo un error al solicitar el desbloqueo de ICCID."</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"Se produjo un error al desbloquear el IMPI."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Se produjo error al solicitar el desbloqueo de proveedor de servicios de subconjunto de redes."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"Se desbloqueó correctamente la red de la SIM."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"Se desbloqueó correctamente el subconjunto de redes de tarjeta SIM."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"Se desbloqueó correctamente el proveedor de servicios de tarjeta SIM."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Desbloqueo corporativo de tarjeta SIM correcto."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"Desbloqueo de tarjeta SIM correcto."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"Se desbloqueó correctamente el RUIM de Network1."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"Se desbloqueó correctamente el RUIM de Network 2."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"Se produjo un error al desbloquear el HRPD de RUIM."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"Se desbloqueó correctamente el proveedor de servicios de RUIM."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Se desbloqueó correctamente el RUIM corporativo."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"Se desbloqueó correctamente el RUIM."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"Se desbloqueó correctamente el PUK."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"Desbloqueo de SPN correcto."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"Se desbloqueó correctamente el PLMN del SP equivalente a la de hogar."</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"Se desbloqueó correctamente el ICCID."</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"Se desbloqueó correctamente el IMPI."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"Se desbloqueó correctamente el proveedor de servicios de subconjunto de redes."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"PIN de desbloqueo del dispositivo para un valor SPN"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"PIN de desbloqueo del dispositivo para el SP del EHPLMN"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"PIN de desbloqueo del dispositivo para ICCID"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"PIN de desbloqueo del dispositivo para IMPI"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"PIN de desbloqueo del dispositivo para el proveedor de servicios del subconjunto de redes"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"Solicitando desbloqueo para la red de tarjeta SIM…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"Solicitando desbloqueo para el subconjunto de redes de tarjeta SIM…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"Solicitando desbloqueo para el proveedor de servicios de tarjeta SIM…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Solicitando desbloqueo corporativo para tarjeta SIM…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"Solicitando desbloqueo para tarjeta SIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"Solicitando desbloqueo para Network1 de RUIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"Solicitando desbloqueo para Network2 de RUIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"Solicitando desbloqueo para la red HRPD…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"Solicitando desbloqueo para el proveedor de servicios de RUIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Solicitando desbloqueo corporativo para RUIM…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"Solicitando desbloqueo para un valor de SPN…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"Solicitando desbloqueo para el SP del EHPLMN…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"Solicitando desbloqueo para ICCID…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"Solicitando desbloqueo para IMPI…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Solicitando desbloqueo para el proveedor de servicios del subconjunto de redes…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"Solicitando desbloqueo para RUIM…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"Solicitando desbloqueo con el PUK…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"Se produjo un error al solicitar el desbloqueo del dispositivo para la red de tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"Se produjo un error al solicitar el desbloqueo del dispositivo para el subconjunto de redes de tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Se produjo un error al solicitar el desbloqueo del dispositivo para el proveedor de servicios de tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Se produjo un error al solicitar el desbloqueo corporativo del dispositivo para tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"Se produjo un error al solicitar el desbloqueo del dispositivo para tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"Se produjo un error al solicitar el desbloqueo del dispositivo para Network1 de RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"Se produjo un error al desbloquear el dispositivo para Network2 de RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"Se produjo un error al solicitar el desbloqueo del dispositivo para la red HRPD."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Se produjo un error al solicitar el desbloqueo corporativo del dispositivo para RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"Se produjo un error al solicitar el desbloqueo del dispositivo para el proveedor de servicios de RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"Se produjo un error al solicitar el desbloqueo para RUIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"Se produjo un error al desbloquear el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"Se produjo un error al solicitar el desbloqueo del dispositivo para un valor SPN."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"Se produjo un error al solicitar el desbloqueo del dispositivo para el SP del EHPLMN."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"Se produjo un error al solicitar el desbloqueo del dispositivo para ICCID."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"Se produjo un error al desbloquear el dispositivo para IMPI."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Se produjo un error al solicitar el desbloqueo del dispositivo para el proveedor de servicios del subconjunto de redes."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"Se desbloqueó correctamente el dispositivo para la red de tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"Se desbloqueó correctamente el dispositivo para el subconjunto de redes de tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"Se desbloqueó correctamente el dispositivo para el proveedor de servicios de tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Desbloqueo corporativo exitoso para tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"Se desbloqueó correctamente el dispositivo para tarjeta SIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"Se desbloqueó correctamente el dispositivo para Network1 de RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"Se desbloqueó correctamente Network2 para RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"Se produjo un error al desbloquear el dispositivo para la red HRPD."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"Desbloqueo del proveedor de servicios exitoso para RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Desbloqueo corporativo exitoso para RUIM."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"Se desbloqueó correctamente el dispositivo para RUIM."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"Se desbloqueó correctamente el dispositivo con el PUK."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"Se desbloqueó correctamente el dispositivo para un valor de SPN."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"Se desbloqueó correctamente el dispositivo para el SP del EHPLMN."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"Se desbloqueó correctamente el dispositivo para ICCID."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"Se desbloqueó correctamente el dispositivo para IMPI."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"Se desbloqueó correctamente el dispositivo para el proveedor de servicios del subconjunto de redes."</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d4dafdf..197a47c 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversación"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversación de grupo"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Trabajo"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Ver contenido personal"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 26d9187..2e9ea38 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Vestlus"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupivestlus"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Isiklik"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Töö"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Isiklik vaade"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index e2e4433..9af4b68 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Ez da onartzen <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Gailuak ez du <xliff:g id="NAME">%s</xliff:g> onartzen. Sakatu onartzen den formatu batean konfiguratzeko."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Gailuak ez du <xliff:g id="NAME">%s</xliff:g> onartzen. Hauta ezazu onartzen den formatu batean konfiguratzeko."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Gailuak ez du onartzen <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ustekabean kendu da"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Kendu aurretik, kanporatu euskarria edukirik ez galtzeko"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Kendu egin da <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Elkarrizketa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Taldeko elkarrizketa"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Pertsonala"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Lanekoa"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Ikuspegi pertsonala"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 710950b..e25dc34 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> پشتیبانی نشده"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"این دستگاه از این <xliff:g id="NAME">%s</xliff:g> پشتیبانی نمی‌کند. برای نصب آن در قالب پشتیبانی‌شده ضربه بزنید."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"این دستگاه از این <xliff:g id="NAME">%s</xliff:g> پشتیبانی نمی‌کند. برای تنظیم در یک قالب پشتیبانی‌شده، آن را انتخاب کنید."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"این دستگاه از این <xliff:g id="NAME">%s</xliff:g> پشتیبانی نمی‌کند."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> به‌طور غیرمنتظره جدا شد"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"برای جلوگیری از از دست رفتن محتوا، رسانه را قبل از برداشتن بیرون برانید"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> برداشته شد"</string>
@@ -2045,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"مکالمه"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"مکالمه گروهی"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"+<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"شخصی"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"کاری"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"نمای شخصی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6883b23..b62d8b0 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Epäyhteensopiva <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"<xliff:g id="NAME">%s</xliff:g> ei ole yhteensopiva tämän laitteen kanssa. Ota se käyttöön tuetussa tilassa napauttamalla."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Tämä laite ei tue laitetta <xliff:g id="NAME">%s</xliff:g>. Valitse laite, niin voit suorittaa määrityksen tuetussa muodossa."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"<xliff:g id="NAME">%s</xliff:g> ei ole yhteensopiva tämän laitteen kanssa."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> poistettiin yllättäen"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Poista media ennen sen irrottamista, niin et menetä sisältöä."</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> poistettu"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Keskustelu"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Ryhmäkeskustelu"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Henkilökohtainen"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Työ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Henkilökohtainen näkymä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0e64840..84c1c18 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g> :"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversation de groupe"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personnel"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Bureau"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Affichage personnel"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 0a310f8..1de01a3 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g> :"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversation de groupe"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personnel"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Professionnel"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vue personnelle"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index ad3f478..1f6e4d7 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversa de grupo"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Persoal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Traballo"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vista persoal"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 90c23f8d..29a9847 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -237,10 +237,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"ફોન વિકલ્પો"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"સ્ક્રીન લૉક"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"પાવર બંધ"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"પાવર"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"ફરી શરૂ કરો"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"કટોકટી"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"બગ રિપોર્ટ"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"સત્ર સમાપ્ત કરો"</string>
@@ -299,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"તમારા સંપર્કોને ઍક્સેસ કરવાની"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"સ્થાન"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"આ ઉપકરણના સ્થાનને ઍક્સેસ કરવાની"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"કૅલેન્ડર"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"તમારા કેલેન્ડરને ઍક્સેસ કરવાની"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS સંદેશા મોકલવાની અને જોવાની"</string>
@@ -440,8 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"ચિત્રો અને વિડિઓઝ લો"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"આ ઍપ્લિકેશન, કૅમેરાનો ઉપયોગ કરીને કોઈપણ સમયે ચિત્રો લઈ અને વિડિઓઝ રેકોર્ડ કરી શકે છે."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"ઍપ્લિકેશન અથવા સેવા ઍક્સેસને સિસ્ટમ કૅમેરાનો ઉપયોગ કરીને ફોટા અને વીડિયો લેવાની મંજૂરી આપો"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"આ વિશેષાધિકૃત અથવા સિસ્ટમ ઍપ કોઈપણ સમયે સિસ્ટમ કૅમેરાનો ઉપયોગ કરીને ફોટા લઈ અને વીડિયો રેકૉર્ડ કરી શકે છે. ઍપ દ્વારા આયોજિત કરવા માટે android.permission.CAMERAની પરવાનગી પણ જરૂરી છે"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"કૅમેરા ડિવાઇસ ચાલુ કે બંધ થવા વિશે કૉલબૅક પ્રાપ્ત કરવાની ઍપ્લિકેશન કે સેવાને મંજૂરી આપો."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"જ્યારે કોઈ કૅમેરા ડિવાઇસ (કયા ઍપ્લિકેશન વડે) ખોલવા કે બંધ કરવામાં આવે, ત્યારે આ ઍપ કૉલબૅક પ્રાપ્ત કરી શકે છે."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"વાઇબ્રેશન નિયંત્રિત કરો"</string>
@@ -1354,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"અસમર્થિત <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"આ ઉપકરણ આ <xliff:g id="NAME">%s</xliff:g> નું સમર્થન કરતું નથી. સમર્થિત ફોર્મેટમાં સેટ કરવા માટે ટૅપ કરો."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"આ ઉપકરણ આ <xliff:g id="NAME">%s</xliff:g> નું સમર્થન કરતું નથી. સમર્થિત ફૉર્મેટમાં સેટ કરવા માટે પસંદ કરો."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"આ ડિવાઇસમાં આ <xliff:g id="NAME">%s</xliff:g> માટે સુવિધા નથી."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> અનપેક્ષિત રીતે દૂર કર્યું"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"કન્ટેન્ટ ગુમાવવાનું ટાળવા માટે મીડિયાને દૂર કરતા પહેલાં બહાર કાઢો"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> કાઢી નાખ્યું"</string>
@@ -1623,24 +1619,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ભલામણ કરેલ સ્તરની ઉપર વૉલ્યૂમ વધાર્યો?\n\nલાંબા સમય સુધી ઊંચા અવાજે સાંભળવું તમારી શ્રવણક્ષમતાને નુકસાન પહોંચાડી શકે છે."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ઍક્સેસિબિલિટી શૉર્ટકટનો ઉપયોગ કરીએ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે."</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ઍક્સેસિબિલિટી સુવિધાઓ ચાલુ કરીએ?"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધાઓ ચાલુ થઈ જાય છે. આનાથી તમારા ડિવાઇસની કામ કરવાની રીત બદલાઈ શકે છે.\n\nવર્તમાન સુવિધાઓ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nતમે સેટિંગ &gt; ઍક્સેસિબિલિટીમાં જઈને પસંદ કરેલી સુવિધાઓને બદલી શકો છો."</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"ટૉકબૅક ચાલુ કરીએ?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ટૉકબૅક ચાલુ થઈ જાય છે, જે એક સ્ક્રીન રીડર છે કે જે દૃષ્ટિહીન અથવા ઓછી દૃષ્ટિવાળા લોકોને સહાયરૂપ થઈ શકે છે. ટૉકબૅકથી તમારા ડિવાઇસની કામ કરવાની રીત પૂર્ણપણે બદલાઈ જાય છે.\n\nતમે સેટિંગ &gt; ઍક્સેસિબિલિટીમાં જઈને આ શૉર્ટકટને બીજી સુવિધામાં બદલી શકો છો."</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g>ને ચાલુ કરીએ?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા એવી <xliff:g id="SERVICE">%1$s</xliff:g> ચાલુ થઈ જાય છે. આનાથી તમારા ડિવાઇસની કામ કરવાની રીત બદલાઈ શકે છે.\n\nતમે સેટિંગ &gt; ઍક્સેસિબિલિટીમાં જઈને આ શૉર્ટકટને બીજી સુવિધામાં બદલી શકો છો."</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ચાલુ કરો"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ચાલુ કરશો નહીં"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"શું <xliff:g id="SERVICE">%1$s</xliff:g>ને તમારા ડિવાઇસના સંપૂર્ણ નિયંત્રણની મંજૂરી આપીએ?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"જો તમે <xliff:g id="SERVICE">%1$s</xliff:g> ચાલુ કરશો, તો તમારું ડિવાઇસ ડેટા એન્ક્રિપ્શનને બહેતર બનાવવા તમારા સ્ક્રીન લૉકનો ઉપયોગ કરશે નહીં."</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"ઍક્સેસિબિલિટી સંબંધિત આવશ્યકતા માટે સહાય કરતી ઍપ માટે સંપૂર્ણ નિયંત્રણ યોગ્ય છે, પણ મોટા ભાગની ઍપ માટે યોગ્ય નથી."</string>
@@ -1651,10 +1638,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"મંજૂરી આપો"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"નકારો"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"સુવિધાનો ઉપયોગ શરૂ કરવા તેના પર ટૅપ કરો:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ઍક્સેસિબિલિટી બટન વડે તમે ઉપયોગમાં લેવા માગો છો તે સુવિધાઓ પસંદ કરો"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"વૉલ્યૂમ કી શૉર્ટકટ વડે તમે ઉપયોગમાં લેવા માગો છો તે સુવિધાઓ પસંદ કરો"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> બંધ કરવામાં આવ્યું છે"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"શૉર્ટકટમાં ફેરફાર કરો"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"થઈ ગયું"</string>
@@ -1662,23 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"રંગનો વ્યુત્ક્રમ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"રંગ સુધારણા"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>નો ઉપયોગ કરવા માટે બન્ને વૉલ્યૂમ કીને ત્રણ સેકન્ડ સુધી દબાવી રાખો"</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"જ્યારે તમે ઍક્સેસિબિલિટી બટન પર ટૅપ કરો, ત્યારે ઉપયોગ કરવાની સુવિધા પસંદ કરો:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ઍક્સેસિબિલિટી સંકેત સાથે ઉપયોગ કરવાની સુવિધા પસંદ કરો (બે આંગળીઓ વડે સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરવા માટે):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ઍક્સેસિબિલિટી સંકેત સાથે ઉપયોગ કરવાની સુવિધા પસંદ કરો (ત્રણ આંગળીઓ વડે સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરવા માટે):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"કોઈ એક સુવિધાથી બીજી સુવિધા પર સ્વિચ કરવા માટે, ઍક્સેસિબિલિટી બટનને ટચ કરીને થોડીવાર દબાવી રાખો."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"કોઈ એક સુવિધાથી બીજી સુવિધા પર સ્વિચ કરવા માટે, બે આંગળીઓ વડે સ્ક્રીનની ઉપરની તરફ સ્વાઇપ કરીને દબાવી રાખો."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"કોઈ એક સુવિધાથી બીજી સુવિધા પર સ્વિચ કરવા માટે, ત્રણ આંગળીઓ વડે સ્ક્રીનની ઉપરની તરફ સ્વાઇપ કરીને દબાવી રાખો."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"વિસ્તૃતીકરણ"</string>
     <string name="user_switched" msgid="7249833311585228097">"વર્તમાન વપરાશકર્તા <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> પર સ્વિચ કરી રહ્યાં છે…"</string>
@@ -2049,8 +2026,7 @@
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ફાઇલ</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ફાઇલ</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"શેર કરવા માટે સૂચન આપવામાં આવેલા કોઈ લોકો નથી"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ઍપની સૂચિ"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"આ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફતે ઑડિયો કૅપ્ચર કરી શકે છે."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"હોમ"</string>
@@ -2068,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"વાતચીત"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ગ્રૂપ વાતચીત"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"વ્યક્તિગત"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"કાર્યાલય"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"વ્યક્તિગત વ્યૂ"</string>
@@ -2086,220 +2064,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"કોઈ ઑફિસ માટેની ઍપ આ કન્ટેન્ટ ખોલી શકતી નથી"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"કોઈ વ્યક્તિગત ઍપ આ કન્ટેન્ટને સપોર્ટ કરી શકતી નથી"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"કોઈ વ્યક્તિગત ઍપ આ કન્ટેન્ટ ખોલી શકતી નથી"</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"સિમ નેટવર્કને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"સિમ નેટવર્ક સબસેટને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"સિમ કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"સિમ સેવા પ્રદાતાના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"સિમને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM network1ના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM network2ના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM hrpdને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"RUIM કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM સેવા પ્રદાતાના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIMના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK દાખલ કરો"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPNને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP Equivalent Home PLMNને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCIDને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPIને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"નેટવર્ક સબસેટ સેવા પ્રદાતાના લૉકને અનલૉક કરવાનો પિન"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"સિમ નેટવર્કને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"સિમ નેટવર્ક સબસેટને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"સિમ સેવા પ્રદાતાના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"સિમ કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"સિમને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM network1ના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM network2ના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM hrpdને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM સેવા પ્રદાતાના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPNને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP Equivalent Home PLMNને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCIDને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPIને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"નેટવર્ક સબસેટ સેવા પ્રદાતાના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIMના લૉકને અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK વડે અનલૉક કરવાની વિનંતી કરી રહ્યાં છીએ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"સિમ નેટવર્કને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"સિમ નેટવર્ક સબસેટને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"સિમ સેવા પ્રદાતાના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"સિમ કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"સિમને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM Network1ના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM Network2ના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpdને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાની વિનંતી નિષ્ફળ રહી."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM સેવા પ્રદાતાના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIMના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK વડે અનલૉક કરવાનું નિષ્ફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPNને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMNને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCIDને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPIને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"નેટવર્ક સબસેટ સેવા પ્રદાતાના લૉકને અનલૉક કરવાની વિનંતી અસફળ રહી."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"સિમ નેટવર્કને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"સિમ નેટવર્ક સબસેટને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"સિમ સેવા પ્રદાતાના લૉકને અનલૉક કરવાનું સફળ રહ્યું ."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"સિમ કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"સિમને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM Network1ના લૉકને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM Network2ના લૉકને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpdને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM સેવા પ્રદાતાના લૉકને અનલૉક કરવાનું અસફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM કૉર્પોરેટ કાર્ડના લૉકને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIMના લૉકને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK વડે અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPNને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP Equivalent Home PLMNને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCIDને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPIને અનલૉક કરવાનું સફળ રહ્યું."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"નેટવર્ક સબસેટ સેવા પ્રદાતાના લૉકને અનલૉક કરવાનું સફળ રહ્યું."</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 862f29b..cd6eec1 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -438,7 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"चित्र और वीडियो लें"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"यह ऐप्लिकेशन किसी भी समय कैमरे का उपयोग करके चित्र ले सकता है और वीडियो रिकॉर्ड कर सकता है."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"तस्वीरें और वीडियो लेने के लिए ऐप्लिकेशन या सेवा को सिस्टम के कैमरे का ऐक्सेस दें"</string>
-    <string name="permdesc_systemCamera" msgid="5938360914419175986">"यह खास या सिस्टम ऐप्लिकेशन जब चाहे, तस्वीरें लेने और वीडियो रिकॉर्ड करने के लिए सिस्टम के कैमरे का इस्तेमाल कर सकता है. इसके लिए ऐप्लिकेशन को android.permission.CAMERA की अनुमति देना भी ज़रूरी है"</string>
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"यह खास सिस्टम ऐप्लिकेशन जब चाहे, तस्वीरें लेने और वीडियो रिकॉर्ड करने के लिए सिस्टम के कैमरे का इस्तेमाल कर सकता है. इसके लिए ऐप्लिकेशन को android.permission.CAMERA की अनुमति देना भी ज़रूरी है"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"डिवाइस का कैमरे चालू या बंद होने पर, किसी ऐप्लिकेशन या सेवा को कॉलबैक पाने की मंज़ूरी दें."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"यह ऐप्लिकेशन, डिवाइस के कैमरे को चालू या बंद करते समय (किसी ऐप्लिकेशन से) कॉलबैक पा सकता है."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"कंपन (वाइब्रेशन) को नियंत्रित करें"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"असमर्थित <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"यह डिवाइस इस <xliff:g id="NAME">%s</xliff:g> का समर्थन नहीं करता है. समर्थित प्रारूप में सेट करने के लिए टैप करें."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"इस डिवाइस पर <xliff:g id="NAME">%s</xliff:g> काम नहीं करता है. काम करने वाले प्रारूप में सेट अप करने के लिए चुनें."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"इस डिवाइस पर <xliff:g id="NAME">%s</xliff:g> काम नहीं करता."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> अप्रत्याशित रूप से निकाला गया"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"पहले मीडिया डिवाइस निकालने का विकल्प चुनें, फिर उसे निकालें ताकि आपकी सामग्री सुरक्षित रहे"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> निकाला गया."</string>
@@ -1624,7 +1623,7 @@
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से सुलभता सुविधाएं चालू हो जाती हैं. ऐसा करने से आपके डिवाइस के काम करने के तरीके में बदलाव हो सकता है.\n\nमौजूदा सुविधाएं:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nआप सेटिंग और सुलभता में जाकर चुनी हुई सुविधाएं बदल सकते हैं."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"टॉकबैक की सुविधा चालू करना चाहते हैं?"</string>
-    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से टॉकबैक चालू हो जाती है. यह एक स्क्रीन रीडर है जो दृष्टिहीन और कम दृष्टि वाले व्यक्तियों के लिए उपयोगी होती है. टॉकबैक की सुविधा चालू करने से आपके डिवाइस के काम करने का तरीका पूरी तरह से बदल जाता है.\n\nआप सेटिंग और सुलभता में जाकर इस शॉर्टकट को किसी दूसरी सुविधा के लिए बदल सकते हैं."</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से टॉकबैक की सुविधा चालू हो जाती है. यह एक स्क्रीन रीडर है जो दृष्टिहीन और कम दृष्टि वाले व्यक्तियों के लिए उपयोगी होती है. टॉकबैक की सुविधा चालू करने से आपके डिवाइस के काम करने का तरीका पूरी तरह से बदल जाता है.\n\nआप सेटिंग और सुलभता में जाकर इस शॉर्टकट को किसी दूसरी सुविधा के लिए बदल सकते हैं."</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> चालू करना चाहते हैं?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से <xliff:g id="SERVICE">%1$s</xliff:g> चालू हो जाती है, जो एक सुलभता सुविधा है. ऐसा करने से आपके डिवाइस के काम करने के तरीके में बदलाव हो सकता है.\n\nआप सेटिंग और सुलभता में जाकर इस शॉर्टकट को किसी दूसरी सुविधा के लिए बदल सकते हैं."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"चालू करें"</string>
@@ -1648,15 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट का उपयोग करें"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"रंग बदलने की सुविधा"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"रंग में सुधार करने की सुविधा"</string>
-    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले बटन को दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
-    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले बटन को दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> इस्तेमाल करने के लिए आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें"</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"सुलभता बटन पर टैप करके, इस्तेमाल करने के लिए सुविधा चुनें:"</string>
-    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"सुलभता वाले जेस्चर के साथ इस्तेमाल करने के लिए सुविधा चुनें (दो उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
-    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"सुलभता वाले जेस्चर के साथ इस्तेमाल करने के लिए सुविधा चुनें (तीन उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"सुलभता वाले हाथ के जेस्चर (हाव-भाव) के साथ इस्तेमाल करने के लिए सुविधा चुनें (दो उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"सुलभता वाले हाथ के जेस्चर (हाव-भाव) के साथ इस्तेमाल करने के लिए सुविधा चुनें (तीन उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"एक सुविधा से दूसरी सुविधा पर जाने के लिए, सुलभता बटन दबाकर रखें."</string>
-    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"एक सुविधा से दूसरी सुविधा पर जाने के लिए, स्क्रीन पर दो उंगलियों से ऊपर की ओर स्वाइप करें और थोड़ी देर तक स्क्रीन पर उंगलियां रखे रहें."</string>
-    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"एक सुविधा से दूसरी सुविधा पर जाने के लिए, स्क्रीन पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और थोड़ी देर तक स्क्रीन पर उंगलियां रखे रहें."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"एक सुविधा से दूसरी सुविधा पर जाने के लिए, स्क्रीन पर दो उंगलियों से ऊपर की ओर स्वाइप करें और थोड़ी देर तक उंगलियां स्क्रीन पर रखे रहें."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"एक सुविधा से दूसरी सुविधा पर जाने के लिए, स्क्रीन पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और थोड़ी देर तक उंगलियां स्क्रीन पर रखे रहें."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"बड़ा करना"</string>
     <string name="user_switched" msgid="7249833311585228097">"मौजूदा उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> पर स्विच किया जा रहा है…"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"बातचीत"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ग्रुप में बातचीत"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"निजी प्रोफ़ाइल"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"वर्क प्रोफ़ाइल"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"निजी व्यू"</string>
@@ -2064,7 +2065,7 @@
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"इस सामग्री का इस्तेमाल, किसी भी निजी ऐप्लिकेशन पर नहीं किया जा सकता"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"किसी भी निजी ऐप्लिकेशन का इस्तेमाल करके, इस सामग्री को खोला नहीं जा सकता"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"सिम नेटवर्क को अनलॉक करने का पिन"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"सिम नेटवर्क के सबसेट को अनलॉक नहीं किया जा सका"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"सिम नेटवर्क के सबसेट को अनलॉक करने का पिन"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"कारोबार के लिए इस्तेमाल होने वाले सिम को अनलॉक करने का पिन"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"सिम नेटवर्क को अनलॉक करने का पिन"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"सिम को अनलॉक करने का पिन"</string>
@@ -2151,7 +2152,7 @@
     <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"सिम को अनलॉक किया गया."</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM कार्ड के network1 को अनलॉक किया गया."</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM कार्ड के network2 को अनलॉक किया गया."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"hrpd नेटवर्क वाले RUIM कार्ड को अनलॉक किया गया."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"Hrpd नेटवर्क वाले RUIM कार्ड को अनलॉक किया गया."</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM कार्ड की सेवा देने वाली कंपनी के लॉक को अनलॉक किया गया."</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"कारोबार के लिए इस्तेमाल होने वाले RUIM कार्ड को अनलॉक किया गया."</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM कार्ड को अनलॉक किया गया."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index cfd4ff0..94ff54c 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -2078,6 +2078,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Razgovor"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupni razgovor"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Osobno"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Posao"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Osobni prikaz"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 31589df..30a75dc 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Beszélgetés"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Csoportos beszélgetés"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Személyes"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Munka"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Személyes nézet"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 85e2a98..21aa148 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>՝"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Նամակագրություն"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Խմբային նամակագրություն"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Անձնական"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Աշխատանքային"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Անձնական"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 01dbf05..9f3c5a7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -484,8 +484,8 @@
     <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Memungkinkan aplikasi mendapatkan daftar akun yang dikenal oleh tablet. Ini mungkin termasuk akun yang dibuat oleh aplikasi yang telah Anda instal."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Mengizinkan aplikasi mendapatkan daftar akun yang dikenal oleh perangkat Android TV. Ini mungkin mencakup akun yang dibuat oleh aplikasi yang telah Anda instal."</string>
     <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Memungkinkan aplikasi mendapatkan daftar akun yang dikenal oleh ponsel. Ini mungkin termasuk akun yang dibuat oleh aplikasi yang telah Anda instal."</string>
-    <string name="permlab_accessNetworkState" msgid="2349126720783633918">"lihat sambungan jaringan"</string>
-    <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Memungkinkan aplikasi melihat informasi tentang sambungan jaringan, misalnya jaringan yang ada dan tersambung."</string>
+    <string name="permlab_accessNetworkState" msgid="2349126720783633918">"lihat koneksi jaringan"</string>
+    <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Memungkinkan aplikasi melihat informasi tentang koneksi jaringan, misalnya jaringan yang ada dan tersambung."</string>
     <string name="permlab_createNetworkSockets" msgid="3224420491603590541">"dapatkan akses jaringan penuh"</string>
     <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Memungkinkan aplikasi membuat soket jaringan dan menggunakan protokol jaringan khusus. Browser dan aplikasi lain menyediakan sarana untuk mengirim data ke internet sehingga izin ini tidak diperlukan untuk mengirim data ke internet."</string>
     <string name="permlab_changeNetworkState" msgid="8945711637530425586">"ubah konektivitas jaringan"</string>
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Percakapan"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Percakapan Grup"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Pribadi"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Kerja"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Tampilan pribadi"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index f12d0de..6f2deee 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1623,7 +1623,7 @@
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Kveikt er á aðgengiseiginleikum þegar báðum hljóðstyrkstökkunum er haldið inni í nokkrar sekúndur. Þetta getur breytt því hvernig tækið virkar.\n\nNúverandi eiginleikar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nÞú getur breytt völdum eiginleikum í Stillingar &gt; Aðgengi."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"Viltu kveikja á TalkBack?"</string>
-    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"Ef báðum hljóðstyrkstökkunum er haldið niðri í nokkrar sekúndur er kveikt á TalkBack, sem er skjálesari sem gagnast blindum eða sjónskertum einstaklingum. TalkBack breytir því algjörlega hvernig tækið virkar.\n\nÞú getur breytt þessari flýtileið í annan eiginleika í Stillingar &gt; Aðgengi."</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"Ef báðum hljóðstyrkstökkunum er haldið niðri í nokkrar sekúndur er kveikt á skjálesaranum TalkBack sem gagnast blindum eða sjónskertum. TalkBack breytir því algjörlega hvernig tækið virkar.\n\nÞú getur breytt þessari flýtileið í annan eiginleika í Stillingar &gt; Aðgengi."</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"Viltu kveikja á <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ef báðum hljóðstyrkstökkunum er haldið inni í nokkrar sekúndur er kveikt á aðgengiseiginleikanum <xliff:g id="SERVICE">%1$s</xliff:g>. Þetta getur breytt því hvernig tækið virkar.\n\nÞú getur breytt þessari flýtileið í annan eiginleika í Stillingar &gt; Aðgengi."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Kveikja"</string>
@@ -2026,7 +2026,7 @@
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> skrá</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> skrá</item>
     </plurals>
-    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Engir einstaklingar sem mælt er með að deila með"</string>
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Engar tillögur um einstaklinga til að deila með"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Forritalisti"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Þetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Heim"</string>
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Samtal"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Hópsamtal"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Persónulegt"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Vinna"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persónulegt yfirlit"</string>
@@ -2062,20 +2064,20 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"Engin vinnuforrit geta opnað þetta efni"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"Engin forrit til einkanota styðja þetta efni"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Engin forrit til einkanota geta opnað þetta efni"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-númer fyrir opnun SIM netkerfis"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-númer fyrir opnun SIM netkerfishlutmengis"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-númer til að opna SIM fyrirtækis"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"PIN-númer fyrir opnun SIM þjónustuaðila"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN-númer fyrir opnun á SIM-korti netkerfis"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN-númer fyrir opnun á SIM-korti netkerfishlutmengis"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN-númer fyrir opnun á SIM-korti fyrirtækis"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"PIN-númer fyrir opnun þjónustuaðila SIM"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"PIN-númer fyrir opnun SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"Slá inn PUK-númer"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"Slá inn PUK-númer"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"Slá inn PUK-númer"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"Slá inn PUK-númer"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"Slá inn PUK-númer"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"PIN-númer fyrir opnun RUIM netkerfis 1"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"PIN-númer fyrir opnun RUIM netkerfis 2"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"PIN-númer fyrir opnun á RUIM-korti netkerfis 1"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"PIN-númer fyrir opnun á RUIM-korti netkerfis 2"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"PIN-númer fyrir opnun RUIM hrpd"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"PIN-númer fyrir opnun RUIM fyrirtækis"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"PIN-númer fyrir opnun á RUIM-korti fyrirtækis"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"PIN-númer fyrir opnun þjónustuaðila RUIM"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"PIN-númer fyrir opnun RUIM"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"Slá inn PUK-númer"</string>
@@ -2089,82 +2091,82 @@
     <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"PIN-númer fyrir opnun ICCID"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"PIN-númer fyrir opnun IMPI"</string>
     <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"PIN-númer fyrir opnun þjónustuaðila netkerfishlutmengis"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"Biður um opnun SIM netkerfis…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"Biður um opnun SIM netkerfishlutmengis…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"Biður um opnun á SIM-korti netkerfis…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"Biður um opnun á SIM-korti netkerfishlutmengis…"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"Biður um opnun þjónustuaðila SIM…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Biður um opnun SIM fyrirtækis…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"Biður um PUK-opnun…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Biður um opnun á SIM-korti fyrirtækis…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"Biður um opnun með PUK-númeri…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"Biður um opnun SIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"Biður um opnun RUIM netkerfis 1…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"Biður um opnun RUIM netkerfis 2…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"Biður um opnun á RUIM-korti netkerfis 1…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"Biður um opnun á RUIM-korti netkerfis 2…"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"Biður um opnun RUIM hrpd…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"Biður um opnun þjónustuaðila RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Biður um opnun RUIM fyrirtækis…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Biður um opnun á RUIM-korti fyrirtækis…"</string>
     <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"Biður um opnun SPN…"</string>
     <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"Biður um opnun SP Equivalent Home PLMN…"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"Biður um opnun ICCID…"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"Biður um opnun IMPI…"</string>
     <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Biður um opnun þjónustuaðila netkerfishlutmengis…"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"Biður um opnun RUIM…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"Biður um PUK-opnun…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"Beiðni um opnun SIM netkerfis tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"Beiðni um opnun SIM netkerfishlutmengis tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Beiðni um opnun þjónustuaðila SIM tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Beiðni um opnun SIM fyrirtækis tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"Beiðni um opnun SIM tókst ekki."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"Beiðni um opnun RUIM netkerfis 1 tókst ekki."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"Beiðni um opnun RUIM netkerfis 2 tókst ekki."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"Biður um opnun með PUK-númeri…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"Beiðni um opnun á SIM-korti netkerfis mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"Beiðni um opnun á SIM-korti netkerfishlutmengis mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Beiðni um opnun þjónustuaðila SIM mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Beiðni um opnun á SIM-korti fyrirtækis mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"Beiðni um opnun SIM mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"Beiðni um opnun á RUIM-korti netkerfis 1 mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"Beiðni um opnun á RUIM-korti netkerfis 2 mistókst."</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"Beiðni um opnun RUIM Hrpd tókst ekki."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Beiðni um opnun RUIM fyrirtækis tókst ekki."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"Beiðni um opnun þjónustuaðila RUIM tókst ekki."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Beiðni um opnun á RUIM-korti fyrirtækis mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"Beiðni um opnun þjónustuaðila RUIM mistókst."</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"Beiðni um opnun RUIM tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK-opnun mistókst."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"Beiðni um opnun SPN tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"Beiðni um opnun SP Equivalent Home PLMN tókst ekki."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"Opnun með PUK-númeri mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"Beiðni um opnun SPN mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"Beiðni um opnun SP Equivalent Home PLMN mistókst."</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"Beiðni um opnun ICCID tókst ekki."</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"Beiðni um opnun IMPI tókst ekki."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Beiðni um opnun þjónustuaðila netkerfishlutmengis tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"Opnun SIM netkerfis tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"Opnun SIM netkerfishlutmengis tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Beiðni um opnun þjónustuaðila netkerfishlutmengis mistókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"Opnun á SIM-korti netkerfis tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"Opnun á SIM-korti netkerfishlutmengis tókst."</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"Opnun þjónustuaðila SIM tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Opnun SIM fyrirtækis tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Opnun á SIM-korti fyrirtækis tókst."</string>
     <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"Opnun SIM tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"Opnun RUIM netkerfis 1 tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"Opnun RUIM netkerfis 2 tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"Opnun á RUIM-korti netkerfis 1 tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"Opnun á RUIM-korti netkerfis 2 tókst."</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"Opnun RUIM Hrpd tókst."</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"Beiðni um opnun þjónustuaðila RUIM tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Opnun RUIM fyrirtækis tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Opnun á RUIM-korti fyrirtækis tókst."</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"Opnun RUIM tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK-opnun tókst."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK-opnun tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"Opnun með PUK-númeri tókst."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"Opnun með PUK-númeri tókst."</string>
     <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"Opnun SPN tókst."</string>
     <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"Opnun SP Equivalent Home PLMN tókst."</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"Opnun ICCID tókst."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index c577f02..39e5a6e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversazione"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversazione di gruppo"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personale"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Lavoro"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualizzazione personale"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1a95c3b..4b13124 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -2112,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"שיחה"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"שיחה קבוצתית"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"אישי"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"עבודה"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"תצוגה אישית"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index c56e2dc..f31f1c8 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"対応していない<xliff:g id="NAME">%s</xliff:g>です"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"このデバイスはこの <xliff:g id="NAME">%s</xliff:g>に対応していません。タップして、対応している形式でセットアップしてください。"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"このデバイスはこの <xliff:g id="NAME">%s</xliff:g>に対応していません。サポートされるフォーマットで設定するには選択してください。"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"このデバイスはこの <xliff:g id="NAME">%s</xliff:g>に対応していません。"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>が不適切に取り外されました"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"コンテンツの喪失を防ぐため、メディアを取り出してから取り外してください"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g>の取り外し"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"会話"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"グループの会話"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"個人用"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"仕事用"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人用ビュー"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 54a88dd..89de803 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -240,7 +240,7 @@
     <string name="global_action_power_options" msgid="1185286119330160073">"ძალა"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"გადატვირთვა"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"საგანგებო სამსახურები"</string>
-    <string name="global_action_bug_report" msgid="5127867163044170003">"ხარვეზის შესახებ ანგარიში"</string>
+    <string name="global_action_bug_report" msgid="5127867163044170003">"ხარვეზის ანგარიში"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"სესიის დასრულება"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"ეკრანის ანაბეჭდი"</string>
     <string name="bugreport_title" msgid="8549990811777373050">"ხარვეზის ანგარიში"</string>
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"მიმოწერა"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ჯგუფური მიმოწერა"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"პირადი"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"სამსახური"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"პირადი ხედი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 63fe2c5..b5892eb 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -237,7 +237,7 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"Телефон опциялары"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"Экранды құлыптау"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"Өшіру"</string>
-    <string name="global_action_power_options" msgid="1185286119330160073">"Қуат түймесі"</string>
+    <string name="global_action_power_options" msgid="1185286119330160073">"Қуат"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"Қайта қосу"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"Төтенше жағдай"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"Вирус туралы хабарлау"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Қолданылмайтын <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Бұл құрылғы <xliff:g id="NAME">%s</xliff:g> картасына қолдау көрсетеді. Қолдау көрсетілетін пішімде орнату үшін түртіңіз."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Бұл құрылғыда <xliff:g id="NAME">%s</xliff:g> картасына қолдау көрсетілмейді. Қолдау көрсетілетін форматта реттеуді таңдаңыз."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Бұл құрылғы <xliff:g id="NAME">%s</xliff:g> картасын қолдамайды."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> кенеттен шығарылды"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Мазмұнды жоғалтып алмау үшін ақпарат тасығышты алдымен ажыратыңыз, содан кейін барып шығарыңыз."</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> жоқ"</string>
@@ -1621,12 +1620,12 @@
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Арнайы мүмкіндік төте жолын пайдалану керек пе?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Түймелер тіркесімі қосулы кезде, екі дыбыс түймесін 3 секунд басып тұрсаңыз, \"Арнайы мүмкіндіктер\" функциясы іске қосылады."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"Арнайы мүмкіндіктер іске қосылсын ба?"</string>
-    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, арнайы мүмкіндіктер іске қосылады. Бұл – құрылғының жұмысына әсер етуі мүмкін.\n\nФункциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТаңдалған функцияларды \"Параметрлер &gt; Accessibility\" бөлімінен өзгерте аласыз."</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, арнайы мүмкіндіктер іске қосылады. Бұл – құрылғының жұмысына әсер етуі мүмкін.\n\nФункциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТаңдалған функцияларды \"Параметрлер &gt; Арнайы мүмкіндіктер\" бөлімінен өзгерте аласыз."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"TalkBack қосылсын ба?"</string>
-    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз TalkBack қосылады. Бұл – зағип немесе көру қабілеті нашар адамдарға арналған экранды оқу құралы. TalkBack құрылғының жұмыс істеуіне әсер етеді.\n\nБұл таңбашаны басқа функцияға \"Параметрлер &gt; Accessibility\" бөлімінде өзгерте аласыз."</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, TalkBack қосылады. Бұл – зағип немесе көру қабілеті нашар адамдарға арналған экранды оқу құралы. TalkBack құрылғының жұмыс істеуіне әсер етеді.\n\nБұл таңбашаны басқа функцияға \"Параметрлер &gt; Арнайы мүмкіндіктер\" бөлімінде өзгерте аласыз."</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> қосылсын ба?"</string>
-    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, <xliff:g id="SERVICE">%1$s</xliff:g> және арнайы мүмкіндіктер іске қосылады. Бұл – құрылғының жүмысына әсер етуі мүмкін.\n\nБұл таңбашаны басқа функцияға \"Параметрлер &gt; Accessibility\" бөлімінен өзгерте аласыз."</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, <xliff:g id="SERVICE">%1$s</xliff:g> арнайы қызметі іске қосылады. Бұл – құрылғының жүмысына әсер етуі мүмкін.\n\nБұл таңбашаны басқа функцияға \"Параметрлер &gt; Арнайы мүмкіндіктер\" бөлімінен өзгерте аласыз."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Қосылсын"</string>
     <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Қосылмасын"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> қызметі құрылғыңызды толық басқаруына рұқсат етілсін бе?"</string>
@@ -1648,13 +1647,13 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Төте жолды пайдалану"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"Түстер инверсиясы"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"Түсті түзету"</string>
-    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дыбыс деңгейі пернелерін басып ұстап тұрыңыз. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
-    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып ұстап тұрыңыз. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірулі."</string>
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірулі."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін пайдалану үшін дыбыс деңгейін реттейтін екі түймені де 3 секунд басып тұрыңыз"</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"\"Арнайы мүмкіндіктер\" түймесін түрткенде пайдаланатын функцияны таңдаңыз:"</string>
-    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Арнайы мүмкіндіктер қимылымен пайдаланатын функцияны таңдаңыз (екі саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз):"</string>
-    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Арнайы мүмкіндіктер қимылымен пайдаланатын функцияны таңдаңыз (үш саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз):"</string>
-    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Бір функциядан екінші функцияға ауысу үшін арнайы мүмкіндіктер түймесін түртіп, оны ұстап тұрыңыз."</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Арнайы мүмкіндіктер қимылымен (екі саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз) пайдаланатын функцияны таңдаңыз:"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Арнайы мүмкіндіктер қимылымен (үш саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз) пайдаланатын функцияны таңдаңыз:"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Бір функциядан екінші функцияға ауысу үшін \"Арнайы мүмкіндіктер\" түймесін түртіп, оны ұстап тұрыңыз."</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Бір функциядан екінші функцияға ауысу үшін екі саусақпен жоғары қарай сырғытып, ұстап тұрыңыз."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Бір функциядан екінші функцияға ауысу үшін үш саусақпен жоғары қарай сырғытып, ұстап тұрыңыз."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ұлғайту"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Чат"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Топтық чат"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Жеке"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Жұмыс"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Жеке көру"</string>
@@ -2065,9 +2066,9 @@
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"Бұл мазмұнды ешқандай жеке қолданба аша алмайды."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM желісінің құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM желісі ішкі жиынтығының құлпын ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Корпоративтік SIM картасын ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"Қызмет көрсетушінің SIM картасын ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIM картасын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"Корпоративтік SIM картасының құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIM картасының қызмет көрсетушісінің құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIM картасының құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK кодын енгізіңіз"</string>
@@ -2075,100 +2076,100 @@
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM network1 желісінің құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM network2 желісінің құлпын ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM картасының HRPD ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Корпоративтік RUIM картасын ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM картасының қызмет көрсетушісін ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM картасын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM картасының HRPD құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Корпоративтік RUIM картасының құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM картасының қызмет көрсетушісінің құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM картасының құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK кодын енгізіңіз"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK кодын енгізіңіз"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP Equivalent Home PLMN ашатын PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID кодын көрсететін PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI кодын көрсететін PIN коды"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"Қызмет көрсетуші желісінің ішкі жиынтығын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP Equivalent Home PLMN құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI құлпын ашатын PIN коды"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"Қызмет көрсетуші желісінің ішкі жиынтығы құлпын ашатын PIN коды"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIM желісінің құлпын ашу сұралуда…"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"SIM желісі ішкі жиынтығының құлпын ашу сұралуда …"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"Қызмет көрсетушінің SIM картасын ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Корпоративтік SIM картасын ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM картасын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"SIM картасының қызмет көрсетушісінің құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"Корпоративтік SIM картасының құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM картасының құлпын ашу сұралуда…"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM network1 желісінің құлпын ашу сұралуда…"</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM network2 желісінің құлпын ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM картасының HRPD ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM картасының қызмет көрсетушісін ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Корпоративтік RUIM картасын ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP Equivalent Home PLMN ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID кодын көрсету сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI кодын көрсету сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Қызмет көрсетуші желісінің ішкі жиынтығын ашу сұралуда.…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM картасының HRPD құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM картасының қызмет көрсетушісінің құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Корпоративтік RUIM картасының құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP Equivalent Home PLMN құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI құлпын ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Қызмет көрсетуші желісінің ішкі жиынтығы құлпын ашу сұралуда.…"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM картасының құлпын ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK кодымен ашу сұралуда…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM желісінің құлпын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM желісі ішкі жиынтығының құлпын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"Қызмет көрсетушінің SIM картасын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Корпоративтік SIM картасын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM картасын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM Network1 желісінің құлпын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM Network2 желісінің құлпын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM картасының HRPD ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Корпоративтік RUIM картасын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM картасының қызмет көрсетушісін ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM картасын ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK кодымен ашылмады."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN ашу сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID кодын көрсету сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI кодын көрсету сұралмады."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Қызмет көрсетуші желісінің ішкі жиынтығын ашу сұралмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"Құлпын PUK кодымен ашу сұралуда…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM желісінің құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM желісі ішкі жиынтығының құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM картасының қызмет көрсетушісінің құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Корпоративтік SIM картасының құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM картасының құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM Network1 желісінің құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM Network2 желісінің құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM картасының HRPD құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Корпоративтік RUIM картасының құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM картасының қызмет көрсетушісінің құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM картасының құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"Құлпы PUK кодымен ашылмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI құлпын ашу сұрауы орындалмады."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Қызмет көрсетуші желісінің ішкі жиынтығы құлпын ашу сұрауы орындалмады."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"SIM желісінің құлпы ашылды."</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM желісі ішкі жиынтығының құлпы ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"Қызмет көрсетуші SIM картасы ашылмады."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Корпоративтік SIM картасы ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM картасы ашылмады."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM картасының қызмет көрсетушісінің құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Корпоративтік SIM картасының құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM картасының құлпы ашылды."</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM Network1 желісінің құлпы ашылды."</string>
     <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM Network2 желісінің құлпы ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM картасының HRPD ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM картасының қызмет көрсетушісі ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Корпоративтік RUIM картасы ашылмады."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM картасы ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK кодымен ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP Equivalent Home PLMN ашылды."</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID коды көрсетілді."</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI көрсетілді."</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"Қызмет көрсетуші желісінің ішкі жиынтығын ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM картасының HRPD құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM картасының қызмет көрсетушісінің құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Корпоративтік RUIM картасының құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM картасының құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"Құлпы PUK кодымен ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP Equivalent Home PLMN құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI құлпы ашылды."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"Қызмет көрсетуші желісінің ішкі жиынтығы құлпы ашылды."</string>
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index bf420e0..7de5a8b 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -438,7 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"ថត​រូប និងវីដេអូ"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"កម្មវិធី​នេះ​អាច​ថត​រូប​ និង​ថត​វីដេអូ​ ដោយ​ប្រើ​កាមេរ៉ា​បាន​គ្រប់​ពេល​។"</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"អនុញ្ញាតឱ្យកម្មវិធី ឬសេវាកម្ម​ចូលប្រើកាមេរ៉ា​ប្រព័ន្ធ ដើម្បីថតរូប និង​ថតវីដេអូ"</string>
-    <string name="permdesc_systemCamera" msgid="5938360914419175986">"កម្មវិធីប្រព័ន្ធ​ដែលមានសិទ្ធិអនុញ្ញាត​នេះអាចថត​រូប និង​ថតវីដេអូ ដោយប្រើ​កាមេរ៉ា​ប្រព័ន្ធបាន​គ្រប់ពេល។ តម្រូវឱ្យមាន​ការអនុញ្ញាត android.permission.CAMERA ដើម្បីឱ្យ​កម្មវិធីអាចធ្វើ​សកម្មភាព​បានផងដែរ"</string>
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"កម្មវិធីប្រព័ន្ធ ឬកម្មវិធីដែលមានសិទ្ធិអនុញ្ញាត​នេះអាចថត​រូប និង​ថតវីដេអូ ដោយប្រើ​កាមេរ៉ា​ប្រព័ន្ធបាន​គ្រប់ពេល។ តម្រូវឱ្យមាន​ការអនុញ្ញាត android.permission.CAMERA ដើម្បីឱ្យ​កម្មវិធីអាចធ្វើ​សកម្មភាព​បានផងដែរ"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"អនុញ្ញាតឱ្យកម្មវិធី ឬសេវាកម្ម​ទទួលការហៅត្រឡប់វិញអំពី​កាមេរ៉ាដែលកំពុងបិទ ឬបើក។"</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"កម្មវិធី​នេះ​អាច​ទទួល​ការហៅត្រឡប់វិញ​បាន នៅពេល​កំពុងបិទ ឬ​បើក​កាមេរ៉ា (ដោយ​កម្មវិធី)​។"</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"ពិនិត្យ​ការ​ញ័រ"</string>
@@ -1353,8 +1353,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> មិនគាំទ្រ"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ឧបករណ៍នេះមិនគាំទ្រ <xliff:g id="NAME">%s</xliff:g> នេះទេ។ ប៉ះដើម្បីកំណត់ទម្រង់ដែលគាំទ្រ។"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"ឧបករណ៍នេះ​មិន​ស្គាល់ <xliff:g id="NAME">%s</xliff:g> នេះ​ទេ។ សូម​ជ្រើសរើស​ដើម្បី​រៀបចំ​ក្នុង​ទម្រង់ដែលស្គាល់។"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"ឧបករណ៍នេះ​មិនស្គាល់ <xliff:g id="NAME">%s</xliff:g> នេះទេ។"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"បានដក <xliff:g id="NAME">%s</xliff:g> ចេញដោយមិនបានរំពឹងទុក"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"ដក​មេឌៀ​មុន​ពេល​យក​វា​ចេញ ដើម្បី​ជៀសវាង​ការ​បាត់​បង់​ខ្លឹមសារ"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"បានយក <xliff:g id="NAME">%s</xliff:g> ចេញ"</string>
@@ -1656,9 +1655,9 @@
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ជ្រើសរើស​មុខងារ​ដែលត្រូវប្រើ នៅពេល​ដែល​អ្នកចុច​ប៊ូតុង​ភាពងាយស្រួល៖"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ជ្រើសរើស​មុខងារ ដើម្បី​ប្រើជាមួយចលនា​ភាពងាយស្រួល (អូស​ឡើងលើ​ពី​ផ្នែកខាងក្រោម​នៃ​អេក្រង់​ដោយប្រើ​ម្រាមដៃ​ពីរ)៖"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ជ្រើសរើស​មុខងារ ដើម្បី​ប្រើជាមួយ​ចលនា​ភាពងាយស្រួល (អូស​ឡើងលើ​ពី​ផ្នែកខាងក្រោម​នៃ​អេក្រង់​ដោយប្រើ​ម្រាមដៃ​បី)៖"</string>
-    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ដើម្បី​ប្ដូរឆ្លាស់រវាង​មុខងារផ្សេងៗ សូមចុច​ប៊ូតុង​ភាពងាយស្រួល​ឱ្យជាប់។"</string>
-    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ដើម្បី​ប្ដូរឆ្លាស់​រវាង​មុខងារផ្សេងៗ សូមអូស​ឡើងលើ​ដោយប្រើ​ម្រាមដៃ​ពីរ ហើយ​សង្កត់ឱ្យជាប់។"</string>
-    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ដើម្បី​ប្ដូរឆ្លាស់​រវាង​មុខងារផ្សេងៗ សូមអូស​ឡើងលើ​ដោយប្រើ​ម្រាមដៃ​បី ហើយ​សង្កត់ឱ្យជាប់។"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ដើម្បី​ប្ដូររវាង​មុខងារផ្សេងៗ សូមចុច​ប៊ូតុង​ភាពងាយស្រួល​ឱ្យជាប់។"</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ដើម្បី​ប្ដូររវាង​មុខងារផ្សេងៗ សូមអូស​ឡើងលើ​ដោយប្រើ​ម្រាមដៃ​ពីរ ហើយ​សង្កត់ឱ្យជាប់។"</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ដើម្បី​ប្ដូររវាង​មុខងារផ្សេងៗ សូមអូស​ឡើងលើ​ដោយប្រើ​ម្រាមដៃ​បី ហើយ​សង្កត់ឱ្យជាប់។"</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"ការ​ពង្រីក"</string>
     <string name="user_switched" msgid="7249833311585228097">"អ្នក​ប្រើ​បច្ចុប្បន្ន <xliff:g id="NAME">%1$s</xliff:g> ។"</string>
     <string name="user_switching_message" msgid="1912993630661332336">"កំពុង​ប្ដូរ​ទៅ <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -2047,6 +2046,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>៖"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"ការ​សន្ទនា"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ការសន្ទនា​ជាក្រុម"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ផ្ទាល់ខ្លួន"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ការងារ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ទិដ្ឋភាពផ្ទាល់ខ្លួន"</string>
@@ -2075,8 +2076,8 @@
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"បញ្ចូល PUK"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"បញ្ចូល PUK"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"បញ្ចូល PUK"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"កូដ PIN ដោះ​សោ RUIM បណ្ដាញ​ប្រភេទទី 1"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"កូដ PIN ដោះ​សោ RUIM បណ្ដាញ​ប្រភេទទី 2"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"កូដ PIN ដោះ​សោ RUIM បណ្ដាញ​ទី 1"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"កូដ PIN ដោះ​សោ RUIM បណ្ដាញ​ទី 2"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"កូដ PIN ដោះសោ RUIM hrpd"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"កូដ PIN ដោះសោ​ក្រុមហ៊ុន RUIM"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"កូដ PIN ដោះសោ​ក្រុមហ៊ុនផ្ដល់​សេវា RUIM"</string>
@@ -2102,8 +2103,8 @@
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"កំពុង​ស្នើសុំ​ដោះសោ PUK…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"កំពុង​ស្នើសុំ​ដោះសោ PUK…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"កំពុង​ស្នើសុំ​ដោះសោស៊ីម…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"កំពុង​ស្នើសុំ​ដោះសោ RUIM បណ្ដាញ​ប្រភេទទី 1…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"កំពុង​ស្នើសុំ​ដោះសោ RUIM បណ្ដាញ​ប្រភេទទី 2…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"កំពុង​ស្នើសុំ​ដោះសោ RUIM បណ្ដាញ​ទី 1…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"កំពុង​ស្នើសុំ​ដោះសោ RUIM បណ្ដាញ​ទី 2…"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"កំពុង​ស្នើសុំ​ដោះសោ RUIM hrpd…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"កំពុង​ស្នើសុំ​ដោះសោ​ក្រុមហ៊ុន​ផ្ដល់សេវា RUIM…"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"កំពុង​ស្នើសុំ​ដោះសោ​ក្រុមហ៊ុន RUIM…"</string>
@@ -2124,8 +2125,8 @@
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"សំណើសុំ​ដោះសោ​ក្រុមហ៊ុន​ផ្ដល់សេវាស៊ីម​មិនទទួលបាន​ជោគជ័យទេ។"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"សំណើសុំ​ដោះសោ​ក្រុមហ៊ុនស៊ីម​មិនទទួលបាន​ជោគជ័យ​ទេ។"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"សំណើសុំ​ដោះសោ​ស៊ីម​មិនទទួលបាន​ជោគជ័យ​ទេ។"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"សំណើ​សុំដោះ​សោ RUIM បណ្ដាញ​ប្រភេទទី 1 មិនទទួលបាន​ជោគជ័យ​ទេ។"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"សំណើ​សុំដោះ​សោ RUIM បណ្ដាញ​ប្រភេទទី 2 មិន​ទទួលបាន​ជោគជ័យ​ទេ។"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"សំណើ​សុំដោះ​សោ RUIM បណ្ដាញ​ទី 1 មិនទទួលបាន​ជោគជ័យ​ទេ។"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"សំណើ​សុំដោះ​សោ RUIM បណ្ដាញ​ទី 2 មិន​ទទួលបាន​ជោគជ័យ​ទេ។"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"សំណើសុំ​ដោះសោ RUIM Hrpd មិនបាន​ទទួល​ជោគជ័យទេ។"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"សំណើ​សុំដោះសោ​ក្រុមហ៊ុន RUIM មិន​ទទួលបាន​ជោគជ័យ​ទេ។"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"សំណើសុំ​ដោះសោ​ក្រុមហ៊ុន​ផ្ដល់សេវា RUIM មិនទទួលបាន​ជោគជ័យទេ។"</string>
@@ -2151,8 +2152,8 @@
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"ការដោះសោ​ក្រុមហ៊ុនផ្ដល់សេវា​ស៊ីមទទួលបាន​ជោគជ័យ​ហើយ។"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"ការដោះសោ​ក្រុមហ៊ុន​ស៊ីម​ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"ការដោះសោ​ស៊ីម​ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"ការដោះ​សោ RUIM បណ្ដាញ​ប្រភេទទី 1 ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"ការដោះ​សោ RUIM បណ្ដាញ​ប្រភេទទី 2 ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"ការដោះ​សោ RUIM បណ្ដាញ​ទី 1 ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"ការដោះ​សោ RUIM បណ្ដាញ​ទី 2 ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"ការដោះសោ RUIM Hrpd ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"ការដោះសោ​ក្រុមហ៊ុន​ផ្ដល់សេវា RUIM ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"ការដោះសោ​ក្រុមហ៊ុន RUIM ទទួលបាន​ជោគជ័យ​ហើយ។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 386b31f..8d4b30a 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -237,10 +237,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"ಫೋನ್ ಆಯ್ಕೆಗಳು"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"ಸ್ಕ್ರೀನ್ ಲಾಕ್"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"ಪವರ್ ಆಫ್ ಮಾಡು"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"ಪವರ್"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"ತುರ್ತು"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"ದೋಷದ ವರದಿ"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"ಸೆಷನ್ ಅಂತ್ಯಗೊಳಿಸಿ"</string>
@@ -299,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"ಸ್ಥಳ"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"ಈ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"ಕ್ಯಾಲೆಂಡರ್"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು"</string>
@@ -440,8 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"ಚಿತ್ರಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಸೆರೆಹಿಡಿಯಿರಿ"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಯಾವ ಸಮಯದಲ್ಲಾದರೂ ಕ್ಯಾಮರಾ ಬಳಸಿಕೊಂಡು ಚಿತ್ರಗಳು ಮತ್ತು ವಿಡಿಯೋಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಸಿಸ್ಟಂ ಕ್ಯಾಮರಾಗಳಿಗೆ ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸೇವಾ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"ಈ ವಿಶೇಷ ಅಥವಾ ಸಿಸ್ಟಂ ಆ್ಯಪ್, ಯಾವುದೇ ಸಮಯದಲ್ಲಾದರೂ ಸಿಸ್ಟಂ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿಕೊಂಡು ಫೋಟೋಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಹುದು ಮತ್ತು ವೀಡಿಯೋಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು. ಆ್ಯಪ್‌ಗೆ android.permission.CAMERA ಅನುಮತಿಯ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"ಕ್ಯಾಮರಾ ಸಾಧನಗಳನ್ನು ತೆರೆಯುತ್ತಿರುವ ಅಥವಾ ಮುಚ್ಚುತ್ತಿರುವ ಕುರಿತು ಕಾಲ್‌ಬ್ಯಾಕ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಆ್ಯಪ್‌ ಅಥವಾ ಸೇವೆಗೆ ಅನುಮತಿಸಿ."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"ಯಾವುದೇ ಕ್ಯಾಮರಾ ಸಾಧನವನ್ನು ತೆರೆಯುತ್ತಿರುವಾಗ ಅಥವಾ ಮುಚ್ಚುತ್ತಿರುವಾಗ (ಯಾವ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಎಂಬ ಮಾಹಿತಿಯ ಮೂಲಕ) ಈ ಆ್ಯಪ್, ಕಾಲ್‌ಬ್ಯಾಕ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಬಹುದು."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"ವೈಬ್ರೇಷನ್‌‌ ನಿಯಂತ್ರಿಸಿ"</string>
@@ -1354,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ಬೆಂಬಲಿಸದಿರುವ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ಈ ಸಾಧನವು <xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬೆಂಬಲಿತ ಫಾರ್ಮ್ಯಾಟ್‌‌ನಲ್ಲಿ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"ಈ ಸಾಧನವು ಈ <xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬೆಂಬಲಿತ ಫಾರ್ಮ್ಯಾಟ್‌‌ನಲ್ಲಿ ಹೊಂದಿಸಲು ಆಯ್ಕೆ ಮಾಡಿ."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"ಈ ಸಾಧನವು ಈ <xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ಅನಿರೀಕ್ಷಿತವಾಗಿ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"ವಿಷಯ ನಷ್ಟವನ್ನು ತಪ್ಪಿಸಲು ತೆಗೆದುಹಾಕುವುದಕ್ಕೂ ಮುನ್ನ ಮಾಧ್ಯಮವನ್ನು ಎಜೆಕ್ಟ್ ಮಾಡಿ"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> ಅವರನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
@@ -1623,24 +1619,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ವಾಲ್ಯೂಮ್‌ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾದ ಮಟ್ಟಕ್ಕಿಂತಲೂ ಹೆಚ್ಚು ಮಾಡುವುದೇ?\n\nದೀರ್ಘ ಅವಧಿಯವರೆಗೆ ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದರಿಂದ ನಿಮ್ಮ ಆಲಿಸುವಿಕೆ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಬಹುದು."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸುವುದೇ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಿದರೆ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವೊಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ."</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡುವುದೇ?"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳು ಆನ್ ಆಗುತ್ತವೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\n ಪ್ರಸ್ತುತ ವೈಶಿಷ್ಟ್ಯಗಳು:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿ ಆಯ್ದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನೀವು ಬದಲಾಯಿಸಬಹುದು."</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"TalkBack ಅನ್ನು ಆನ್ ಮಾಡುವುದೇ?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ TalkBack ಆನ್ ಆಗುತ್ತದೆ, ಇದು ಕುರುಡರು ಅಥವಾ ಕಡಿಮೆ ದೃಷ್ಟಿ ಹೊಂದಿರುವ ಜನರಿಗೆ ಸಹಾಯವಾಗುವ ಒಂದು ಸ್ಕ್ರೀನ್ ರೀಡರ್ ಆಗಿದೆ. ನಿಮ್ಮ ಸಾಧನವು ಕಾರ್ಯನಿರ್ವಹಿಸುವ ವಿಧಾನವನ್ನು TalkBack ಸಂಪೂರ್ಣವಾಗಿ ಬದಲಾಯಿಸುತ್ತದೆ.\n\nನೀವು ಈ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿನ ಮತ್ತೊಂದು ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಬದಲಾಯಿಸಬಹುದು."</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ಅನ್ನು ಆನ್‌ ಮಾಡುವುದೇ?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವಾದ <xliff:g id="SERVICE">%1$s</xliff:g> ಆನ್ ಆಗುತ್ತದೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\nನೀವು ಈ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿನ ಮತ್ತೊಂದು ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಬದಲಾಯಿಸಬಹುದು."</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ಆನ್ ಮಾಡಿ"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ಆನ್ ಮಾಡಬೇಡಿ"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"ನಿಮ್ಮ ಸಾಧನದ ಪೂರ್ಣ ನಿಯಂತ್ರಣ ಹೊಂದಲು <xliff:g id="SERVICE">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"ನೀವು <xliff:g id="SERVICE">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಿದರೆ, ನಿಮ್ಮ ಸಾಧನವು ಡೇಟಾ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಅನ್ನು ವರ್ಧಿಸಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ಲಾಕ್ ಅನ್ನು ಬಳಸುವುದಿಲ್ಲ."</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"ಪ್ರವೇಶಿಸುವಿಕೆಯ ಅವಶ್ಯಕತೆಗಳಿಗೆ ಸಹಾಯ ಮಾಡುವ ಆ್ಯಪ್‌ಗಳಿಗೆ ಪೂರ್ಣ ನಿಯಂತ್ರಣ ನೀಡುವುದು ಸೂಕ್ತವಾಗಿರುತ್ತದೆ, ಆದರೆ ಬಹುತೇಕ ಆ್ಯಪ್‌ಗಳಿಗೆ ಇದು ಸೂಕ್ತವಲ್ಲ."</string>
@@ -1651,10 +1638,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"ಅನುಮತಿಸಿ"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ನಿರಾಕರಿಸಿ"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ವೈಶಿಷ್ಟ್ದ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ಅದನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್ ಜೊತೆಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ವಾಲ್ಯೂಮ್ ಕೀ ಶಾರ್ಟ್‌ಕಟ್ ಜೊತೆಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ಶಾರ್ಟ್‌ಕಟ್‌‍ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
@@ -1662,23 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸಿ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ಬಣ್ಣ ವಿಲೋಮ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ಬಣ್ಣ ತಿದ್ದುಪಡಿ"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸಲು ಎರಡೂ ಧ್ವನಿ ಕೀಗಳನ್ನು ಮೂರು ಸೆಕೆಂಡ್‌ಗಳ ಕಾಲ ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ನೀವು ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್ ಟ್ಯಾಪ್ ಮಾಡಿದಾಗ ಬಳಸುವುದಕ್ಕಾಗಿ ವೈಶಿಷ್ಟ್ಯವೊಂದನ್ನು ಆರಿಸಿ:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್‌ನೊಂದಿಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯವೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಎರಡು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಪರದೆಯ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್‌ನೊಂದಿಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯವೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಪರದೆಯ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ವೈಶಿಷ್ಟ್ಯಗಳ ನಡುವೆ ಬದಲಿಸಲು, ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹೋಲ್ಡ್‌ ಮಾಡಿ."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ವೈಶಿಷ್ಟ್ಯಗಳ ನಡುವೆ ಬದಲಿಸಲು, ಎರಡು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ವೈಶಿಷ್ಟ್ಯಗಳ ನಡುವೆ ಬದಲಿಸಲು, ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"ಹಿಗ್ಗಿಸುವಿಕೆ"</string>
     <string name="user_switched" msgid="7249833311585228097">"ಪ್ರಸ್ತುತ ಬಳಕೆದಾರರು <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗುತ್ತಿದೆ…"</string>
@@ -2049,8 +2026,7 @@
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್‌ಗಳು</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್‌ಗಳು</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ಹಂಚಿಕೊಳ್ಳಲು, ಯಾವುದೇ ಶಿಫಾರಸು ಮಾಡಲಾದ ಜನರಿಲ್ಲ"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ಆ್ಯಪ್‌ಗಳ ಪಟ್ಟಿ"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ಈ ಆ್ಯಪ್‌ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಲ್ಲದು."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ಹೋಮ್"</string>
@@ -2068,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"ಸಂವಾದ"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ಗುಂಪು ಸಂವಾದ"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ವೈಯಕ್ತಿಕ"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ಕೆಲಸ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ವೈಯಕ್ತಿಕ ವೀಕ್ಷಣೆ"</string>
@@ -2086,220 +2064,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಯಾವುದೇ ಆ್ಯಪ್‌ಗಳು ಈ ವಿಷಯವನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ಯಾವುದೇ ವೈಯಕ್ತಿಕ ಆ್ಯಪ್‌ಗಳು ಈ ವಿಷಯವನ್ನು ಬೆಂಬಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ಯಾವುದೇ ವೈಯಕ್ತಿಕ ಆ್ಯಪ್‌ಗಳು ಈ ವಿಷಯವನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ನೆಟ್‌ವರ್ಕ್‌ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ನ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIM ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM network1 ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM network2 ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM hrpd ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"RUIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK ನಮೂದಿಸಿ"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP Equivalent Home PLMN ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಪಿನ್‌"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIM ನೆಟ್‌ವರ್ಕ್ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"SIM ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ …"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"SIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"SIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM network1 ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM network2 ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM hrpd ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP Equivalent Home PLMN ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ ಸೇವಾ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK ಅನ್‌ಲಾಕ್‌ಗಾಗಿ ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM Network ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ ಅನ್‌ಲಾಕ್‌ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"SIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM Network1 ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM Network2 ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK ಅನ್‌ಲಾಕ್ ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್ ವಿನಂತಿಯು ವಿಫಲವಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"SIM ನೆಟ್‌ವರ್ಕ್ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ನ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM ಸೇವೆ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"SIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM Network1 ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM Network2 ಅನ್‌ಲಾಕ್ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpd ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM ಸೇವಾ ಪೂರೈಕೆದಾರರ ಅನ್‌ಲಾಕ್ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM ಕಾರ್ಪೊರೇಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP Equivalent Home PLMN ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"ನೆಟ್‌ವರ್ಕ್ ಸಬ್‌ಸೆಟ್‌ ಸೇವಾ ಒದಗಿಸುವವರ ಅನ್‌ಲಾಕ್ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ."</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 4d38d3f..73a769b 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"지원되지 않는 <xliff:g id="NAME">%s</xliff:g>입니다."</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"이 기기는 <xliff:g id="NAME">%s</xliff:g>을(를) 지원하지 않습니다. 지원하는 형식으로 설정하려면 탭하세요."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"이 기기는 이 <xliff:g id="NAME">%s</xliff:g>을(를) 지원하지 않습니다. 선택하여 지원되는 형식으로 설정하세요."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"기기가 이 <xliff:g id="NAME">%s</xliff:g>을(를) 지원하지 않습니다."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>이(가) 예기치 않게 삭제됨"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"콘텐츠 손실을 피하려면 미디어를 제거하기 전에 마운트 해제하세요."</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> 제거됨"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"대화"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"그룹 대화"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"개인"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"직장"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"개인 뷰"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 6a634ef..69d886f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> колдоого алынбайт"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Бул түзмөктө <xliff:g id="NAME">%s</xliff:g> колдоого алынбайт. Колдоого алынуучу форматта орнотуу үчүн таптап коюңуз."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Бул түзмөктө <xliff:g id="NAME">%s</xliff:g> колдоого алынбайт. Колдоого алынуучу форматта орнотуу үчүн тандаңыз."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Бул түзмөктө <xliff:g id="NAME">%s</xliff:g> колдоого алынбайт."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> күтүүсүздөн өчүрүлдү"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Мазмунду жоготуп албаш үчүн алып салуудан мурда медианы өчүрүңүз"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> чыгарылды"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Жазышуу"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Топтук маек"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Жеке"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Жумуш"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Жеке көрүнүш"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 1f03694..2e331a0 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"ການສົນທະນາ"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ການສົນທະນາກຸ່ມ"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ສ່ວນຕົວ"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ວຽກ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ມຸມມອງສ່ວນຕົວ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 3956dbd..021717d 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -243,7 +243,7 @@
     <string name="global_action_power_off" msgid="4404936470711393203">"Išjungiamas maitinimas"</string>
     <string name="global_action_power_options" msgid="1185286119330160073">"Maitinimas"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"Paleisti iš naujo"</string>
-    <string name="global_action_emergency" msgid="1387617624177105088">"Skambutis pagalbos numeriu"</string>
+    <string name="global_action_emergency" msgid="1387617624177105088">"Skubus atvejis"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"Pranešimas apie riktą"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"Baigti seansą"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"Ekrano kopija"</string>
@@ -1391,8 +1391,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nepalaikoma saugykla (<xliff:g id="NAME">%s</xliff:g>)"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Šis įrenginys nepalaiko šios <xliff:g id="NAME">%s</xliff:g>. Palieskite, kad nustatytumėte palaikomu formatu."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Šis įrenginys nepalaiko šios <xliff:g id="NAME">%s</xliff:g>. Pasirinkite ir nustatykite palaikomu formatu."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Šiame įrenginyje nepalaikoma <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> netikėtai pašalinta"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Prieš šalindami išimkite laikmeną, kad neprarastumėte turinio"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Laikmena (<xliff:g id="NAME">%s</xliff:g>) atjungta"</string>
@@ -2113,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Pokalbis"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupės pokalbis"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Asmeninė"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Darbo"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Asmeninė peržiūra"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 778a08b..6ea61a1 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1371,8 +1371,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Neatbalstīts datu nesējs (<xliff:g id="NAME">%s</xliff:g>)"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Šī ierīce neatbalsta datu nesēju <xliff:g id="NAME">%s</xliff:g>. Pieskarieties, lai iestatītu to atbalstītā formātā."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Šajā ierīcē netiek atbalstīta šī <xliff:g id="NAME">%s</xliff:g>. Atlasiet, lai iestatītu atbalstītu formātu."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Šajā ierīcē netiek atbalstīta šī <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> tika negaidīti izņemta"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Lai nezaudētu saturu, pirms izņemšanas izstumiet datu nesēju."</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Ierīce <xliff:g id="NAME">%s</xliff:g> izņemta"</string>
@@ -2079,6 +2078,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Saruna"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupas saruna"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Privātais profils"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Darba profils"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personisks skats"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4c75e99..9c434db 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -2046,6 +2046,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Разговор"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Групен разговор"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Лични"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Службени"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Личен приказ"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 84dfa95..ad0cde1 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -237,10 +237,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"ഫോൺ ഓപ്‌ഷനുകൾ"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"സ്‌ക്രീൻ ലോക്ക്"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"പവർ ഓഫാക്കുക"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"പവർ"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"റീസ്റ്റാർട്ട് ചെയ്യുക"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"അടിയന്തിരാവശ്യം"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"ബഗ് റിപ്പോർട്ട്"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"സെഷൻ അവസാനിപ്പിക്കുക"</string>
@@ -299,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്‌സസ്സ് ചെയ്യുക"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"ലൊക്കേഷൻ"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"ഈ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്സസ് ചെയ്യാൻ"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"കലണ്ടർ"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"നിങ്ങളുടെ കലണ്ടർ ആക്‌സസ്സ് ചെയ്യുക"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS സന്ദേശങ്ങൾ അയയ്‌ക്കുകയും കാണുകയും ചെയ്യുക"</string>
@@ -440,8 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"ചിത്രങ്ങളും വീഡിയോകളും എടുക്കുക"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"ഏതുസമയത്തും ക്യാമറ ഉപയോഗിച്ചുകൊണ്ട് ചിത്രങ്ങൾ എടുക്കാനും വീഡിയോകൾ റെക്കോർഡുചെയ്യാനും ഈ ആപ്പിന് കഴിയും."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"ചിത്രങ്ങളും വീഡിയോകളും എടുക്കാൻ, സിസ്‌റ്റം ക്യാമറ ആക്‌സസ് ചെയ്യുന്നതിന് ആപ്പിനെയോ സേവനത്തെയോ അനുവദിക്കുക"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"സിസ്‌റ്റം ക്യാമറ ഉപയോഗിച്ച് ഏത് സമയത്തും ചിത്രങ്ങളെടുക്കാനും വീഡിയോകൾ റെക്കോർഡ് ചെയ്യാനും ഈ വിശേഷാധികാര അല്ലെങ്കിൽ സിസ്‌റ്റം ആപ്പിന് കഴിയും. ആപ്പിലും android.permission.CAMERA അനുമതി ഉണ്ടായിരിക്കണം"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"ക്യാമറയുള്ള ഉപകരണങ്ങൾ ഓണാക്കുന്നതിനെയോ അടയ്ക്കുന്നതിനെയോ കുറിച്ചുള്ള കോൾബാക്കുകൾ സ്വീകരിക്കാൻ ആപ്പിനെയോ സേവനത്തെയോ അനുവദിക്കുക."</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"ഏതെങ്കിലും ക്യാമറ ഉപകരണം തുറക്കുമ്പോഴോ (ഏത് ആപ്പ് ഉപയോഗിച്ചും) അടയ്ക്കുമ്പോഴോ ഈ ആപ്പിന് കോൾബാക്കുകൾ സ്വീകരിക്കാനാവും."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"വൈബ്രേറ്റുചെയ്യൽ നിയന്ത്രിക്കുക"</string>
@@ -1354,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"പിന്തുണയില്ലാത്ത <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ഈ ഉപകരണം <xliff:g id="NAME">%s</xliff:g> പിന്തുണയ്ക്കുന്നതല്ല. പിന്തുണയുള്ള ഫോർമാറ്റിൽ സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"<xliff:g id="NAME">%s</xliff:g> ഈ ഉപകരണത്തിന് അനുയോജ്യമല്ല. അനുയോജ്യമായ ഒരു ഫോർമാറ്റിൽ സജ്ജമാക്കുന്നതിന് തിരഞ്ഞെടുക്കുക."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"ഈ ഉപകരണം ഈ <xliff:g id="NAME">%s</xliff:g> പിന്തുണയ്ക്കുന്നില്ല."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> അപ്രതീക്ഷിതമായി നീക്കംചെയ്‌തു"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"ഉള്ളടക്കം നഷ്‌ടമാകുന്നത് തടയാൻ, നീക്കം ചെയ്യുന്നതിന് മുൻപ് മീഡിയ ഒഴിവാക്കുക"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> നീക്കം ചെ‌യ്‌തു"</string>
@@ -1623,24 +1619,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"മുകളിൽക്കൊടുത്തിരിക്കുന്ന ശുപാർശചെയ്‌ത ലെവലിലേക്ക് വോളിയം വർദ്ധിപ്പിക്കണോ?\n\nഉയർന്ന വോളിയത്തിൽ ദീർഘനേരം കേൾക്കുന്നത് നിങ്ങളുടെ ശ്രവണ ശേഷിയെ ദോഷകരമായി ബാധിക്കാം."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ഉപയോഗസഹായി കുറുക്കുവഴി ഉപയോഗിക്കണോ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"കുറുക്കുവഴി ഓണായിരിക്കുമ്പോൾ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും."</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കണോ?"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത്, ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം ഇത് മാറ്റിയേക്കാം.\n\nനിലവിലുള്ള ഫീച്ചറുകൾ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nതിരഞ്ഞെടുത്ത ഫീച്ചറുകൾ ക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിൽ മാറ്റാനാവും."</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"TalkBack ഓണാക്കണോ?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത്, കാഴ്ചക്കുറവുള്ളവർക്കോ അന്ധർക്കോ ഉപകാരപ്പെടുന്ന TalkBack എന്ന സ്ക്രീൻ റീഡർ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം TalkBack പൂർണ്ണമായും മാറ്റുന്നു.\n\nക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിലെ മറ്റൊരു ഫീച്ചറിലേക്ക് നിങ്ങൾക്ക് ഈ കുറുക്കുവഴി മാറ്റാനാവും."</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ഓണാക്കണോ?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത് ഉപയോഗസഹായി ഫീച്ചറായ <xliff:g id="SERVICE">%1$s</xliff:g> എന്നതിനെ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം ഇത് മാറ്റിയേക്കാം.\n\nക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിലെ മറ്റൊരു ഫീച്ചറിലേക്ക് നിങ്ങൾക്ക് ഈ കുറുക്കുവഴി മാറ്റാനാവും."</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ഓണാക്കുക"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ഓണാക്കരുത്"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> എന്നതിന് നിങ്ങളുടെ ഉപകരണത്തിന്മേൽ പൂർണ്ണ നിയന്ത്രണം അനുവദിക്കണോ?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"<xliff:g id="SERVICE">%1$s</xliff:g> ഓണാക്കിയെങ്കിൽ, ഡാറ്റ എൻക്രിപ്‌ഷൻ മെച്ചപ്പെടുത്താൻ ഉപകരണം നിങ്ങളുടെ സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിക്കില്ല."</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"ഉപയോഗസഹായി ആവശ്യങ്ങൾക്കായി നിങ്ങളെ സഹായിക്കുന്ന ആപ്പുകൾക്ക് പൂർണ്ണ നിയന്ത്രണം അനുയോജ്യമാണെങ്കിലും മിക്ക ആപ്പുകൾക്കും അനുയോജ്യമല്ല."</string>
@@ -1651,10 +1638,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"അനുവദിക്കൂ"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"നിരസിക്കുക"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ഇത് ഉപയോഗിക്കാൻ ആരംഭിക്കുന്നതിന് ഫീച്ചർ ടാപ്പ് ചെയ്യുക:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ഉപയോഗസഹായി ബട്ടണിന്റെ സഹായത്തോടെ, ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"വോളിയം കീ കുറുക്കുവഴിയുടെ സഹായത്തോടെ, ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ഓഫാക്കിയിരിക്കുന്നു"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"കുറുക്കുവഴികൾ തിരുത്തുക"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"പൂർത്തിയാക്കി"</string>
@@ -1662,23 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"കുറുക്കുവഴി ഉപയോഗിക്കുക"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"വർണ്ണ വിപര്യയം"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"വർണ്ണം ക്രമീകരിക്കൽ"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഉപയോഗിക്കാൻ, രണ്ട് വോളിയം കീകളും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക"</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"നിങ്ങൾ ഉപയോഗസഹായി ബട്ടൺ ടാപ്പ് ചെയ്യുമ്പോൾ ഉപയോഗിക്കുന്നതിന് ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക (രണ്ട് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക (മൂന്ന് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ഫീച്ചറുകൾക്കിടയിൽ മാറാൻ, ഉപയോഗസഹായി ബട്ടൺ സ്‌പർശിച്ച് പിടിക്കുക."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ഫീച്ചറുകൾക്കിടയിൽ മാറാൻ, രണ്ട് വിരലുകളുപയോഗിച്ച് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്‌ത് പിടിക്കുക."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ഫീച്ചറുകൾക്കിടയിൽ മാറാൻ, മൂന്ന് വിരലുകളുപയോഗിച്ച് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്‌ത് പിടിക്കുക."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"മാഗ്നിഫിക്കേഷൻ"</string>
     <string name="user_switched" msgid="7249833311585228097">"നിലവിലെ ഉപയോക്താവ് <xliff:g id="NAME">%1$s</xliff:g> ആണ്."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> എന്ന ഉപയോക്താവിലേക്ക് മാറുന്നു…"</string>
@@ -2049,8 +2026,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ഫയലുകൾ</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ഫയൽ</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"പങ്കിടാൻ, നിർദ്ദേശിക്കപ്പെട്ട ആളുകളൊന്നുമില്ല"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ആപ്പുകളുടെ ലിസ്‌റ്റ്"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ഹോം"</string>
@@ -2068,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"സംഭാഷണം"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ഗ്രൂപ്പ് സംഭാഷണം"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"വ്യക്തിപരമായത്"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ജോലിസ്ഥലം"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"വ്യക്തിപര കാഴ്‌ച"</string>
@@ -2086,220 +2064,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ഔദ്യോഗിക ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കം തുറക്കാനാവില്ല"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"വ്യക്തിപര ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കത്തെ പിന്തുണയ്‌ക്കാനാവില്ല"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"വ്യക്തിപര ആപ്പുകൾക്കൊന്നും ഈ ഉള്ളടക്കം തുറക്കാനാവില്ല"</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"സിം നെറ്റ്‌വർക്ക് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"സിം നെറ്റ്‌വർക്ക് സബ്സെറ്റ് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"സിം കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"സിം സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"സിം അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM നെറ്റ്‌വർക്ക്1 അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM നെറ്റ്‌വർക്ക്2 അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM എച്ച്ആർപി‌ഡി അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"ഉപകരണത്തിൽ RUIM സേവനദാതാവ് നൽകിയ കോർപ്പറേറ്റ് ലോക്ക് അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK നൽകുക"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP ഇക്വിവാലന്റ് ഹോം PLMN അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"നെറ്റ്‌വർക്ക് സബ്സെറ്റ് സേവനദാതാവിനെ അൺലോക്ക് ചെയ്യാനുള്ള പിൻ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIM അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"സിം നെറ്റ്‌വർക്ക് സബ്സെറ്റ് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു …"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"സിം സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"സിം കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"സിം അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM നെറ്റ്‌വർക്ക്1 അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM നെറ്റ്‌വർക്ക്2 അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM എച്ച്ആർപി‌ഡി അൺലോക്ക് അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"ഉപകരണത്തിൽ RUIM സേവനദാതാവ് നൽകിയ കോർപ്പറേറ്റ് ലോക്ക് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു..."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN അൺലോക്ക് അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP ഇക്വിവാലന്റ് ഹോം PLMN അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"നെറ്റ്‌വർക്ക് സബ്സെറ്റ് സേവനദാതാവിനെ അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കുന്നു…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"സിം നെറ്റ്‌വർക്ക് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"സിം നെറ്റ്‌വർക്ക് സബ്സെറ്റ് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"സിം സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"സിം കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"സിം അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM നെറ്റ്‌വർക്ക്1 അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM നെറ്റ്‌വർക്ക്2 അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM എച്ച്ആർപി‌ഡി അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK അൺലോക്ക് ചെയ്യാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP ഇക്വിവാലന്റ് ഹോം PLMN അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"നെറ്റ്‌വർക്ക് സബ്സെറ്റ് സേവനദാതാവിനെ അൺലോക്ക് ചെയ്യാൻ അഭ്യർത്ഥിക്കാനായില്ല."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"സിം നെറ്റ്‌വർക്ക് അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"സിം നെറ്റ്‌വർക്ക് സബ്സെറ്റ് അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"സിം സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"സിം കോർപ്പറേറ്റ് അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"സിം അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM നെറ്റ്‌വർക്ക്1 അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM നെറ്റ്‌വർക്ക്2 അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM എച്ച്ആർപി‌ഡി അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM സേവന ദാതാവിനെ അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"ഉപകരണത്തിൽ RUIM സേവനദാതാവ് നൽകിയ കോർപ്പറേറ്റ് ലോക്ക് അൺലോക്ക് ചെയ്‍തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP ഇക്വിവാലന്റ് ഹോം PLMN അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI അൺലോക്ക് ചെയ്തു."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"നെറ്റ്‌വർക്ക് സബ്സെറ്റ് സേവനദാതാവിനെ അൺലോക്ക് ചെയ്തു."</string>
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index a3d21ec..462d3a5 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Харилцан яриа"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Бүлгийн харилцан яриа"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Хувийн"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Ажил"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Хувийн харагдах байдал"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 8176542..5dc7433 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -297,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"आपल्या संपर्कांवर प्रवेश"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"स्थान"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"या डिव्हाइसच्या स्थानावर प्रवेश"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"कॅलेंडर"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"आपल्या कॅलेंडरवर प्रवेश"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS मेसेज पाठवणे आणि पाहणे हे"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> असमर्थित"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी टॅप करा."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी निवडा."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"हे डिव्हाइस या <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> अनपेक्षितरित्या काढले"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"आशय गमावणे टाळण्यासाठी काढून टाकण्यापूर्वी मीडिया इजेक्ट करा"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> काढून टाकले आहे."</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"संभाषण"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"गट संभाषण"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"वैयक्तिक"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ऑफिस"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"वैयक्तिक दृश्य"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b4d0fa3da..752a9c7 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Perbualan"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Perbualan Kumpulan"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Peribadi"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Kerja"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Paparan peribadi"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index f7107a4..e94e553 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>-"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"စကားဝိုင်း"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"အဖွဲ့စကားဝိုင်း"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ကိုယ်ပိုင်"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"အလုပ်"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ပုဂ္ဂိုလ်ရေးဆိုင်ရာ မြင်ကွင်း"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 6d78f89..e41127b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Samtale"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Gruppesamtale"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personlig"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Jobb"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personlig visning"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index be86c40..6693823 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -438,7 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"तस्बिरहरू र भिडियोहरू लिनुहोस्।"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"अनुप्रयोग वा सेवालाई तस्बिर र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
-    <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA सम्बन्धी अनुमति हुनु पर्छ"</string>
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"कुनै अनुप्रयोग वा सेवालाई खोलिँदै वा बन्द गरिँदै गरेका क्यामेरा यन्त्रहरूका बारेमा कलब्याक प्राप्त गर्ने अनुमति दिनुहोस्।"</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"कुनै क्यामेरा यन्त्र खोलिँदा (कुन अनुप्रयोगले खोलेको भन्ने बारेमा) वा बन्द गरिँदा यो अनुप्रयोगले कलब्याक प्राप्त गर्न सक्छ।"</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"कम्पन नियन्त्रण गर्नुहोस्"</string>
@@ -1357,8 +1357,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"असमर्थित <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"यस यन्त्रले यस <xliff:g id="NAME">%s</xliff:g> लाई समर्थन गर्दैन। एक समर्थित ढाँचामा सेटअप गर्न ट्याप गर्नुहोस्।"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"यो यन्त्रले यस <xliff:g id="NAME">%s</xliff:g> लाई समर्थन गर्दैन। एक समर्थित ढाँचामा सेटअप गर्न चयन गर्नुहोस्।"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"यो यन्त्रमा यो <xliff:g id="NAME">%s</xliff:g> चल्दैन।"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> अप्रत्याशित रूपमा निकालियो"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"सामग्री गुम्न नदिनका लागि मिडिया हटाउनुअघि त्यसलाई इजेक्ट गर्नुहोस्"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> हटाइयो"</string>
@@ -1630,11 +1629,11 @@
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले पहुँचसम्बन्धी सुविधाहरू सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nहालका सुविधाहरू:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतपाईं सेटिङ &gt; पहुँचमा गएर चयन गरिएका सुविधाहरू परिवर्तन गर्न सक्नुहुन्छ।"</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"TalkBack सक्रिय गर्ने हो?"</string>
-    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले TalkBack सक्रिय गर्छ। यो दृष्टिविहीन वा दृष्टि कमजोर भएका मान्छेहरूका लागि उपयोगी हुने एउटा स्क्रिन रिडर हो। TalkBack ले तपाईंको यन्त्रले काम गर्ने तरिका पूर्णतया परिवर्तन गर्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत खुल्ने सुविधा परिवर्तन गर्न सक्नुहुन्छ।"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले TalkBack सक्रिय गर्छ। यो दृष्टिविहीन वा दृष्टि कमजोर भएका मान्छेहरूका लागि उपयोगी हुने एउटा स्क्रिन रिडर हो। TalkBack ले तपाईंको यन्त्रले काम गर्ने तरिका पूर्णतया परिवर्तन गर्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्ने हो?"</string>
-    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्छ। यो पहुँचसम्बन्धी एउटा सुविधा हो। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत खुल्ने सुविधा परिवर्तन गर्न सक्नुहुन्छ।"</string>
-    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गर्नुहोस्"</string>
-    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"सक्रिय नगर्नुहोस्"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> नामक पहुँचसम्बन्धी सुविधा  सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गरियोस्"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"सक्रिय नगरियोस्"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> लाई तपाईंको यन्त्र पूर्ण रूपमा नियन्त्रण गर्न दिने हो?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"तपाईंले <xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्नुभयो भने तपाईंको यन्त्रले डेटा इन्क्रिप्ट गर्ने सुविधाको स्तरोन्नति गर्न तपाईंको स्क्रिन लक सुविधाको प्रयोग गर्ने छैन।"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"तपाईंलाई पहुँच राख्न आवश्यक पर्ने कुरामा सहयोग गर्ने अनुप्रयोगहरूमाथि पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश अनुप्रयोगहरूका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
@@ -1645,8 +1644,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"अनुमति दिनुहोस्"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"इन्कार गर्नु⋯"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"कुनै सुविधा प्रयोग गर्न थाल्न उक्त सुविधामा ट्याप गर्नुहोस्:"</string>
-    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"पहुँचको बटनमार्फत प्रयोग गरिने सुविधाहरू छनौट गर्नुहोस्"</string>
-    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"भोल्युम कुञ्जीको सर्टकटमार्फत प्रयोग गरिने सुविधाहरू छनौट गर्नुहोस्"</string>
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"पहुँचको बटनमार्फत प्रयोग गर्न चाहेका सुविधाहरू छनौट गर्नुहोस्"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"भोल्युम कुञ्जीको सर्टकटमार्फत प्रयोग गर्न चाहेका सुविधाहरू छनौट गर्नुहोस्"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> निष्क्रिय पारिएको छ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"सर्टकटहरू सम्पादन गर्नुहोस्"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"सम्पन्न भयो"</string>
@@ -1657,7 +1656,7 @@
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सक्रिय पारियो।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> निष्क्रिय पारियो।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> प्रयोग गर्न दुवै भोल्युम कुञ्जीहरूलाई तीन सेकेन्डसम्म थिचिराख्नुहोस्"</string>
-    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"तपाईंले पहुँचको बटन ट्याप गरेर प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस्:"</string>
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"तपाईंले पहुँचको बटन ट्याप गर्दा प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस्:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (दुईवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (तीनवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"एउटा सुविधाबाट अर्को सुविधामा जान पहुँचको बटनमा छोइराख्नुहोस्।"</string>
@@ -2033,7 +2032,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फाइलहरू</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> फाइल</item>
     </plurals>
-    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"सेयर गर्न सिफारिस गरिएको कुनै पनि व्यक्ति छैन"</string>
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"कुनै पनि व्यक्तिसँग सेयर गर्ने सिफारिस गरिएको छैन"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"अनुप्रयोगहरूको सूची"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"यो अनुप्रयोगलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले यो USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"गृहपृष्ठ"</string>
@@ -2051,6 +2050,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"वार्तालाप"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"सामूहिक वार्तालाप"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"व्यक्तिगत"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"काम"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"व्यक्तिगत दृश्य"</string>
@@ -2070,7 +2071,7 @@
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"यो सामग्री कुनै पनि व्यक्तिगत अनुप्रयोगमार्फत सेयर गर्न मिल्दैन"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"यो सामग्री कुनै पनि व्यक्तिगत अनुप्रयोगमार्फत खोल्न मिल्दैन"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM को नेटवर्क अनलक गर्ने PIN"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM को नेटवर्कको उपसमूह अनलक गर्ने PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM को नेटवर्कको सबसेट अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM को कर्पोरेट लक खोल्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIM को सेवा प्रदायकसम्बन्धी लक खोल्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIM अनलक गर्ने PIN"</string>
@@ -2079,8 +2080,8 @@
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK प्रविष्टि गर्नुहोस्"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK प्रविष्टि गर्नुहोस्"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK प्रविष्टि गर्नुहोस्"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM को network1 नेटवर्क अनलक गर्ने PIN"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM को network2 नेटवर्क अनलक गर्ने PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM को network1 अनलक गर्ने PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM को network2 अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM को hrpd अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"RUIM को कर्पोरेट लक खोल्ने PIN"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM को सेवा प्रदायकसम्बन्धी लक खोल्ने PIN"</string>
@@ -2095,19 +2096,19 @@
     <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"घरमा जोडिने SP सरहको PLMN अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID अनलक गर्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI अनलक गर्ने PIN"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"नेटवर्कको उपसमूहको सेवा प्रदायकसम्बन्धी लक खोल्ने PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"नेटवर्कको सबसेटको सेवा प्रदायकसम्बन्धी लक खोल्ने PIN"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIM को नेटवर्क अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"SIM को नेटवर्कको उपसमूह अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"SIM को नेटवर्कको सबसेट अनलक गरिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"SIM को सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"SIM को कर्पोरेट लक खोलिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM को network1 नेटवर्क अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM को network2 नेटवर्क अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM को network1 अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM को network2 अनलक गरिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM को hrpd अनलक गरिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM को सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM को कर्पोरेट लक खोलिदिन अनुरोध गर्दै…"</string>
@@ -2115,66 +2116,66 @@
     <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"घरमा जोडिने SP सरहको PLMN अनलक गरिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID अनलक गरिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"नेटवर्कको उपसमूहको सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"नेटवर्कको सबसेटको सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्दै…"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK प्रयोग गरेर अनलक गरिदिन अनुरोध गर्दै…"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM को नेटवर्क अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM को नेटवर्कको उपसमूह अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK अनलक गरिदिन अनुरोध गर्दै…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM को नेटवर्क अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM को नेटवर्कको सबसेट अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM को सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्न सकिएन।"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"SIM को कर्पोरेट लक खोलिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM को Network1 नेटवर्क अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM को Network2 नेटवर्क अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM को Hrpd अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM को कर्पोरेट लक खोलिदिन अनुरोध गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM को Network1 अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM को Network2 अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM को Hrpd अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM को कर्पोरेट लक खोलिदिन गरिएको अनुरोध असफल भयो"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM को सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK प्रयोग गरेर अनलक गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"घरमा जोडिने SP सरहको PLMN अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI अनलक गरिदिन अनुरोध गर्न सकिएन।"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"नेटवर्कको उपसमूहको सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK अनलक गर्न सकिएन।"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"घरमा जोडिने SP सरहको PLMN अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI अनलक गर्न गरिएको अनुरोध असफल भयो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"नेटवर्कको सबसेटको सेवा प्रदायकसम्बन्धी लक खोलिदिन अनुरोध गर्न सकिएन।"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"SIM को नेटवर्क अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM को नेटवर्कको उपसमूह अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM को नेटवर्कको सबसेट अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM को सेवा प्रदायकसम्बन्धी लक खोलियो ।"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"SIM को कर्पोरेट लक खोलियो।"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM को Network1 नेटवर्क अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM को Network2 नेटवर्क अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM को Network1 अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM को network2 अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM को Hrpd अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM को सेवा प्रदायकसम्बन्धी लक खोलियो।"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM को कर्पोरेट लक खोलियो।"</string>
     <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK प्रयोग गरेर अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK प्रयोग गरेर अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK अनलक गरियो।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"घरमा जोडिने SP सरहको PLMN अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID अनलक गरियो।"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI अनलक गरियो।"</string>
-    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"नेटवर्कको उपसमूहको सेवा प्रदायकसम्बन्धी लक खोलियो।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"नेटवर्कको सबसेटको सेवा प्रदायकसम्बन्धी लक खोलियो।"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8017f65..2fb675c 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Gesprek"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Groepsgesprek"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Persoonlijk"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Werk"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persoonlijke weergave"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 2a19325..b5757c6 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -237,10 +237,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"ଫୋନ ବିକଳ୍ପ"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"ସ୍କ୍ରୀନ୍‌ ଲକ୍‌"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"ପାୱାର୍ ବନ୍ଦ"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"ପାୱାର"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"ଜରୁରୀକାଳୀନ"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"ବଗ୍‌ ରିପୋର୍ଟ"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"ସେସନ୍‍ ଶେଷ କରନ୍ତୁ"</string>
@@ -440,8 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"ଫଟୋ ଓ ଭିଡିଓଗୁଡ଼ିକୁ ନିଅନ୍ତୁ"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"ଏହି ଆପ୍‍ ଯେକୌଣସି ସମୟରେ କ୍ୟାମେରା ବ୍ୟବହାର କରି ଫଟୋ ଉଠାଇପାରେ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିପାରେ।"</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"ଛବି ଏବଂ ଭିଡିଓଗୁଡ଼ିକୁ ନେବା ପାଇଁ ସିଷ୍ଟମ୍ କ୍ୟାମେରା‌ଗୁଡ଼ିକୁ କୌଣସି ଆପ୍ଲିକେସନ୍ କିମ୍ବା ସେବା ଆକ୍ସେସ୍ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"ବିଶେଷ ଅଧିକାର ଥିବା ଏହି ଆପ୍ କିମ୍ବା ସିଷ୍ଟମ୍ ଆପ୍ ଯେ କୌଣସି ସମୟରେ ଏକ ସିଷ୍ଟମ୍ କ୍ୟାମେରା ବ୍ୟବହାର କରି ଛବି ଉଠାଇପାରିବ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିପାରିବ। ଆପରେ ମଧ୍ୟ android.permission.CAMERA ଅନୁମତି ଆବଶ୍ୟକ"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"କ୍ୟାମେରା ଡିଭାଇସଗୁଡ଼ିକ ଖୋଲିବା କିମ୍ବା ବନ୍ଦ କରିବା ବିଷୟରେ କଲବ୍ୟାକଗୁଡ଼ିକ ପାଇବାକୁ ଏକ ଆପ୍ଲିକେସନ୍ କିମ୍ବା ସେବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"ଯେ କୌଣସି କ୍ୟାମେରା ଡିଭାଇସ୍ ଖୋଲାଗଲେ (କେଉଁ ଆପ୍ଲିକେସନ୍ ଦ୍ୱାରା) କିମ୍ବା ବନ୍ଦ କରାଗଲେ ଏହି ଆପ୍ କଲବ୍ୟାକ୍ ପାଇପାରିବ।"</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"କମ୍ପନ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
@@ -1354,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> ସପୋର୍ଟ କରୁନାହିଁ"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସପୋର୍ଟ କରେନାହିଁ। ଗୋଟିଏ ସପୋର୍ଟ କରୁଥିବା ଫର୍ମାଟ୍‌ରେ ସେଟ୍‍ ଅପ୍‍ କରିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସପୋର୍ଟ କରେ ନାହିଁ। ଗୋଟିଏ ସପୋର୍ଟ କରୁଥିବା ଫର୍ମାଟରେ ସେଟ୍‍ ଅପ୍‍ କରିବାକୁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"ଏହି ଡିଭାଇସ୍ ଏହି <xliff:g id="NAME">%s</xliff:g>କୁ ସମର୍ଥନ କରେ ନାହିଁ।"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>କୁ ହଠାତ୍‌ କାଢ଼ିଦିଆଗଲା"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"କଣ୍ଟେଣ୍ତ ହରାଇବାକୁ ଏଡ଼ାଇବା ପାଇଁ କାଢ଼ିବା ପୂର୍ବରୁ ମିଡିଆକୁ ଇଜେକ୍ଟ କରନ୍ତୁ"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g>କୁ କାଢ଼ିଦିଆଗଲା"</string>
@@ -1623,24 +1619,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିଶ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ଆକ୍ସେସବିଲିଟି ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ସର୍ଟକଟ୍ ଚାଲୁ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍ ବଟନ୍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଏକ ଆକ୍ସେସବିଲିଟି ଫିଚର୍ ଆରମ୍ଭ ହେବ।"</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକୁ ଚାଲୁ କରିବେ?"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକ ଚାଲୁ ହୁଏ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାମ କରେ ତାହା ପରିବର୍ତ୍ତନ କରିପାରେ।\n\nବର୍ତ୍ତମାନର ଫିଚରଗୁଡ଼ିକ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n ଆପଣ ସେଟିଂସ୍ &amp;gt ଆକ୍ସେସିବିଲିଟୀରେ ଚୟନିତ ଫିଚରଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"TalkBack ଚାଲୁ କରିବେ?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଅନ୍ଧ କିମ୍ବା କମ୍ ଦେଖାଯାଉଥିବା ଲୋକମାନଙ୍କ ପାଇଁ ଏକ ସାହାଯ୍ୟକାରୀ ସ୍କ୍ରିନ୍ ରିଡର୍ TalkBack ଚାଲୁ ହୁଏ। ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାର୍ଯ୍ୟ କରେ, ତାହା TalkBack ସମ୍ପୂର୍ଣ୍ଣ ଭାବେ ପରିବର୍ତ୍ତନ କରିଥାଏ।\n\nଆପଣ ସେଟିଂସ୍ &amp;gt ଆକ୍ସେସିବିଲିଟୀରେ ଏହି ସର୍ଚକଟକୁ ଅନ୍ୟ ଏକ ଫିଚରରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ଚାଲୁ କରିବେ?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଏକ ଆକ୍ସେସିବିଲିଟୀ ଫିଚର୍ <xliff:g id="SERVICE">%1$s</xliff:g> ଚାଲୁ ହୁଏ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାମ କରେ ତାହା ପରିବର୍ତ୍ତନ କରିପାରେ।\n\nଆପଣ ସେଟିଂସ୍ &amp;gt ଆକ୍ସେସିବିଲିଟୀରେ ଏହି ସର୍ଚକଟକୁ ଅନ୍ୟ ଏକ ଫିଚରରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ଚାଲୁ କରନ୍ତୁ"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ଚାଲୁ କରନ୍ତୁ ନାହିଁ"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g>କୁ ଆପଣଙ୍କ ଡିଭାଇସର ସମ୍ପୂର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣର ଅନୁମତି ଦେବେ?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"ଯଦି ଆପଣ <xliff:g id="SERVICE">%1$s</xliff:g> ଚାଲୁ କରନ୍ତି, ତେବେ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଡାଟା ଏନକ୍ରିପ୍ସନ୍ ବୃଦ୍ଧି କରିବାକୁ ଆପଣଙ୍କର ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରିବ ନାହିଁ।"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"ଯେଉଁ ଆପ୍ସ ଆପଣଙ୍କୁ ଆକ୍ସେସିବିଲିଟୀ ଆବଶ୍ୟକତାରେ ସହାୟତା କରେ, ସେହି ଆପ୍ସ ପାଇଁ ସମ୍ପୂର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ ଉପଯୁକ୍ତ ଅଟେ, କିନ୍ତୁ ଅଧିକାଂଶ ଆପ୍ସ ପାଇଁ ଉପଯୁକ୍ତ ନୁହେଁ।"</string>
@@ -1651,10 +1638,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"ଅନୁମତି"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ପ୍ରତ୍ୟାଖ୍ୟାନ"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ଏକ ଫିଚର୍ ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ଏହାକୁ ଟାପ୍ କରନ୍ତୁ:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ଭଲ୍ୟୁମ୍ କୀ ସର୍ଟକଟ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ବନ୍ଦ ହୋଇଯାଇଛି"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ସର୍ଟକଟଗୁଡ଼ିକୁ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ହୋଇଗଲା"</string>
@@ -1662,23 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ରଙ୍ଗ ବଦଳାଇବାର ସୁବିଧା"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବାକୁ ତିନି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍‍ କୀ ଦବାଇ ଧରି ରଖନ୍ତୁ"</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ଆପଣ ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ଟାପ୍ କରିବା ବେଳେ ଏକ ଫିଚର୍ ବ୍ୟବହାର କରିବାକୁ ବାଛନ୍ତୁ:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚର୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଏକ ଫିଚର୍ ବାଛନ୍ତୁ (ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚର୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଏକ ଫିଚର୍ ବାଛନ୍ତୁ (ତିନୋଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ଫିଚରଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ଫିଚରଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ।"</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ଫିଚରଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ, ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"ମ୍ୟାଗ୍ନିଫିକେସନ୍‍"</string>
     <string name="user_switched" msgid="7249833311585228097">"ବର୍ତ୍ତମାନର ୟୁଜର୍‌ ହେଉଛନ୍ତି <xliff:g id="NAME">%1$s</xliff:g>।"</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> ରେ ସୁଇଚ୍ କରନ୍ତୁ…"</string>
@@ -2049,8 +2026,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g>ଟି ଫାଇଲ୍</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g>ଟି ଫାଇଲ୍</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ଏହାକୁ ସେୟାର୍ କରିବା ପାଇଁ କୌଣସି ସୁପାରିଶ କରାଯାଇଥିବା ଲୋକ ନାହାଁନ୍ତି"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ଆପ୍ସ ତାଲିକା"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ଏହି ଆପ୍‌କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍‍ଚର୍‍ କରିପାରିବ।"</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ମୂଳପୃଷ୍ଠା"</string>
@@ -2068,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"ବାର୍ତ୍ତାଳାପ"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ଗୋଷ୍ଠୀ ବାର୍ତ୍ତାଳାପ"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ବ୍ୟକ୍ତିଗତ"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"କାର୍ଯ୍ୟ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ବ୍ୟକ୍ତିଗତ ଭ୍ୟୁ"</string>
@@ -2086,220 +2064,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"କୌଣସି କାର୍ଯ୍ୟସ୍ଥଳୀ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ଖୋଲିପାରିବ ନାହିଁ"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ସମର୍ଥନ କରିପାରିବ ନାହିଁ"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"କୌଣସି ବ୍ୟକ୍ତିଗତ ଆପ୍ ଏହି ବିଷୟବସ୍ତୁକୁ ଖୋଲିପାରିବ ନାହିଁ"</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM ନେଟୱାର୍କ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM ନେଟୱାର୍କର ସବସେଟ୍ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM କର୍ପୋରେଟ୍ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIM ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM ନେଟୱାର୍କ1 ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM ନେଟୱାର୍କ2 ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM hrpd ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"RUIM କର୍ପୋରେଟ୍ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK ଲେଖନ୍ତୁ"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ PIN"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIM ନେଟୱାର୍କ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"SIM ନେଟୱାର୍କର ସବସେଟ୍ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି …"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"SIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"SIM କର୍ପୋରେଟ୍ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM ନେଟୱାର୍କ1 ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM ନେଟୱାର୍କ2 ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM hrpd ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM କର୍ପୋରେଟ୍ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK ଅନଲକ୍ କରିବାକୁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM ନେଟୱାର୍କ ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM ନେଟୱାର୍କର ସବସେଟ୍ ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"SIM କର୍ପୋରେଟ୍ ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM ନେଟୱାର୍କ1 ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM ନେଟୱାର୍କ2 ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpdକୁ ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM କର୍ପୋରେଟକୁ ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବା ଅନୁରୋଧ ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI ଅନଲକ୍ କରିବା ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବା ବିଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"SIM ନେଟୱାର୍କ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM ନେଟୱାର୍କର ସବସେଟ୍ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"SIM କର୍ପୋରେଟ୍ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM ନେଟୱାର୍କ1 ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM ନେଟୱାର୍କ2 ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpd ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM ସେବା ପ୍ରଦାନକାରୀ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM କର୍ପୋରେଟକୁ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP ଇକ୍ୟୁଭେଲେଣ୍ଟ ହୋମ୍ PLMN ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"ନେଟୱାର୍କ ସବସେଟର ସେବା ପ୍ରଦାନକାରୀକୁ ଅନଲକ୍ କରିବା ସଫଳ ହୋଇଛି।"</string>
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 2122643..760b08b 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -237,10 +237,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"ਫ਼ੋਨ ਚੋਣਾਂ"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"ਸਕ੍ਰੀਨ ਲਾਕ"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"ਫ਼ੋਨ ਬੰਦ ਕਰੋ"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"ਪਾਵਰ"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"ਸੰਕਟਕਾਲ"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"ਬਗ ਰਿਪੋਰਟ"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
@@ -299,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"ਟਿਕਾਣਾ"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਧਾਰਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚੋ"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"ਕੈਲੰਡਰ"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string>
@@ -440,8 +438,7 @@
     <string name="permlab_camera" msgid="6320282492904119413">"ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਬਣਾਓ"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"ਇਹ ਐਪ ਕਿਸੇ ਵੀ ਸਮੇਂ ਕੈਮਰੇ ਨੂੰ ਵਰਤ ਕੇ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕਦੀ ਹੈ ਅਤੇ ਵੀਡੀਓ ਫ਼ਾਈਲਾਂ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"ਸਿਸਟਮ ਕੈਮਰੇ ਨੂੰ ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਬਣਾਉਣ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਜਾਂ ਸੇਵਾ ਤੱਕ ਪਹੁੰਚ ਦਿਓ"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"ਇਹ ਵਿਸ਼ੇਸ਼ ਅਧਿਕ੍ਰਿਤ ਜਾਂ ਸਿਸਟਮ ਐਪ ਕਿਸੇ ਵੇਲੇ ਵੀ ਸਿਸਟਮ ਕੈਮਰੇ ਨੂੰ ਵਰਤ ਕੇ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕਦੀ ਹੈ ਅਤੇ ਵੀਡੀਓ ਫ਼ਾਈਲਾਂ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਨੂੰ ਵੀ android.permission.CAMERA ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"ਐਪਲੀਕੇਸ਼ਨ ਜਾਂ ਸੇਵਾ ਨੂੰ ਕੈਮਰਾ ਡੀਵਾਈਸਾਂ ਦੇ ਚਾਲੂ ਜਾਂ ਬੰਦ ਕੀਤੇ ਜਾਣ ਬਾਰੇ ਕਾਲਬੈਕ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ।"</string>
     <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"ਇਹ ਐਪ ਕੋਈ ਵੀ ਕੈਮਰਾ ਡੀਵਾਈਸ ਚਾਲੂ ਹੋਣ (ਕਿਸ ਐਪਲੀਕੇਸ਼ਨ ਰਾਹੀਂ) ਜਾਂ ਬੰਦ ਹੋਣ \'ਤੇ ਕਾਲਬੈਕ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"ਵਾਈਬ੍ਰੇਸ਼ਨ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
@@ -1354,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ਅਸਮਰਥਿਤ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ।"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਅਚਨਚੇਤ ਹਟਾਇਆ ਗਿਆ"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"ਸਮੱਗਰੀ ਗੁਆਉਣ ਤੋਂ ਬਚਣ ਲਈ ਹਟਾਉਣ ਤੋਂ ਪਹਿਲਾਂ ਮੀਡੀਆ ਕੱਢੋ"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string>
@@ -1623,24 +1619,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ਕੀ ਵੌਲਿਊਮ  ਸਿਫ਼ਾਰਸ਼  ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ, ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਮੌਜੂਦਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਚੁਣੀਆਂ ਗਈਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"ਕੀ TalkBack ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ TalkBack ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ, ਜੋ ਕਿ ਇੱਕ ਅਜਿਹਾ ਸਕ੍ਰੀਨ ਰੀਡਰ ਹੈ ਜੋ ਨੇਤਰਹੀਣ ਜਾਂ ਘੱਟ ਦ੍ਰਿਸ਼ਟੀ ਵਾਲੇ ਲੋਕਾਂ ਲਈ ਲਾਭਕਾਰੀ ਹੈ। TalkBack ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਪੂਰੀ ਤਰ੍ਹਾਂ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਕਿਸੇ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾ ਵਿੱਚ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ <xliff:g id="SERVICE">%1$s</xliff:g>, ਇੱਕ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਕਿਸੇ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾ ਵਿੱਚ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ਚਾਲੂ ਕਰੋ"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ਚਾਲੂ ਨਾ ਕਰੋ"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪੂਰਾ ਕੰਟਰੋਲ ਦੇਣਾ ਹੈ?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"ਜੇਕਰ ਤੁਸੀਂ <xliff:g id="SERVICE">%1$s</xliff:g> ਚਾਲੂ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਸ਼ਨ ਦਾ ਵਿਸਤਾਰ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰੇਗਾ।"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"ਪੂਰਾ ਕੰਟਰੋਲ ਉਹਨਾਂ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਹੈ ਜੋ ਪਹੁੰਚਯੋਗਤਾ ਸੰਬੰਧੀ ਲੋੜਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕਰਦੀਆਂ ਹਨ, ਪਰ ਜ਼ਿਆਦਾਤਰ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਨਹੀਂ ਹੁੰਦਾ।"</string>
@@ -1651,10 +1638,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"ਕਰਨ ਦਿਓ"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ਮਨ੍ਹਾਂ ਕਰੋ"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ਕਿਸੇ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਉਸ \'ਤੇ ਟੈਪ ਕਰੋ:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ਅਵਾਜ਼ ਕੁੰਜੀ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ਸ਼ਾਰਟਕੱਟਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ਹੋ ਗਿਆ"</string>
@@ -1662,23 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"ਰੰਗ ਦੀ ਉਲਟੀ ਤਰਤੀਬ"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"ਰੰਗ ਸੁਧਾਈ"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਟੈਪ ਕੀਤੇ ਜਾਣ \'ਤੇ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ (ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ (ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ \'ਤੇ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।"</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string>
     <string name="user_switched" msgid="7249833311585228097">"ਮੌਜੂਦਾ ਉਪਭੋਗਤਾ <xliff:g id="NAME">%1$s</xliff:g>।"</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> ਤੇ ਸਵਿਚ ਕਰ ਰਿਹਾ ਹੈ…"</string>
@@ -2049,8 +2026,7 @@
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ਫ਼ਾਈਲ</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ਫ਼ਾਈਲਾਂ</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ਸਾਂਝਾ ਕਰਨ ਲਈ ਕੋਈ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੇ ਲੋਕ ਨਹੀਂ"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ਐਪ ਸੂਚੀ"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ਹੋਮ"</string>
@@ -2068,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"ਗੱਲਬਾਤ"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"ਗੁਰੱਪ ਗੱਲਬਾਤ"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ਨਿੱਜੀ"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"ਕੰਮ"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ਵਿਅਕਤੀਗਤ ਦ੍ਰਿਸ਼"</string>
@@ -2086,220 +2064,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"ਕੋਈ ਕੰਮ ਸੰਬੰਧੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਨਹੀਂ ਖੋਲ੍ਹ ਸਕਦੀ"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"ਕੋਈ ਨਿੱਜੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰ ਸਕਦੀ"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"ਕੋਈ ਨਿੱਜੀ ਐਪ ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਨਹੀਂ ਖੋਲ੍ਹ ਸਕਦੀ"</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"ਸਿਮ ਨੈੱਟਵਰਕ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"ਸਿਮ ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"ਸਿਮ ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"ਸਿਮ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"ਸਿਮ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM ਨੈੱਟਵਰਕ1 ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM ਨੈੱਟਵਰਕ2 ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM hrpd ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"RUIM ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK ਦਾਖਲ ਕਰੋ"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP ਸਮਾਨ ਹੋਮ PLMN ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਪਿੰਨ"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"ਸਿਮ ਨੈੱਟਵਰਕ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"ਸਿਮ ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ …"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"ਸਿਮ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"ਸਿਮ ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"ਸਿਮ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM ਨੈੱਟਵਰਕ1 ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM ਨੈੱਟਵਰਕ2 ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM hrpd ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP ਸਮਾਨ ਹੋਮ PLMN ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"ਸਿਮ ਨੈੱਟਵਰਕ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"ਸਿਮ ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"ਸਿਮ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"ਸਿਮ ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"ਸਿਮ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM ਨੈੱਟਵਰਕ1 ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM ਨੈੱਟਵਰਕ2 ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK ਅਣਲਾਕ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP ਸਮਾਨ ਹੋਮ PLMN ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਬੇਨਤੀ ਅਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"ਸਿਮ ਨੈੱਟਵਰਕ ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"ਸਿਮ ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"ਸਿਮ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"ਸਿਮ ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"ਸਿਮ ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM ਨੈੱਟਵਰਕ1 ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM ਨੈੱਟਵਰਕ2 ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpd ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਕਰਨ ਦੀ ਬੇਨਤੀ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM ਕਾਰਪੋਰੇਟ ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP ਸਮਾਨ ਹੋਮ PLMN ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI ਅਣਲਾਕ ਸਫਲ।"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"ਨੈੱਟਵਰਕ ਸਬਸੈੱਟ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਅਣਲਾਕ ਸਫਲ।"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e98e120..aa48ea6f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1391,8 +1391,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Nośnik <xliff:g id="NAME">%s</xliff:g> nieobsługiwany"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"To urządzenie nie obsługuje <xliff:g id="NAME">%s</xliff:g>. Kliknij, by użyć obsługiwanego formatu."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"To urządzenie nie obsługuje nośnika <xliff:g id="NAME">%s</xliff:g>. Wybierz, by skonfigurować obsługiwany format."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"To urządzenie nie obsługuje <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g>: nieoczekiwane wyjęcie"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Zanim wyjmiesz nośnik, odłącz go, by uniknąć utraty danych"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> – odłączono"</string>
@@ -2113,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Rozmowa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Rozmowa grupowa"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Osobiste"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Do pracy"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Widok osobisty"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 36b4615..3400cb1 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversa em grupo"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Pessoal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Trabalho"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualização pessoal"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e6dacdd..6ad26b5 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversa de grupo"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"&gt; <xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Pessoal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Trabalho"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Vista pessoal"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 36b4615..3400cb1 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversa"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversa em grupo"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Pessoal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Trabalho"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Visualização pessoal"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 1842982..3dbc019 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -2078,6 +2078,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Conversație"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Conversație de grup"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Serviciu"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Afișarea conținutului personal"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ca2f8f2..7f4f005 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1391,8 +1391,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> не поддерживается"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Устройство не поддерживает этот носитель (<xliff:g id="NAME">%s</xliff:g>). Нажмите, чтобы настроить."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Внешний носитель (<xliff:g id="NAME">%s</xliff:g>) не поддерживается на этом устройстве. Выберите, чтобы изменить формат."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"<xliff:g id="NAME">%s</xliff:g> не поддерживается на этом устройстве."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Карта \"<xliff:g id="NAME">%s</xliff:g>\" извлечена неправильно"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Перед тем как извлечь накопитель, отключите его, чтобы избежать потери данных."</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Накопитель (<xliff:g id="NAME">%s</xliff:g>) извлечен"</string>
@@ -2113,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Чат"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Групповой чат"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Личный"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Рабочий"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Просмотр личных данных"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 64d3f70..a2e556d 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -2046,6 +2046,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"සංවාදය"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"සමූහ සංවාදය"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"පුද්ගලික"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"කාර්යාල"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"පෞද්ගලික දසුන"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e064c37..8039c1a 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -2112,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Konverzácia"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Skupinová konverzácia"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Osobné"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Práca"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Osobné zobrazenie"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b6ba6ee..2d742ef 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -2112,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Pogovor"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Skupinski pogovor"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Osebno"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Služba"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Pogled osebnega profila"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index a1fcf3f..460287d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Biseda"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Bisedë në grup"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Puna"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Pamja personale"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 2e793a6..d72c209 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1371,8 +1371,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"Уређај <xliff:g id="NAME">%s</xliff:g> није подржан"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Овај уређај не подржава овај уређај <xliff:g id="NAME">%s</xliff:g>. Додирните да бисте подесили подржани формат."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Овај уређај не подржава овај медиј (<xliff:g id="NAME">%s</xliff:g>). Изаберите да га подесите у подржаном формату."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Овај уређај не подржава: <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Уређај <xliff:g id="NAME">%s</xliff:g> је неочекивано уклоњен"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Избаците медијум пре него што га уклоните да не бисте изгубили садржај"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> је уклоњен/а"</string>
@@ -2079,6 +2078,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Конверзација"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Групна конверзација"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Лични"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Пословни"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Лични приказ"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 0b2962c..9b7318b 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Konversation"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Gruppkonversation"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Privat"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Jobb"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personlig vy"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0360106..f6a831a 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Mazungumzo"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Mazungumzo ya Kikundi"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Binafsi"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Kazini"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Mwonekano wa binafsi"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6ec7c75..43eca0e 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -299,7 +299,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"தொடர்புகளை அணுக வேண்டும்"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"இருப்பிடம்"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"இந்தச் சாதனத்தின் இருப்பிடத்தை அறிந்து கொள்ள"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"கேலெண்டர்"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"கேலெண்டரை அணுகலாம்"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS அனுப்பலாம், வந்த SMSகளைப் பார்க்கலாம்"</string>
@@ -443,8 +443,7 @@
     <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
     <skip />
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"கேமரா சாதனங்கள் திறக்கப்படும்போதோ மூடப்படும்போதோ அது குறித்த கால்பேக்குகளைப் பெற ஒரு ஆப்ஸையோ சேவையையோ அனுமதிக்கவும்."</string>
-    <!-- no translation found for permdesc_cameraOpenCloseListener (2002636131008772908) -->
-    <skip />
+    <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"எந்தக் கேமரா சாதனமும் (எந்த ஆப்ஸாலும்) திறக்கப்படும்போதோ மூடப்படும்போதோ இந்த ஆப்ஸால் கால்பேக்குகளைப் பெற முடியும்."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"அதிர்வைக் கட்டுப்படுத்துதல்"</string>
     <string name="permdesc_vibrate" msgid="8733343234582083721">"அதிர்வைக் கட்டுப்படுத்தப் ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permdesc_vibrator_state" msgid="7050024956594170724">"அதிர்வு நிலையை அணுக ஆப்ஸை அனுமதிக்கும்."</string>
@@ -2066,11 +2065,10 @@
     <string name="accessibility_system_action_accessibility_menu_label" msgid="8436484650391125184">"அணுகல்தன்மை மெனு"</string>
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸின் தலைப்புப் பட்டி."</string>
     <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> என்பதை வரம்பிடப்பட்ட பக்கெட்திற்குள் சேர்க்கப்பட்டது"</string>
-    <!-- no translation found for conversation_single_line_name_display (8958948312915255999) -->
-    <skip />
-    <!-- no translation found for conversation_title_fallback_one_to_one (1980753619726908614) -->
-    <skip />
-    <!-- no translation found for conversation_title_fallback_group_chat (456073374993104303) -->
+    <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
+    <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"உரையாடல்"</string>
+    <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"குழு உரையாடல்"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
     <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"தனிப்பட்ட சுயவிவரம்"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"பணிச் சுயவிவரம்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 8bd07f3..f9e95a6 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -237,10 +237,8 @@
     <string name="global_actions" product="default" msgid="6410072189971495460">"ఫోన్ ఎంపికలు"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"స్క్రీన్ లాక్"</string>
     <string name="global_action_power_off" msgid="4404936470711393203">"పవర్ ఆఫ్ చేయి"</string>
-    <!-- no translation found for global_action_power_options (1185286119330160073) -->
-    <skip />
-    <!-- no translation found for global_action_restart (4678451019561687074) -->
-    <skip />
+    <string name="global_action_power_options" msgid="1185286119330160073">"పవర్"</string>
+    <string name="global_action_restart" msgid="4678451019561687074">"రీస్టార్ట్ చేయి"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"అత్యవసరం"</string>
     <string name="global_action_bug_report" msgid="5127867163044170003">"బగ్ నివేదిక"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"సెషన్‌ను ముగించు"</string>
@@ -299,7 +297,7 @@
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"మీ పరిచయాలను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"స్థానం"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి"</string>
-    <string name="permgrouplab_calendar" msgid="6426860926123033230">"క్యాలెండర్"</string>
+    <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"మీ క్యాలెండర్‌ను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string>
@@ -440,10 +438,9 @@
     <string name="permlab_camera" msgid="6320282492904119413">"చిత్రాలు మరియు వీడియోలు తీయడం"</string>
     <string name="permdesc_camera" msgid="1354600178048761499">"ఈ యాప్‌ కెమెరాను ఉపయోగించి ఎప్పుడైనా చిత్రాలను తీయగలదు మరియు వీడియోలను రికార్డ్ చేయగలదు."</string>
     <string name="permlab_systemCamera" msgid="3642917457796210580">"ఫోటోలు, వీడియోలు తీయడానికి సిస్టమ్ కెమెరాలకు యాప్, లేదా సేవా యాక్సెస్‌ను అనుమతించండి"</string>
-    <!-- no translation found for permdesc_systemCamera (5938360914419175986) -->
-    <skip />
+    <string name="permdesc_systemCamera" msgid="5938360914419175986">"ఈ విశేష లేదా సిస్టమ్ యాప్ ఎప్పుడైనా సిస్టమ్ కెమెరాను ఉపయోగించి ఫోటోలు తీయగలదు, వీడియోలను రికార్డ్ చేయగలదు. యాప్‌కు android.permission.CAMERA అనుమతి ఇవ్వడం కూడా అవసరం"</string>
     <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"కెమెరా పరికరాలు తెరుచుకుంటున్నప్పుడు లేదా మూసుకుంటున్నప్పుడు కాల్‌బ్యాక్‌లను స్వీకరించడానికి యాప్‌ను లేదా సర్వీస్‌ను అనుమతించండి."</string>
-    <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"ఏదైనా కెమెరా పరికరం తెరుచుకుంటున్నప్పుడు (ఏదైనా యాప్ ద్వారా) లేదా మూసుకుంటున్నప్పుడు ఈ సిగ్నేచర్ యాప్ కాల్‌బ్యాక్‌లను అందుకోగలదు."</string>
+    <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"ఏదైనా కెమెరా పరికరం తెరుచుకుంటున్నప్పుడు (ఏదైనా యాప్ ద్వారా) లేదా మూసుకుంటున్నప్పుడు ఈ యాప్ కాల్‌బ్యాక్‌లను అందుకోగలదు."</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"వైబ్రేషన్‌ను నియంత్రించడం"</string>
     <string name="permdesc_vibrate" msgid="8733343234582083721">"వైబ్రేటర్‌ను నియంత్రించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permdesc_vibrator_state" msgid="7050024956594170724">"వైబ్రేటర్ స్థితిని యాక్సెస్ చేసేందుకు యాప్‌ను అనుమతిస్తుంది."</string>
@@ -1354,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>కి మద్దతు లేదు"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>కి మద్దతు ఇవ్వదు. మద్దతు కలిగిన ఆకృతిలో సెటప్ చేయడానికి నొక్కండి."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>కి మద్దతు ఇవ్వదు. మద్దతు కలిగిన ఆకృతిలో సెటప్ చేయడానికి ఎంచుకోండి."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>ను సపోర్ట్ చేయదు."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ఊహించని విధంగా తీసివేయబడింది"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"కంటెంట్‌ని కోల్పోవడాన్ని నివారించాలంటే తీసివేయబోయే ముందు మీడియాని తొలగించండి"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> తీసివేయబడింది"</string>
@@ -1623,24 +1619,15 @@
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్‌ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్‌లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"యాక్సెస్ సామర్థ్యం షార్ట్‌కట్‌ను ఉపయోగించాలా?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"షార్ట్‌కట్ ఆన్ చేసి ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్‌లను 3 సెకన్ల పాటు నొక్కి ఉంచితే యాక్సెస్ సౌలభ్య ఫీచర్ ప్రారంభం అవుతుంది."</string>
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (8417489297036013065) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_warning (3740723309483706911) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_multiple_service_list (6935581470716541531) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning_title (3410100187167382427) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_talkback_warning (8412954203626349109) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning_title (2819109500943271385) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_single_service_warning (6363127705112844257) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_on (5463618449556111344) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_off (3651336255403648739) -->
-    <skip />
+    <string name="accessibility_shortcut_multiple_service_warning_title" msgid="8417489297036013065">"యాక్సెసిబిలిటీ‌లను ఆన్ చేయాలా?"</string>
+    <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"రెండు వాల్యూమ్ కీలను కొంత సేపు నొక్కి పట్టుకోవడం ద్వారా యాక్సెసిబిలిటీలు ఆన్ అవుతాయి. ఇది మీ పరికరం పనిచేసే విధానాన్ని మార్చవచ్చు.\n\nప్రస్తుత ఫీచర్లు:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nఎంపిక చేసిన ఫీచర్లను మీరు సెట్టింగ్‌లు&gt;యాక్సెసిబిలిటీలో మార్చవచ్చు."</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"\'TalkBack\'ను ఆన్ చేయాలా?"</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"రెండు వాల్యూమ్ కీలను కొన్ని సెకన్ల పాటు నొక్కి, పట్టుకోవడం ద్వారా TalkBack ఆన్ అవుతుంది, ఇది అంధులకు, చూపు సరిగా లేని వారికి ఉపయోగపడే స్క్రీన్ రీడర్. మీ పరికరం పని చేసే విధానాన్ని TalkBack పూర్తిగా మార్చివేస్తుంది.\n\nసెట్టింగ్‌లు &gt; యాక్సెసిబిలిటీలో, వేరొక ఫీచర్‌ను ప్రారంభించేలా ఈ షార్ట్ కట్‌ను మీరు మార్చవచ్చు."</string>
+    <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> ఆన్ చేయాాలా?"</string>
+    <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"రెండు వాల్యూమ్ కీలను కొన్ని సెకన్ల పాటు నొక్కి పట్టుకోవడం ద్వారా యాక్సెసిబిలిటీ అయిన <xliff:g id="SERVICE">%1$s</xliff:g> ఆన్ అవుతుంది. ఇది మీ పరికరం పని చేసే విధానాన్ని మార్చవచ్చు.\n\nసెట్టింగ్‌లు &gt; యాక్సెసిబిలిటీలో, వేరొక ఫీచర్‌ను ప్రారంభించేలా ఈ షార్ట్ కట్‌ను మీరు మార్చవచ్చు."</string>
+    <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ఆన్ చేయి"</string>
+    <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ఆన్ చేయకండి"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g>కి మీ పరికరంపై పూర్తి నియంత్రణను ఇవ్వాలనుకుంటున్నారా?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"మీరు <xliff:g id="SERVICE">%1$s</xliff:g>ని ఆన్ చేస్తే, డేటా ఎన్‌క్రిప్షన్‌ను మెరుగుపరచడానికి మీ పరికరం మీ స్క్రీన్ లాక్‌ను ఉపయోగించదు."</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"అవసరమైన యాక్సెస్ సామర్ధ్యం కోసం యాప్‌లకు పూర్తి నియంత్రణ ఇవ్వడం తగిన పనే అయినా, అన్ని యాప్‌లకు అలా ఇవ్వడం సరికాదు."</string>
@@ -1651,10 +1638,8 @@
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"అనుమతించు"</string>
     <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"నిరాకరించు"</string>
     <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ఫీచర్‌ని ఉపయోగించడం ప్రారంభించడానికి, దాన్ని ట్యాప్ చేయండి:"</string>
-    <!-- no translation found for accessibility_edit_shortcut_menu_button_title (239446795930436325) -->
-    <skip />
-    <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (1077294237378645981) -->
-    <skip />
+    <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"యాక్సెసిబిలిటీ బటన్‌తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
+    <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"వాల్యూమ్ కీ షార్ట్‌కట్‌తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
     <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ఆఫ్ చేయబడింది"</string>
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"షార్ట్‌కట్‌లను ఎడిట్ చేయి"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"పూర్తయింది"</string>
@@ -1662,23 +1647,15 @@
     <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string>
     <string name="color_inversion_feature_name" msgid="326050048927789012">"రంగుల మార్పిడి"</string>
     <string name="color_correction_feature_name" msgid="3655077237805422597">"రంగు సవరణ"</string>
-    <!-- no translation found for accessibility_shortcut_enabling_service (5473495203759847687) -->
-    <skip />
-    <!-- no translation found for accessibility_shortcut_disabling_service (8675244165062700619) -->
-    <skip />
+    <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
+    <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
-    <!-- no translation found for accessibility_button_prompt_text (8343213623338605305) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_prompt_text (8742535972130563952) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_prompt_text (5211827854510660203) -->
-    <skip />
-    <!-- no translation found for accessibility_button_instructional_text (8853928358872550500) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_instructional_text (9196230728837090497) -->
-    <skip />
-    <!-- no translation found for accessibility_gesture_3finger_instructional_text (3425123684990193765) -->
-    <skip />
+    <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"యాక్సెస్ సామర్థ్య బటన్‌ను మీరు నొక్కినప్పుడు ఉపయోగించాల్సిన ఒక ఫీచర్‌ను ఎంచుకోండి:"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"యాక్సెసిబిలిటీ సంజ్ఞతో ఉపయోగించడానికి ఒక ఫీచర్‌ని ఎంచుకోండి (రెండు వేళ్లతో స్క్రీన్‌ను కింద నుండి పైకి స్వైప్ చేయండి):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"యాక్సెసిబిలిటీ సంజ్ఞతో ఉపయోగించడానికి ఒక ఫీచర్‌ను ఎంచుకోండి (మూడు చేతి వేళ్లతో స్క్రీన్‌ను కింద నుండి పైకి స్వైప్ చేయండి):"</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"ఫీచర్ల మధ్య మారడానికి, యాక్సెసిబిలిటీ బటన్‌ను నొక్కి &amp; పట్టుకోండి."</string>
+    <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"ఫీచర్ల మధ్య మారడానికి, రెండు చేతి వేళ్ళతో పైకి స్వైప్ చేసి పట్టుకోండి."</string>
+    <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"ఫీచర్ల మధ్య మారడానికి, మూడు చేతి వేళ్ళతో పైకి స్వైప్ చేసి పట్టుకోండి."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"మాగ్నిఫికేషన్"</string>
     <string name="user_switched" msgid="7249833311585228097">"ప్రస్తుత వినియోగదారు <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g>కి మారుస్తోంది…"</string>
@@ -2049,8 +2026,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ఫైల్‌లు</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ఫైల్</item>
     </plurals>
-    <!-- no translation found for chooser_no_direct_share_targets (1511722103987329028) -->
-    <skip />
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"షేర్ చేయకూడని వ్యక్తులు"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"యాప్‌ల జాబితా"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ఈ యాప్‌కు రికార్డ్ చేసే అనుమతి మంజూరు కాలేదు, అయినా ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"హోమ్"</string>
@@ -2068,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"సంభాషణ"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"గ్రూప్ సంభాషణ"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"వ్యక్తిగతం"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"కార్యాలయం"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"వ్యక్తిగత వీక్షణ"</string>
@@ -2086,220 +2064,112 @@
     <string name="resolver_no_work_apps_available_resolve" msgid="1244844292366099399">"కార్యాలయ యాప్‌లు ఏవీ ఈ కంటెంట్‌ను తెరవలేవు"</string>
     <string name="resolver_no_personal_apps_available_share" msgid="5639102815174748732">"వ్యక్తిగత యాప్‌లు ఏవీ ఈ కంటెంట్‌ను సపోర్ట్ చేయలేవు"</string>
     <string name="resolver_no_personal_apps_available_resolve" msgid="5120671970531446978">"వ్యక్తిగత యాప్‌లు ఏవీ ఈ కంటెంట్‌ను తెరవలేవు"</string>
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ENTRY (8050953231914637819) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY (7164399703751688214) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ENTRY (4447629474818217364) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY (973059024670737358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ENTRY (4487435301206073787) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY (768060297218652809) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY (7129527319490548930) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY (2876126640607573252) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY (8952595089930109282) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ENTRY (3013902515773728996) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ENTRY (2974411408893410289) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ENTRY (687618528751880721) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ENTRY (6810596579655575381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ENTRY (2715929642540980259) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY (8557791623303951590) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ENTRY (7382468767274580323) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY (6730880791104286987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY (6432126539782267026) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY (1730510161529488920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY (3369885925003346830) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY (9129139686191167829) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY (2869929685874615358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ENTRY (1238663472392741771) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY (3988705848553894358) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ENTRY (6186770686690993200) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ENTRY (7043865376145617024) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ENTRY (6144227308185112176) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS (4233355366318061180) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS (6742563947637715645) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS (2033399698172403560) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS (4795977251920732254) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS (1090425878157254446) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS (6476898876518094438) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS (6006806734293747731) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (6546680489620881893) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS (3506845511000727015) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_IN_PROGRESS (6709169861932992750) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS (4013870911606478520) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS (9032651188219523434) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS (6584576506344491207) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS (830981927724888114) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS (7851790973098894802) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_IN_PROGRESS (1149560739586960121) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS (5708964693522116025) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS (7288103122966483455) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS (4036752174056147753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS (5089536274515338566) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS (6737197986936251958) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS (5658767775619998623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS (665978313257653727) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS (3857142652251836850) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS (2695664012344346788) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS (2695678959963807782) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS (1230605365926493599) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_ERROR (1924844017037151535) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR (3372797822292089708) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR (1878443146720411381) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_ERROR (7664778312218023192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_ERROR (2472944311643350302) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_ERROR (828089694480999120) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_ERROR (17619001007092511) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_ERROR (807214229604353614) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_ERROR (8644184447744175747) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR (3801002648649640407) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_ERROR (707397021218680753) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR (894358680773257820) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR (352466878146726991) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR (7353389721907138671) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR (2655263155490857920) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_ERROR (6903740900892931310) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR (5165901670447518687) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR (2856763216589267623) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR (817542684437829139) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR (5178635064113393143) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR (5391587926974531008) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR (4895494864493315868) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_ERROR (9017576601595353649) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR (1116993930995545742) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_ERROR (7559167306794441462) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_ERROR (2782926139511136588) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_ERROR (1890493954453456758) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUCCESS (4886243367747126325) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS (4053809277733513987) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS (8249342930499801740) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_SUCCESS (2339794542560381270) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_SUCCESS (6975608174152828954) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS (2846699261330463192) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS (5335414726057102801) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_SUCCESS (8868100318474971969) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS (6020936629725666932) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS (6944873647584595489) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_SUCCESS (2526483514124121988) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS (7662200333621664621) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS (2861223407953766632) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS (5345648571175243272) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS (3725278343103422466) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS (6998502547560297983) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS (8555433771162560361) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS (3555767296933606232) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS (6778051818199974237) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS (4080108758498911429) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS (7873675303000794343) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS (1763198215069819523) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SPN_SUCCESS (2053891977727320532) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS (8146602361895007345) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_ICCID_SUCCESS (8058678548991999545) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_IMPI_SUCCESS (2545608067978550571) -->
-    <skip />
-    <!-- no translation found for PERSOSUBSTATE_SIM_NS_SP_SUCCESS (4352382949744625007) -->
-    <skip />
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM నెట్‌వర్క్ అన్‌లాక్ పిన్‌"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM నెట్‌వర్క్ సబ్‌సెట్ అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"SIM కార్పొరేట్ అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ENTRY" msgid="973059024670737358">"SIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్‌ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ENTRY" msgid="4487435301206073787">"SIM అన్‌లాక్‌ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ENTRY" msgid="768060297218652809">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ENTRY" msgid="7129527319490548930">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM నెట్‌వర్క్1 అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM నెట్‌వర్క్2 అన్‌లాక్ పిన్‌"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM hrpd అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"RUIM కార్పొరేట్ అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ENTRY" msgid="7382468767274580323">"RUIM అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ENTRY" msgid="6730880791104286987">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ENTRY" msgid="6432126539782267026">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ENTRY" msgid="1730510161529488920">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="3369885925003346830">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUKని నమోదు చేయండి"</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN అన్‌లాక్‌ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"SP Equivalent Home PLMN అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"నెట్‌వర్క్ సబ్‌సెట్ సర్వీస్ ప్రొవైడర్ అన్‌లాక్ పిన్"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_IN_PROGRESS" msgid="4233355366318061180">"SIM నెట్‌వర్క్ అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_IN_PROGRESS" msgid="6742563947637715645">"SIM నెట్‌వర్క్ సబ్‌సెట్ అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="2033399698172403560">"SIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్‌ అభ్యర్థించబడుతోంది..."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_IN_PROGRESS" msgid="4795977251920732254">"SIM కార్పొరేట్ అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_IN_PROGRESS" msgid="1090425878157254446">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_IN_PROGRESS" msgid="6476898876518094438">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_IN_PROGRESS" msgid="6006806734293747731">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM అన్‌లాక్‌ని అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM నెట్‌వర్క్1 అన్‌లాక్ అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM నెట్‌వర్క్2 అన్‌లాక్ అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM hrpd అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"RUIM కార్పొరేట్ అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"SP Equivalent Home PLMN అన్‌లాక్‌ను అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"నెట్‌వర్క్ సబ్‌సెట్ సర్వీస్ ప్రొవైడర్ అన్‌లాక్‌ని అభ్యర్థిస్తోంది..."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_IN_PROGRESS" msgid="6737197986936251958">"RUIM అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_IN_PROGRESS" msgid="5658767775619998623">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_IN_PROGRESS" msgid="665978313257653727">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_IN_PROGRESS" msgid="3857142652251836850">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_IN_PROGRESS" msgid="2695664012344346788">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="2695678959963807782">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_IN_PROGRESS" msgid="1230605365926493599">"PUK అన్‌లాక్‌ను అభ్యర్థిస్తోంది…"</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_ERROR" msgid="1924844017037151535">"SIM నెట్‌వర్క్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ERROR" msgid="3372797822292089708">"SIM నెట్‌వర్క్ సబ్‌సెట్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"SIM కార్పొరేట్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM అన్‌లాక్‌ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM నెట్‌వర్క్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM నెట్‌వర్క్2 అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM Hrpd అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"RUIM కార్పొరేట్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_ERROR" msgid="707397021218680753">"RUIM అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_ERROR" msgid="894358680773257820">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_ERROR" msgid="352466878146726991">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ERROR" msgid="7353389721907138671">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ERROR" msgid="2655263155490857920">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_ERROR" msgid="6903740900892931310">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_ERROR" msgid="5165901670447518687">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_ERROR" msgid="2856763216589267623">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_ERROR" msgid="817542684437829139">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_ERROR" msgid="5178635064113393143">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK అన్‌లాక్ విజయవంతం కాలేదు."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"SP Equivalent Home PLMN అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI నెట్‌వర్క్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"నెట్‌వర్క్ సబ్‌సెట్ సర్వీస్ ప్రొవైడర్ అన్‌లాక్ అభ్యర్థన విఫలమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUCCESS" msgid="4886243367747126325">"SIM నెట్‌వర్క్ అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_SUCCESS" msgid="4053809277733513987">"SIM నెట్‌వర్క్ సబ్‌సెట్ అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"SIM కార్పొరేట్ అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM అన్‌లాక్‌ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM నెట్‌వర్క్1 అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM నెట్‌వర్క్2 అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM Hrpd అన్‌లాక్ అభ్యర్థన విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM సర్వీస్ ప్రొవైడర్ అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"RUIM కార్పొరేట్ అన్‌లాక్ అభ్యర్థన విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_SUCCESS" msgid="2526483514124121988">"RUIM అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_PUK_SUCCESS" msgid="7662200333621664621">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK_SUCCESS" msgid="2861223407953766632">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_SUCCESS" msgid="5345648571175243272">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="3725278343103422466">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SIM_PUK_SUCCESS" msgid="6998502547560297983">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_PUK_SUCCESS" msgid="8555433771162560361">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_PUK_SUCCESS" msgid="3555767296933606232">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_HRPD_PUK_SUCCESS" msgid="6778051818199974237">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_SUCCESS" msgid="4080108758498911429">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK_SUCCESS" msgid="7873675303000794343">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_SUCCESS" msgid="1763198215069819523">"PUK అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SPN_SUCCESS" msgid="2053891977727320532">"SPN అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_SUCCESS" msgid="8146602361895007345">"SP Equivalent Home PLMN అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_ICCID_SUCCESS" msgid="8058678548991999545">"ICCID అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_IMPI_SUCCESS" msgid="2545608067978550571">"IMPI అన్‌లాక్ విజయవంతమైంది."</string>
+    <string name="PERSOSUBSTATE_SIM_NS_SP_SUCCESS" msgid="4352382949744625007">"నెట్‌వర్క్ సబ్‌సెట్ సర్వీస్ ప్రొవైడర్ అన్‌లాక్ విజయవంతమైంది."</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d22f3e2..041423d 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"ไม่สนับสนุน <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"อุปกรณ์นี้ไม่สนับสนุน <xliff:g id="NAME">%s</xliff:g> นี้ แตะเพื่อตั้งค่าในรูปแบบที่สนับสนุน"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"อุปกรณ์นี้ไม่รองรับ <xliff:g id="NAME">%s</xliff:g> นี้ เลือกเพื่อตั้งค่าในรูปแบบที่รองรับ"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"อุปกรณ์เครื่องนี้ไม่รองรับ <xliff:g id="NAME">%s</xliff:g> นี้"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ถูกนำออกไปโดยไม่คาดคิด"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"ยกเลิกการต่อเชื่อมสื่อก่อนที่จะนำออกเพื่อหลีกเลี่ยงไม่ให้เนื้อหาสูญหาย"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"นำ <xliff:g id="NAME">%s</xliff:g> ออกแล้ว"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"การสนทนา"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"บทสนทนากลุ่ม"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ส่วนตัว"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"งาน"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"มุมมองส่วนตัว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 07e204e..0b1ee65 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Pag-uusap"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Panggrupong Pag-uusap"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Personal"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Trabaho"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Personal na view"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 2433cb0..5861589 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Görüşme"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grup Görüşmesi"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Kişisel"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"İş"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Kişisel görünüm"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 659d1ac..0cb185c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -2112,6 +2112,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Чат"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Груповий чат"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Особисте"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Робоче"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Особистий перегляд"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 6607431..e717898 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"غیر تعاون یافتہ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"یہ آلہ <xliff:g id="NAME">%s</xliff:g> کو سپورٹ نہیں کرتا۔ ایک سپورٹ یافتہ فارمیٹ میں سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"یہ آلہ اس <xliff:g id="NAME">%s</xliff:g> کو سپورٹ نہیں کرتا ہے۔ ایک سپورٹ یافتہ فارمیٹ میں سیٹ اپ کرنے کیلئے منتخب کریں۔"</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"یہ آلہ اس <xliff:g id="NAME">%s</xliff:g> کو سپورٹ نہیں کرتا ہے۔"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> غیر متوقع طور پر ہٹا دیا گیا"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"مواد کھونے سے بچنے کے لئے ہٹانے سے پہلے میڈیا خارج کریں"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> کو ہٹا دیا گیا"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"گفتگو"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"گروپ گفتگو"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"ذاتی"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"دفتر"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"ذاتی ملاحظہ"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 442686f..d2dde71 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -240,7 +240,7 @@
     <string name="global_action_power_options" msgid="1185286119330160073">"Quvvat"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"Qayta ishga tushirish"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"Favqulodda chaqiruv"</string>
-    <string name="global_action_bug_report" msgid="5127867163044170003">"Nosozlik haqida ma’lumot berish"</string>
+    <string name="global_action_bug_report" msgid="5127867163044170003">"Xatoliklar hisoboti"</string>
     <string name="global_action_logout" msgid="6093581310002476511">"Seansni yakunlash"</string>
     <string name="global_action_screenshot" msgid="2610053466156478564">"Skrinshot"</string>
     <string name="bugreport_title" msgid="8549990811777373050">"Xatoliklar hisoboti"</string>
@@ -1623,7 +1623,7 @@
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Maxsus imkoniyatlarni yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. Qurilmangiz ishlashida oʻzgarish yuz berishi mumkin.\n\nJoriy funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nTanlangan funksiyalarni Sozlamalar ichidagi Maxsus imkoniyatlar ustiga bosib oʻzgartirishingiz mumkin."</string>
     <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_talkback_warning_title" msgid="3410100187167382427">"TalkBack yoqilsinmi?"</string>
-    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"TalkBack funksiyasini yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. U ekrandan oʻqish dasturi hisoblanib, koʻzi xira koʻradigan va koʻzi ojiz insonlar uchun juda foydali. TalkBack funksiyasi qulringizning ishlashini butunlay oʻzgartirib yuborishi mumkin.\n\nBu tezkor tugmalarni boshqa funksiyaga Sozlamalar ichidagi Maxsus imkoniyatlar orqali tayinlash mumkin."</string>
+    <string name="accessibility_shortcut_talkback_warning" msgid="8412954203626349109">"TalkBack funksiyasini yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. U ekrandan oʻqish dasturi hisoblanib, koʻzi xira koʻradigan va koʻzi ojiz insonlar uchun juda foydali. TalkBack funksiyasi qurilmangiz ishlashini butunlay oʻzgartirib yuborishi mumkin.\n\nBu tezkor tugmalarni boshqa funksiyaga Sozlamalar ichidagi Maxsus imkoniyatlar orqali tayinlash mumkin."</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="2819109500943271385">"<xliff:g id="SERVICE">%1$s</xliff:g> yoqilsinmi?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> funksiyasini yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. Qurilmangiz ishlashida oʻzgarish yuz berishi mumkin.\n\nBu tezkor tugmalarni boshqa funksiyaga Sozlamalar ichidagi Maxsus imkoniyatlar orqali tayinlash mumkin."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Yoqilsin"</string>
@@ -1653,7 +1653,7 @@
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Maxsus imkoniyatlar tugmasi bosilganda ishga tushadigan funksiyani tanlang:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Maxsus imkoniyatlar ishorasi bilan ishga tushadigan funksiyani tanlang (ikkita barmoq bilan ekranning pastidan tepaga surib tortilganda):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Maxsus imkoniyatlar ishorasi bilan ishga tushadigan funksiyani tanlang (uchta barmoq bilan ekranning pastidan tepaga surib tortilganda):"</string>
-    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Funksiyalarni almashtirihs uchun maxsus imkoniyatlar tugmasini bosib turing."</string>
+    <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Funksiyalarni almashtirish uchun maxsus imkoniyatlar tugmasini bosib turing."</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Funksiyalarni almashtirish uchun ikkita barmoq bilan tepaga suring va bosib turing."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Funksiyalarni almashtirish uchun uchta barmoq bilan tepaga suring va bosib turing."</string>
     <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Kattalashtirish"</string>
@@ -2026,7 +2026,7 @@
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ta fayl</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ta fayl</item>
     </plurals>
-    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Ulashish uchun hech qanday odam tavsiya qilinmagan"</string>
+    <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Ulashish uchun hech kim tavsiya qilinmagan"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Ilovalar roʻyxati"</string>
     <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Bu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string>
     <string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Bosh sahifa"</string>
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Suhbat"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Guruh suhbati"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Shaxsiy"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Ish"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Shaxsiy rejim"</string>
@@ -2072,8 +2073,8 @@
     <string name="PERSOSUBSTATE_SIM_CORPORATE_PUK_ENTRY" msgid="2876126640607573252">"PUK kodni kiriting"</string>
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_ENTRY" msgid="8952595089930109282">"PUK kodni kiriting"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_ENTRY" msgid="3013902515773728996">"PUK kodni kiriting"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM kartalaridagi tarmoq1 qulfini ochish uchun PIN kod"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM kartalaridagi tarmoq2 qulfini ochish uchun PIN kod"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ENTRY" msgid="2974411408893410289">"RUIM kartalaridagi network1 qulfini ochish uchun PIN kod"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ENTRY" msgid="687618528751880721">"RUIM kartalaridagi network2 qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ENTRY" msgid="6810596579655575381">"RUIM HRPD kartalari qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_ENTRY" msgid="2715929642540980259">"Korporativ RUIM kartalar qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ENTRY" msgid="8557791623303951590">"RUIM kartalari aloqa operatori qulfini ochish uchun PIN kod"</string>
@@ -2085,7 +2086,7 @@
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ENTRY" msgid="9129139686191167829">"PUK kodni kiriting"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ENTRY" msgid="2869929685874615358">"PUK kodni kiriting"</string>
     <string name="PERSOSUBSTATE_SIM_SPN_ENTRY" msgid="1238663472392741771">"SPN qulfini ochish uchun PIN kod"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"PLMN operatorining muqobil uy tarmoqlarini qulfini ochish uchun PIN kod"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ENTRY" msgid="3988705848553894358">"PLMN operatorining muqobil uy tarmoqlari qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_ENTRY" msgid="6186770686690993200">"ICCID qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_ENTRY" msgid="7043865376145617024">"IMPI qulfini ochish uchun PIN kod"</string>
     <string name="PERSOSUBSTATE_SIM_NS_SP_ENTRY" msgid="6144227308185112176">"SIM karta tarmoq qismi aloqa operatorini qulfdan chiqarish uchun PIN kod"</string>
@@ -2099,13 +2100,13 @@
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK_IN_PROGRESS" msgid="6546680489620881893">"PUK kod bilan qulfni ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_PUK_IN_PROGRESS" msgid="3506845511000727015">"PUK kod bilan qulfni ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_SIM_SIM_IN_PROGRESS" msgid="6709169861932992750">"SIM karta qulfini ochish soʻralmoqda…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM kartalaridagi tarmoq1 qulfini ochish soʻralmoqda…"</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM kartalaridagi tarmoq2 qulfini ochish soʻralmoqda…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_IN_PROGRESS" msgid="4013870911606478520">"RUIM kartalaridagi network1 qulfini ochish soʻralmoqda…"</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_IN_PROGRESS" msgid="9032651188219523434">"RUIM kartalaridagi network2 qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_IN_PROGRESS" msgid="6584576506344491207">"RUIM HRPD kartalari qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_IN_PROGRESS" msgid="830981927724888114">"RUIM kartalari aloqa operatori qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_IN_PROGRESS" msgid="7851790973098894802">"Korporativ RUIM kartalari qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_SIM_SPN_IN_PROGRESS" msgid="1149560739586960121">"SPN qulfini ochish soʻralmoqda…"</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"PLMN operatorining muqobil uy tarmoqlarini qulfini ochish soʻralmoqda…"</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_IN_PROGRESS" msgid="5708964693522116025">"PLMN operatorining muqobil uy tarmoqlari qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_IN_PROGRESS" msgid="7288103122966483455">"ICCID qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_IN_PROGRESS" msgid="4036752174056147753">"IMPI qulfini ochish soʻralmoqda…"</string>
     <string name="PERSOSUBSTATE_SIM_NS_SP_IN_PROGRESS" msgid="5089536274515338566">"Aloqa operatori tarmoq qismini qulfdan chiqarish soʻralmoqda…"</string>
@@ -2121,8 +2122,8 @@
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_ERROR" msgid="1878443146720411381">"SIM karta tegishli aloqa operatori qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ERROR" msgid="7664778312218023192">"Korporativ SIM kartalar qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_SIM_SIM_ERROR" msgid="2472944311643350302">"SIM karta qulfini ochish soʻrovi yuborilmadi."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM kartalaridagi tarmoq1 qulfini ochish soʻrovi yuborilmadi."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM kartalaridagi tarmoq2 qulfini ochish soʻrovi yuborilmadi."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_ERROR" msgid="828089694480999120">"RUIM kartalaridagi network1 qulfini ochish soʻrovi yuborilmadi."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_ERROR" msgid="17619001007092511">"RUIM kartalaridagi network2 qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_ERROR" msgid="807214229604353614">"RUIM HRPD kartalari qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_ERROR" msgid="8644184447744175747">"Korporativ RUIM kartalar qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_ERROR" msgid="3801002648649640407">"RUIM kartalari aloqa operatori qulfini ochish soʻrovi yuborilmadi."</string>
@@ -2139,7 +2140,7 @@
     <string name="PERSOSUBSTATE_RUIM_RUIM_PUK_ERROR" msgid="5391587926974531008">"PUK kod bilan qulf ochilmadi."</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_PUK_ERROR" msgid="4895494864493315868">"PUK kod bilan qulf ochilmadi."</string>
     <string name="PERSOSUBSTATE_SIM_SPN_ERROR" msgid="9017576601595353649">"SPN qulfini ochish soʻrovi yuborilmadi."</string>
-    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"PLMN operatorining muqobil uy tarmoqlarini qulfi ochilmadi."</string>
+    <string name="PERSOSUBSTATE_SIM_SP_EHPLMN_ERROR" msgid="1116993930995545742">"PLMN operatorining muqobil uy tarmoqlari qulfi ochilmadi."</string>
     <string name="PERSOSUBSTATE_SIM_ICCID_ERROR" msgid="7559167306794441462">"ICCID qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_SIM_IMPI_ERROR" msgid="2782926139511136588">"IMPI qulfini ochish soʻrovi yuborilmadi."</string>
     <string name="PERSOSUBSTATE_SIM_NS_SP_ERROR" msgid="1890493954453456758">"Aloqa operatori tarmoq qismini qulfdan chiqarish soʻrovi yuborilmadi."</string>
@@ -2148,8 +2149,8 @@
     <string name="PERSOSUBSTATE_SIM_SERVICE_PROVIDER_SUCCESS" msgid="8249342930499801740">"SIM karta tegishli aloqa operatori qulfi ochildi"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_SUCCESS" msgid="2339794542560381270">"Korporativ SIM kartalar qulfi ochildi."</string>
     <string name="PERSOSUBSTATE_SIM_SIM_SUCCESS" msgid="6975608174152828954">"SIM karta qulfi ochildi."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM kartalaridagi tarmoq1 qulfi ochildi."</string>
-    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM kartalaridagi tarmoq2 qulfi ochildi."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK1_SUCCESS" msgid="2846699261330463192">"RUIM kartalaridagi network1 qulfi ochildi."</string>
+    <string name="PERSOSUBSTATE_RUIM_NETWORK2_SUCCESS" msgid="5335414726057102801">"RUIM kartalaridagi network2 qulfi ochildi."</string>
     <string name="PERSOSUBSTATE_RUIM_HRPD_SUCCESS" msgid="8868100318474971969">"RUIM HRPD kartalari qulfi ochilmadi"</string>
     <string name="PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_SUCCESS" msgid="6020936629725666932">"RUIM kartalari aloqa operatori qulfi ochildi."</string>
     <string name="PERSOSUBSTATE_RUIM_CORPORATE_SUCCESS" msgid="6944873647584595489">"Korporativ RUIM kartasi qulfi ochildi."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 1ddc27d..cbe131f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1309,9 +1309,9 @@
     <string name="adb_active_notification_title" msgid="408390247354560331">"Đã kết nối chế độ gỡ lỗi qua USB"</string>
     <string name="adb_active_notification_message" msgid="5617264033476778211">"Nhấn để tắt chế độ gỡ lỗi qua USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Chọn để tắt chế độ gỡ lỗi qua USB."</string>
-    <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Đã kết nối tính năng gỡ lỗi không dây"</string>
-    <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Nhấn để tắt tính năng gỡ lỗi không dây"</string>
-    <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Chọn để tắt tính năng gỡ lỗi không dây."</string>
+    <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Đã kết nối tính năng gỡ lỗi qua Wi-Fi"</string>
+    <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Nhấn để tắt tính năng gỡ lỗi qua Wi-Fi"</string>
+    <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Chọn để tắt tính năng gỡ lỗi qua Wi-Fi."</string>
     <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Đã bật Chế độ khai thác kiểm thử"</string>
     <string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Khôi phục cài đặt gốc để tắt Chế độ khai thác kiểm thử."</string>
     <string name="console_running_notification_title" msgid="6087888939261635904">"Đã bật bảng điều khiển cổng nối tiếp"</string>
@@ -1351,8 +1351,7 @@
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g> không được hỗ trợ"</string>
     <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"Thiết bị này không hỗ trợ <xliff:g id="NAME">%s</xliff:g> này. Nhấn để thiết lập ở định dạng được hỗ trợ."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="7744945987775645685">"Thiết bị này không hỗ trợ <xliff:g id="NAME">%s</xliff:g> này. Chọn để thiết lập ở định dạng được hỗ trợ."</string>
-    <!-- no translation found for ext_media_unsupported_notification_message (7657357085538772913) -->
-    <skip />
+    <string name="ext_media_unsupported_notification_message" product="automotive" msgid="7657357085538772913">"Thiết bị này không hỗ trợ <xliff:g id="NAME">%s</xliff:g> này."</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"Đã tháo đột ngột <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"Hãy ngắt kết nối phương tiện trước khi tháo để tránh mất nội dung"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"Đã xóa <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -2045,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Cuộc trò chuyện"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Cuộc trò chuyện nhóm"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Cá nhân"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Cơ quan"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Chế độ xem cá nhân"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 7100546..5f921bc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"对话"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"群组对话"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"个人"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"工作"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"个人视图"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 3ccadf1..d85b271 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"對話"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"群組對話"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"個人"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"公司"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人檢視模式"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 02aa964..88301a9 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -2044,6 +2044,8 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"對話"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"群組對話"</string>
+    <!-- no translation found for unread_convo_overflow (920517615597353833) -->
+    <skip />
     <string name="resolver_personal_tab" msgid="2051260504014442073">"個人"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"工作"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人檢視模式"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c8e6839..cd5cca2 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -2044,6 +2044,7 @@
     <string name="conversation_single_line_name_display" msgid="8958948312915255999">"<xliff:g id="SENDER_NAME">%1$s</xliff:g>:"</string>
     <string name="conversation_title_fallback_one_to_one" msgid="1980753619726908614">"Ingxoxo"</string>
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Ingxoxo Yeqembu"</string>
+    <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Okomuntu siqu"</string>
     <string name="resolver_work_tab" msgid="2690019516263167035">"Umsebenzi"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Ukubuka komuntu siqu"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4c4b7e6..340dd4d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1910,6 +1910,9 @@
     <!-- The name of the package that will hold the system gallery role. -->
     <string name="config_systemGallery" translatable="false">com.android.gallery</string>
 
+    <!-- The name of the package that will be allowed to change its components' label/icon. -->
+    <string name="config_overrideComponentUiPackage" translatable="false"></string>
+
     <!-- Enable/disable default bluetooth profiles:
         HSP_AG, ObexObjectPush, Audio, NAP -->
     <bool name="config_bluetooth_default_profiles">true</bool>
@@ -3343,6 +3346,10 @@
          This should only be set when the device has gestural navigation enabled by default. -->
     <bool name="config_showGesturalNavigationHints">false</bool>
 
+    <!-- Controls the free snap mode for the docked stack divider. In this mode, the divider can be
+         snapped to any position between the first target and the last target. -->
+    <bool name="config_dockedStackDividerFreeSnapMode">false</bool>
+
     <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows.
          These values are in DPs and will be converted to pixel sizes internally. -->
     <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">16x16</string>
@@ -4418,7 +4425,7 @@
     <string name="config_customSessionPolicyProvider"></string>
 
     <!-- The max scale for the wallpaper when it's zoomed in -->
-    <item name="config_wallpaperMaxScale" format="float" type="dimen">1.15</item>
+    <item name="config_wallpaperMaxScale" format="float" type="dimen">1.10</item>
 
     <!-- Package name that will receive an explicit manifest broadcast for
          android.os.action.POWER_SAVE_MODE_CHANGED. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 42718cb..ef1e8b7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1667,6 +1667,7 @@
   <java-symbol type="bool" name="config_perDisplayFocusEnabled" />
   <java-symbol type="bool" name="config_showNavigationBar" />
   <java-symbol type="bool" name="config_supportAutoRotation" />
+  <java-symbol type="bool" name="config_dockedStackDividerFreeSnapMode" />
   <java-symbol type="dimen" name="docked_stack_divider_thickness" />
   <java-symbol type="dimen" name="docked_stack_divider_insets" />
   <java-symbol type="dimen" name="docked_stack_minimize_thickness" />
@@ -3865,6 +3866,7 @@
   <java-symbol type="id" name="conversation_icon_badge_ring" />
   <java-symbol type="id" name="conversation_icon_badge_bg" />
   <java-symbol type="id" name="expand_button_container" />
+  <java-symbol type="id" name="expand_button_inner_container" />
   <java-symbol type="id" name="messaging_group_content_container" />
   <java-symbol type="id" name="expand_button_and_content_container" />
   <java-symbol type="id" name="conversation_header" />
@@ -3961,4 +3963,6 @@
 
   <!-- Set to true to make assistant show in front of the dream/screensaver. -->
   <java-symbol type="bool" name="config_assistantOnTopOfDream"/>
+
+  <java-symbol type="string" name="config_overrideComponentUiPackage" />
 </resources>
diff --git a/core/tests/ResourceLoaderTests/Android.bp b/core/tests/ResourceLoaderTests/Android.bp
deleted file mode 100644
index 2b14bca..0000000
--- a/core/tests/ResourceLoaderTests/Android.bp
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-android_test {
-    name: "FrameworksResourceLoaderTests",
-    srcs: [
-        "src/**/*.kt"
-    ],
-    libs: [
-        "android.test.runner",
-        "android.test.base"
-    ],
-    static_libs: [
-        "FrameworksResourceLoaderTests_Providers",
-        "androidx.test.espresso.core",
-        "androidx.test.ext.junit",
-        "androidx.test.runner",
-        "androidx.test.rules",
-        "mockito-target-minus-junit4",
-        "truth-prebuilt"
-    ],
-    resource_dirs: ["res", "resources/provider_stable/res"],
-    platform_apis: true,
-    test_suites: ["device-tests"],
-    aaptflags: ["-0 .txt"],
-    data: [
-        ":FrameworksResourceLoaderTests_ProviderOne_Split",
-        ":FrameworksResourceLoaderTests_ProviderTwo_Split",
-        ":FrameworksResourceLoaderTests_ProviderThree_Split",
-        ":FrameworksResourceLoaderTests_ProviderFour_Split"
-    ]
-}
-
-java_genrule {
-    name: "FrameworksResourceLoaderTests_Providers",
-    tools: ["soong_zip"],
-    srcs : [
-        ":FrameworksResourceLoaderTests_ProviderOne",
-        ":FrameworksResourceLoaderTests_ProviderOne_ARSC",
-        ":FrameworksResourceLoaderTests_ProviderTwo",
-        ":FrameworksResourceLoaderTests_ProviderTwo_ARSC",
-        ":FrameworksResourceLoaderTests_ProviderThree",
-        ":FrameworksResourceLoaderTests_ProviderThree_ARSC",
-        ":FrameworksResourceLoaderTests_ProviderFour",
-        ":FrameworksResourceLoaderTests_ProviderFour_ARSC"
-    ],
-    out: ["FrameworksResourceLoaderTests_Providers.jar"],
-    cmd: "mkdir -p $(genDir)/assets/ && cp $(in) $(genDir)/assets/ && " +
-         "$(location soong_zip) -o $(out) " +
-         "-L 0 -C $(genDir) -D $(genDir)/assets/"
-}
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/AndroidManifest.xml b/core/tests/ResourceLoaderTests/AndroidManifest.xml
deleted file mode 100644
index 00b4ccb..0000000
--- a/core/tests/ResourceLoaderTests/AndroidManifest.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<!-- Split loading is tested separately, so this must be marked isolated -->
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.res.loader.test"
-    android:isolatedSplits="true"
-    >
-
-    <uses-sdk android:minSdkVersion="29"/>
-
-    <application>
-        <uses-library android:name="android.test.runner"/>
-
-        <activity
-            android:name=".TestActivity"
-            android:configChanges="orientation"
-            />
-    </application>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:label="ResourceLoaderTests"
-        android:targetPackage="android.content.res.loader.test"
-        />
-
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/AndroidTest.xml b/core/tests/ResourceLoaderTests/AndroidTest.xml
deleted file mode 100644
index 800e7a7..0000000
--- a/core/tests/ResourceLoaderTests/AndroidTest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<configuration description="Test module config for ResourceLoaderTests">
-    <option name="test-tag" value="ResourceLoaderTests" />
-
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="cleanup-apks" value="true" />
-        <!-- The following value cannot be multi-line as whitespace is parsed by the installer -->
-        <option name="split-apk-file-names"
-            value="FrameworksResourceLoaderTests.apk,FrameworksResourceLoaderTests_ProviderOne_Split.apk,FrameworksResourceLoaderTests_ProviderTwo_Split.apk,FrameworksResourceLoaderTests_ProviderThree_Split.apk,FrameworksResourceLoaderTests_ProviderFour_Split.apk" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="android.content.res.loader.test" />
-    </test>
-</configuration>
diff --git a/core/tests/ResourceLoaderTests/assets/asset.txt b/core/tests/ResourceLoaderTests/assets/asset.txt
deleted file mode 100644
index 271704b..0000000
--- a/core/tests/ResourceLoaderTests/assets/asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-In assets directory
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/assets/base_asset.txt b/core/tests/ResourceLoaderTests/assets/base_asset.txt
deleted file mode 100644
index 8e62cc3..0000000
--- a/core/tests/ResourceLoaderTests/assets/base_asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-Base
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-reflect-sources.jar b/core/tests/ResourceLoaderTests/lib/kotlin-reflect-sources.jar
deleted file mode 100644
index a12e33a..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-reflect-sources.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-reflect.jar b/core/tests/ResourceLoaderTests/lib/kotlin-reflect.jar
deleted file mode 100644
index 182cbab..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-reflect.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk7-sources.jar b/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk7-sources.jar
deleted file mode 100644
index e6b5f15b..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk7-sources.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk7.jar b/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk7.jar
deleted file mode 100644
index e9c743c..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk7.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk8-sources.jar b/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk8-sources.jar
deleted file mode 100644
index cd05360..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk8-sources.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk8.jar b/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk8.jar
deleted file mode 100644
index dc8aa90..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-jdk8.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-sources.jar b/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-sources.jar
deleted file mode 100644
index 8a672ba..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib-sources.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib.jar b/core/tests/ResourceLoaderTests/lib/kotlin-stdlib.jar
deleted file mode 100644
index 56f3d1e..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-stdlib.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-test-sources.jar b/core/tests/ResourceLoaderTests/lib/kotlin-test-sources.jar
deleted file mode 100644
index 663d312..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-test-sources.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/lib/kotlin-test.jar b/core/tests/ResourceLoaderTests/lib/kotlin-test.jar
deleted file mode 100644
index 5f6e4b8..0000000
--- a/core/tests/ResourceLoaderTests/lib/kotlin-test.jar
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/res/drawable-nodpi/drawable_png.png b/core/tests/ResourceLoaderTests/res/drawable-nodpi/drawable_png.png
deleted file mode 100644
index 8102d15..0000000
--- a/core/tests/ResourceLoaderTests/res/drawable-nodpi/drawable_png.png
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/res/drawable-nodpi/drawable_xml.xml b/core/tests/ResourceLoaderTests/res/drawable-nodpi/drawable_xml.xml
deleted file mode 100644
index d1211c5..0000000
--- a/core/tests/ResourceLoaderTests/res/drawable-nodpi/drawable_xml.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<color
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#B2D2F2"
-    />
diff --git a/core/tests/ResourceLoaderTests/res/layout/layout.xml b/core/tests/ResourceLoaderTests/res/layout/layout.xml
deleted file mode 100644
index 05499ed..0000000
--- a/core/tests/ResourceLoaderTests/res/layout/layout.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<MysteryLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    />
-
diff --git a/core/tests/ResourceLoaderTests/res/values/values.xml b/core/tests/ResourceLoaderTests/res/values/values.xml
deleted file mode 100644
index ad78532..0000000
--- a/core/tests/ResourceLoaderTests/res/values/values.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <dimen name="test">0dp</dimen>
-    <string name="test">Not overlaid</string>
-</resources>
diff --git a/core/tests/ResourceLoaderTests/resources/Android.bp b/core/tests/ResourceLoaderTests/resources/Android.bp
deleted file mode 100644
index 18ef64b..0000000
--- a/core/tests/ResourceLoaderTests/resources/Android.bp
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderOne",
-    manifest: "AndroidManifestApp.xml",
-    asset_dirs: ["provider1/assets"],
-    resource_dirs: ["provider1/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderTwo",
-    manifest: "AndroidManifestApp.xml",
-    asset_dirs: ["provider2/assets"],
-    resource_dirs: ["provider2/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderThree",
-    manifest: "AndroidManifestApp.xml",
-    asset_dirs: ["provider3/assets"],
-    resource_dirs: ["provider3/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderFour",
-    manifest: "AndroidManifestApp.xml",
-    asset_dirs: ["provider4/assets"],
-    resource_dirs: ["provider4/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-// Resources.arsc(s)
-
-genrule {
-    name: "FrameworksResourceLoaderTests_ProviderOne_ARSC",
-    srcs: [":FrameworksResourceLoaderTests_ProviderOne"],
-    cmd: "unzip $(in) resources.arsc -d $(genDir) && "
-         + " mv $(genDir)/resources.arsc $(genDir)/FrameworksResourceLoaderTests_ProviderOne.arsc",
-    out: ["FrameworksResourceLoaderTests_ProviderOne.arsc"]
-}
-
-genrule {
-    name: "FrameworksResourceLoaderTests_ProviderTwo_ARSC",
-    srcs: [":FrameworksResourceLoaderTests_ProviderTwo"],
-    cmd: "unzip $(in) resources.arsc -d $(genDir) && "
-         + " mv $(genDir)/resources.arsc $(genDir)/FrameworksResourceLoaderTests_ProviderTwo.arsc",
-    out: ["FrameworksResourceLoaderTests_ProviderTwo.arsc"]
-}
-
-genrule {
-    name: "FrameworksResourceLoaderTests_ProviderThree_ARSC",
-    srcs: [":FrameworksResourceLoaderTests_ProviderThree"],
-    cmd: "unzip $(in) resources.arsc -d $(genDir) && "
-         + " mv $(genDir)/resources.arsc $(genDir)/FrameworksResourceLoaderTests_ProviderThree.arsc",
-    out: ["FrameworksResourceLoaderTests_ProviderThree.arsc"]
-}
-
-genrule {
-    name: "FrameworksResourceLoaderTests_ProviderFour_ARSC",
-    srcs: [":FrameworksResourceLoaderTests_ProviderFour"],
-    cmd: "unzip $(in) resources.arsc -d $(genDir) && "
-         + " mv $(genDir)/resources.arsc $(genDir)/FrameworksResourceLoaderTests_ProviderFour.arsc",
-    out: ["FrameworksResourceLoaderTests_ProviderFour.arsc"]
-}
-
-// Split APKs
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderOne_Split",
-    manifest: "AndroidManifestSplit1.xml",
-    asset_dirs: ["provider1/assets"],
-    resource_dirs: ["provider1/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderTwo_Split",
-    manifest: "AndroidManifestSplit2.xml",
-    asset_dirs: ["provider2/assets"],
-    resource_dirs: ["provider2/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderThree_Split",
-    manifest: "AndroidManifestSplit3.xml",
-    asset_dirs: ["provider3/assets"],
-    resource_dirs: ["provider3/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
-
-android_test_helper_app {
-    name: "FrameworksResourceLoaderTests_ProviderFour_Split",
-    manifest: "AndroidManifestSplit4.xml",
-    asset_dirs: ["provider4/assets"],
-    resource_dirs: ["provider4/res", "provider_stable/res"],
-    aaptflags: ["-0 .txt"]
-}
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/AndroidManifestApp.xml b/core/tests/ResourceLoaderTests/resources/AndroidManifestApp.xml
deleted file mode 100644
index c8a3590..0000000
--- a/core/tests/ResourceLoaderTests/resources/AndroidManifestApp.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.content.res.loader.test">
-
-    <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="1" />
-    <application/>
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/resources/AndroidManifestFramework.xml b/core/tests/ResourceLoaderTests/resources/AndroidManifestFramework.xml
deleted file mode 100644
index d5fa83f..0000000
--- a/core/tests/ResourceLoaderTests/resources/AndroidManifestFramework.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<!-- Mocks the framework package name so that AAPT2 assigns the correct package -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android">
-
-    <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="1" />
-    <application/>
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit1.xml b/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit1.xml
deleted file mode 100644
index 5cd4227..0000000
--- a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit1.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.res.loader.test"
-    split="FrameworksResourceLoaderTests_ProviderOne_Split"
-    android:isFeatureSplit="true"
-    >
-
-    <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="1" />
-    <application android:hasCode="false" />
-
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit2.xml b/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit2.xml
deleted file mode 100644
index b5180e6..0000000
--- a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit2.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.res.loader.test"
-    split="FrameworksResourceLoaderTests_ProviderTwo_Split"
-    android:isFeatureSplit="true"
-    >
-
-    <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="1" />
-    <application android:hasCode="false" />
-
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit3.xml b/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit3.xml
deleted file mode 100644
index 8ddb892..0000000
--- a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit3.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.res.loader.test"
-    split="FrameworksResourceLoaderTests_ProviderThree_Split"
-    android:isFeatureSplit="true"
-    >
-
-    <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="1" />
-    <application android:hasCode="false" />
-
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit4.xml b/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit4.xml
deleted file mode 100644
index b6bf552..0000000
--- a/core/tests/ResourceLoaderTests/resources/AndroidManifestSplit4.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.res.loader.test"
-    split="FrameworksResourceLoaderTests_ProviderFour_Split"
-    android:isFeatureSplit="true"
-    >
-
-    <uses-sdk android:minSdkVersion="1" android:targetSdkVersion="1" />
-    <application android:hasCode="false" />
-
-</manifest>
diff --git a/core/tests/ResourceLoaderTests/resources/framework/res/drawable-mdpi/ic_delete.png b/core/tests/ResourceLoaderTests/resources/framework/res/drawable-mdpi/ic_delete.png
deleted file mode 100644
index f3e53d7..0000000
--- a/core/tests/ResourceLoaderTests/resources/framework/res/drawable-mdpi/ic_delete.png
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/resources/framework/res/layout/activity_list_item.xml b/core/tests/ResourceLoaderTests/resources/framework/res/layout/activity_list_item.xml
deleted file mode 100644
index d59059b..0000000
--- a/core/tests/ResourceLoaderTests/resources/framework/res/layout/activity_list_item.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    />
-
diff --git a/core/tests/ResourceLoaderTests/resources/framework/res/values/public.xml b/core/tests/ResourceLoaderTests/resources/framework/res/values/public.xml
deleted file mode 100644
index 2e50182..0000000
--- a/core/tests/ResourceLoaderTests/resources/framework/res/values/public.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <public type="drawable" name="ic_delete" id="0x0108001d" />
-    <public type="layout" name="activity_list_item" id="0x01090000" />
-    <public type="string" name="cancel" id="0x01040000" />
-</resources>
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider1/assets/asset.txt b/core/tests/ResourceLoaderTests/resources/provider1/assets/asset.txt
deleted file mode 100644
index 6dcd8e4..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider1/assets/asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-One
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider1/assets/loader_asset.txt b/core/tests/ResourceLoaderTests/resources/provider1/assets/loader_asset.txt
deleted file mode 100644
index 0e41ffa..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider1/assets/loader_asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-LoaderOne
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider1/res/drawable-nodpi/drawable_png.png b/core/tests/ResourceLoaderTests/resources/provider1/res/drawable-nodpi/drawable_png.png
deleted file mode 100644
index 4eb8ca3..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider1/res/drawable-nodpi/drawable_png.png
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/resources/provider1/res/drawable-nodpi/drawable_xml.xml b/core/tests/ResourceLoaderTests/resources/provider1/res/drawable-nodpi/drawable_xml.xml
deleted file mode 100644
index 57a8cf1..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider1/res/drawable-nodpi/drawable_xml.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<color
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#000001"
-    />
diff --git a/core/tests/ResourceLoaderTests/resources/provider1/res/layout/layout.xml b/core/tests/ResourceLoaderTests/resources/provider1/res/layout/layout.xml
deleted file mode 100644
index ede3838..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider1/res/layout/layout.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    />
-
diff --git a/core/tests/ResourceLoaderTests/resources/provider1/res/values/values.xml b/core/tests/ResourceLoaderTests/resources/provider1/res/values/values.xml
deleted file mode 100644
index 5ef75d5..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider1/res/values/values.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <dimen name="test">100dp</dimen>
-    <string name="test">One</string>
-
-    <string name="additional">One</string>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider2/assets/asset.txt b/core/tests/ResourceLoaderTests/resources/provider2/assets/asset.txt
deleted file mode 100644
index 5673baa..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider2/assets/asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-Two
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider2/assets/loader_asset.txt b/core/tests/ResourceLoaderTests/resources/provider2/assets/loader_asset.txt
deleted file mode 100644
index bca782e..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider2/assets/loader_asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-LoaderTwo
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider2/res/drawable-nodpi/drawable_png.png b/core/tests/ResourceLoaderTests/resources/provider2/res/drawable-nodpi/drawable_png.png
deleted file mode 100644
index 671d6d0..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider2/res/drawable-nodpi/drawable_png.png
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/resources/provider2/res/drawable-nodpi/drawable_xml.xml b/core/tests/ResourceLoaderTests/resources/provider2/res/drawable-nodpi/drawable_xml.xml
deleted file mode 100644
index 333fe34..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider2/res/drawable-nodpi/drawable_xml.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<color
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#000002"
-    />
diff --git a/core/tests/ResourceLoaderTests/resources/provider2/res/layout/layout.xml b/core/tests/ResourceLoaderTests/resources/provider2/res/layout/layout.xml
deleted file mode 100644
index d8bff90..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider2/res/layout/layout.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT 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:layout_width="match_parent"
-    android:layout_height="match_parent"
-    />
-
diff --git a/core/tests/ResourceLoaderTests/resources/provider2/res/values/values.xml b/core/tests/ResourceLoaderTests/resources/provider2/res/values/values.xml
deleted file mode 100644
index 387c519..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider2/res/values/values.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <dimen name="test">200dp</dimen>
-    <string name="test">Two</string>
-
-    <string name="additional">Two</string>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider3/assets/asset.txt b/core/tests/ResourceLoaderTests/resources/provider3/assets/asset.txt
deleted file mode 100644
index 368c34d..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider3/assets/asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-Three
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider3/assets/loader_asset.txt b/core/tests/ResourceLoaderTests/resources/provider3/assets/loader_asset.txt
deleted file mode 100644
index bae8ef7..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider3/assets/loader_asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-LoaderThree
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider3/res/drawable-nodpi/drawable_png.png b/core/tests/ResourceLoaderTests/resources/provider3/res/drawable-nodpi/drawable_png.png
deleted file mode 100644
index 5231d17..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider3/res/drawable-nodpi/drawable_png.png
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/resources/provider3/res/drawable-nodpi/drawable_xml.xml b/core/tests/ResourceLoaderTests/resources/provider3/res/drawable-nodpi/drawable_xml.xml
deleted file mode 100644
index 41095d4..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider3/res/drawable-nodpi/drawable_xml.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<color
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#000003"
-    />
diff --git a/core/tests/ResourceLoaderTests/resources/provider3/res/layout/layout.xml b/core/tests/ResourceLoaderTests/resources/provider3/res/layout/layout.xml
deleted file mode 100644
index d58d3db..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider3/res/layout/layout.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    />
-
diff --git a/core/tests/ResourceLoaderTests/resources/provider3/res/values/values.xml b/core/tests/ResourceLoaderTests/resources/provider3/res/values/values.xml
deleted file mode 100644
index ab75bfa..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider3/res/values/values.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <dimen name="test">300dp</dimen>
-    <string name="test">Three</string>
-
-    <string name="additional">Three</string>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/assets/asset.txt b/core/tests/ResourceLoaderTests/resources/provider4/assets/asset.txt
deleted file mode 100644
index ad70cdd..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider4/assets/asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-Four
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/assets/loader_asset.txt b/core/tests/ResourceLoaderTests/resources/provider4/assets/loader_asset.txt
deleted file mode 100644
index b75d996..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider4/assets/loader_asset.txt
+++ /dev/null
@@ -1 +0,0 @@
-LoaderFour
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/res/drawable-nodpi/drawable_png.png b/core/tests/ResourceLoaderTests/resources/provider4/res/drawable-nodpi/drawable_png.png
deleted file mode 100644
index e9a4cfc..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider4/res/drawable-nodpi/drawable_png.png
+++ /dev/null
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/res/drawable-nodpi/drawable_xml.xml b/core/tests/ResourceLoaderTests/resources/provider4/res/drawable-nodpi/drawable_xml.xml
deleted file mode 100644
index 0623245..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider4/res/drawable-nodpi/drawable_xml.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<color
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#000004"
-    />
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/res/layout/layout.xml b/core/tests/ResourceLoaderTests/resources/provider4/res/layout/layout.xml
deleted file mode 100644
index ab9e265..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider4/res/layout/layout.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<TableLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    />
-
diff --git a/core/tests/ResourceLoaderTests/resources/provider_additional/res/values/values.xml b/core/tests/ResourceLoaderTests/resources/provider_additional/res/values/values.xml
deleted file mode 100644
index 29918d7..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider_additional/res/values/values.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
diff --git a/core/tests/ResourceLoaderTests/resources/provider_stable/res/values/public.xml b/core/tests/ResourceLoaderTests/resources/provider_stable/res/values/public.xml
deleted file mode 100644
index 269c40f..0000000
--- a/core/tests/ResourceLoaderTests/resources/provider_stable/res/values/public.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<resources>
-    <public type="dimen" name="test" id="0x7f010000" />
-    <public type="drawable" name="drawable_png" id="0x7f020000" />
-    <public type="drawable" name="drawable_xml" id="0x7f020001" />
-    <public type="layout" name="layout" id="0x7f030000" />
-    <public type="string" name="test" id="0x7f040000" />
-</resources>
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderTestBase.kt b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderTestBase.kt
deleted file mode 100644
index ec6a605..0000000
--- a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderTestBase.kt
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.content.res.loader.test
-
-import android.content.Context
-import android.content.res.AssetFileDescriptor
-import android.content.res.Configuration
-import android.content.res.Resources
-import android.content.res.loader.AssetsProvider
-import android.content.res.loader.ResourcesProvider
-import android.os.ParcelFileDescriptor
-import android.system.Os
-import android.util.ArrayMap
-import androidx.test.InstrumentationRegistry
-import org.json.JSONObject
-import org.junit.After
-import org.junit.Before
-import java.io.Closeable
-import java.io.FileOutputStream
-import java.io.File
-import java.io.FileDescriptor
-import java.util.zip.ZipInputStream
-
-abstract class ResourceLoaderTestBase {
-    protected val PROVIDER_ONE: String = "FrameworksResourceLoaderTests_ProviderOne"
-    protected val PROVIDER_TWO: String = "FrameworksResourceLoaderTests_ProviderTwo"
-    protected val PROVIDER_THREE: String = "FrameworksResourceLoaderTests_ProviderThree"
-    protected val PROVIDER_FOUR: String = "FrameworksResourceLoaderTests_ProviderFour"
-    protected val PROVIDER_EMPTY: String = "empty"
-
-    companion object {
-        /** Converts the map to a stable JSON string representation. */
-        fun mapToString(m: Map<String, String>): String {
-            return JSONObject(ArrayMap<String, String>().apply { putAll(m) }).toString()
-        }
-
-        /** Creates a lambda that runs multiple resources queries and concatenates the results. */
-        fun query(queries: Map<String, (Resources) -> String>): Resources.() -> String {
-            return {
-                val resultMap = ArrayMap<String, String>()
-                queries.forEach { q ->
-                    resultMap[q.key] = try {
-                        q.value.invoke(this)
-                    } catch (e: Exception) {
-                        e.javaClass.simpleName
-                    }
-                }
-                mapToString(resultMap)
-            }
-        }
-    }
-
-    // Data type of the current test iteration
-    open lateinit var dataType: DataType
-
-    protected lateinit var context: Context
-    protected lateinit var resources: Resources
-
-    // Track opened streams and ResourcesProviders to close them after testing
-    private val openedObjects = mutableListOf<Closeable>()
-
-    @Before
-    fun setUpBase() {
-        context = InstrumentationRegistry.getTargetContext()
-                .createConfigurationContext(Configuration())
-        resources = context.resources
-    }
-
-    @After
-    fun removeAllLoaders() {
-        resources.clearLoaders()
-        context.applicationContext.resources.clearLoaders()
-        openedObjects.forEach {
-            try {
-                it.close()
-            } catch (ignored: Exception) {
-            }
-        }
-    }
-
-    protected fun String.openProvider(dataType: DataType,
-                                      assetsProvider: MemoryAssetsProvider?): ResourcesProvider {
-        if (assetsProvider != null) {
-            openedObjects += assetsProvider
-        }
-        return when (dataType) {
-            DataType.APK_DISK_FD -> {
-                val file = context.copiedAssetFile("$this.apk")
-                ResourcesProvider.loadFromApk(ParcelFileDescriptor.fromFd(file.fd),
-                        assetsProvider).apply {
-                    file.close()
-                }
-            }
-            DataType.APK_DISK_FD_OFFSETS -> {
-                val asset = context.assets.openFd("$this.apk")
-                ResourcesProvider.loadFromApk(asset.parcelFileDescriptor, asset.startOffset,
-                        asset.length, assetsProvider).apply {
-                    asset.close()
-                }
-            }
-            DataType.ARSC_DISK_FD -> {
-                val file = context.copiedAssetFile("$this.arsc")
-                ResourcesProvider.loadFromTable(ParcelFileDescriptor.fromFd(file.fd),
-                        assetsProvider).apply {
-                    file.close()
-                }
-            }
-            DataType.ARSC_DISK_FD_OFFSETS -> {
-                val asset = context.assets.openFd("$this.arsc")
-                ResourcesProvider.loadFromTable(asset.parcelFileDescriptor, asset.startOffset,
-                        asset.length, assetsProvider).apply {
-                    asset.close()
-                }
-            }
-            DataType.APK_RAM_OFFSETS -> {
-                val asset = context.assets.openFd("$this.apk")
-                val leadingGarbageSize = 100L
-                val trailingGarbageSize = 55L
-                val fd = loadAssetIntoMemory(asset, leadingGarbageSize.toInt(),
-                        trailingGarbageSize.toInt())
-                ResourcesProvider.loadFromApk(fd, leadingGarbageSize, asset.declaredLength,
-                        assetsProvider).apply {
-                    asset.close()
-                    fd.close()
-                }
-            }
-            DataType.APK_RAM_FD -> {
-                val asset = context.assets.openFd("$this.apk")
-                var fd = loadAssetIntoMemory(asset)
-                ResourcesProvider.loadFromApk(fd, assetsProvider).apply {
-                    asset.close()
-                    fd.close()
-                }
-            }
-            DataType.ARSC_RAM_MEMORY -> {
-                val asset = context.assets.openFd("$this.arsc")
-                var fd = loadAssetIntoMemory(asset)
-                ResourcesProvider.loadFromTable(fd, assetsProvider).apply {
-                    asset.close()
-                    fd.close()
-                }
-            }
-            DataType.ARSC_RAM_MEMORY_OFFSETS -> {
-                val asset = context.assets.openFd("$this.arsc")
-                val leadingGarbageSize = 100L
-                val trailingGarbageSize = 55L
-                val fd = loadAssetIntoMemory(asset, leadingGarbageSize.toInt(),
-                        trailingGarbageSize.toInt())
-                ResourcesProvider.loadFromTable(fd, leadingGarbageSize, asset.declaredLength,
-                        assetsProvider).apply {
-                    asset.close()
-                    fd.close()
-                }
-            }
-            DataType.EMPTY -> {
-                if (equals(PROVIDER_EMPTY)) {
-                    ResourcesProvider.empty(EmptyAssetsProvider())
-                } else {
-                    if (assetsProvider == null) ResourcesProvider.empty(ZipAssetsProvider(this))
-                        else ResourcesProvider.empty(assetsProvider)
-                }
-            }
-            DataType.DIRECTORY -> {
-                ResourcesProvider.loadFromDirectory(zipToDir("$this.apk").absolutePath,
-                        assetsProvider)
-            }
-            DataType.SPLIT -> {
-                ResourcesProvider.loadFromSplit(context, "${this}_Split")
-            }
-        }
-    }
-
-    class EmptyAssetsProvider : AssetsProvider
-
-    /** An AssetsProvider that reads from a zip asset. */
-    inner class ZipAssetsProvider(val providerName: String) : AssetsProvider {
-        val root: File = zipToDir("$providerName.apk")
-
-        override fun loadAssetFd(path: String, accessMode: Int): AssetFileDescriptor? {
-            val f = File(root, path)
-            return if (f.exists()) AssetFileDescriptor(
-                    ParcelFileDescriptor.open(File(root, path),
-                            ParcelFileDescriptor.MODE_READ_ONLY), 0,
-                    AssetFileDescriptor.UNKNOWN_LENGTH) else null
-        }
-    }
-
-    /** AssetsProvider for testing that returns file descriptors to files in RAM. */
-    class MemoryAssetsProvider : AssetsProvider, Closeable {
-        var loadAssetResults = HashMap<String, FileDescriptor>()
-
-        fun addLoadAssetFdResult(path: String, value: String) = apply {
-            val fd = Os.memfd_create(path, 0)
-            val valueBytes = value.toByteArray()
-            Os.write(fd, valueBytes, 0, valueBytes.size)
-            loadAssetResults[path] = fd
-        }
-
-        override fun loadAssetFd(path: String, accessMode: Int): AssetFileDescriptor? {
-            return if (loadAssetResults.containsKey(path)) AssetFileDescriptor(
-                    ParcelFileDescriptor.dup(loadAssetResults[path]), 0,
-                    AssetFileDescriptor.UNKNOWN_LENGTH) else null
-        }
-
-        override fun close() {
-            for (f in loadAssetResults.values) {
-                Os.close(f)
-            }
-        }
-    }
-
-    /** Extracts an archive-based asset into a directory on disk. */
-    private fun zipToDir(name: String): File {
-        val root = File(context.filesDir, name.split('.')[0])
-        if (root.exists()) {
-            return root
-        }
-
-        root.mkdir()
-        ZipInputStream(context.assets.open(name)).use { zis ->
-            while (true) {
-                val entry = zis.nextEntry ?: break
-                val file = File(root, entry.name)
-                if (entry.isDirectory) {
-                    continue
-                }
-
-                file.parentFile.mkdirs()
-                file.outputStream().use { output ->
-                    var b = zis.read()
-                    while (b != -1) {
-                        output.write(b)
-                        b = zis.read()
-                    }
-                }
-            }
-        }
-        return root
-    }
-
-    /** Loads the asset into a temporary file stored in RAM. */
-    private fun loadAssetIntoMemory(
-        asset: AssetFileDescriptor,
-        leadingGarbageSize: Int = 0,
-        trailingGarbageSize: Int = 0
-    ): ParcelFileDescriptor {
-        val originalFd = Os.memfd_create(asset.toString(), 0 /* flags */)
-        val fd = ParcelFileDescriptor.dup(originalFd)
-        Os.close(originalFd)
-
-        val input = asset.createInputStream()
-        FileOutputStream(fd.fileDescriptor).use { output ->
-            // Add garbage before the APK data
-            for (i in 0 until leadingGarbageSize) {
-                output.write(Math.random().toInt())
-            }
-
-            for (i in 0 until asset.length.toInt()) {
-                output.write(input.read())
-            }
-
-            // Add garbage after the APK data
-            for (i in 0 until trailingGarbageSize) {
-                output.write(Math.random().toInt())
-            }
-        }
-
-        return fd
-    }
-
-    enum class DataType {
-        APK_DISK_FD,
-        APK_DISK_FD_OFFSETS,
-        APK_RAM_FD,
-        APK_RAM_OFFSETS,
-        ARSC_DISK_FD,
-        ARSC_DISK_FD_OFFSETS,
-        ARSC_RAM_MEMORY,
-        ARSC_RAM_MEMORY_OFFSETS,
-        EMPTY,
-        DIRECTORY,
-        SPLIT
-    }
-}
diff --git a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt
deleted file mode 100644
index 5aa8814..0000000
--- a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/ResourceLoaderValuesTest.kt
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.content.res.loader.test
-
-import android.app.Activity
-import android.content.Context
-import android.content.Intent
-import android.content.res.AssetManager
-import android.content.res.Configuration
-import android.content.res.Resources
-import android.content.res.loader.ResourcesLoader
-import android.graphics.Color
-import android.graphics.drawable.BitmapDrawable
-import android.graphics.drawable.ColorDrawable
-import android.os.IBinder
-import androidx.test.rule.ActivityTestRule
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertNotEquals
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import java.util.Collections
-
-/**
- * Tests generic ResourceLoader behavior. Intentionally abstract in its test methodology because
- * the behavior being verified isn't specific to any resource type. As long as it can pass an
- * equals check.
- *
- * Currently tests strings and dimens since String and any Number seemed most relevant to verify.
- */
-@RunWith(Parameterized::class)
-class ResourceLoaderValuesTest : ResourceLoaderTestBase() {
-
-    @get:Rule
-    private val mTestActivityRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
-
-    companion object {
-        @Parameterized.Parameters(name = "{1} {0}")
-        @JvmStatic
-        fun parameters(): Array<Any> {
-            val parameters = mutableListOf<Parameter>()
-
-            // Test resolution of resources encoded within the resources.arsc.
-            parameters += Parameter(
-                    "tableBased",
-                    query(mapOf(
-                            "getOverlaid" to { res ->
-                                res.getString(R.string.test)
-                            },
-                            "getAdditional" to { res ->
-                                res.getString(0x7f0400fe /* R.string.additional */)
-                            },
-                            "getIdentifier" to { res ->
-                                res.getString(res.getIdentifier("test", "string",
-                                        "android.content.res.loader.test"))
-                            },
-                            "getIdentifierAdditional" to { res ->
-                                res.getString(res.getIdentifier("additional", "string",
-                                        "android.content.res.loader.test"))
-                            }
-                    )),
-                    mapOf("getOverlaid" to "Not overlaid",
-                            "getAdditional" to "NotFoundException",
-                            "getIdentifier" to "Not overlaid",
-                            "getIdentifierAdditional" to "NotFoundException"),
-
-                    mapOf("getOverlaid" to "One",
-                            "getAdditional" to "One",
-                            "getIdentifier" to "One",
-                            "getIdentifierAdditional" to "One"),
-
-                    mapOf("getOverlaid" to "Two",
-                            "getAdditional" to "Two",
-                            "getIdentifier" to "Two",
-                            "getIdentifierAdditional" to "Two"),
-
-                    mapOf("getOverlaid" to "Three",
-                            "getAdditional" to "Three",
-                            "getIdentifier" to "Three",
-                            "getIdentifierAdditional" to "Three"),
-
-                    mapOf("getOverlaid" to "Four",
-                            "getAdditional" to "Four",
-                            "getIdentifier" to "Four",
-                            "getIdentifierAdditional" to "Four"),
-                    listOf(DataType.APK_DISK_FD, DataType.APK_DISK_FD_OFFSETS, DataType.APK_RAM_FD,
-                            DataType.APK_RAM_OFFSETS, DataType.ARSC_DISK_FD,
-                            DataType.ARSC_DISK_FD_OFFSETS, DataType.ARSC_RAM_MEMORY,
-                            DataType.ARSC_RAM_MEMORY_OFFSETS, DataType.SPLIT, DataType.DIRECTORY)
-            )
-
-            // Test resolution of file-based resources and assets with no assets provider.
-            parameters += Parameter(
-                    "tableFileBased",
-                    query(mapOf(
-                            // Drawable xml in res directory
-                            "drawableXml" to { res ->
-                                (res.getDrawable(R.drawable.drawable_xml) as ColorDrawable)
-                                        .color.toString()
-                            },
-                            // Asset as compiled XML layout in res directory
-                            "layout" to { res ->
-                                res.getLayout(R.layout.layout).advanceToRoot().name
-                            },
-                            // Bitmap drawable in res directory
-                            "drawablePng" to { res ->
-                                (res.getDrawable(R.drawable.drawable_png) as BitmapDrawable)
-                                        .bitmap.getColor(0, 0).toArgb().toString()
-                            }
-                    )),
-                    mapOf("drawableXml" to Color.parseColor("#B2D2F2").toString(),
-                            "layout" to "MysteryLayout",
-                            "drawablePng" to Color.parseColor("#FF00FF").toString()),
-
-                    mapOf("drawableXml" to Color.parseColor("#000001").toString(),
-                            "layout" to "RelativeLayout",
-                            "drawablePng" to Color.RED.toString()),
-
-                    mapOf("drawableXml" to Color.parseColor("#000002").toString(),
-                            "layout" to "LinearLayout",
-                            "drawablePng" to Color.GREEN.toString()),
-
-                    mapOf("drawableXml" to Color.parseColor("#000003").toString(),
-                            "layout" to "FrameLayout",
-                            "drawablePng" to Color.BLUE.toString()),
-
-                    mapOf("drawableXml" to Color.parseColor("#000004").toString(),
-                            "layout" to "TableLayout",
-                            "drawablePng" to Color.WHITE.toString()),
-                    listOf(DataType.APK_DISK_FD, DataType.APK_DISK_FD_OFFSETS, DataType.APK_RAM_FD,
-                            DataType.APK_RAM_OFFSETS, DataType.SPLIT, DataType.DIRECTORY)
-            )
-
-            // Test resolution of assets.
-            parameters += Parameter(
-                    "fileBased",
-                    query(mapOf(
-                            // File in the assets directory
-                            "openAsset" to { res ->
-                                res.assets.open("asset.txt").reader().readText()
-                            },
-                            // From assets directory returning file descriptor
-                            "openAssetFd" to { res ->
-                                res.assets.openFd("asset.txt").readText()
-                            },
-                            // Asset as compiled XML layout in res directory
-                            "layout" to { res ->
-                                res.assets.openXmlResourceParser("res/layout/layout.xml")
-                                        .advanceToRoot().name
-                            }
-                    )),
-                    mapOf("openAsset" to "In assets directory",
-                            "openAssetFd" to "In assets directory",
-                            "layout" to "MysteryLayout"),
-
-                    mapOf("openAsset" to "One",
-                            "openAssetFd" to "One",
-                            "layout" to "RelativeLayout"),
-
-                    mapOf("openAsset" to "Two",
-                            "openAssetFd" to "Two",
-                            "layout" to "LinearLayout"),
-
-                    mapOf("openAsset" to "Three",
-                            "openAssetFd" to "Three",
-                            "layout" to "FrameLayout"),
-
-                    mapOf("openAsset" to "Four",
-                            "openAssetFd" to "Four",
-                            "layout" to "TableLayout"),
-                    listOf(DataType.EMPTY)
-            )
-
-            // Test assets from apk and provider
-            parameters += Parameter(
-                    "fileBasedApkAssetsProvider",
-                    query(mapOf(
-                            // File in the assets directory
-                            "openAsset" to { res ->
-                                res.assets.open("asset.txt").reader().readText()
-                            },
-                            // From assets directory returning file descriptor
-                            "openAssetFd" to { res ->
-                                res.assets.openFd("asset.txt").readText()
-                            }
-                    )),
-                    mapOf("openAsset" to "In assets directory",
-                            "openAssetFd" to "In assets directory"),
-
-                    mapOf("openAsset" to "AssetsOne",
-                            "openAssetFd" to "AssetsOne"),
-                    { MemoryAssetsProvider().addLoadAssetFdResult("assets/asset.txt",
-                            "AssetsOne") },
-
-                    mapOf("openAsset" to "Two",
-                            "openAssetFd" to "Two"),
-                    null /* assetProviderTwo */,
-
-                    mapOf("openAsset" to "AssetsThree",
-                            "openAssetFd" to "AssetsThree"),
-                    { MemoryAssetsProvider().addLoadAssetFdResult("assets/asset.txt",
-                            "AssetsThree") },
-
-                    mapOf("openAsset" to "Four",
-                            "openAssetFd" to "Four"),
-                    null /* assetProviderFour */,
-                    listOf(DataType.APK_DISK_FD, DataType.APK_DISK_FD_OFFSETS, DataType.APK_RAM_FD,
-                            DataType.APK_RAM_OFFSETS, DataType.DIRECTORY)
-
-            )
-
-            // TODO(151949807): Increase testing for cookie based APIs and for what happens when
-            // some providers do not overlay base resources
-
-            return parameters.flatMap { parameter ->
-                parameter.dataTypes.map { dataType ->
-                    arrayOf(dataType, parameter)
-                }
-            }.toTypedArray()
-        }
-    }
-
-    @Suppress("LateinitVarOverridesLateinitVar")
-    @field:Parameterized.Parameter(0)
-    override lateinit var dataType: DataType
-
-    @field:Parameterized.Parameter(1)
-    lateinit var parameter: Parameter
-
-    private val valueOriginal by lazy { mapToString(parameter.valueOriginal) }
-    private val valueOne by lazy { mapToString(parameter.valueOne) }
-    private val valueTwo by lazy { mapToString(parameter.valueTwo) }
-    private val valueThree by lazy { mapToString(parameter.valueThree) }
-    private val valueFour by lazy { mapToString(parameter.valueFour) }
-
-    private fun openOne() = PROVIDER_ONE.openProvider(dataType,
-            parameter.assetProviderOne?.invoke())
-    private fun openTwo() = PROVIDER_TWO.openProvider(dataType,
-            parameter.assetProviderTwo?.invoke())
-    private fun openThree() = PROVIDER_THREE.openProvider(dataType,
-            parameter.assetProviderThree?.invoke())
-    private fun openFour() = PROVIDER_FOUR.openProvider(dataType,
-            parameter.assetProviderFour?.invoke())
-    private fun openEmpty() = PROVIDER_EMPTY.openProvider(DataType.EMPTY, null)
-
-    // Class method for syntax highlighting purposes
-    private fun getValue(c: Context = context) = parameter.getValue(c.resources)
-    private fun getValue(r: Resources) = parameter.getValue(r)
-
-    @Test
-    fun assertValueUniqueness() {
-        // Ensure the parameters are valid in case of coding errors
-        val original = getValue()
-        assertEquals(valueOriginal, original)
-        assertNotEquals(valueOne, original)
-        assertNotEquals(valueTwo, original)
-        assertNotEquals(valueThree, original)
-        assertNotEquals(valueFour, original)
-        assertNotEquals(valueTwo, valueOne)
-        assertNotEquals(valueThree, valueOne)
-        assertNotEquals(valueFour, valueOne)
-        assertNotEquals(valueThree, valueTwo)
-        assertNotEquals(valueFour, valueTwo)
-        assertNotEquals(valueFour, valueThree)
-    }
-
-    @Test
-    fun addProvidersRepeatedly() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.addProvider(testOne)
-        assertEquals(valueOne, getValue())
-
-        loader.addProvider(testTwo)
-        assertEquals(valueTwo, getValue())
-
-        loader.removeProvider(testOne)
-        assertEquals(valueTwo, getValue())
-
-        loader.removeProvider(testTwo)
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test
-    fun addLoadersRepeatedly() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader1 = ResourcesLoader()
-        val loader2 = ResourcesLoader()
-
-        resources.addLoaders(loader1)
-        loader1.addProvider(testOne)
-        assertEquals(valueOne, getValue())
-
-        resources.addLoaders(loader2)
-        loader2.addProvider(testTwo)
-        assertEquals(valueTwo, getValue())
-
-        resources.removeLoaders(loader1)
-        assertEquals(valueTwo, getValue())
-
-        resources.removeLoaders(loader2)
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test
-    fun setMultipleProviders() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.providers = listOf(testOne, testTwo)
-        assertEquals(valueTwo, getValue())
-
-        loader.removeProvider(testTwo)
-        assertEquals(valueOne, getValue())
-
-        loader.providers = Collections.emptyList()
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test
-    fun addMultipleLoaders() {
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(openOne())
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(openTwo())
-
-        resources.addLoaders(loader1, loader2)
-        assertEquals(valueTwo, getValue())
-
-        resources.removeLoaders(loader2)
-        assertEquals(valueOne, getValue())
-
-        resources.removeLoaders(loader1)
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test
-    fun emptyProvider() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val testEmpty = openEmpty()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.providers = listOf(testOne, testEmpty, testTwo)
-        assertEquals(valueTwo, getValue())
-
-        loader.removeProvider(testTwo)
-        assertEquals(valueOne, getValue())
-
-        loader.removeProvider(testOne)
-        assertEquals(valueOriginal, getValue())
-
-        loader.providers = Collections.emptyList()
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test(expected = UnsupportedOperationException::class)
-    fun getProvidersDoesNotLeakMutability() {
-        val testOne = openOne()
-        val loader = ResourcesLoader()
-        val providers = loader.providers
-        providers += testOne
-    }
-
-    @Test(expected = UnsupportedOperationException::class)
-    fun getLoadersDoesNotLeakMutability() {
-        val loaders = resources.loaders
-        loaders += ResourcesLoader()
-    }
-
-    @Test
-    fun alreadyAddedProviderNoOps() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.addProvider(testOne)
-        loader.addProvider(testTwo)
-        loader.addProvider(testOne)
-
-        assertEquals(2, loader.providers.size)
-        assertEquals(loader.providers[0], testOne)
-        assertEquals(loader.providers[1], testTwo)
-    }
-
-    @Test
-    fun alreadyAddedLoaderNoOps() {
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(openOne())
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(openTwo())
-
-        resources.addLoaders(loader1)
-        resources.addLoaders(loader2)
-        resources.addLoaders(loader1)
-
-        assertEquals(2, resources.loaders.size)
-        assertEquals(resources.loaders[0], loader1)
-        assertEquals(resources.loaders[1], loader2)
-    }
-
-    @Test
-    fun repeatedRemoveProviderNoOps() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.addProvider(testOne)
-        loader.addProvider(testTwo)
-
-        loader.removeProvider(testOne)
-        loader.removeProvider(testOne)
-
-        assertEquals(1, loader.providers.size)
-        assertEquals(loader.providers[0], testTwo)
-    }
-
-    @Test
-    fun repeatedRemoveLoaderNoOps() {
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(openOne())
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(openTwo())
-
-        resources.addLoaders(loader1, loader2)
-        resources.removeLoaders(loader1)
-        resources.removeLoaders(loader1)
-
-        assertEquals(1, resources.loaders.size)
-        assertEquals(resources.loaders[0], loader2)
-
-        resources.removeLoaders(loader2, loader2)
-
-        assertEquals(0, resources.loaders.size)
-    }
-
-    @Test
-    fun repeatedSetProvider() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.providers = listOf(testOne, testTwo)
-        loader.providers = listOf(testOne, testTwo)
-
-        assertEquals(2, loader.providers.size)
-        assertEquals(loader.providers[0], testOne)
-        assertEquals(loader.providers[1], testTwo)
-    }
-
-    @Test
-    fun repeatedAddMultipleLoaders() {
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(openOne())
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(openTwo())
-
-        resources.addLoaders(loader1, loader2)
-        resources.addLoaders(loader1, loader2)
-
-        assertEquals(2, resources.loaders.size)
-        assertEquals(resources.loaders[0], loader1)
-        assertEquals(resources.loaders[1], loader2)
-    }
-
-    @Test
-    fun reorderProviders() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.addProvider(testOne)
-        loader.addProvider(testTwo)
-        assertEquals(valueTwo, getValue())
-
-        loader.removeProvider(testOne)
-        assertEquals(valueTwo, getValue())
-
-        loader.addProvider(testOne)
-        assertEquals(valueOne, getValue())
-
-        loader.removeProvider(testTwo)
-        assertEquals(valueOne, getValue())
-
-        loader.removeProvider(testOne)
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test
-    fun reorderLoaders() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(testOne)
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(testTwo)
-
-        resources.addLoaders(loader1)
-        resources.addLoaders(loader2)
-        assertEquals(valueTwo, getValue())
-
-        resources.removeLoaders(loader1)
-        assertEquals(valueTwo, getValue())
-
-        resources.addLoaders(loader1)
-        assertEquals(valueOne, getValue())
-
-        resources.removeLoaders(loader2)
-        assertEquals(valueOne, getValue())
-
-        resources.removeLoaders(loader1)
-        assertEquals(valueOriginal, getValue())
-    }
-
-    @Test
-    fun reorderMultipleLoadersAndProviders() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val testThree = openThree()
-        val testFour = openFour()
-
-        val loader1 = ResourcesLoader()
-        loader1.providers = listOf(testOne, testTwo)
-
-        val loader2 = ResourcesLoader()
-        loader2.providers = listOf(testThree, testFour)
-
-        resources.addLoaders(loader1, loader2)
-        assertEquals(valueFour, getValue())
-
-        resources.removeLoaders(loader1)
-        resources.addLoaders(loader1)
-        assertEquals(valueTwo, getValue())
-
-        loader1.removeProvider(testTwo)
-        assertEquals(valueOne, getValue())
-
-        loader1.removeProvider(testOne)
-        assertEquals(valueFour, getValue())
-
-        loader2.removeProvider(testFour)
-        assertEquals(valueThree, getValue())
-    }
-
-    private fun createContext(context: Context, id: Int): Context {
-        val overrideConfig = Configuration()
-        overrideConfig.orientation = Int.MAX_VALUE - id
-        return context.createConfigurationContext(overrideConfig)
-    }
-
-    @Test
-    fun copyContextLoaders() {
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(openOne())
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(openTwo())
-
-        resources.addLoaders(loader1)
-        assertEquals(valueOne, getValue())
-
-        // The child context should include the loaders of the original context.
-        val childContext = createContext(context, 0)
-        assertEquals(valueOne, getValue(childContext))
-
-        // Changing the loaders of the child context should not affect the original context.
-        childContext.resources.addLoaders(loader2)
-        assertEquals(valueOne, getValue())
-        assertEquals(valueTwo, getValue(childContext))
-
-        // Changing the loaders of the original context should not affect the child context.
-        resources.removeLoaders(loader1)
-        assertEquals(valueOriginal, getValue())
-        assertEquals(valueTwo, getValue(childContext))
-
-        // A new context created from the original after an update to the original's loaders should
-        // have the updated loaders.
-        val originalPrime = createContext(context, 2)
-        assertEquals(valueOriginal, getValue(originalPrime))
-
-        // A new context created from the child context after an update to the child's loaders
-        // should have the updated loaders.
-        val childPrime = createContext(childContext, 1)
-        assertEquals(valueTwo, getValue(childPrime))
-    }
-
-    @Test
-    fun loaderUpdatesAffectContexts() {
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        resources.addLoaders(loader)
-        loader.addProvider(testOne)
-        assertEquals(valueOne, getValue())
-
-        val childContext = createContext(context, 0)
-        assertEquals(valueOne, getValue(childContext))
-
-        // Adding a provider to a loader affects all contexts that use the loader.
-        loader.addProvider(testTwo)
-        assertEquals(valueTwo, getValue())
-        assertEquals(valueTwo, getValue(childContext))
-
-        // Changes to the loaders for a context do not affect providers.
-        resources.clearLoaders()
-        assertEquals(valueOriginal, getValue())
-        assertEquals(valueTwo, getValue(childContext))
-
-        val childContext2 = createContext(context, 1)
-        assertEquals(valueOriginal, getValue())
-        assertEquals(valueOriginal, getValue(childContext2))
-
-        childContext2.resources.addLoaders(loader)
-        assertEquals(valueOriginal, getValue())
-        assertEquals(valueTwo, getValue(childContext))
-        assertEquals(valueTwo, getValue(childContext2))
-    }
-
-    @Test
-    fun appLoadersIncludedInActivityContexts() {
-        val loader = ResourcesLoader()
-        loader.addProvider(openOne())
-
-        val applicationContext = context.applicationContext
-        applicationContext.resources.addLoaders(loader)
-        assertEquals(valueOne, getValue(applicationContext))
-
-        val activity = mTestActivityRule.launchActivity(Intent())
-        assertEquals(valueOne, getValue(activity))
-
-        applicationContext.resources.clearLoaders()
-    }
-
-    @Test
-    fun loadersApplicationInfoChanged() {
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(openOne())
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(openTwo())
-
-        val applicationContext = context.applicationContext
-        applicationContext.resources.addLoaders(loader1)
-        assertEquals(valueOne, getValue(applicationContext))
-
-        var token: IBinder? = null
-        val activity = mTestActivityRule.launchActivity(Intent())
-        mTestActivityRule.runOnUiThread(Runnable {
-            token = activity.activityToken
-            val at = activity.activityThread
-
-            // The activity should have the loaders from the application.
-            assertEquals(valueOne, getValue(applicationContext))
-            assertEquals(valueOne, getValue(activity))
-
-            activity.resources.addLoaders(loader2)
-            assertEquals(valueOne, getValue(applicationContext))
-            assertEquals(valueTwo, getValue(activity))
-
-            // Relaunches the activity.
-            at.handleApplicationInfoChanged(activity.applicationInfo)
-        })
-
-        mTestActivityRule.runOnUiThread(Runnable {
-            val activityThread = activity.activityThread
-            val newActivity = activityThread.getActivity(token)
-
-            // The loader added to the activity loaders should not be persisted.
-            assertEquals(valueOne, getValue(applicationContext))
-            assertEquals(valueOne, getValue(newActivity))
-        })
-
-        applicationContext.resources.clearLoaders()
-    }
-
-    @Test
-    fun multipleLoadersHaveSameProviders() {
-        val provider1 = openOne()
-        val loader1 = ResourcesLoader()
-        loader1.addProvider(provider1)
-        val loader2 = ResourcesLoader()
-        loader2.addProvider(provider1)
-        loader2.addProvider(openTwo())
-
-        resources.addLoaders(loader1, loader2)
-        assertEquals(valueTwo, getValue())
-
-        resources.removeLoaders(loader1)
-        resources.addLoaders(loader1)
-        assertEquals(valueOne, getValue())
-
-        assertEquals(2, resources.assets.apkAssets.count { apkAssets -> apkAssets.isForLoader })
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun cannotUseClosedProvider() {
-        val provider = openOne()
-        provider.close()
-        val loader = ResourcesLoader()
-        loader.addProvider(provider)
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun cannotCloseUsedProvider() {
-        val provider = openOne()
-        val loader = ResourcesLoader()
-        loader.addProvider(provider)
-        provider.close()
-    }
-
-    @Test
-    fun addLoadersRepeatedlyCustomResources() {
-        val res = Resources(AssetManager::class.java.newInstance(), resources.displayMetrics,
-                resources.configuration!!)
-        val originalValue = getValue(res)
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader1 = ResourcesLoader()
-        val loader2 = ResourcesLoader()
-
-        res.addLoaders(loader1)
-        loader1.addProvider(testOne)
-        assertEquals(valueOne, getValue(res))
-
-        res.addLoaders(loader2)
-        loader2.addProvider(testTwo)
-        assertEquals(valueTwo, getValue(res))
-
-        res.removeLoaders(loader1)
-        res.addLoaders(loader1)
-        assertEquals(valueOne, getValue(res))
-
-        res.removeLoaders(loader1)
-        assertEquals(valueTwo, getValue(res))
-
-        res.removeLoaders(loader2)
-        assertEquals(originalValue, getValue(res))
-    }
-
-    @Test
-    fun setMultipleProvidersCustomResources() {
-        val res = Resources(AssetManager::class.java.newInstance(), resources.displayMetrics,
-                resources.configuration!!)
-        val originalValue = getValue(res)
-        val testOne = openOne()
-        val testTwo = openTwo()
-        val loader = ResourcesLoader()
-
-        res.addLoaders(loader)
-        loader.providers = listOf(testOne, testTwo)
-        assertEquals(valueTwo, getValue(res))
-
-        loader.removeProvider(testTwo)
-        assertEquals(valueOne, getValue(res))
-
-        loader.providers = Collections.emptyList()
-        assertEquals(originalValue, getValue(res))
-    }
-
-    data class Parameter(
-        val testPrefix: String,
-        val getValue: Resources.() -> String,
-        val valueOriginal: Map<String, String>,
-        val valueOne: Map<String, String>,
-        val assetProviderOne: (() -> MemoryAssetsProvider)? = null,
-        val valueTwo: Map<String, String>,
-        val assetProviderTwo: (() -> MemoryAssetsProvider)? = null,
-        val valueThree: Map<String, String>,
-        val assetProviderThree: (() -> MemoryAssetsProvider)? = null,
-        val valueFour: Map<String, String>,
-        val assetProviderFour: (() -> MemoryAssetsProvider)? = null,
-        val dataTypes: List<DataType>
-    ) {
-        constructor(
-            testPrefix: String,
-            getValue: Resources.() -> String,
-            valueOriginal: Map<String, String>,
-            valueOne: Map<String, String>,
-            valueTwo: Map<String, String>,
-            valueThree: Map<String, String>,
-            valueFour: Map<String, String>,
-            dataTypes: List<DataType>
-        ): this(testPrefix, getValue, valueOriginal, valueOne,
-                null, valueTwo, null, valueThree, null, valueFour, null, dataTypes)
-
-        override fun toString() = testPrefix
-    }
-}
-
-class TestActivity : Activity()
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/Utils.kt b/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/Utils.kt
deleted file mode 100644
index 526160d..0000000
--- a/core/tests/ResourceLoaderTests/src/android/content/res/loader/test/Utils.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res.loader.test
-
-import android.content.Context
-import android.content.res.AssetFileDescriptor
-import android.content.res.Resources
-import android.os.ParcelFileDescriptor
-import android.util.TypedValue
-import org.mockito.Answers
-import org.mockito.stubbing.Answer
-import org.xmlpull.v1.XmlPullParser
-import java.io.File
-
-object Utils {
-    val ANSWER_THROWS = Answer<Any> {
-        when (val name = it.method.name) {
-            "toString" -> return@Answer Answers.CALLS_REAL_METHODS.answer(it)
-            else -> throw UnsupportedOperationException("$name with " +
-                    "${it.arguments?.joinToString()} should not be called")
-        }
-    }
-}
-
-fun Int.dpToPx(resources: Resources) = TypedValue.applyDimension(
-        TypedValue.COMPLEX_UNIT_DIP,
-        this.toFloat(),
-        resources.displayMetrics
-).toInt()
-
-fun AssetFileDescriptor.readText() = createInputStream().reader().readText()
-
-fun XmlPullParser.advanceToRoot() = apply {
-    while (next() != XmlPullParser.START_TAG) {
-        // Empty
-    }
-}
-
-fun Context.copiedAssetFile(fileName: String): ParcelFileDescriptor {
-    return resources.assets.open(fileName).use { input ->
-        // AssetManager doesn't expose a direct file descriptor to the asset, so copy it to
-        // an individual file so one can be created manually.
-        val copiedFile = File(filesDir, fileName)
-        copiedFile.outputStream().use { output ->
-            input.copyTo(output)
-        }
-        ParcelFileDescriptor.open(copiedFile, ParcelFileDescriptor.MODE_READ_WRITE)
-    }
-}
diff --git a/core/tests/coretests/src/android/content/pm/ShortcutQueryWrapperTest.java b/core/tests/coretests/src/android/content/pm/ShortcutQueryWrapperTest.java
new file mode 100644
index 0000000..8f8488f
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/ShortcutQueryWrapperTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.ComponentName;
+import android.content.LocusId;
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.android.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public class ShortcutQueryWrapperTest {
+
+    private static final long CHANGED_SINCE = TimeUnit.SECONDS.toMillis(1);
+    private static final String PACKAGE_NAME = "com.android.test";
+    private static final List<String> SHORTCUT_IDS = Lists.newArrayList("s1", "s2", "s3");
+    private static final List<LocusId> LOCUS_IDS = Lists.newArrayList(
+            new LocusId("id1"), new LocusId("id2"), new LocusId("id3"));
+    private static final ComponentName COMPONENT_NAME = new ComponentName(
+            PACKAGE_NAME, "ShortcutQueryTest");
+    private static final int QUERY_FLAG = LauncherApps.ShortcutQuery.FLAG_MATCH_ALL_KINDS;
+
+    private ShortcutQueryWrapper mShortcutQuery;
+
+    @Before
+    public void setUp() throws Exception {
+        mShortcutQuery = new ShortcutQueryWrapper(new LauncherApps.ShortcutQuery()
+                .setChangedSince(CHANGED_SINCE)
+                .setPackage(PACKAGE_NAME)
+                .setShortcutIds(SHORTCUT_IDS)
+                .setLocusIds(LOCUS_IDS)
+                .setActivity(COMPONENT_NAME)
+                .setQueryFlags(QUERY_FLAG));
+    }
+
+    @Test
+    public void testWriteAndReadFromParcel() {
+        Parcel p = Parcel.obtain();
+        mShortcutQuery.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        ShortcutQueryWrapper q = ShortcutQueryWrapper.CREATOR.createFromParcel(p);
+        assertEquals("Changed since doesn't match!", CHANGED_SINCE, q.getChangedSince());
+        assertEquals("Package name doesn't match!", PACKAGE_NAME, q.getPackage());
+        assertEquals("Shortcut ids doesn't match", SHORTCUT_IDS, q.getShortcutIds());
+        assertEquals("Locus ids doesn't match", LOCUS_IDS, q.getLocusIds());
+        assertEquals("Component name doesn't match", COMPONENT_NAME, q.getActivity());
+        assertEquals("Query flag doesn't match", QUERY_FLAG, q.getQueryFlags());
+        p.recycle();
+    }
+}
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index d649b94..61f58b0 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -645,14 +645,60 @@
 
         Properties modifiedProperties2 = new Properties.Builder(namespaceToBan2).setString(KEY,
                 VALUE)
+                .setString(KEY3, NULL_VALUE).setString(KEY4, VALUE2).build();
+        DeviceConfig.setProperties(modifiedProperties2);
+        modifiedProperties2 = DeviceConfig.getProperties(namespaceToBan2);
+        assertThat(modifiedProperties2.getKeyset()).containsExactly(KEY, KEY3, KEY4);
+        assertThat(modifiedProperties2.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(modifiedProperties2.getString(KEY4, DEFAULT_VALUE)).isEqualTo(VALUE2);
+        // Since value is null DEFAULT_VALUE should be returned
+        assertThat(modifiedProperties2.getString(KEY3, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+    }
+
+    @Test
+    public void allConfigsUnbannedIfAnyUnbannedConfigUpdated()
+            throws DeviceConfig.BadConfigException {
+        // Given namespaces will be permanently banned, thus they need to be different every time
+        final String namespaceToBan1 = NAMESPACE + System.currentTimeMillis();
+        final String namespaceToBan2 = NAMESPACE + System.currentTimeMillis() + 1;
+
+        // Set namespaces properties
+        Properties properties1 = new Properties.Builder(namespaceToBan1).setString(KEY, VALUE)
+                .setString(KEY4, NULL_VALUE).build();
+        DeviceConfig.setProperties(properties1);
+        Properties properties2 = new Properties.Builder(namespaceToBan2).setString(KEY2, VALUE2)
+                .setString(KEY4, NULL_VALUE).build();
+        DeviceConfig.setProperties(properties2);
+
+        // Ban namespace with related properties
+        DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan1);
+        DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan2);
+
+        // Verify given namespace properties are banned
+        assertThrows(DeviceConfig.BadConfigException.class,
+                () -> DeviceConfig.setProperties(properties1));
+        assertThrows(DeviceConfig.BadConfigException.class,
+                () -> DeviceConfig.setProperties(properties2));
+
+        // Modify properties and verify we can set them
+        Properties modifiedProperties1 = new Properties.Builder(namespaceToBan1).setString(KEY,
+                VALUE)
                 .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
         DeviceConfig.setProperties(modifiedProperties1);
-        modifiedProperties2 = DeviceConfig.getProperties(namespaceToBan1);
-        assertThat(modifiedProperties2.getKeyset()).containsExactly(KEY, KEY2, KEY4);
-        assertThat(modifiedProperties2.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
-        assertThat(modifiedProperties2.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+        modifiedProperties1 = DeviceConfig.getProperties(namespaceToBan1);
+        assertThat(modifiedProperties1.getKeyset()).containsExactly(KEY, KEY2, KEY4);
+        assertThat(modifiedProperties1.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+        assertThat(modifiedProperties1.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
         // Since value is null DEFAULT_VALUE should be returned
-        assertThat(modifiedProperties2.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+        assertThat(modifiedProperties1.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+
+        // verify that other banned namespaces are unbanned now.
+        DeviceConfig.setProperties(properties2);
+        Properties result = DeviceConfig.getProperties(namespaceToBan2);
+        assertThat(result.getKeyset()).containsExactly(KEY2, KEY4);
+        assertThat(result.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+        // Since value is null DEFAULT_VALUE should be returned
+        assertThat(result.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
     }
 
     // TODO(mpape): resolve b/142727848 and re-enable listener tests
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 9d251da..5f12bf0 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -229,7 +229,7 @@
         doAnswer(invocation -> {
             mController.applyChangeInsets(mInsetsState);
             return null;
-        }).when(mMockController).scheduleApplyChangeInsets();
+        }).when(mMockController).scheduleApplyChangeInsets(any());
         mController.finish(true /* shown */);
         assertEquals(Insets.of(0, 100, 100, 0), mController.getCurrentInsets());
         verify(mMockController).notifyFinished(eq(mController), eq(true /* shown */));
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index b9c71a2..d432dda 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -32,6 +32,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -638,7 +639,31 @@
         });
     }
 
+    @Test
+    public void testFrameUpdateDuringAnimation() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
 
+            mController.onControlsChanged(createSingletonControl(ITYPE_IME));
+
+            // Pretend IME is calling
+            mController.show(ime(), true /* fromIme */);
+
+            InsetsState copy = new InsetsState(mController.getState(), true /* copySources */);
+            copy.getSource(ITYPE_IME).setFrame(0, 1, 2, 3);
+            copy.getSource(ITYPE_IME).setVisibleFrame(new Rect(4, 5, 6, 7));
+            mController.onStateChanged(copy);
+            assertNotEquals(new Rect(0, 1, 2, 3),
+                    mController.getState().getSource(ITYPE_IME).getFrame());
+            assertNotEquals(new Rect(4, 5, 6, 7),
+                    mController.getState().getSource(ITYPE_IME).getVisibleFrame());
+            mController.cancelExistingAnimation();
+            assertEquals(new Rect(0, 1, 2, 3),
+                    mController.getState().getSource(ITYPE_IME).getFrame());
+            assertEquals(new Rect(4, 5, 6, 7),
+                    mController.getState().getSource(ITYPE_IME).getVisibleFrame());
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
 
     @Test
     public void testCaptionInsetsStateAssemble() {
@@ -671,8 +696,7 @@
 
         // Simulate binder behavior by copying SurfaceControl. Otherwise, InsetsController will
         // attempt to release mLeash directly.
-        SurfaceControl copy = new SurfaceControl();
-        copy.copyFrom(mLeash);
+        SurfaceControl copy = new SurfaceControl(mLeash);
         return new InsetsSourceControl(type, copy, new Point());
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java
new file mode 100644
index 0000000..374edb8
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.app;
+
+import com.android.internal.logging.InstanceId;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ChooserActivityLoggerFake implements ChooserActivityLogger {
+    static class CallRecord {
+        // shared fields between all logs
+        public int atomId;
+        public String packageName;
+        public InstanceId instanceId;
+
+        // generic log field
+        public UiEventLogger.UiEventEnum event;
+
+        // share started fields
+        public String mimeType;
+        public int appProvidedDirect;
+        public int appProvidedApp;
+        public boolean isWorkprofile;
+        public int previewType;
+        public String intent;
+
+        // share completed fields
+        public int targetType;
+        public int positionPicked;
+
+        CallRecord(int atomId, UiEventLogger.UiEventEnum eventId,
+                String packageName, InstanceId instanceId) {
+            this.atomId = atomId;
+            this.packageName = packageName;
+            this.instanceId = instanceId;
+            this.event = eventId;
+        }
+
+        CallRecord(int atomId, String packageName, InstanceId instanceId, String mimeType,
+                int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType,
+                String intent) {
+            this.atomId = atomId;
+            this.packageName = packageName;
+            this.instanceId = instanceId;
+            this.mimeType = mimeType;
+            this.appProvidedDirect = appProvidedDirect;
+            this.appProvidedApp = appProvidedApp;
+            this.isWorkprofile = isWorkprofile;
+            this.previewType = previewType;
+            this.intent = intent;
+        }
+
+        CallRecord(int atomId, String packageName, InstanceId instanceId, int targetType,
+                int positionPicked) {
+            this.atomId = atomId;
+            this.packageName = packageName;
+            this.instanceId = instanceId;
+            this.targetType = targetType;
+            this.positionPicked = positionPicked;
+        }
+
+    }
+    private List<CallRecord> mCalls = new ArrayList<>();
+
+    public int numCalls() {
+        return mCalls.size();
+    }
+
+    List<CallRecord> getCalls() {
+        return mCalls;
+    }
+
+    CallRecord get(int index) {
+        return mCalls.get(index);
+    }
+
+    UiEventLogger.UiEventEnum event(int index) {
+        return mCalls.get(index).event;
+    }
+
+    @Override
+    public void logShareStarted(int eventId, String packageName, String mimeType,
+            int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType,
+            String intent) {
+        mCalls.add(new CallRecord(FrameworkStatsLog.SHARESHEET_STARTED, packageName,
+                getInstanceId(), mimeType, appProvidedDirect, appProvidedApp, isWorkprofile,
+                previewType, intent));
+    }
+
+    @Override
+    public void logShareTargetSelected(int targetType, String packageName, int positionPicked) {
+        mCalls.add(new CallRecord(FrameworkStatsLog.RANKING_SELECTED, packageName, getInstanceId(),
+                SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), positionPicked));
+    }
+
+    @Override
+    public void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) {
+        mCalls.add(new CallRecord(FrameworkStatsLog.UI_EVENT_REPORTED,
+                    event, "", instanceId));
+    }
+
+    @Override
+    public InstanceId getInstanceId() {
+        return InstanceId.fakeInstanceId(-1);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 812e2a6..583c751 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -34,6 +34,8 @@
 import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
 import static com.android.internal.app.MatcherUtils.first;
 
+import static junit.framework.Assert.assertTrue;
+
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.notNullValue;
@@ -67,6 +69,7 @@
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.service.chooser.ChooserTarget;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -75,8 +78,10 @@
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
 import com.android.internal.app.chooser.DisplayResolveInfo;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.FrameworkStatsLog;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -140,6 +145,10 @@
     public void cleanOverrideData() {
         sOverrides.reset();
         sOverrides.createPackageManager = mPackageManagerOverride;
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.APPEND_DIRECT_SHARE_ENABLED,
+                Boolean.toString(false),
+                true /* makeDefault*/);
     }
 
     @Test
@@ -988,7 +997,7 @@
                         serviceTargets,
                         TARGET_TYPE_CHOOSER_TARGET,
                         directShareToShortcutInfos,
-                        null)
+                        List.of())
         );
 
         // Thread.sleep shouldn't be a thing in an integration test but it's
@@ -1060,7 +1069,7 @@
                         serviceTargets,
                         TARGET_TYPE_CHOOSER_TARGET,
                         directShareToShortcutInfos,
-                        null)
+                        List.of())
         );
         // Thread.sleep shouldn't be a thing in an integration test but it's
         // necessary here because of the way the code is structured
@@ -1148,7 +1157,7 @@
                         serviceTargets,
                         TARGET_TYPE_CHOOSER_TARGET,
                         directShareToShortcutInfos,
-                        null)
+                        List.of())
         );
         // Thread.sleep shouldn't be a thing in an integration test but it's
         // necessary here because of the way the code is structured
@@ -1330,15 +1339,8 @@
                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
         List<ResolvedComponentInfo> workResolvedComponentInfos =
                 createResolvedComponentsForTest(workProfileTargets);
-        when(sOverrides.workResolverListController.getUserStateIndependentResolversAsUser(
-                Mockito.isA(List.class),
-                Mockito.isA(UserHandle.class)))
-                .thenReturn(new ArrayList<>(workResolvedComponentInfos));
         sOverrides.isQuietModeEnabled = true;
-        // When work profile is disabled, we get 0 results when we query the work profile
-        // intents.
-        setupResolverControllers(personalResolvedComponentInfos,
-                /* workResolvedComponentInfos */ new ArrayList<>());
+        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
         Intent sendIntent = createSendTextIntent();
         sendIntent.setType("TestType");
 
@@ -1430,6 +1432,299 @@
                 .check(matches(isDisplayed()));
     }
 
+    @Test
+    public void testAppTargetLogging() throws InterruptedException {
+        Intent sendIntent = createSendTextIntent();
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+
+        assertThat(activity.getAdapter().getCount(), is(2));
+        onView(withId(R.id.profile_button)).check(doesNotExist());
+
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
+        onView(withText(toChoose.activityInfo.name))
+                .perform(click());
+        waitForIdle();
+
+        ChooserActivityLoggerFake logger =
+                (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+        assertThat(logger.numCalls(), is(6));
+        // first one should be SHARESHEET_TRIGGERED uievent
+        assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(0).event.getId(),
+                is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+        // second one should be SHARESHEET_STARTED event
+        assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+        assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+        assertThat(logger.get(1).mimeType, is("text/plain"));
+        assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+        assertThat(logger.get(1).appProvidedApp, is(0));
+        assertThat(logger.get(1).appProvidedDirect, is(0));
+        assertThat(logger.get(1).isWorkprofile, is(false));
+        assertThat(logger.get(1).previewType, is(3));
+        // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+        assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(2).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+        // fourth and fifth are just artifacts of test set-up
+        // sixth one should be ranking atom with SHARESHEET_APP_TARGET_SELECTED event
+        assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
+        assertThat(logger.get(5).targetType,
+                is(ChooserActivityLogger
+                        .SharesheetTargetSelectedEvent.SHARESHEET_APP_TARGET_SELECTED.getId()));
+    }
+
+    @Test
+    public void testDirectTargetLogging() throws InterruptedException {
+        Intent sendIntent = createSendTextIntent();
+        // We need app targets for direct targets to get displayed
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        // Create direct share target
+        List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
+                resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
+        ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+
+        // Start activity
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+
+        // Insert the direct share target
+        Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos = new HashMap<>();
+        directShareToShortcutInfos.put(serviceTargets.get(0), null);
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                () -> activity.getAdapter().addServiceResults(
+                        activity.createTestDisplayResolveInfo(sendIntent,
+                                ri,
+                                "testLabel",
+                                "testInfo",
+                                sendIntent,
+                                /* resolveInfoPresentationGetter */ null),
+                        serviceTargets,
+                        TARGET_TYPE_CHOOSER_TARGET,
+                        directShareToShortcutInfos,
+                        null)
+        );
+        // Thread.sleep shouldn't be a thing in an integration test but it's
+        // necessary here because of the way the code is structured
+        // TODO: restructure the tests b/129870719
+        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+
+        assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
+                activity.getAdapter().getCount(), is(3));
+        assertThat("Chooser should have exactly one selectable direct target",
+                activity.getAdapter().getSelectableServiceTargetCount(), is(1));
+        assertThat("The resolver info must match the resolver info used to create the target",
+                activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
+
+        // Click on the direct target
+        String name = serviceTargets.get(0).getTitle().toString();
+        onView(withText(name))
+                .perform(click());
+        waitForIdle();
+
+        ChooserActivityLoggerFake logger =
+                (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+        assertThat(logger.numCalls(), is(6));
+        // first one should be SHARESHEET_TRIGGERED uievent
+        assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(0).event.getId(),
+                is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+        // second one should be SHARESHEET_STARTED event
+        assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+        assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+        assertThat(logger.get(1).mimeType, is("text/plain"));
+        assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+        assertThat(logger.get(1).appProvidedApp, is(0));
+        assertThat(logger.get(1).appProvidedDirect, is(0));
+        assertThat(logger.get(1).isWorkprofile, is(false));
+        assertThat(logger.get(1).previewType, is(3));
+        // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+        assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(2).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+        // fourth and fifth are just artifacts of test set-up
+        // sixth one should be ranking atom with SHARESHEET_COPY_TARGET_SELECTED event
+        assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
+        assertThat(logger.get(5).targetType,
+                is(ChooserActivityLogger
+                        .SharesheetTargetSelectedEvent.SHARESHEET_SERVICE_TARGET_SELECTED.getId()));
+    }
+
+    @Test
+    public void testCopyTextToClipboardLogging() throws Exception {
+        Intent sendIntent = createSendTextIntent();
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
+                Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+
+        onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed()));
+        onView(withId(R.id.chooser_copy_button)).perform(click());
+
+        ChooserActivityLoggerFake logger =
+                (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+        assertThat(logger.numCalls(), is(6));
+        // first one should be SHARESHEET_TRIGGERED uievent
+        assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(0).event.getId(),
+                is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+        // second one should be SHARESHEET_STARTED event
+        assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+        assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+        assertThat(logger.get(1).mimeType, is("text/plain"));
+        assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+        assertThat(logger.get(1).appProvidedApp, is(0));
+        assertThat(logger.get(1).appProvidedDirect, is(0));
+        assertThat(logger.get(1).isWorkprofile, is(false));
+        assertThat(logger.get(1).previewType, is(3));
+        // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+        assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(2).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+        // fourth and fifth are just artifacts of test set-up
+        // sixth one should be ranking atom with SHARESHEET_COPY_TARGET_SELECTED event
+        assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
+        assertThat(logger.get(5).targetType,
+                is(ChooserActivityLogger
+                        .SharesheetTargetSelectedEvent.SHARESHEET_COPY_TARGET_SELECTED.getId()));
+    }
+
+    @Test
+    public void testSwitchProfileLogging() throws InterruptedException {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        int workProfileTargets = 4;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
+        List<ResolvedComponentInfo> workResolvedComponentInfos =
+                createResolvedComponentsForTest(workProfileTargets);
+        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+
+        final ChooserWrapperActivity activity =
+                mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab)).perform(click());
+        waitForIdle();
+        onView(withText(R.string.resolver_personal_tab)).perform(click());
+        waitForIdle();
+
+        ChooserActivityLoggerFake logger =
+                (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+        assertThat(logger.numCalls(), is(8));
+        // first one should be SHARESHEET_TRIGGERED uievent
+        assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(0).event.getId(),
+                is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+        // second one should be SHARESHEET_STARTED event
+        assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+        assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+        assertThat(logger.get(1).mimeType, is("TestType"));
+        assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+        assertThat(logger.get(1).appProvidedApp, is(0));
+        assertThat(logger.get(1).appProvidedDirect, is(0));
+        assertThat(logger.get(1).isWorkprofile, is(false));
+        assertThat(logger.get(1).previewType, is(3));
+        // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+        assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(2).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+        // fourth one is artifact of test setup
+        // fifth one is switch to work profile
+        assertThat(logger.get(4).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(4).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED.getId()));
+        // sixth one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+        assertThat(logger.get(5).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(5).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+        // seventh one is artifact of test setup
+        // eigth one is switch to work profile
+        assertThat(logger.get(7).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+        assertThat(logger.get(7).event.getId(),
+                is(ChooserActivityLogger
+                        .SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED.getId()));
+    }
+
+    @Test
+    public void testAutolaunch_singleTarget_wifthWorkProfileAndTabbedViewOff_noAutolaunch() {
+        ResolverActivity.ENABLE_TABBED_VIEW = false;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+        waitForIdle();
+
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+
+        assertTrue(chosen[0] == null);
+    }
+
+    @Test
+    public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
+        ResolverActivity.ENABLE_TABBED_VIEW = false;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(1);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+        waitForIdle();
+
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+
+        assertThat(chosen[0], is(personalResolvedComponentInfos.get(0).getResolveInfoAt(0)));
+    }
+
     private Intent createSendTextIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 363551b..5b83f95 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -146,6 +146,11 @@
     }
 
     @Override
+    protected ChooserActivityLogger getChooserActivityLogger() {
+        return sOverrides.chooserActivityLogger;
+    }
+
+    @Override
     public Cursor queryResolver(ContentResolver resolver, Uri uri) {
         if (sOverrides.resolverCursor != null) {
             return sOverrides.resolverCursor;
@@ -205,6 +210,7 @@
         public boolean resolverForceException;
         public Bitmap previewThumbnail;
         public MetricsLogger metricsLogger;
+        public ChooserActivityLogger chooserActivityLogger;
         public int alternateProfileSetting;
         public Resources resources;
         public UserHandle workProfileUserHandle;
@@ -223,6 +229,7 @@
             resolverListController = mock(ResolverListController.class);
             workResolverListController = mock(ResolverListController.class);
             metricsLogger = mock(MetricsLogger.class);
+            chooserActivityLogger = new ChooserActivityLoggerFake();
             alternateProfileSetting = 0;
             resources = null;
             workProfileUserHandle = null;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 5a3aff9..eb39d58 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -30,6 +30,8 @@
 import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo;
 import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
 
+import static junit.framework.Assert.assertTrue;
+
 import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
@@ -612,15 +614,8 @@
                 createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
         List<ResolvedComponentInfo> workResolvedComponentInfos =
                 createResolvedComponentsForTest(workProfileTargets);
-        when(sOverrides.workResolverListController.getUserStateIndependentResolversAsUser(
-                Mockito.isA(List.class),
-                Mockito.isA(UserHandle.class)))
-                .thenReturn(new ArrayList<>(workResolvedComponentInfos));
         sOverrides.isQuietModeEnabled = true;
-        // When work profile is disabled, we get 0 results when we query the work profile
-        // intents.
-        setupResolverControllers(personalResolvedComponentInfos,
-                /* workResolvedComponentInfos */ new ArrayList<>());
+        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
         Intent sendIntent = createSendImageIntent();
         sendIntent.setType("TestType");
 
@@ -710,6 +705,54 @@
                 .check(matches(isDisplayed()));
     }
 
+    @Test
+    public void testAutolaunch_singleTarget_withWorkProfileAndTabbedViewOff_noAutolaunch() {
+        ResolverActivity.ENABLE_TABBED_VIEW = false;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+        Intent sendIntent = createSendImageIntent();
+        sendIntent.setType("TestType");
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+        waitForIdle();
+
+        mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+
+        assertTrue(chosen[0] == null);
+    }
+
+    @Test
+    public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
+        ResolverActivity.ENABLE_TABBED_VIEW = false;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(1);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+        Intent sendIntent = createSendImageIntent();
+        sendIntent.setType("TestType");
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+        waitForIdle();
+
+        mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+
+        assertThat(chosen[0], is(personalResolvedComponentInfos.get(0).getResolveInfoAt(0)));
+    }
+
     private Intent createSendImageIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
index d019704..3e40466 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -20,24 +20,19 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.app.Activity;
-import android.app.EmptyActivity;
 import android.content.Context;
 import android.hardware.display.DisplayManagerGlobal;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
 import android.view.DisplayAdjustments;
 import android.view.DisplayInfo;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 
-import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
-import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -51,13 +46,9 @@
     private Context mContext;
     private static final int EXTERNAL_DISPLAY = DEFAULT_DISPLAY + 1;
 
-    @Rule
-    public ActivityTestRule<EmptyActivity> mActivityRule =
-            new ActivityTestRule<>(EmptyActivity.class);
-
     @Before
-    public void setUp() {
-        mContext = ApplicationProvider.getApplicationContext();
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
     }
 
     @Test
@@ -85,19 +76,4 @@
         Display associatedDisplay = decorContext.getDisplay();
         assertEquals(expectedDisplayId, associatedDisplay.getDisplayId());
     }
-
-    @Test
-    public void testGetWindowManagerFromVisualDecorContext() throws Throwable {
-        mActivityRule.runOnUiThread(() -> {
-            Activity activity = mActivityRule.getActivity();
-            final DecorContext decorContext = new DecorContext(mContext.getApplicationContext(),
-                    activity);
-            WindowManagerImpl actualWm = (WindowManagerImpl)
-                    decorContext.getSystemService(WindowManager.class);
-            WindowManagerImpl expectedWm = (WindowManagerImpl)
-                    activity.getSystemService(WindowManager.class);
-            // Verify that window manager is from activity not application context.
-            assertEquals(expectedWm.mContext, actualWm.mContext);
-        });
-    }
 }
diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp
index a2a2168..ca655f1 100644
--- a/core/xsd/vts/Android.bp
+++ b/core/xsd/vts/Android.bp
@@ -36,7 +36,7 @@
     ],
     test_suites: [
         "general-tests",
-        "vts-core"
+        "vts"
     ],
     test_config: "vts_permission_validate_test.xml",
 }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index f63ec6b..6af887d 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -162,7 +162,6 @@
     <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
     <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />
     <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="audioserver" />
-    <assign-permission name="android.permission.PREEMPT_SOUND_TRIGGER" uid="audioserver" />
 
     <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index b753704..07cf415 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -25,6 +25,12 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
+    "-2101985723": {
+      "message": "Failed looking up window session=%s callers=%s",
+      "level": "WARN",
+      "group": "WM_ERROR",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "-2072089308": {
       "message": "Attempted to add window with token that is a sub-window: %s.  Aborting.",
       "level": "WARN",
@@ -655,12 +661,6 @@
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-747671114": {
-      "message": "Failed looking up window callers=%s",
-      "level": "WARN",
-      "group": "WM_ERROR",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-714291355": {
       "message": "Losing delayed focus: %s",
       "level": "INFO",
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index d1a6a5c..777aa0b 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -5,7 +5,7 @@
       "host": true
     },
     {
-      "name": "FrameworksResourceLoaderTests"
+      "name": "CtsResourcesLoaderTests"
     }
   ]
 }
\ No newline at end of file
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index ac2fd98..aa842ff 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -171,7 +171,6 @@
 
 cc_defaults {
     name: "android_graphics_apex",
-    host_supported: true,
     cflags: [
         "-Wno-unused-parameter",
         "-Wno-non-virtual-dtor",
@@ -231,7 +230,6 @@
 
 cc_defaults {
     name: "android_graphics_jni",
-    host_supported: true,
     cflags: [
         "-Wno-unused-parameter",
         "-Wno-non-virtual-dtor",
@@ -537,7 +535,11 @@
 
 cc_test {
     name: "hwui_unit_tests",
-    defaults: ["hwui_test_defaults"],
+    defaults: [
+        "hwui_test_defaults",
+        "android_graphics_apex",
+        "android_graphics_jni",
+    ],
 
     static_libs: [
         "libgmock",
@@ -549,6 +551,7 @@
 
     srcs: [
         "tests/unit/main.cpp",
+        "tests/unit/ABitmapTests.cpp",
         "tests/unit/CacheManagerTests.cpp",
         "tests/unit/CanvasContextTests.cpp",
         "tests/unit/CommonPoolTests.cpp",
diff --git a/libs/hwui/apex/android_bitmap.cpp b/libs/hwui/apex/android_bitmap.cpp
index b56a619..3780ba0 100644
--- a/libs/hwui/apex/android_bitmap.cpp
+++ b/libs/hwui/apex/android_bitmap.cpp
@@ -163,10 +163,9 @@
 
 void ABitmap_notifyPixelsChanged(ABitmap* bitmapHandle) {
     Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
-    if (bitmap->isImmutable()) {
-        ALOGE("Attempting to modify an immutable Bitmap!");
+    if (!bitmap->isImmutable()) {
+        bitmap->notifyPixelsChanged();
     }
-    return bitmap->notifyPixelsChanged();
 }
 
 namespace {
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index afd82ac..43cc4f2 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -50,10 +50,8 @@
 }
 
 SkAlphaType ImageDecoder::getOutAlphaType() const {
-    // While an SkBitmap may want to use kOpaque_SkAlphaType for a performance
-    // optimization, this class just outputs raw pixels. Using either
-    // premultiplication choice has no effect on decoding an opaque encoded image.
-    return mUnpremultipliedRequired ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
+    return opaque() ? kOpaque_SkAlphaType
+                    : mUnpremultipliedRequired ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
 }
 
 bool ImageDecoder::setTargetSize(int width, int height) {
@@ -82,8 +80,7 @@
     SkISize targetSize = { width, height }, decodeSize = targetSize;
     int sampleSize = mCodec->computeSampleSize(&decodeSize);
 
-    if (decodeSize != targetSize && mUnpremultipliedRequired
-            && !mCodec->getInfo().isOpaque()) {
+    if (decodeSize != targetSize && mUnpremultipliedRequired && !opaque()) {
         return false;
     }
 
diff --git a/libs/hwui/jni/AnimatedImageDrawable.cpp b/libs/hwui/jni/AnimatedImageDrawable.cpp
index 055075d..1ff1565 100644
--- a/libs/hwui/jni/AnimatedImageDrawable.cpp
+++ b/libs/hwui/jni/AnimatedImageDrawable.cpp
@@ -183,7 +183,7 @@
     }
 
     ~InvokeListener() override {
-        auto* env = get_env_or_die(mJvm);
+        auto* env = requireEnv(mJvm);
         env->DeleteWeakGlobalRef(mWeakRef);
     }
 
diff --git a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp
index db5f6f6..b10540c 100644
--- a/libs/hwui/jni/ByteBufferStreamAdaptor.cpp
+++ b/libs/hwui/jni/ByteBufferStreamAdaptor.cpp
@@ -9,24 +9,6 @@
 static jmethodID gByteBuffer_getMethodID;
 static jmethodID gByteBuffer_setPositionMethodID;
 
-/**
- * Helper method for accessing the JNI interface pointer.
- *
- * Image decoding (which this supports) is started on a thread that is already
- * attached to the Java VM. But an AnimatedImageDrawable continues decoding on
- * the AnimatedImageThread, which is not attached. This will attach if
- * necessary.
- */
-static JNIEnv* requireEnv(JavaVM* jvm) {
-    JNIEnv* env;
-    if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
-            LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
-        }
-    }
-    return env;
-}
-
 class ByteBufferStream : public SkStreamAsset {
 private:
     ByteBufferStream(JavaVM* jvm, jobject jbyteBuffer, size_t initialPosition, size_t length,
@@ -304,7 +286,7 @@
         auto* context = new release_proc_context{jvm, jbyteBuffer};
         auto releaseProc = [](const void*, void* context) {
             auto* c = reinterpret_cast<release_proc_context*>(context);
-            JNIEnv* env = get_env_or_die(c->jvm);
+            JNIEnv* env = requireEnv(c->jvm);
             env->DeleteGlobalRef(c->jbyteBuffer);
             delete c;
         };
diff --git a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
index 39483b5..f1c6b29 100644
--- a/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
+++ b/libs/hwui/jni/CreateJavaOutputStreamAdaptor.cpp
@@ -49,13 +49,13 @@
     }
 
     ~JavaInputStreamAdaptor() override {
-        auto* env = android::get_env_or_die(fJvm);
+        auto* env = android::requireEnv(fJvm);
         env->DeleteGlobalRef(fJavaInputStream);
         env->DeleteGlobalRef(fJavaByteArray);
     }
 
     size_t read(void* buffer, size_t size) override {
-        auto* env = android::get_env_or_die(fJvm);
+        auto* env = android::requireEnv(fJvm);
         if (!fSwallowExceptions && checkException(env)) {
             // Just in case the caller did not clear from a previous exception.
             return 0;
diff --git a/libs/hwui/jni/ImageDecoder.cpp b/libs/hwui/jni/ImageDecoder.cpp
index b6b3785..41d939b 100644
--- a/libs/hwui/jni/ImageDecoder.cpp
+++ b/libs/hwui/jni/ImageDecoder.cpp
@@ -305,9 +305,6 @@
     }
 
     SkImageInfo bitmapInfo = decoder->getOutputInfo();
-    if (decoder->opaque()) {
-        bitmapInfo = bitmapInfo.makeAlphaType(kOpaque_SkAlphaType);
-    }
     if (asAlphaMask && colorType == kGray_8_SkColorType) {
         bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType);
     }
diff --git a/libs/hwui/jni/Utils.cpp b/libs/hwui/jni/Utils.cpp
index 17c194d..34fd668 100644
--- a/libs/hwui/jni/Utils.cpp
+++ b/libs/hwui/jni/Utils.cpp
@@ -159,3 +159,13 @@
     }
     return env;
 }
+
+JNIEnv* android::requireEnv(JavaVM* jvm) {
+    JNIEnv* env;
+    if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
+            LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
+        }
+    }
+    return env;
+}
diff --git a/libs/hwui/jni/Utils.h b/libs/hwui/jni/Utils.h
index 8925517..f628cc3 100644
--- a/libs/hwui/jni/Utils.h
+++ b/libs/hwui/jni/Utils.h
@@ -78,6 +78,16 @@
 
 JNIEnv* get_env_or_die(JavaVM* jvm);
 
+/**
+ * Helper method for accessing the JNI interface pointer.
+ *
+ * Image decoding (which this supports) is started on a thread that is already
+ * attached to the Java VM. But an AnimatedImageDrawable continues decoding on
+ * the AnimatedImageThread, which is not attached. This will attach if
+ * necessary.
+ */
+JNIEnv* requireEnv(JavaVM* jvm);
+
 }; // namespace android
 
 #endif  // _ANDROID_GRAPHICS_UTILS_H_
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 41aa1ff..5088494 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -418,9 +418,9 @@
                 auto data = picture->serialize();
                 savePictureAsync(data, mCapturedFile);
                 mCaptureSequence = 0;
+                mCaptureMode = CaptureMode::None;
             }
         }
-        mCaptureMode = CaptureMode::None;
         mRecorder.reset();
     }
 }
diff --git a/libs/hwui/tests/unit/ABitmapTests.cpp b/libs/hwui/tests/unit/ABitmapTests.cpp
new file mode 100644
index 0000000..8e2f7e0
--- /dev/null
+++ b/libs/hwui/tests/unit/ABitmapTests.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "android/graphics/bitmap.h"
+#include "apex/TypeCast.h"
+#include "hwui/Bitmap.h"
+#include "tests/common/TestUtils.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+TEST(ABitmap, notifyPixelsChanged) {
+    // generate a bitmap and its public API handle
+    sk_sp<Bitmap> bitmap(TestUtils::createBitmap(1, 1));
+    ABitmap* abmp = android::TypeCast::toABitmap(bitmap.get());
+
+    // verify that notification changes the genID
+    uint32_t genID = bitmap->getGenerationID();
+    ABitmap_notifyPixelsChanged(abmp);
+    ASSERT_TRUE(bitmap->getGenerationID() != genID);
+
+    // mark the bitmap as immutable
+    ASSERT_FALSE(bitmap->isImmutable());
+    bitmap->setImmutable();
+    ASSERT_TRUE(bitmap->isImmutable());
+
+    // attempt to notify that the pixels have changed
+    genID = bitmap->getGenerationID();
+    ABitmap_notifyPixelsChanged(abmp);
+    ASSERT_TRUE(bitmap->getGenerationID() == genID);
+}
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 90bcd1c..1208062 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -403,3 +403,40 @@
     renderThread.destroyRenderingContext();
     EXPECT_FALSE(pipeline->isSurfaceReady());
 }
+
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, pictureCallback) {
+    // create a pipeline and add a picture callback
+    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+    int callbackCount = 0;
+    pipeline->setPictureCapturedCallback(
+            [&callbackCount](sk_sp<SkPicture>&& picture) { callbackCount += 1; });
+
+    // create basic red frame and render it
+    auto redNode = TestUtils::createSkiaNode(
+            0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+                redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+            });
+    LayerUpdateQueue layerUpdateQueue;
+    SkRect dirty = SkRectMakeLargest();
+    std::vector<sp<RenderNode>> renderNodes;
+    renderNodes.push_back(redNode);
+    bool opaque = true;
+    android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
+    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+                          SkMatrix::I());
+
+    // verify the callback was called
+    EXPECT_EQ(1, callbackCount);
+
+    // render a second frame and check the callback count
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+                          SkMatrix::I());
+    EXPECT_EQ(2, callbackCount);
+
+    // unset the callback, render another frame, check callback was not invoked
+    pipeline->setPictureCapturedCallback(nullptr);
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
+                          SkMatrix::I());
+    EXPECT_EQ(2, callbackCount);
+}
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index f3e4d81..4dd1a29 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -71,8 +71,7 @@
  * heavy-weight work after receiving an update - such as using the network.
  *
  * <p>Activities should strongly consider removing all location
- * request when entering the background
- * (for example at {@link android.app.Activity#onPause}), or
+ * request when entering the background, or
  * at least swap the request to a larger interval and lower quality.
  * Future version of the location manager may automatically perform background
  * throttling on behalf of applications.
@@ -146,38 +145,32 @@
      */
     public static final int POWER_HIGH = 203;
 
-    /**
-     * By default, mFastestInterval = FASTEST_INTERVAL_MULTIPLE * mInterval
-     */
+    private static final long DEFAULT_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
     private static final double FASTEST_INTERVAL_FACTOR = 6.0;  // 6x
 
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private int mQuality = POWER_LOW;
     @UnsupportedAppUsage
-    private long mInterval = 60 * 60 * 1000;   // 60 minutes
+    private String mProvider;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private long mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR);  // 10 minutes
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private boolean mExplicitFastestInterval = false;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private long mExpireAt = Long.MAX_VALUE;  // no expiry
-    private long mExpireIn = Long.MAX_VALUE;  // no expiry
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private int mNumUpdates = Integer.MAX_VALUE;  // no expiry
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private float mSmallestDisplacement = 0.0f;    // meters
+    private int mQuality;
     @UnsupportedAppUsage
-    private WorkSource mWorkSource = null;
+    private long mInterval;
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    private long mFastestInterval;
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    private boolean mExplicitFastestInterval;
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    private long mExpireAt;
+    private long mExpireIn;
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    private int mNumUpdates;
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    private float mSmallestDisplacement;
     @UnsupportedAppUsage
-    private boolean mHideFromAppOps = false; // True if this request shouldn't be counted by AppOps
-    private boolean mLocationSettingsIgnored = false;
-
+    private boolean mHideFromAppOps;
+    private boolean mLocationSettingsIgnored;
+    private boolean mLowPowerMode;
     @UnsupportedAppUsage
-    private String mProvider = LocationManager.FUSED_PROVIDER;
-            // for deprecated APIs that explicitly request a provider
-
-    /** If true, GNSS chipset will make strong tradeoffs to substantially restrict power use */
-    private boolean mLowPowerMode = false;
+    private @Nullable WorkSource mWorkSource;
 
     /**
      * Create a location request with default parameters.
@@ -260,23 +253,71 @@
 
     /** @hide */
     public LocationRequest() {
+        this(
+                /* provider= */ LocationManager.FUSED_PROVIDER,
+                /* quality= */ POWER_LOW,
+                /* interval= */ DEFAULT_INTERVAL_MS,
+                /* fastestInterval= */ (long) (DEFAULT_INTERVAL_MS / FASTEST_INTERVAL_FACTOR),
+                /* explicitFastestInterval= */ false,
+                /* expireAt= */ Long.MAX_VALUE,
+                /* expireIn= */ Long.MAX_VALUE,
+                /* numUpdates= */ Integer.MAX_VALUE,
+                /* smallestDisplacement= */ 0,
+                /* hideFromAppOps= */ false,
+                /* lowPowerMode= */ false,
+                /* locationSettingsIgnored= */ false,
+                /* workSource= */ null);
     }
 
     /** @hide */
     public LocationRequest(LocationRequest src) {
-        mQuality = src.mQuality;
-        mInterval = src.mInterval;
-        mFastestInterval = src.mFastestInterval;
-        mExplicitFastestInterval = src.mExplicitFastestInterval;
-        mExpireAt = src.mExpireAt;
-        mExpireIn = src.mExpireIn;
-        mNumUpdates = src.mNumUpdates;
-        mSmallestDisplacement = src.mSmallestDisplacement;
-        mProvider = src.mProvider;
-        mWorkSource = src.mWorkSource;
-        mHideFromAppOps = src.mHideFromAppOps;
-        mLowPowerMode = src.mLowPowerMode;
-        mLocationSettingsIgnored = src.mLocationSettingsIgnored;
+        this(
+                src.mProvider,
+                src.mQuality,
+                src.mInterval,
+                src.mFastestInterval,
+                src.mExplicitFastestInterval,
+                src.mExpireAt,
+                src.mExpireIn,
+                src.mNumUpdates,
+                src.mSmallestDisplacement,
+                src.mHideFromAppOps,
+                src.mLowPowerMode,
+                src.mLocationSettingsIgnored,
+                src.mWorkSource);
+    }
+
+    private LocationRequest(
+            @NonNull String provider,
+            int quality,
+            long intervalMs,
+            long fastestIntervalMs,
+            boolean explicitFastestInterval,
+            long expireAt,
+            long expireInMs,
+            int numUpdates,
+            float smallestDisplacementM,
+            boolean hideFromAppOps,
+            boolean locationSettingsIgnored,
+            boolean lowPowerMode,
+            WorkSource workSource) {
+        Preconditions.checkArgument(provider != null, "invalid provider: null");
+        checkQuality(quality);
+
+        mProvider = provider;
+        mQuality = quality;
+        mInterval = intervalMs;
+        mFastestInterval = fastestIntervalMs;
+        mExplicitFastestInterval = explicitFastestInterval;
+        mExpireAt = expireAt;
+        mExpireIn = expireInMs;
+        mNumUpdates = numUpdates;
+        mSmallestDisplacement = Preconditions.checkArgumentInRange(smallestDisplacementM, 0,
+                Float.MAX_VALUE, "smallestDisplacementM");
+        mHideFromAppOps = hideFromAppOps;
+        mLowPowerMode = lowPowerMode;
+        mLocationSettingsIgnored = locationSettingsIgnored;
+        mWorkSource = workSource;
     }
 
     /**
@@ -567,7 +608,7 @@
 
     /** Sets the provider to use for this location request. */
     public @NonNull LocationRequest setProvider(@NonNull String provider) {
-        checkProvider(provider);
+        Preconditions.checkArgument(provider != null, "invalid provider: null");
         mProvider = provider;
         return this;
     }
@@ -580,9 +621,9 @@
 
     /** @hide */
     @SystemApi
-    public @NonNull LocationRequest setSmallestDisplacement(float meters) {
-        checkDisplacement(meters);
-        mSmallestDisplacement = meters;
+    public @NonNull LocationRequest setSmallestDisplacement(float smallestDisplacementM) {
+        mSmallestDisplacement = Preconditions.checkArgumentInRange(smallestDisplacementM, 0,
+                Float.MAX_VALUE, "smallestDisplacementM");
         return this;
     }
 
@@ -653,40 +694,24 @@
         }
     }
 
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private static void checkDisplacement(float meters) {
-        if (meters < 0.0f) {
-            throw new IllegalArgumentException("invalid displacement: " + meters);
-        }
-    }
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private static void checkProvider(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("invalid provider: null");
-        }
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<LocationRequest> CREATOR =
+    public static final @NonNull Parcelable.Creator<LocationRequest> CREATOR =
             new Parcelable.Creator<LocationRequest>() {
                 @Override
                 public LocationRequest createFromParcel(Parcel in) {
-                    LocationRequest request = new LocationRequest();
-                    request.setQuality(in.readInt());
-                    request.setFastestInterval(in.readLong());
-                    request.setInterval(in.readLong());
-                    request.setExpireAt(in.readLong());
-                    request.setExpireIn(in.readLong());
-                    request.setNumUpdates(in.readInt());
-                    request.setSmallestDisplacement(in.readFloat());
-                    request.setHideFromAppOps(in.readInt() != 0);
-                    request.setLowPowerMode(in.readInt() != 0);
-                    request.setLocationSettingsIgnored(in.readInt() != 0);
-                    String provider = in.readString();
-                    if (provider != null) request.setProvider(provider);
-                    WorkSource workSource = in.readParcelable(null);
-                    if (workSource != null) request.setWorkSource(workSource);
-                    return request;
+                    return new LocationRequest(
+                            /* provider= */ in.readString(),
+                            /* quality= */ in.readInt(),
+                            /* interval= */ in.readLong(),
+                            /* fastestInterval= */ in.readLong(),
+                            /* explicitFastestInterval= */ in.readBoolean(),
+                            /* expireAt= */ in.readLong(),
+                            /* expireIn= */ in.readLong(),
+                            /* numUpdates= */ in.readInt(),
+                            /* smallestDisplacement= */ in.readFloat(),
+                            /* hideFromAppOps= */ in.readBoolean(),
+                            /* locationSettingsIgnored= */ in.readBoolean(),
+                            /* lowPowerMode= */ in.readBoolean(),
+                            /* workSource= */ in.readTypedObject(WorkSource.CREATOR));
                 }
 
                 @Override
@@ -702,18 +727,19 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mProvider);
         parcel.writeInt(mQuality);
-        parcel.writeLong(mFastestInterval);
         parcel.writeLong(mInterval);
+        parcel.writeLong(mFastestInterval);
+        parcel.writeBoolean(mExplicitFastestInterval);
         parcel.writeLong(mExpireAt);
         parcel.writeLong(mExpireIn);
         parcel.writeInt(mNumUpdates);
         parcel.writeFloat(mSmallestDisplacement);
-        parcel.writeInt(mHideFromAppOps ? 1 : 0);
-        parcel.writeInt(mLowPowerMode ? 1 : 0);
-        parcel.writeInt(mLocationSettingsIgnored ? 1 : 0);
-        parcel.writeString(mProvider);
-        parcel.writeParcelable(mWorkSource, 0);
+        parcel.writeBoolean(mHideFromAppOps);
+        parcel.writeBoolean(mLocationSettingsIgnored);
+        parcel.writeBoolean(mLowPowerMode);
+        parcel.writeTypedObject(mWorkSource, 0);
     }
 
     /** @hide */
@@ -740,16 +766,19 @@
     @Override
     public String toString() {
         StringBuilder s = new StringBuilder();
-        s.append("Request[").append(qualityToString(mQuality));
-        if (mProvider != null) s.append(' ').append(mProvider);
+        s.append("Request[");
+        s.append(qualityToString(mQuality));
+        s.append(" ").append(mProvider);
         if (mQuality != POWER_NONE) {
-            s.append(" requested=");
+            s.append(" interval=");
             TimeUtils.formatDuration(mInterval, s);
+            if (mExplicitFastestInterval) {
+                s.append(" fastestInterval=");
+                TimeUtils.formatDuration(mFastestInterval, s);
+            }
         }
-        s.append(" fastest=");
-        TimeUtils.formatDuration(mFastestInterval, s);
         if (mExpireAt != Long.MAX_VALUE) {
-            s.append(" expireAt=").append(TimeUtils.formatUptime(mExpireAt));
+            s.append(" expireAt=").append(TimeUtils.formatRealtime(mExpireAt));
         }
         if (mExpireIn != Long.MAX_VALUE) {
             s.append(" expireIn=");
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index 572fbc3..a81ddfe 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -23,7 +23,6 @@
 import android.os.WorkSource;
 import android.util.TimeUtils;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -83,18 +82,14 @@
             new Parcelable.Creator<ProviderRequest>() {
                 @Override
                 public ProviderRequest createFromParcel(Parcel in) {
-                    boolean reportLocation = in.readInt() == 1;
-                    long interval = in.readLong();
-                    boolean lowPowerMode = in.readBoolean();
-                    boolean locationSettingsIgnored = in.readBoolean();
-                    int count = in.readInt();
-                    ArrayList<LocationRequest> locationRequests = new ArrayList<>(count);
-                    for (int i = 0; i < count; i++) {
-                        locationRequests.add(LocationRequest.CREATOR.createFromParcel(in));
-                    }
-                    WorkSource workSource = in.readParcelable(null);
-                    return new ProviderRequest(reportLocation, interval, lowPowerMode,
-                            locationSettingsIgnored, locationRequests, workSource);
+                    return new ProviderRequest(
+                            /* reportLocation= */ in.readBoolean(),
+                            /* interval= */ in.readLong(),
+                            /* lowPowerMode= */ in.readBoolean(),
+                            /* locationSettingsIgnored= */ in.readBoolean(),
+                            /* locationRequests= */
+                            in.createTypedArrayList(LocationRequest.CREATOR),
+                            /* workSource= */ in.readTypedObject(WorkSource.CREATOR));
                 }
 
                 @Override
@@ -110,15 +105,12 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeInt(reportLocation ? 1 : 0);
+        parcel.writeBoolean(reportLocation);
         parcel.writeLong(interval);
         parcel.writeBoolean(lowPowerMode);
         parcel.writeBoolean(locationSettingsIgnored);
-        parcel.writeInt(locationRequests.size());
-        for (LocationRequest request : locationRequests) {
-            request.writeToParcel(parcel, flags);
-        }
-        parcel.writeParcelable(workSource, flags);
+        parcel.writeTypedList(locationRequests);
+        parcel.writeTypedObject(workSource, flags);
     }
 
     @Override
diff --git a/media/java/android/media/AudioDeviceAttributes.java b/media/java/android/media/AudioDeviceAttributes.java
index f5b0806..0ab62c1 100644
--- a/media/java/android/media/AudioDeviceAttributes.java
+++ b/media/java/android/media/AudioDeviceAttributes.java
@@ -99,11 +99,11 @@
         if (role != ROLE_OUTPUT && role != ROLE_INPUT) {
             throw new IllegalArgumentException("Invalid role " + role);
         }
-        if (role == ROLE_OUTPUT && !AudioDeviceInfo.isValidAudioDeviceTypeOut(type)) {
-            throw new IllegalArgumentException("Invalid output device type " + type);
+        if (role == ROLE_OUTPUT) {
+            AudioDeviceInfo.enforceValidAudioDeviceTypeOut(type);
         }
-        if (role == ROLE_INPUT && !AudioDeviceInfo.isValidAudioDeviceTypeIn(type)) {
-            throw new IllegalArgumentException("Invalid input device type " + type);
+        if (role == ROLE_INPUT) {
+            AudioDeviceInfo.enforceValidAudioDeviceTypeIn(type);
         }
 
         mRole = role;
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index db2a1e8..6b0e17d 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -280,6 +280,28 @@
         }
     }
 
+    /**
+     * @hide
+     * Throws IAE on an invalid output device type
+     * @param type
+     */
+    public static void enforceValidAudioDeviceTypeOut(int type) {
+        if (!isValidAudioDeviceTypeOut(type)) {
+            throw new IllegalArgumentException("Illegal output device type " + type);
+        }
+    }
+
+    /**
+     * @hide
+     * Throws IAE on an invalid input device type
+     * @param type
+     */
+    public static void enforceValidAudioDeviceTypeIn(int type) {
+        if (!isValidAudioDeviceTypeIn(type)) {
+            throw new IllegalArgumentException("Illegal input device type " + type);
+        }
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7408987e..8477aa3 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4571,6 +4571,150 @@
         }
     }
 
+    /**
+     * @hide
+     * Volume behavior for an audio device where a software attenuation is applied
+     * @see #setDeviceVolumeBehavior(int, String, int)
+     */
+    public static final int DEVICE_VOLUME_BEHAVIOR_VARIABLE = 0;
+    /**
+     * @hide
+     * Volume behavior for an audio device where the volume is always set to provide no attenuation
+     *     nor gain (e.g. unit gain).
+     * @see #setDeviceVolumeBehavior(int, String, int)
+     */
+    public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1;
+    /**
+     * @hide
+     * Volume behavior for an audio device where the volume is either set to muted, or to provide
+     *     no attenuation nor gain (e.g. unit gain).
+     * @see #setDeviceVolumeBehavior(int, String, int)
+     */
+    public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2;
+    /**
+     * @hide
+     * Volume behavior for an audio device where no software attenuation is applied, and
+     *     the volume is kept synchronized between the host and the device itself through a
+     *     device-specific protocol such as BT AVRCP.
+     * @see #setDeviceVolumeBehavior(int, String, int)
+     */
+    public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE = 3;
+    /**
+     * @hide
+     * Volume behavior for an audio device where no software attenuation is applied, and
+     *     the volume is kept synchronized between the host and the device itself through a
+     *     device-specific protocol (such as for hearing aids), based on the audio mode (e.g.
+     *     normal vs in phone call).
+     * @see #setMode(int)
+     * @see #setDeviceVolumeBehavior(int, String, int)
+     */
+    public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4;
+
+    /** @hide */
+    @IntDef({
+            DEVICE_VOLUME_BEHAVIOR_VARIABLE,
+            DEVICE_VOLUME_BEHAVIOR_FULL,
+            DEVICE_VOLUME_BEHAVIOR_FIXED,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeviceVolumeBehavior {}
+
+    /**
+     * @hide
+     * Throws IAE on an invalid volume behavior value
+     * @param volumeBehavior behavior value to check
+     */
+    public static void enforceValidVolumeBehavior(int volumeBehavior) {
+        switch (volumeBehavior) {
+            case DEVICE_VOLUME_BEHAVIOR_VARIABLE:
+            case DEVICE_VOLUME_BEHAVIOR_FULL:
+            case DEVICE_VOLUME_BEHAVIOR_FIXED:
+            case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
+            case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
+                return;
+            default:
+                throw new IllegalArgumentException("Illegal volume behavior " + volumeBehavior);
+        }
+    }
+
+    /**
+     * @hide
+     * Sets the volume behavior for an audio output device.
+     * @param deviceType the type of audio device to be affected. Currently only supports
+     *     {@link AudioDeviceInfo#TYPE_HDMI}, {@link AudioDeviceInfo#TYPE_HDMI_ARC},
+     *     {@link AudioDeviceInfo#TYPE_LINE_DIGITAL} and {@link AudioDeviceInfo#TYPE_AUX_LINE}
+     * @param deviceAddress the address of the device, if any
+     * @param deviceVolumeBehavior one of the device behaviors
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public void setDeviceVolumeBehavior(int deviceType, @Nullable String deviceAddress,
+            @DeviceVolumeBehavior int deviceVolumeBehavior) {
+        setDeviceVolumeBehavior(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
+                deviceType, deviceAddress), deviceVolumeBehavior);
+    }
+
+    /**
+     * @hide
+     * Sets the volume behavior for an audio output device.
+     * @param device the device to be affected. Currently only supports devices of type
+     *     {@link AudioDeviceInfo#TYPE_HDMI}, {@link AudioDeviceInfo#TYPE_HDMI_ARC},
+     *     {@link AudioDeviceInfo#TYPE_LINE_DIGITAL} and {@link AudioDeviceInfo#TYPE_AUX_LINE}
+     * @param deviceVolumeBehavior one of the device behaviors
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device,
+            @DeviceVolumeBehavior int deviceVolumeBehavior) {
+        // verify arguments (validity of device type is enforced in server)
+        Objects.requireNonNull(device);
+        enforceValidVolumeBehavior(deviceVolumeBehavior);
+        // communicate with service
+        final IAudioService service = getService();
+        try {
+            service.setDeviceVolumeBehavior(device, deviceVolumeBehavior,
+                    mApplicationContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     * Returns the volume device behavior for the given device type and address
+     * @param deviceType an audio output device type, as defined in {@link AudioDeviceInfo}
+     * @param deviceAddress the address of the audio device, if any.
+     * @return the volume behavior for the device
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public @DeviceVolumeBehavior int getDeviceVolumeBehavior(int deviceType,
+            @Nullable String deviceAddress) {
+        // verify arguments
+        AudioDeviceInfo.enforceValidAudioDeviceTypeOut(deviceType);
+        return getDeviceVolumeBehavior(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
+                deviceType, deviceAddress));
+    }
+
+    /**
+     * @hide
+     * Returns the volume device behavior for the given audio device
+     * @param device the audio device
+     * @return the volume behavior for the device
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public @DeviceVolumeBehavior int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device)
+    {
+        // verify arguments (validity of device type is enforced in server)
+        Objects.requireNonNull(device);
+        // communicate with service
+        final IAudioService service = getService();
+        try {
+            return service.getDeviceVolumeBehavior(device);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
      /**
      * Indicate wired accessory connection state change.
      * @param device type of device connected/disconnected (AudioManager.DEVICE_OUT_xxx)
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 155eb1c..c11762b 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -44,46 +44,56 @@
 /**
  * @hide
  */
+@TestApi
 public class AudioSystem
 {
     private static final boolean DEBUG_VOLUME = false;
 
     private static final String TAG = "AudioSystem";
+
+    // private constructor to prevent instantiating AudioSystem
+    private AudioSystem() {
+        throw new UnsupportedOperationException("Trying to instantiate AudioSystem");
+    }
+
     /* These values must be kept in sync with system/audio.h */
     /*
      * If these are modified, please also update Settings.System.VOLUME_SETTINGS
      * and attrs.xml and AudioManager.java.
      */
-    /** Used to identify the default audio stream volume */
+    /** @hide Used to identify the default audio stream volume */
+    @TestApi
     public static final int STREAM_DEFAULT = -1;
-    /** Used to identify the volume of audio streams for phone calls */
+    /** @hide Used to identify the volume of audio streams for phone calls */
     public static final int STREAM_VOICE_CALL = 0;
-    /** Used to identify the volume of audio streams for system sounds */
+    /** @hide Used to identify the volume of audio streams for system sounds */
     public static final int STREAM_SYSTEM = 1;
-    /** Used to identify the volume of audio streams for the phone ring and message alerts */
+    /** @hide Used to identify the volume of audio streams for the phone ring and message alerts */
     public static final int STREAM_RING = 2;
-    /** Used to identify the volume of audio streams for music playback */
+    /** @hide Used to identify the volume of audio streams for music playback */
     public static final int STREAM_MUSIC = 3;
-    /** Used to identify the volume of audio streams for alarms */
+    /** @hide Used to identify the volume of audio streams for alarms */
     public static final int STREAM_ALARM = 4;
-    /** Used to identify the volume of audio streams for notifications */
+    /** @hide Used to identify the volume of audio streams for notifications */
     public static final int STREAM_NOTIFICATION = 5;
-    /** Used to identify the volume of audio streams for phone calls when connected on bluetooth */
+    /** @hide
+     *  Used to identify the volume of audio streams for phone calls when connected on bluetooth */
     public static final int STREAM_BLUETOOTH_SCO = 6;
-    /** Used to identify the volume of audio streams for enforced system sounds in certain
+    /** @hide Used to identify the volume of audio streams for enforced system sounds in certain
      * countries (e.g camera in Japan) */
     @UnsupportedAppUsage
     public static final int STREAM_SYSTEM_ENFORCED = 7;
-    /** Used to identify the volume of audio streams for DTMF tones */
+    /** @hide Used to identify the volume of audio streams for DTMF tones */
     public static final int STREAM_DTMF = 8;
-    /** Used to identify the volume of audio streams exclusively transmitted through the
+    /** @hide Used to identify the volume of audio streams exclusively transmitted through the
      *  speaker (TTS) of the device */
     public static final int STREAM_TTS = 9;
-    /** Used to identify the volume of audio streams for accessibility prompts */
+    /** @hide Used to identify the volume of audio streams for accessibility prompts */
     public static final int STREAM_ACCESSIBILITY = 10;
-    /** Used to identify the volume of audio streams for virtual assistant */
+    /** @hide Used to identify the volume of audio streams for virtual assistant */
     public static final int STREAM_ASSISTANT = 11;
     /**
+     * @hide
      * @deprecated Use {@link #numStreamTypes() instead}
      */
     public static final int NUM_STREAMS = 5;
@@ -96,9 +106,16 @@
 
     // Expose only the getter method publicly so we can change it in the future
     private static final int NUM_STREAM_TYPES = 12;
+
+    /**
+     * @hide
+     * @return total number of stream types
+     */
     @UnsupportedAppUsage
+    @TestApi
     public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
 
+    /** @hide */
     public static final String[] STREAM_NAMES = new String[] {
         "STREAM_VOICE_CALL",
         "STREAM_SYSTEM",
@@ -114,7 +131,8 @@
         "STREAM_ASSISTANT"
     };
 
-    /*
+    /**
+     * @hide
      * Sets the microphone mute on or off.
      *
      * @param on set <var>true</var> to mute the microphone;
@@ -124,7 +142,8 @@
     @UnsupportedAppUsage
     public static native int muteMicrophone(boolean on);
 
-    /*
+    /**
+     * @hide
      * Checks whether the microphone mute is on or off.
      *
      * @return true if microphone is muted, false if it's not
@@ -133,15 +152,24 @@
     public static native boolean isMicrophoneMuted();
 
     /* modes for setPhoneState, must match AudioSystem.h audio_mode */
+    /** @hide */
     public static final int MODE_INVALID            = -2;
+    /** @hide */
     public static final int MODE_CURRENT            = -1;
+    /** @hide */
     public static final int MODE_NORMAL             = 0;
+    /** @hide */
     public static final int MODE_RINGTONE           = 1;
+    /** @hide */
     public static final int MODE_IN_CALL            = 2;
+    /** @hide */
     public static final int MODE_IN_COMMUNICATION   = 3;
+    /** @hide */
     public static final int MODE_CALL_SCREENING     = 4;
+    /** @hide */
     public static final int NUM_MODES               = 5;
 
+    /** @hide */
     public static String modeToString(int mode) {
         switch (mode) {
             case MODE_CURRENT: return "MODE_CURRENT";
@@ -156,15 +184,23 @@
     }
 
     /* Formats for A2DP codecs, must match system/audio-base.h audio_format_t */
+    /** @hide */
     public static final int AUDIO_FORMAT_INVALID        = 0xFFFFFFFF;
+    /** @hide */
     public static final int AUDIO_FORMAT_DEFAULT        = 0;
+    /** @hide */
     public static final int AUDIO_FORMAT_AAC            = 0x04000000;
+    /** @hide */
     public static final int AUDIO_FORMAT_SBC            = 0x1F000000;
+    /** @hide */
     public static final int AUDIO_FORMAT_APTX           = 0x20000000;
+    /** @hide */
     public static final int AUDIO_FORMAT_APTX_HD        = 0x21000000;
+    /** @hide */
     public static final int AUDIO_FORMAT_LDAC           = 0x23000000;
 
     /**
+     * @hide
      * Convert audio format enum values to Bluetooth codec values
      */
     public static int audioFormatToBluetoothSourceCodec(int audioFormat) {
@@ -179,25 +215,27 @@
     }
 
     /* Routing bits for the former setRouting/getRouting API */
-    /** @deprecated */
+    /** @hide @deprecated */
     @Deprecated public static final int ROUTE_EARPIECE          = (1 << 0);
-    /** @deprecated */
+    /** @hide @deprecated */
     @Deprecated public static final int ROUTE_SPEAKER           = (1 << 1);
-    /** @deprecated use {@link #ROUTE_BLUETOOTH_SCO} */
+    /** @hide @deprecated use {@link #ROUTE_BLUETOOTH_SCO} */
     @Deprecated public static final int ROUTE_BLUETOOTH = (1 << 2);
-    /** @deprecated */
+    /** @hide @deprecated */
     @Deprecated public static final int ROUTE_BLUETOOTH_SCO     = (1 << 2);
-    /** @deprecated */
+    /** @hide @deprecated */
     @Deprecated public static final int ROUTE_HEADSET           = (1 << 3);
-    /** @deprecated */
+    /** @hide @deprecated */
     @Deprecated public static final int ROUTE_BLUETOOTH_A2DP    = (1 << 4);
-    /** @deprecated */
+    /** @hide @deprecated */
     @Deprecated public static final int ROUTE_ALL               = 0xFFFFFFFF;
 
     // Keep in sync with system/media/audio/include/system/audio.h
+    /**  @hide */
     public static final int AUDIO_SESSION_ALLOCATE = 0;
 
-    /*
+    /**
+     * @hide
      * Checks whether the specified stream type is active.
      *
      * return true if any track playing on this stream is active.
@@ -205,7 +243,8 @@
     @UnsupportedAppUsage
     public static native boolean isStreamActive(int stream, int inPastMs);
 
-    /*
+    /**
+     * @hide
      * Checks whether the specified stream type is active on a remotely connected device. The notion
      * of what constitutes a remote device is enforced by the audio policy manager of the platform.
      *
@@ -213,7 +252,8 @@
      */
     public static native boolean isStreamActiveRemotely(int stream, int inPastMs);
 
-    /*
+    /**
+     * @hide
      * Checks whether the specified audio source is active.
      *
      * return true if any recorder using this source is currently recording
@@ -221,23 +261,27 @@
     @UnsupportedAppUsage
     public static native boolean isSourceActive(int source);
 
-    /*
+    /**
+     * @hide
      * Returns a new unused audio session ID
      */
     public static native int newAudioSessionId();
 
-    /*
+    /**
+     * @hide
      * Returns a new unused audio player ID
      */
     public static native int newAudioPlayerId();
 
     /**
+     * @hide
      * Returns a new unused audio recorder ID
      */
     public static native int newAudioRecorderId();
 
 
-    /*
+    /**
+     * @hide
      * Sets a group generic audio configuration parameters. The use of these parameters
      * are platform dependent, see libaudio
      *
@@ -247,7 +291,8 @@
     @UnsupportedAppUsage
     public static native int setParameters(String keyValuePairs);
 
-    /*
+    /**
+     * @hide
      * Gets a group generic audio configuration parameters. The use of these parameters
      * are platform dependent, see libaudio
      *
@@ -259,16 +304,16 @@
     public static native String getParameters(String keys);
 
     // These match the enum AudioError in frameworks/base/core/jni/android_media_AudioSystem.cpp
-    /* Command sucessful or Media server restarted. see ErrorCallback */
+    /** @hide Command successful or Media server restarted. see ErrorCallback */
     public static final int AUDIO_STATUS_OK = 0;
-    /* Command failed or unspecified audio error.  see ErrorCallback */
+    /** @hide Command failed or unspecified audio error.  see ErrorCallback */
     public static final int AUDIO_STATUS_ERROR = 1;
-    /* Media server died. see ErrorCallback */
+    /** @hide Media server died. see ErrorCallback */
     public static final int AUDIO_STATUS_SERVER_DIED = 100;
 
-    private static ErrorCallback mErrorCallback;
+    private static ErrorCallback sErrorCallback;
 
-    /*
+    /** @hide
      * Handles the audio error callback.
      */
     public interface ErrorCallback
@@ -283,7 +328,8 @@
         void onError(int error);
     };
 
-    /*
+    /**
+     * @hide
      * Registers a callback to be invoked when an error occurs.
      * @param cb the callback to run
      */
@@ -291,7 +337,7 @@
     public static void setErrorCallback(ErrorCallback cb)
     {
         synchronized (AudioSystem.class) {
-            mErrorCallback = cb;
+            sErrorCallback = cb;
             if (cb != null) {
                 cb.onError(checkAudioFlinger());
             }
@@ -303,8 +349,8 @@
     {
         ErrorCallback errorCallback = null;
         synchronized (AudioSystem.class) {
-            if (mErrorCallback != null) {
-                errorCallback = mErrorCallback;
+            if (sErrorCallback != null) {
+                errorCallback = sErrorCallback;
             }
         }
         if (errorCallback != null) {
@@ -313,6 +359,7 @@
     }
 
     /**
+     * @hide
      * Handles events from the audio policy manager about dynamic audio policies
      * @see android.media.audiopolicy.AudioPolicy
      */
@@ -326,6 +373,7 @@
 
     private static DynamicPolicyCallback sDynPolicyCallback;
 
+    /** @hide */
     public static void setDynamicPolicyCallback(DynamicPolicyCallback cb)
     {
         synchronized (AudioSystem.class) {
@@ -355,6 +403,7 @@
     }
 
     /**
+     * @hide
      * Handles events from the audio policy manager about recording events
      * @see android.media.AudioManager.AudioRecordingCallback
      */
@@ -386,6 +435,7 @@
 
     private static AudioRecordingCallback sRecordingCallback;
 
+    /** @hide */
     public static void setRecordingCallback(AudioRecordingCallback cb) {
         synchronized (AudioSystem.class) {
             sRecordingCallback = cb;
@@ -434,13 +484,21 @@
      * Error codes used by public APIs (AudioTrack, AudioRecord, AudioManager ...)
      * Must be kept in sync with frameworks/base/core/jni/android_media_AudioErrors.h
      */
+    /** @hide */
     public static final int SUCCESS            = 0;
+    /** @hide */
     public static final int ERROR              = -1;
+    /** @hide */
     public static final int BAD_VALUE          = -2;
+    /** @hide */
     public static final int INVALID_OPERATION  = -3;
+    /** @hide */
     public static final int PERMISSION_DENIED  = -4;
+    /** @hide */
     public static final int NO_INIT            = -5;
+    /** @hide */
     public static final int DEAD_OBJECT        = -6;
+    /** @hide */
     public static final int WOULD_BLOCK        = -7;
 
     /** @hide */
@@ -458,6 +516,7 @@
     public @interface AudioSystemError {}
 
     /**
+     * @hide
      * Convert an int error value to its String value for readability.
      * Accepted error values are the java AudioSystem errors, matching android_media_AudioErrors.h,
      * which map onto the native status_t type.
@@ -494,74 +553,113 @@
     //
     // audio device definitions: must be kept in sync with values in system/core/audio.h
     //
-
+    /** @hide */
     public static final int DEVICE_NONE = 0x0;
     // reserved bits
+    /** @hide */
     public static final int DEVICE_BIT_IN = 0x80000000;
+    /** @hide */
     public static final int DEVICE_BIT_DEFAULT = 0x40000000;
     // output devices, be sure to update AudioManager.java also
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_EARPIECE = 0x1;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_SPEAKER = 0x2;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_WIRED_HEADSET = 0x4;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
+    /** @hide */
     public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;
+    /** @hide */
     public static final int DEVICE_OUT_LINE = 0x20000;
+    /** @hide */
     public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
+    /** @hide */
     public static final int DEVICE_OUT_SPDIF = 0x80000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_FM = 0x100000;
+    /** @hide */
     public static final int DEVICE_OUT_AUX_LINE = 0x200000;
+    /** @hide */
     public static final int DEVICE_OUT_SPEAKER_SAFE = 0x400000;
+    /** @hide */
     public static final int DEVICE_OUT_IP = 0x800000;
+    /** @hide */
     public static final int DEVICE_OUT_BUS = 0x1000000;
+    /** @hide */
     public static final int DEVICE_OUT_PROXY = 0x2000000;
+    /** @hide */
     public static final int DEVICE_OUT_USB_HEADSET = 0x4000000;
+    /** @hide */
     public static final int DEVICE_OUT_HEARING_AID = 0x8000000;
 
+    /** @hide */
     public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
 
     // Deprecated in R because multiple device types are no longer accessed as a bit mask.
     // Removing this will get lint warning about changing hidden apis.
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
                                                   DEVICE_OUT_USB_DEVICE |
                                                   DEVICE_OUT_USB_HEADSET);
 
+    /** @hide */
     public static final Set<Integer> DEVICE_OUT_ALL_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_OUT_ALL_A2DP_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_OUT_ALL_SCO_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_OUT_ALL_USB_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET;
     static {
         DEVICE_OUT_ALL_SET = new HashSet<>();
@@ -621,53 +719,85 @@
     }
 
     // input devices
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_COMMUNICATION = DEVICE_BIT_IN | 0x1;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_AMBIENT = DEVICE_BIT_IN | 0x2;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_BUILTIN_MIC = DEVICE_BIT_IN | 0x4;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;
+    /** @hide */
     public static final int DEVICE_IN_HDMI = DEVICE_IN_AUX_DIGITAL;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
+    /** @hide */
     public static final int DEVICE_IN_TELEPHONY_RX = DEVICE_IN_VOICE_CALL;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_BACK_MIC = DEVICE_BIT_IN | 0x80;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_REMOTE_SUBMIX = DEVICE_BIT_IN | 0x100;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_ANLG_DOCK_HEADSET = DEVICE_BIT_IN | 0x200;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_DGTL_DOCK_HEADSET = DEVICE_BIT_IN | 0x400;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_USB_ACCESSORY = DEVICE_BIT_IN | 0x800;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000;
+    /** @hide */
     public static final int DEVICE_IN_FM_TUNER = DEVICE_BIT_IN | 0x2000;
+    /** @hide */
     public static final int DEVICE_IN_TV_TUNER = DEVICE_BIT_IN | 0x4000;
+    /** @hide */
     public static final int DEVICE_IN_LINE = DEVICE_BIT_IN | 0x8000;
+    /** @hide */
     public static final int DEVICE_IN_SPDIF = DEVICE_BIT_IN | 0x10000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_BLUETOOTH_A2DP = DEVICE_BIT_IN | 0x20000;
+    /** @hide */
     public static final int DEVICE_IN_LOOPBACK = DEVICE_BIT_IN | 0x40000;
+    /** @hide */
     public static final int DEVICE_IN_IP = DEVICE_BIT_IN | 0x80000;
+    /** @hide */
     public static final int DEVICE_IN_BUS = DEVICE_BIT_IN | 0x100000;
+    /** @hide */
     public static final int DEVICE_IN_PROXY = DEVICE_BIT_IN | 0x1000000;
+    /** @hide */
     public static final int DEVICE_IN_USB_HEADSET = DEVICE_BIT_IN | 0x2000000;
+    /** @hide */
     public static final int DEVICE_IN_BLUETOOTH_BLE = DEVICE_BIT_IN | 0x4000000;
+    /** @hide */
     public static final int DEVICE_IN_HDMI_ARC = DEVICE_BIT_IN | 0x8000000;
+    /** @hide */
     public static final int DEVICE_IN_ECHO_REFERENCE = DEVICE_BIT_IN | 0x10000000;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
 
+    /** @hide */
     public static final Set<Integer> DEVICE_IN_ALL_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_IN_ALL_SCO_SET;
+    /** @hide */
     public static final Set<Integer> DEVICE_IN_ALL_USB_SET;
     static {
         DEVICE_IN_ALL_SET = new HashSet<>();
@@ -708,15 +838,19 @@
         DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);
     }
 
+    /** @hide */
     public static final String LEGACY_REMOTE_SUBMIX_ADDRESS = "0";
 
     // device states, must match AudioSystem::device_connection_state
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_STATE_UNAVAILABLE = 0;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int DEVICE_STATE_AVAILABLE = 1;
     private static final int NUM_DEVICE_STATES = 1;
 
+    /** @hide */
     public static String deviceStateToString(int state) {
         switch (state) {
             case DEVICE_STATE_UNAVAILABLE: return "DEVICE_STATE_UNAVAILABLE";
@@ -725,63 +859,65 @@
         }
     }
 
-    public static final String DEVICE_OUT_EARPIECE_NAME = "earpiece";
-    public static final String DEVICE_OUT_SPEAKER_NAME = "speaker";
-    public static final String DEVICE_OUT_WIRED_HEADSET_NAME = "headset";
-    public static final String DEVICE_OUT_WIRED_HEADPHONE_NAME = "headphone";
-    public static final String DEVICE_OUT_BLUETOOTH_SCO_NAME = "bt_sco";
-    public static final String DEVICE_OUT_BLUETOOTH_SCO_HEADSET_NAME = "bt_sco_hs";
-    public static final String DEVICE_OUT_BLUETOOTH_SCO_CARKIT_NAME = "bt_sco_carkit";
-    public static final String DEVICE_OUT_BLUETOOTH_A2DP_NAME = "bt_a2dp";
+    /** @hide */ public static final String DEVICE_OUT_EARPIECE_NAME = "earpiece";
+    /** @hide */ public static final String DEVICE_OUT_SPEAKER_NAME = "speaker";
+    /** @hide */ public static final String DEVICE_OUT_WIRED_HEADSET_NAME = "headset";
+    /** @hide */ public static final String DEVICE_OUT_WIRED_HEADPHONE_NAME = "headphone";
+    /** @hide */ public static final String DEVICE_OUT_BLUETOOTH_SCO_NAME = "bt_sco";
+    /** @hide */ public static final String DEVICE_OUT_BLUETOOTH_SCO_HEADSET_NAME = "bt_sco_hs";
+    /** @hide */ public static final String DEVICE_OUT_BLUETOOTH_SCO_CARKIT_NAME = "bt_sco_carkit";
+    /** @hide */ public static final String DEVICE_OUT_BLUETOOTH_A2DP_NAME = "bt_a2dp";
+    /** @hide */
     public static final String DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME = "bt_a2dp_hp";
-    public static final String DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME = "bt_a2dp_spk";
-    public static final String DEVICE_OUT_AUX_DIGITAL_NAME = "aux_digital";
-    public static final String DEVICE_OUT_HDMI_NAME = "hdmi";
-    public static final String DEVICE_OUT_ANLG_DOCK_HEADSET_NAME = "analog_dock";
-    public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock";
-    public static final String DEVICE_OUT_USB_ACCESSORY_NAME = "usb_accessory";
-    public static final String DEVICE_OUT_USB_DEVICE_NAME = "usb_device";
-    public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
-    public static final String DEVICE_OUT_TELEPHONY_TX_NAME = "telephony_tx";
-    public static final String DEVICE_OUT_LINE_NAME = "line";
-    public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
-    public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
-    public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
-    public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line";
-    public static final String DEVICE_OUT_SPEAKER_SAFE_NAME = "speaker_safe";
-    public static final String DEVICE_OUT_IP_NAME = "ip";
-    public static final String DEVICE_OUT_BUS_NAME = "bus";
-    public static final String DEVICE_OUT_PROXY_NAME = "proxy";
-    public static final String DEVICE_OUT_USB_HEADSET_NAME = "usb_headset";
-    public static final String DEVICE_OUT_HEARING_AID_NAME = "hearing_aid_out";
+    /** @hide */ public static final String DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME = "bt_a2dp_spk";
+    /** @hide */ public static final String DEVICE_OUT_AUX_DIGITAL_NAME = "aux_digital";
+    /** @hide */ public static final String DEVICE_OUT_HDMI_NAME = "hdmi";
+    /** @hide */ public static final String DEVICE_OUT_ANLG_DOCK_HEADSET_NAME = "analog_dock";
+    /** @hide */ public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock";
+    /** @hide */ public static final String DEVICE_OUT_USB_ACCESSORY_NAME = "usb_accessory";
+    /** @hide */ public static final String DEVICE_OUT_USB_DEVICE_NAME = "usb_device";
+    /** @hide */ public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
+    /** @hide */ public static final String DEVICE_OUT_TELEPHONY_TX_NAME = "telephony_tx";
+    /** @hide */ public static final String DEVICE_OUT_LINE_NAME = "line";
+    /** @hide */ public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
+    /** @hide */ public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
+    /** @hide */ public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
+    /** @hide */ public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line";
+    /** @hide */ public static final String DEVICE_OUT_SPEAKER_SAFE_NAME = "speaker_safe";
+    /** @hide */ public static final String DEVICE_OUT_IP_NAME = "ip";
+    /** @hide */ public static final String DEVICE_OUT_BUS_NAME = "bus";
+    /** @hide */ public static final String DEVICE_OUT_PROXY_NAME = "proxy";
+    /** @hide */ public static final String DEVICE_OUT_USB_HEADSET_NAME = "usb_headset";
+    /** @hide */ public static final String DEVICE_OUT_HEARING_AID_NAME = "hearing_aid_out";
 
-    public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
-    public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
-    public static final String DEVICE_IN_BUILTIN_MIC_NAME = "mic";
-    public static final String DEVICE_IN_BLUETOOTH_SCO_HEADSET_NAME = "bt_sco_hs";
-    public static final String DEVICE_IN_WIRED_HEADSET_NAME = "headset";
-    public static final String DEVICE_IN_AUX_DIGITAL_NAME = "aux_digital";
-    public static final String DEVICE_IN_TELEPHONY_RX_NAME = "telephony_rx";
-    public static final String DEVICE_IN_BACK_MIC_NAME = "back_mic";
-    public static final String DEVICE_IN_REMOTE_SUBMIX_NAME = "remote_submix";
-    public static final String DEVICE_IN_ANLG_DOCK_HEADSET_NAME = "analog_dock";
-    public static final String DEVICE_IN_DGTL_DOCK_HEADSET_NAME = "digital_dock";
-    public static final String DEVICE_IN_USB_ACCESSORY_NAME = "usb_accessory";
-    public static final String DEVICE_IN_USB_DEVICE_NAME = "usb_device";
-    public static final String DEVICE_IN_FM_TUNER_NAME = "fm_tuner";
-    public static final String DEVICE_IN_TV_TUNER_NAME = "tv_tuner";
-    public static final String DEVICE_IN_LINE_NAME = "line";
-    public static final String DEVICE_IN_SPDIF_NAME = "spdif";
-    public static final String DEVICE_IN_BLUETOOTH_A2DP_NAME = "bt_a2dp";
-    public static final String DEVICE_IN_LOOPBACK_NAME = "loopback";
-    public static final String DEVICE_IN_IP_NAME = "ip";
-    public static final String DEVICE_IN_BUS_NAME = "bus";
-    public static final String DEVICE_IN_PROXY_NAME = "proxy";
-    public static final String DEVICE_IN_USB_HEADSET_NAME = "usb_headset";
-    public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble";
-    public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference";
-    public static final String DEVICE_IN_HDMI_ARC_NAME = "hdmi_arc";
+    /** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
+    /** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
+    /** @hide */ public static final String DEVICE_IN_BUILTIN_MIC_NAME = "mic";
+    /** @hide */ public static final String DEVICE_IN_BLUETOOTH_SCO_HEADSET_NAME = "bt_sco_hs";
+    /** @hide */ public static final String DEVICE_IN_WIRED_HEADSET_NAME = "headset";
+    /** @hide */ public static final String DEVICE_IN_AUX_DIGITAL_NAME = "aux_digital";
+    /** @hide */ public static final String DEVICE_IN_TELEPHONY_RX_NAME = "telephony_rx";
+    /** @hide */ public static final String DEVICE_IN_BACK_MIC_NAME = "back_mic";
+    /** @hide */ public static final String DEVICE_IN_REMOTE_SUBMIX_NAME = "remote_submix";
+    /** @hide */ public static final String DEVICE_IN_ANLG_DOCK_HEADSET_NAME = "analog_dock";
+    /** @hide */ public static final String DEVICE_IN_DGTL_DOCK_HEADSET_NAME = "digital_dock";
+    /** @hide */ public static final String DEVICE_IN_USB_ACCESSORY_NAME = "usb_accessory";
+    /** @hide */ public static final String DEVICE_IN_USB_DEVICE_NAME = "usb_device";
+    /** @hide */ public static final String DEVICE_IN_FM_TUNER_NAME = "fm_tuner";
+    /** @hide */ public static final String DEVICE_IN_TV_TUNER_NAME = "tv_tuner";
+    /** @hide */ public static final String DEVICE_IN_LINE_NAME = "line";
+    /** @hide */ public static final String DEVICE_IN_SPDIF_NAME = "spdif";
+    /** @hide */ public static final String DEVICE_IN_BLUETOOTH_A2DP_NAME = "bt_a2dp";
+    /** @hide */ public static final String DEVICE_IN_LOOPBACK_NAME = "loopback";
+    /** @hide */ public static final String DEVICE_IN_IP_NAME = "ip";
+    /** @hide */ public static final String DEVICE_IN_BUS_NAME = "bus";
+    /** @hide */ public static final String DEVICE_IN_PROXY_NAME = "proxy";
+    /** @hide */ public static final String DEVICE_IN_USB_HEADSET_NAME = "usb_headset";
+    /** @hide */ public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble";
+    /** @hide */ public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference";
+    /** @hide */ public static final String DEVICE_IN_HDMI_ARC_NAME = "hdmi_arc";
 
+    /** @hide */
     @UnsupportedAppUsage
     public static String getOutputDeviceName(int device)
     {
@@ -848,6 +984,7 @@
         }
     }
 
+    /** @hide */
     public static String getInputDeviceName(int device)
     {
         switch(device) {
@@ -910,6 +1047,7 @@
     }
 
     /**
+     * @hide
      * Returns a human readable name for a given device type
      * @param device a native device type, NOT an AudioDeviceInfo type
      * @return a string describing the device type
@@ -922,35 +1060,31 @@
     }
 
     // phone state, match audio_mode???
-    public static final int PHONE_STATE_OFFCALL = 0;
-    public static final int PHONE_STATE_RINGING = 1;
-    public static final int PHONE_STATE_INCALL = 2;
+    /** @hide */ public static final int PHONE_STATE_OFFCALL = 0;
+    /** @hide */ public static final int PHONE_STATE_RINGING = 1;
+    /** @hide */ public static final int PHONE_STATE_INCALL = 2;
 
     // device categories config for setForceUse, must match audio_policy_forced_cfg_t
-    @UnsupportedAppUsage
-    public static final int FORCE_NONE = 0;
-    public static final int FORCE_SPEAKER = 1;
-    public static final int FORCE_HEADPHONES = 2;
-    public static final int FORCE_BT_SCO = 3;
-    public static final int FORCE_BT_A2DP = 4;
-    public static final int FORCE_WIRED_ACCESSORY = 5;
-    @UnsupportedAppUsage
-    public static final int FORCE_BT_CAR_DOCK = 6;
-    @UnsupportedAppUsage
-    public static final int FORCE_BT_DESK_DOCK = 7;
-    @UnsupportedAppUsage
-    public static final int FORCE_ANALOG_DOCK = 8;
-    @UnsupportedAppUsage
-    public static final int FORCE_DIGITAL_DOCK = 9;
-    public static final int FORCE_NO_BT_A2DP = 10;
-    public static final int FORCE_SYSTEM_ENFORCED = 11;
-    public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
-    public static final int FORCE_ENCODED_SURROUND_NEVER = 13;
-    public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14;
-    public static final int FORCE_ENCODED_SURROUND_MANUAL = 15;
-    public static final int NUM_FORCE_CONFIG = 16;
-    public static final int FORCE_DEFAULT = FORCE_NONE;
+    /** @hide */ @UnsupportedAppUsage public static final int FORCE_NONE = 0;
+    /** @hide */ public static final int FORCE_SPEAKER = 1;
+    /** @hide */ public static final int FORCE_HEADPHONES = 2;
+    /** @hide */ public static final int FORCE_BT_SCO = 3;
+    /** @hide */ public static final int FORCE_BT_A2DP = 4;
+    /** @hide */ public static final int FORCE_WIRED_ACCESSORY = 5;
+    /** @hide */ @UnsupportedAppUsage public static final int FORCE_BT_CAR_DOCK = 6;
+    /** @hide */ @UnsupportedAppUsage public static final int FORCE_BT_DESK_DOCK = 7;
+    /** @hide */ @UnsupportedAppUsage public static final int FORCE_ANALOG_DOCK = 8;
+    /** @hide */ @UnsupportedAppUsage public static final int FORCE_DIGITAL_DOCK = 9;
+    /** @hide */ public static final int FORCE_NO_BT_A2DP = 10;
+    /** @hide */ public static final int FORCE_SYSTEM_ENFORCED = 11;
+    /** @hide */ public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
+    /** @hide */ public static final int FORCE_ENCODED_SURROUND_NEVER = 13;
+    /** @hide */ public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14;
+    /** @hide */ public static final int FORCE_ENCODED_SURROUND_MANUAL = 15;
+    /** @hide */ public static final int NUM_FORCE_CONFIG = 16;
+    /** @hide */ public static final int FORCE_DEFAULT = FORCE_NONE;
 
+    /** @hide */
     public static String forceUseConfigToString(int config) {
         switch (config) {
             case FORCE_NONE: return "FORCE_NONE";
@@ -974,16 +1108,17 @@
     }
 
     // usage for setForceUse, must match audio_policy_force_use_t
-    public static final int FOR_COMMUNICATION = 0;
-    public static final int FOR_MEDIA = 1;
-    public static final int FOR_RECORD = 2;
-    public static final int FOR_DOCK = 3;
-    public static final int FOR_SYSTEM = 4;
-    public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
-    public static final int FOR_ENCODED_SURROUND = 6;
-    public static final int FOR_VIBRATE_RINGING = 7;
+    /** @hide */ public static final int FOR_COMMUNICATION = 0;
+    /** @hide */ public static final int FOR_MEDIA = 1;
+    /** @hide */ public static final int FOR_RECORD = 2;
+    /** @hide */ public static final int FOR_DOCK = 3;
+    /** @hide */ public static final int FOR_SYSTEM = 4;
+    /** @hide */ public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
+    /** @hide */ public static final int FOR_ENCODED_SURROUND = 6;
+    /** @hide */ public static final int FOR_VIBRATE_RINGING = 7;
     private static final int NUM_FORCE_USE = 8;
 
+    /** @hide */
     public static String forceUseUsageToString(int usage) {
         switch (usage) {
             case FOR_COMMUNICATION: return "FOR_COMMUNICATION";
@@ -998,7 +1133,7 @@
         }
     }
 
-    /** Wrapper for native methods called from AudioService */
+    /** @hide Wrapper for native methods called from AudioService */
     public static int setStreamVolumeIndexAS(int stream, int index, int device) {
         if (DEBUG_VOLUME) {
             Log.i(TAG, "setStreamVolumeIndex: " + STREAM_NAMES[stream]
@@ -1008,10 +1143,11 @@
     }
 
     // usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
-    public static final int SYNC_EVENT_NONE = 0;
-    public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1;
+    /** @hide */ public static final int SYNC_EVENT_NONE = 0;
+    /** @hide */ public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1;
 
     /**
+     * @hide
      * @return command completion status, one of {@link #AUDIO_STATUS_OK},
      *     {@link #AUDIO_STATUS_ERROR} or {@link #AUDIO_STATUS_SERVER_DIED}
      */
@@ -1019,12 +1155,15 @@
     public static native int setDeviceConnectionState(int device, int state,
                                                       String device_address, String device_name,
                                                       int codecFormat);
+    /** @hide */
     @UnsupportedAppUsage
     public static native int getDeviceConnectionState(int device, String device_address);
+    /** @hide */
     public static native int handleDeviceConfigChange(int device,
                                                       String device_address,
                                                       String device_name,
                                                       int codecFormat);
+    /** @hide */
     @UnsupportedAppUsage
     public static int setPhoneState(int state) {
         Log.w(TAG, "Do not use this method! Use AudioManager.setMode() instead.");
@@ -1038,14 +1177,18 @@
      * @return command completion status.
      */
     public static native int setPhoneState(int state, int uid);
+    /** @hide */
     @UnsupportedAppUsage
     public static native int setForceUse(int usage, int config);
+    /** @hide */
     @UnsupportedAppUsage
     public static native int getForceUse(int usage);
+    /** @hide */
     @UnsupportedAppUsage
     public static native int initStreamVolume(int stream, int indexMin, int indexMax);
     @UnsupportedAppUsage
     private static native int setStreamVolumeIndex(int stream, int index, int device);
+    /** @hide */
     public static native int getStreamVolumeIndex(int stream, int device);
     /**
      * @hide
@@ -1082,16 +1225,22 @@
      */
     public static native int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attributes);
 
+    /** @hide */
     public static native int setMasterVolume(float value);
+    /** @hide */
     public static native float getMasterVolume();
+    /** @hide */
     @UnsupportedAppUsage
     public static native int setMasterMute(boolean mute);
+    /** @hide */
     @UnsupportedAppUsage
     public static native boolean getMasterMute();
+    /** @hide */
     @UnsupportedAppUsage
     public static native int getDevicesForStream(int stream);
 
     /**
+     * @hide
      * Do not use directly, see {@link AudioManager#getDevicesForAttributes(AudioAttributes)}
      * Get the audio devices that would be used for the routing of the given audio attributes.
      * @param attributes the {@link AudioAttributes} for which the routing is being queried
@@ -1136,31 +1285,43 @@
     /** @hide returns master balance value in range -1.f -> 1.f, where 0.f is dead center. */
     @TestApi
     public static native float getMasterBalance();
-    /** @hide changes the audio balance of the device. */
+    /** @hide Changes the audio balance of the device. */
     @TestApi
     public static native int setMasterBalance(float balance);
 
     // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+    /** @hide */
     @UnsupportedAppUsage(trackingBug = 134049522)
     public static native int getPrimaryOutputSamplingRate();
+    /** @hide */
     @UnsupportedAppUsage(trackingBug = 134049522)
     public static native int getPrimaryOutputFrameCount();
+    /** @hide */
     @UnsupportedAppUsage
     public static native int getOutputLatency(int stream);
 
+    /** @hide */
     public static native int setLowRamDevice(boolean isLowRamDevice, long totalMemory);
+    /** @hide */
     @UnsupportedAppUsage
     public static native int checkAudioFlinger();
 
+    /** @hide */
     public static native int listAudioPorts(ArrayList<AudioPort> ports, int[] generation);
+    /** @hide */
     public static native int createAudioPatch(AudioPatch[] patch,
                                             AudioPortConfig[] sources, AudioPortConfig[] sinks);
+    /** @hide */
     public static native int releaseAudioPatch(AudioPatch patch);
+    /** @hide */
     public static native int listAudioPatches(ArrayList<AudioPatch> patches, int[] generation);
+    /** @hide */
     public static native int setAudioPortConfig(AudioPortConfig config);
 
+    /** @hide */
     public static native int startAudioSource(AudioPortConfig config,
                                               AudioAttributes audioAttributes);
+    /** @hide */
     public static native int stopAudioSource(int handle);
 
     // declare this instance as having a dynamic policy callback handler
@@ -1169,36 +1330,42 @@
     private static native final void native_register_recording_callback();
 
     // must be kept in sync with value in include/system/audio.h
-    public static final int AUDIO_HW_SYNC_INVALID = 0;
+    /** @hide */ public static final int AUDIO_HW_SYNC_INVALID = 0;
 
+    /** @hide */
     public static native int getAudioHwSyncForSession(int sessionId);
 
+    /** @hide */
     public static native int registerPolicyMixes(ArrayList<AudioMix> mixes, boolean register);
 
-    /** see AudioPolicy.setUidDeviceAffinities() */
+    /** @hide see AudioPolicy.setUidDeviceAffinities() */
     public static native int setUidDeviceAffinities(int uid, @NonNull int[] types,
             @NonNull String[] addresses);
 
-    /** see AudioPolicy.removeUidDeviceAffinities() */
+    /** @hide see AudioPolicy.removeUidDeviceAffinities() */
     public static native int removeUidDeviceAffinities(int uid);
 
-    /** see AudioPolicy.setUserIdDeviceAffinities() */
+    /** @hide see AudioPolicy.setUserIdDeviceAffinities() */
     public static native int setUserIdDeviceAffinities(int userId, @NonNull int[] types,
             @NonNull String[] addresses);
 
-    /** see AudioPolicy.removeUserIdDeviceAffinities() */
+    /** @hide see AudioPolicy.removeUserIdDeviceAffinities() */
     public static native int removeUserIdDeviceAffinities(int userId);
 
+    /** @hide */
     public static native int systemReady();
 
+    /** @hide */
     public static native float getStreamVolumeDB(int stream, int index, int device);
 
     /**
+     * @hide
      * Communicate supported system usages to audio policy service.
      */
     public static native int setSupportedSystemUsages(int[] systemUsages);
 
     /**
+     * @hide
      * @see AudioManager#setAllowedCapturePolicy()
      */
     public static native int setAllowedCapturePolicy(int uid, int flags);
@@ -1212,45 +1379,57 @@
     private static native boolean native_is_offload_supported(int encoding, int sampleRate,
             int channelMask, int channelIndexMask, int streamType);
 
+    /** @hide */
     public static native int getMicrophones(ArrayList<MicrophoneInfo> microphonesInfo);
 
+    /** @hide */
     public static native int getSurroundFormats(Map<Integer, Boolean> surroundFormats,
                                                 boolean reported);
 
     /**
+     * @hide
      * Returns a list of audio formats (codec) supported on the A2DP offload path.
      */
     public static native int getHwOffloadEncodingFormatsSupportedForA2DP(
             ArrayList<Integer> formatList);
 
+    /** @hide */
     public static native int setSurroundFormatEnabled(int audioFormat, boolean enabled);
 
     /**
+     * @hide
      * Communicate UID of active assistant to audio policy service.
      */
     public static native int setAssistantUid(int uid);
+
     /**
+     * @hide
      * Communicate UIDs of active accessibility services to audio policy service.
      */
     public static native int setA11yServicesUids(int[] uids);
+
     /**
+     * @hide
      * Communicate UID of current InputMethodService to audio policy service.
      */
     public static native int setCurrentImeUid(int uid);
 
 
     /**
+     * @hide
      * @see AudioManager#isHapticPlaybackSupported()
      */
     public static native boolean isHapticPlaybackSupported();
 
     /**
+     * @hide
      * Send audio HAL server process pids to native audioserver process for use
      * when generating audio HAL servers tombstones
      */
     public static native int setAudioHalPids(int[] pids);
 
     /**
+     * @hide
      * @see AudioManager#isCallScreeningModeSupported()
      */
     public static native boolean isCallScreeningModeSupported();
@@ -1258,6 +1437,7 @@
     // use case routing by product strategy
 
     /**
+     * @hide
      * Sets the preferred device to use for a given audio strategy in the audio policy engine
      * @param strategy the id of the strategy to configure
      * @param device the device type and address to route to when available
@@ -1270,6 +1450,7 @@
                 device.getAddress());
     }
     /**
+     * @hide
      * Set device routing per product strategy.
      * @param strategy the id of the strategy to configure
      * @param deviceType the native device type, NOT AudioDeviceInfo types
@@ -1280,6 +1461,7 @@
             int strategy, int deviceType, String deviceAddress);
 
     /**
+     * @hide
      * Remove preferred routing for the strategy
      * @param strategy the id of the strategy to configure
      * @return {@link #SUCCESS} if successfully removed
@@ -1287,6 +1469,7 @@
     public static native int removePreferredDeviceForStrategy(int strategy);
 
     /**
+     * @hide
      * Query previously set preferred device for a strategy
      * @param strategy the id of the strategy to query for
      * @param device an array of size 1 that will contain the preferred device, or null if
@@ -1300,6 +1483,7 @@
     // Items shared with audio service
 
     /**
+     * @hide
      * The delay before playing a sound. This small period exists so the user
      * can press another key (non-volume keys, too) to have it NOT be audible.
      * <p>
@@ -1308,6 +1492,7 @@
     public static final int PLAY_SOUND_DELAY = 300;
 
     /**
+     * @hide
      * Constant to identify a focus stack entry that is used to hold the focus while the phone
      * is ringing or during a call. Used by com.android.internal.telephony.CallManager when
      * entering and exiting calls.
@@ -1315,6 +1500,7 @@
     public final static String IN_VOICE_COMM_FOCUS_ID = "AudioFocus_For_Phone_Ring_And_Calls";
 
     /**
+     * @hide
      * @see AudioManager#setVibrateSetting(int, int)
      */
     public static int getValueForVibrateSetting(int existingValue, int vibrateType,
@@ -1330,10 +1516,12 @@
         return existingValue;
     }
 
+    /** @hide */
     public static int getDefaultStreamVolume(int streamType) {
         return DEFAULT_STREAM_VOLUME[streamType];
     }
 
+    /** @hide */
     public static int[] DEFAULT_STREAM_VOLUME = new int[] {
         4,  // STREAM_VOICE_CALL
         7,  // STREAM_SYSTEM
@@ -1349,20 +1537,22 @@
         5, // STREAM_ASSISTANT
     };
 
+    /** @hide */
     public static String streamToString(int stream) {
         if (stream >= 0 && stream < STREAM_NAMES.length) return STREAM_NAMES[stream];
         if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) return "USE_DEFAULT_STREAM_TYPE";
         return "UNKNOWN_STREAM_" + stream;
     }
 
-    /** The platform has no specific capabilities */
+    /** @hide The platform has no specific capabilities */
     public static final int PLATFORM_DEFAULT = 0;
-    /** The platform is voice call capable (a phone) */
+    /** @hide The platform is voice call capable (a phone) */
     public static final int PLATFORM_VOICE = 1;
-    /** The platform is a television or a set-top box */
+    /** @hide The platform is a television or a set-top box */
     public static final int PLATFORM_TELEVISION = 2;
 
     /**
+     * @hide
      * Return the platform type that this is running on. One of:
      * <ul>
      * <li>{@link #PLATFORM_VOICE}</li>
@@ -1392,6 +1582,7 @@
     }
 
     /**
+     * @hide
      * Return a set of audio device types from a bit mask audio device type, which may
      * represent multiple audio device types.
      * FIXME: Remove this when getting ride of bit mask usage of audio device types.
@@ -1409,6 +1600,7 @@
     }
 
     /**
+     * @hide
      * Return the intersection of two audio device types collections.
      */
     public static Set<Integer> intersectionAudioDeviceTypes(
@@ -1419,12 +1611,14 @@
     }
 
     /**
+     * @hide
      * Return true if the audio device types collection only contains the given device type.
      */
     public static boolean isSingleAudioDeviceType(@NonNull Set<Integer> types, int type) {
         return types.size() == 1 && types.contains(type);
     }
 
+    /** @hide */
     public static final int DEFAULT_MUTE_STREAMS_AFFECTED =
             (1 << STREAM_MUSIC) |
             (1 << STREAM_RING) |
@@ -1434,6 +1628,7 @@
             (1 << STREAM_BLUETOOTH_SCO);
 
     /**
+     * @hide
      * Event posted by AudioTrack and AudioRecord JNI (JNIDeviceCallback) when routing changes.
      * Keep in sync with core/jni/android_media_DeviceCallback.h.
      */
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 453a5d8..bb10e1f 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -294,6 +294,11 @@
 
     oneway void setRttEnabled(in boolean rttEnabled);
 
+    void setDeviceVolumeBehavior(in AudioDeviceAttributes device,
+             in int deviceVolumeBehavior, in String pkgName);
+
+    int getDeviceVolumeBehavior(in AudioDeviceAttributes device);
+
     // WARNING: read warning at top of file, new methods that need to be used by native
     // code via IAudioManager.h need to be added to the top section.
 }
diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
index a2f9ee9..5925d38 100644
--- a/media/java/android/media/IMediaRouter2Manager.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -24,8 +24,8 @@
  * {@hide}
  */
 oneway interface IMediaRouter2Manager {
-    void notifySessionCreated(in RoutingSessionInfo sessionInfo);
-    void notifySessionsUpdated();
+    void notifySessionCreated(int requestId, in RoutingSessionInfo sessionInfo);
+    void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
     void notifyPreferredFeaturesChanged(String packageName, in List<String> preferredFeatures);
     void notifyRoutesAdded(in List<MediaRoute2Info> routes);
     void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index ad9486c..405410a 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.hardware.cas.V1_0.HidlCasPluginDescriptor;
 import android.hardware.cas.V1_0.ICas;
@@ -1076,6 +1077,17 @@
         }
     }
 
+    /**
+     * Release Cas session. This is primarily used as a test API for CTS.
+     * @hide
+     */
+    @TestApi
+    public void forceResourceLost() {
+        if (mResourceListener != null) {
+            mResourceListener.onReclaimResources();
+        }
+    }
+
     @Override
     public void close() {
         if (mICas != null) {
diff --git a/media/java/android/media/MediaMetrics.java b/media/java/android/media/MediaMetrics.java
index 88a8295..540955f 100644
--- a/media/java/android/media/MediaMetrics.java
+++ b/media/java/android/media/MediaMetrics.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.os.Bundle;
 
@@ -24,6 +25,7 @@
 import java.nio.ByteOrder;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import java.util.Objects;
 
 /**
  * MediaMetrics is the Java interface to the MediaMetrics service.
@@ -50,6 +52,77 @@
     private static final Charset MEDIAMETRICS_CHARSET = StandardCharsets.UTF_8;
 
     /**
+     * Key interface.
+     *
+     * The presence of this {@code Key} interface on an object allows
+     * it to be used to set metrics.
+     *
+     * @param <T> type of value associated with {@code Key}.
+     */
+    public interface Key<T> {
+        /**
+         * Returns the internal name of the key.
+         */
+        @NonNull
+        String getName();
+
+        /**
+         * Returns the class type of the associated value.
+         */
+        @NonNull
+        Class<T> getValueClass();
+    }
+
+    /**
+     * Returns a Key object with the correct interface for MediaMetrics.
+     *
+     * @param name The name of the key.
+     * @param type The class type of the value represented by the key.
+     * @param <T> The type of value.
+     * @return a new key interface.
+     */
+    @NonNull
+    public static <T> Key<T> createKey(@NonNull String name, @NonNull Class<T> type) {
+        // Implementation specific.
+        return new Key<T>() {
+            private final String mName = name;
+            private final Class<T> mType = type;
+
+            @Override
+            @NonNull
+            public String getName() {
+                return mName;
+            }
+
+            @Override
+            @NonNull
+            public Class<T> getValueClass() {
+                return mType;
+            }
+
+            /**
+             * Return true if the name and the type of two objects are the same.
+             */
+            @Override
+            public boolean equals(Object obj) {
+                if (obj == this) {
+                    return true;
+                }
+                if (!(obj instanceof Key)) {
+                    return false;
+                }
+                Key<?> other = (Key<?>) obj;
+                return mName.equals(other.getName()) && mType.equals(other.getValueClass());
+            }
+
+            @Override
+            public int hashCode() {
+                return Objects.hash(mName, mType);
+            }
+        };
+    }
+
+    /**
      * Item records properties and delivers to the MediaMetrics service
      *
      */
@@ -202,6 +275,28 @@
         }
 
         /**
+         * Sets a metrics typed key
+         * @param key
+         * @param value
+         * @param <T>
+         * @return
+         */
+        @NonNull
+        public <T> Item set(@NonNull Key<T> key, @Nullable T value) {
+            if (value instanceof Integer) {
+                putInt(key.getName(), (int) value);
+            } else if (value instanceof Long) {
+                putLong(key.getName(), (long) value);
+            } else if (value instanceof Double) {
+                putDouble(key.getName(), (double) value);
+            } else if (value instanceof String) {
+                putString(key.getName(), (String) value);
+            }
+            // if value is null, etc. no error is raised.
+            return this;
+        }
+
+        /**
          * Sets the property with key to an integer (32 bit) value.
          *
          * @param key
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 88bcd6a..b694fd0 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -75,6 +75,8 @@
     final ConcurrentMap<String, List<String>> mPreferredFeaturesMap = new ConcurrentHashMap<>();
 
     private final AtomicInteger mNextRequestId = new AtomicInteger(1);
+    private final CopyOnWriteArrayList<TransferRequest> mTransferRequests =
+            new CopyOnWriteArrayList<>();
 
     /**
      * Gets an instance of media router manager that controls media route of other applications.
@@ -328,6 +330,9 @@
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
+                //TODO: Ensure that every request is eventually removed.
+                mTransferRequests.add(new TransferRequest(requestId, sessionInfo, route));
+
                 mMediaRouterService.requestCreateSessionWithManager(
                         client, requestId, sessionInfo.getClientPackageName(), route);
             } catch (RemoteException ex) {
@@ -446,6 +451,77 @@
         }
     }
 
+    void createSessionOnHandler(int requestId, RoutingSessionInfo sessionInfo) {
+        TransferRequest matchingRequest = null;
+        for (TransferRequest request : mTransferRequests) {
+            if (request.mRequestId == requestId) {
+                matchingRequest = request;
+                break;
+            }
+        }
+
+        if (matchingRequest == null) {
+            return;
+        }
+
+        mTransferRequests.remove(matchingRequest);
+
+        MediaRoute2Info requestedRoute = matchingRequest.mTargetRoute;
+
+        if (sessionInfo == null) {
+            notifyTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute);
+            return;
+        } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
+            Log.w(TAG, "The session does not contain the requested route. "
+                    + "(requestedRouteId=" + requestedRoute.getId()
+                    + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
+                    + ")");
+            notifyTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute);
+            return;
+        } else if (!TextUtils.equals(requestedRoute.getProviderId(),
+                sessionInfo.getProviderId())) {
+            Log.w(TAG, "The session's provider ID does not match the requested route's. "
+                    + "(requested route's providerId=" + requestedRoute.getProviderId()
+                    + ", actual providerId=" + sessionInfo.getProviderId()
+                    + ")");
+            notifyTransferFailed(matchingRequest.mOldSessionInfo, requestedRoute);
+            return;
+        }
+        notifyTransferred(matchingRequest.mOldSessionInfo, sessionInfo);
+    }
+
+    void handleFailureOnHandler(int requestId, int reason) {
+        TransferRequest matchingRequest = null;
+        for (TransferRequest request : mTransferRequests) {
+            if (request.mRequestId == requestId) {
+                matchingRequest = request;
+                break;
+            }
+        }
+
+        if (matchingRequest != null) {
+            mTransferRequests.remove(matchingRequest);
+            notifyTransferFailed(matchingRequest.mOldSessionInfo, matchingRequest.mTargetRoute);
+            return;
+        }
+        notifyRequestFailed(reason);
+    }
+
+    void handleSessionsUpdated(RoutingSessionInfo sessionInfo) {
+        for (TransferRequest request : mTransferRequests) {
+            String sessionId = request.mOldSessionInfo.getId();
+            if (!TextUtils.equals(sessionId, sessionInfo.getId())) {
+                continue;
+            }
+            if (sessionInfo.getSelectedRoutes().contains(request.mTargetRoute.getId())) {
+                notifyTransferred(request.mOldSessionInfo, sessionInfo);
+                mTransferRequests.remove(request);
+                break;
+            }
+        }
+        notifySessionUpdated(sessionInfo);
+    }
+
     private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
         for (CallbackRecord record: mCallbackRecords) {
             record.mExecutor.execute(
@@ -467,16 +543,9 @@
         }
     }
 
-    void notifySessionCreated(RoutingSessionInfo sessionInfo) {
+    void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
         for (CallbackRecord record : mCallbackRecords) {
-            record.mExecutor.execute(() -> record.mCallback.onSessionCreated(
-                    new RoutingController(sessionInfo)));
-        }
-    }
-
-    void notifySessionInfosChanged() {
-        for (CallbackRecord record : mCallbackRecords) {
-            record.mExecutor.execute(() -> record.mCallback.onSessionsUpdated());
+            record.mExecutor.execute(() -> record.mCallback.onSessionUpdated(sessionInfo));
         }
     }
 
@@ -569,7 +638,7 @@
      *
      * @see #getSelectedRoutes(RoutingSessionInfo)
      * @see #getSelectableRoutes(RoutingSessionInfo)
-     * @see Callback#onSessionsUpdated()
+     * @see Callback#onSessionUpdated(RoutingSessionInfo)
      */
     public void selectRoute(@NonNull RoutingSessionInfo sessionInfo,
             @NonNull MediaRoute2Info route) {
@@ -614,7 +683,7 @@
      *
      * @see #getSelectedRoutes(RoutingSessionInfo)
      * @see #getDeselectableRoutes(RoutingSessionInfo)
-     * @see Callback#onSessionsUpdated()
+     * @see Callback#onSessionUpdated(RoutingSessionInfo)
      */
     public void deselectRoute(@NonNull RoutingSessionInfo sessionInfo,
             @NonNull MediaRoute2Info route) {
@@ -667,13 +736,15 @@
             return;
         }
 
+        int requestId = mNextRequestId.getAndIncrement();
+        mTransferRequests.add(new TransferRequest(requestId, sessionInfo, route));
+
         Client client;
         synchronized (sLock) {
             client = mClient;
         }
         if (client != null) {
             try {
-                int requestId = mNextRequestId.getAndIncrement();
                 mMediaRouterService.transferToRouteWithManager(
                         mClient, requestId, sessionInfo.getId(), route);
             } catch (RemoteException ex) {
@@ -884,20 +955,12 @@
         public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
 
         /**
-         * Called when a routing session is created.
-         *
-         * @param controller the controller to control the created session
+         * Called when a session is changed.
+         * @param sessionInfo the updated session
          */
-        public void onSessionCreated(@NonNull RoutingController controller) {}
+        public void onSessionUpdated(@NonNull RoutingSessionInfo sessionInfo) {}
 
         /**
-         * Called when at least one session info is changed.
-         * Call {@link #getActiveSessions()} to get current active session info.
-         */
-        public void onSessionsUpdated() {}
-
-        //TODO: Call this.
-        /**
          * Called when media is transferred.
          *
          * @param oldSession the previous session
@@ -906,7 +969,6 @@
         public void onTransferred(@NonNull RoutingSessionInfo oldSession,
                 @Nullable RoutingSessionInfo newSession) { }
 
-        //TODO: Call this.
         /**
          * Called when {@link #transfer(RoutingSessionInfo, MediaRoute2Info)} fails.
          */
@@ -971,25 +1033,37 @@
         }
     }
 
+    static final class TransferRequest {
+        public final int mRequestId;
+        public final RoutingSessionInfo mOldSessionInfo;
+        public final MediaRoute2Info mTargetRoute;
+
+        TransferRequest(int requestId, @NonNull RoutingSessionInfo oldSessionInfo,
+                @NonNull MediaRoute2Info targetRoute) {
+            mRequestId = requestId;
+            mOldSessionInfo = oldSessionInfo;
+            mTargetRoute = targetRoute;
+        }
+    }
+
     class Client extends IMediaRouter2Manager.Stub {
         @Override
-        public void notifySessionCreated(RoutingSessionInfo sessionInfo) {
-            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifySessionCreated,
-                    MediaRouter2Manager.this, sessionInfo));
+        public void notifySessionCreated(int requestId, RoutingSessionInfo sessionInfo) {
+            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::createSessionOnHandler,
+                    MediaRouter2Manager.this, requestId, sessionInfo));
         }
 
         @Override
-        public void notifySessionsUpdated() {
-            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifySessionInfosChanged,
-                    MediaRouter2Manager.this));
-            // do nothing
+        public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
+            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::handleSessionsUpdated,
+                    MediaRouter2Manager.this, sessionInfo));
         }
 
         @Override
         public void notifyRequestFailed(int requestId, int reason) {
             // Note: requestId is not used.
-            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyRequestFailed,
-                    MediaRouter2Manager.this, reason));
+            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::handleFailureOnHandler,
+                    MediaRouter2Manager.this, requestId, reason));
         }
 
         @Override
diff --git a/media/java/android/media/RouteDiscoveryPreference.java b/media/java/android/media/RouteDiscoveryPreference.java
index 2e038e6..68f2964 100644
--- a/media/java/android/media/RouteDiscoveryPreference.java
+++ b/media/java/android/media/RouteDiscoveryPreference.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -29,6 +30,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * A media route discovery preference describing the features of routes that media router
@@ -169,8 +171,9 @@
         Bundle mExtras;
 
         public Builder(@NonNull List<String> preferredFeatures, boolean activeScan) {
-            mPreferredFeatures = new ArrayList<>(Objects.requireNonNull(preferredFeatures,
-                    "preferredFeatures must not be null"));
+            Objects.requireNonNull(preferredFeatures, "preferredFeatures must not be null");
+            mPreferredFeatures = preferredFeatures.stream().filter(str -> !TextUtils.isEmpty(str))
+                    .collect(Collectors.toList());
             mActiveScan = activeScan;
         }
 
@@ -211,8 +214,9 @@
          */
         @NonNull
         public Builder setPreferredFeatures(@NonNull List<String> preferredFeatures) {
-            mPreferredFeatures = new ArrayList<>(Objects.requireNonNull(preferredFeatures,
-                            "preferredFeatures must not be null"));
+            Objects.requireNonNull(preferredFeatures, "preferredFeatures must not be null");
+            mPreferredFeatures = preferredFeatures.stream().filter(str -> !TextUtils.isEmpty(str))
+                    .collect(Collectors.toList());
             return this;
         }
 
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 632cfb0..37e1415 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
 import android.os.Handler;
@@ -100,11 +101,18 @@
             int width, int height, int dpi, boolean isSecure, @Nullable Surface surface,
             @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
         DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-        int flags = isSecure ? DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE : 0;
-        return dm.createVirtualDisplay(this, name, width, height, dpi, surface,
-                    flags | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR |
-                    DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, callback, handler,
-                    null /* uniqueId */);
+        int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
+                | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
+        if (isSecure) {
+            flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+        }
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+                height, dpi);
+        builder.setFlags(flags);
+        if (surface != null) {
+            builder.setSurface(surface);
+        }
+        return dm.createVirtualDisplay(this, builder.build(), callback, handler);
     }
 
     /**
@@ -133,9 +141,35 @@
     public VirtualDisplay createVirtualDisplay(@NonNull String name,
             int width, int height, int dpi, int flags, @Nullable Surface surface,
             @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
-        DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-        return dm.createVirtualDisplay(this, name, width, height, dpi, surface, flags, callback,
-                handler, null /* uniqueId */);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+                height, dpi);
+        builder.setFlags(flags);
+        if (surface != null) {
+            builder.setSurface(surface);
+        }
+        return createVirtualDisplay(builder.build(), callback, handler);
+    }
+
+    /**
+     * Creates a {@link android.hardware.display.VirtualDisplay} to capture the
+     * contents of the screen.
+     *
+     * @param virtualDisplayConfig The arguments for the virtual display configuration. See
+     * {@link VirtualDisplayConfig} for using it.
+     * @param callback Callback to call when the virtual display's state
+     * changes, or null if none.
+     * @param handler The {@link android.os.Handler} on which the callback should be
+     * invoked, or null if the callback should be invoked on the calling
+     * thread's main {@link android.os.Looper}.
+     *
+     * @see android.hardware.display.VirtualDisplay
+     * @hide
+     */
+    @Nullable
+    public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
+            @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+        DisplayManager dm = mContext.getSystemService(DisplayManager.class);
+        return dm.createVirtualDisplay(this, virtualDisplayConfig, callback, handler);
     }
 
     /**
diff --git a/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl b/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
index 8033307..06c3907 100644
--- a/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
+++ b/media/java/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
@@ -39,10 +39,4 @@
      * one of the handles from the returned list.
      */
     ISoundTriggerModule attach(int handle, ISoundTriggerCallback callback);
-
-    /**
-     * Notify the service that external input capture is taking place. This may cause some of the
-     * active recognitions to be aborted.
-     */
-    void setExternalCaptureState(boolean active);
 }
\ No newline at end of file
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 9ce895e..9913d23 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -20,12 +20,12 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.tuner.Tuner.Result;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
 
 /**
  * LNB (low-noise block downconverter) for satellite tuner.
@@ -145,7 +145,8 @@
 
     int mId;
     LnbCallback mCallback;
-    Context mContext;
+    Executor mExecutor;
+
 
     private native int nativeSetVoltage(int voltage);
     private native int nativeSetTone(int tone);
@@ -159,10 +160,20 @@
         mId = id;
     }
 
-    void setCallback(@Nullable LnbCallback callback) {
+    void setCallback(Executor executor, @Nullable LnbCallback callback) {
         mCallback = callback;
-        if (mCallback == null) {
-            return;
+        mExecutor = executor;
+    }
+
+    private void onEvent(int eventType) {
+        if (mExecutor != null && mCallback != null) {
+            mExecutor.execute(() -> mCallback.onEvent(eventType));
+        }
+    }
+
+    private void onDiseqcMessage(byte[] diseqcMessage) {
+        if (mExecutor != null && mCallback != null) {
+            mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage));
         }
     }
 
@@ -218,6 +229,9 @@
      * Releases the LNB instance.
      */
     public void close() {
-        nativeClose();
+        int res = nativeClose();
+        if (res != Tuner.RESULT_SUCCESS) {
+            TunerUtils.throwExceptionForResult(res, "Failed to close LNB");
+        }
     }
 }
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index d4494acb7e..48aed34 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -45,6 +45,7 @@
 import android.media.tv.tunerresourcemanager.ResourceClientProfile;
 import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
 import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
+import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
 import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
 import android.media.tv.tunerresourcemanager.TunerLnbRequest;
 import android.media.tv.tunerresourcemanager.TunerResourceManager;
@@ -256,6 +257,36 @@
         mTunerResourceManager.registerClientProfile(
                 profile, new HandlerExecutor(mHandler), mResourceListener, clientId);
         mClientId = clientId[0];
+
+        setFrontendInfoList();
+        setLnbIds();
+    }
+
+    private void setFrontendInfoList() {
+        List<Integer> ids = nativeGetFrontendIds();
+        if (ids == null) {
+            return;
+        }
+        TunerFrontendInfo[] infos = new TunerFrontendInfo[ids.size()];
+        for (int i = 0; i < ids.size(); i++) {
+            int id = ids.get(i);
+            FrontendInfo frontendInfo = nativeGetFrontendInfo(id);
+            if (frontendInfo == null) {
+                continue;
+            }
+            TunerFrontendInfo tunerFrontendInfo = new TunerFrontendInfo(
+                    id, frontendInfo.getType(), frontendInfo.getExclusiveGroupId());
+            infos[i] = tunerFrontendInfo;
+        }
+        mTunerResourceManager.setFrontendInfoList(infos);
+    }
+
+    private void setLnbIds() {
+        int[] ids = nativeGetLnbIds();
+        if (ids == null) {
+            return;
+        }
+        mTunerResourceManager.setLnbInfoList(ids);
     }
 
     /**
@@ -358,7 +389,7 @@
     private native Filter nativeOpenFilter(int type, int subType, long bufferSize);
     private native TimeFilter nativeOpenTimeFilter();
 
-    private native List<Integer> nativeGetLnbIds();
+    private native int[] nativeGetLnbIds();
     private native Lnb nativeOpenLnbByHandle(int handle);
     private native Lnb nativeOpenLnbByName(String name);
 
@@ -602,6 +633,9 @@
      */
     @Nullable
     public FrontendStatus getFrontendStatus(@NonNull @FrontendStatusType int[] statusTypes) {
+        if (mFrontend == null) {
+            throw new IllegalStateException("frontend is not initialized");
+        }
         return nativeGetFrontendStatus(statusTypes);
     }
 
@@ -826,6 +860,9 @@
         Objects.requireNonNull(executor, "executor must not be null");
         Objects.requireNonNull(cb, "LnbCallback must not be null");
         checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB);
+        if (mLnb != null) {
+            mLnb.setCallback(executor, cb);
+        }
         return mLnb;
     }
 
@@ -844,7 +881,11 @@
         Objects.requireNonNull(name, "LNB name must not be null");
         Objects.requireNonNull(executor, "executor must not be null");
         Objects.requireNonNull(cb, "LnbCallback must not be null");
-        return nativeOpenLnbByName(name);
+        mLnb = nativeOpenLnbByName(name);
+        if (mLnb != null) {
+            mLnb.setCallback(executor, cb);
+        }
+        return mLnb;
     }
 
     private boolean requestLnb() {
@@ -869,12 +910,6 @@
         return nativeOpenTimeFilter();
     }
 
-    private void onLnbEvent(int eventType) {
-        if (mHandler != null) {
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_LNB_EVENT, eventType, 0));
-        }
-    }
-
     /**
      * Opens a Descrambler in tuner.
      *
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index 547a492..c1589cf 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -137,6 +137,8 @@
             msg = "";
         }
         switch (r) {
+            case Tuner.RESULT_SUCCESS:
+                return;
             case Tuner.RESULT_INVALID_ARGUMENT:
                 throw new IllegalArgumentException(msg);
             case Tuner.RESULT_INVALID_STATE:
diff --git a/media/java/android/media/tv/tuner/filter/TimeFilter.java b/media/java/android/media/tv/tuner/filter/TimeFilter.java
index da77b50..93599e6 100644
--- a/media/java/android/media/tv/tuner/filter/TimeFilter.java
+++ b/media/java/android/media/tv/tuner/filter/TimeFilter.java
@@ -83,7 +83,7 @@
     @Result
     public int clearTimestamp() {
         int res = nativeClearTimestamp();
-        if (res == 0) {
+        if (res == Tuner.RESULT_SUCCESS) {
             mEnable = false;
         }
         return res;
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index 63a71e2..2c8899c 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -390,7 +390,7 @@
      * <li>If no Lnb system can be granted, the API would return false.
      * <ul>
      *
-     * <p><strong>Note:</strong> {@link #setLnbInfos(int[])} must be called before this request.
+     * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this request.
      *
      * @param request {@link TunerLnbRequest} information of the current request.
      * @param lnbId a one-element array to return the granted Lnb id.
@@ -479,7 +479,7 @@
      *
      * <p>Client must call this whenever it releases an Lnb.
      *
-     * <p><strong>Note:</strong> {@link #setLnbInfos(int[])} must be called before this release.
+     * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this release.
      *
      * @param lnbId the id of the released Tuner Lnb.
      */
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 4a7e8e1..ac7fe5d 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -124,7 +124,11 @@
 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
 using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
+using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
 using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendStatus;
+using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
 using ::android::hardware::tv::tuner::V1_0::FrontendType;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
 using ::android::hardware::tv::tuner::V1_0::LnbPosition;
@@ -151,6 +155,7 @@
     jmethodID onFilterEventID;
     jmethodID lnbInitID;
     jmethodID onLnbEventID;
+    jmethodID onLnbDiseqcMessageID;
     jmethodID onDvrRecordStatusID;
     jmethodID onDvrPlaybackStatusID;
     jmethodID descramblerInitID;
@@ -166,19 +171,31 @@
 
 namespace android {
 /////////////// LnbCallback ///////////////////////
-LnbCallback::LnbCallback(jweak tunerObj, LnbId id) : mObject(tunerObj), mId(id) {}
+LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    mLnb = env->NewWeakGlobalRef(lnbObj);
+}
 
 Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
     ALOGD("LnbCallback::onEvent, type=%d", lnbEventType);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(
-            mObject,
+            mLnb,
             gFields.onLnbEventID,
             (jint)lnbEventType);
     return Void();
 }
-Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
+Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
     ALOGD("LnbCallback::onDiseqcMessage");
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    jbyteArray array = env->NewByteArray(diseqcMessage.size());
+    env->SetByteArrayRegion(
+            array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
+
+    env->CallVoidMethod(
+            mLnb,
+            gFields.onLnbDiseqcMessageID,
+            array);
     return Void();
 }
 
@@ -871,6 +888,10 @@
         return NULL;
     }
     mFe = fe;
+    mFeId = id;
+    if (mDemux != NULL) {
+        mDemux->setFrontendDataSource(mFeId);
+    }
     sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
     fe->setCallback(feCb);
 
@@ -1058,43 +1079,40 @@
             maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps);
 }
 
-jobject JTuner::getLnbIds() {
+jintArray JTuner::getLnbIds() {
     ALOGD("JTuner::getLnbIds()");
-    mTuner->getLnbIds([&](Result, const hidl_vec<FrontendId>& lnbIds) {
-        mLnbIds = lnbIds;
+    Result res;
+    hidl_vec<LnbId> lnbIds;
+    mTuner->getLnbIds([&](Result r, const hidl_vec<LnbId>& ids) {
+        lnbIds = ids;
+        res = r;
     });
-    if (mLnbIds.size() == 0) {
+    if (res != Result::SUCCESS || mLnbIds.size() == 0) {
         ALOGW("Lnb isn't available");
         return NULL;
     }
 
+    mLnbIds = lnbIds;
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    jclass arrayListClazz = env->FindClass("java/util/ArrayList");
-    jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z");
-    jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V"));
 
-    jclass integerClazz = env->FindClass("java/lang/Integer");
-    jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
+    jintArray ids = env->NewIntArray(mLnbIds.size());
+    env->SetIntArrayRegion(ids, 0, mLnbIds.size(), reinterpret_cast<jint*>(&mLnbIds[0]));
 
-    for (int i=0; i < mLnbIds.size(); i++) {
-       jobject idObj = env->NewObject(integerClazz, intInit, mLnbIds[i]);
-       env->CallBooleanMethod(obj, arrayListAdd, idObj);
-    }
-    return obj;
+    return ids;
 }
 
 jobject JTuner::openLnbById(int id) {
     sp<ILnb> iLnbSp;
-    mTuner->openLnbById(id, [&](Result, const sp<ILnb>& lnb) {
+    Result r;
+    mTuner->openLnbById(id, [&](Result res, const sp<ILnb>& lnb) {
+        r = res;
         iLnbSp = lnb;
     });
-    if (iLnbSp == nullptr) {
+    if (r != Result::SUCCESS || iLnbSp == nullptr) {
         ALOGE("Failed to open lnb");
         return NULL;
     }
     mLnb = iLnbSp;
-    sp<LnbCallback> lnbCb = new LnbCallback(mObject, id);
-    mLnb->setCallback(lnbCb);
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject lnbObj = env->NewObject(
@@ -1102,6 +1120,9 @@
             gFields.lnbInitID,
             (jint) id);
 
+    sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
+    mLnb->setCallback(lnbCb);
+
     sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
     lnbSp->incStrong(lnbObj);
     env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
@@ -1125,14 +1146,15 @@
         return NULL;
     }
     mLnb = iLnbSp;
-    sp<LnbCallback> lnbCb = new LnbCallback(mObject, id);
-    mLnb->setCallback(lnbCb);
 
     jobject lnbObj = env->NewObject(
             env->FindClass("android/media/tv/tuner/Lnb"),
             gFields.lnbInitID,
             id);
 
+    sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
+    mLnb->setCallback(lnbCb);
+
     sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
     lnbSp->incStrong(lnbObj);
     env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
@@ -1202,12 +1224,21 @@
         return Result::SUCCESS;
     }
     Result res;
+    uint32_t id;
+    sp<IDemux> demuxSp;
     mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
-        mDemux = demux;
-        mDemuxId = demuxId;
+        demuxSp = demux;
+        id = demuxId;
         res = r;
         ALOGD("open demux, id = %d", demuxId);
     });
+    if (res == Result::SUCCESS) {
+        mDemux = demuxSp;
+        mDemuxId = id;
+        if (mFe != NULL) {
+            mDemux->setFrontendDataSource(mFeId);
+        }
+    }
     return res;
 }
 
@@ -1453,6 +1484,254 @@
             numBytesInSectionFilter, filterCaps, linkCaps, bTimeFilter);
 }
 
+jobject JTuner::getFrontendStatus(jintArray types) {
+    if (mFe == NULL) {
+        return NULL;
+    }
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    jsize size = env->GetArrayLength(types);
+    std::vector<FrontendStatusType> v(size);
+    env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0]));
+
+    Result res;
+    hidl_vec<FrontendStatus> status;
+    mFe->getStatus(v,
+            [&](Result r, const hidl_vec<FrontendStatus>& s) {
+                res = r;
+                status = s;
+            });
+    if (res != Result::SUCCESS) {
+        return NULL;
+    }
+
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
+    jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
+    jobject statusObj = env->NewObject(clazz, init);
+
+    jclass intClazz = env->FindClass("java/lang/Integer");
+    jmethodID initInt = env->GetMethodID(intClazz, "<init>", "(I)V");
+    jclass booleanClazz = env->FindClass("java/lang/Boolean");
+    jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V");
+
+    for (auto s : status) {
+        switch(s.getDiscriminator()) {
+            case FrontendStatus::hidl_discriminator::isDemodLocked: {
+                jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;");
+                jobject newBooleanObj = env->NewObject(
+                        booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked()));
+                env->SetObjectField(statusObj, field, newBooleanObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::snr: {
+                jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.snr()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::ber: {
+                jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.ber()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::per: {
+                jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.per()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::preBer: {
+                jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.preBer()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::signalQuality: {
+                jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.signalQuality()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::signalStrength: {
+                jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.signalStrength()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::symbolRate: {
+                jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.symbolRate()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::innerFec: {
+                jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;");
+                jclass longClazz = env->FindClass("java/lang/Long");
+                jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V");
+                jobject newLongObj = env->NewObject(
+                        longClazz, initLong, static_cast<jlong>(s.innerFec()));
+                env->SetObjectField(statusObj, field, newLongObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::modulation: {
+                jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;");
+                FrontendModulationStatus modulation = s.modulation();
+                jint intModulation;
+                bool valid = true;
+                switch(modulation.getDiscriminator()) {
+                    case FrontendModulationStatus::hidl_discriminator::dvbc: {
+                        intModulation = static_cast<jint>(modulation.dvbc());
+                        break;
+                    }
+                    case FrontendModulationStatus::hidl_discriminator::dvbs: {
+                        intModulation = static_cast<jint>(modulation.dvbs());
+                        break;
+                    }
+                    case FrontendModulationStatus::hidl_discriminator::isdbs: {
+                        intModulation = static_cast<jint>(modulation.isdbs());
+                        break;
+                    }
+                    case FrontendModulationStatus::hidl_discriminator::isdbs3: {
+                        intModulation = static_cast<jint>(modulation.isdbs3());
+                        break;
+                    }
+                    case FrontendModulationStatus::hidl_discriminator::isdbt: {
+                        intModulation = static_cast<jint>(modulation.isdbt());
+                        break;
+                    }
+                    default: {
+                        valid = false;
+                        break;
+                    }
+                }
+                if (valid) {
+                    jobject newIntegerObj = env->NewObject(intClazz, initInt, intModulation);
+                    env->SetObjectField(statusObj, field, newIntegerObj);
+                }
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::inversion: {
+                jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.inversion()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::lnbVoltage: {
+                jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.lnbVoltage()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::plpId: {
+                jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.plpId()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::isEWBS: {
+                jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;");
+                jobject newBooleanObj = env->NewObject(
+                        booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS()));
+                env->SetObjectField(statusObj, field, newBooleanObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::agc: {
+                jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.agc()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::isLnaOn: {
+                jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;");
+                jobject newBooleanObj = env->NewObject(
+                        booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn()));
+                env->SetObjectField(statusObj, field, newBooleanObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::isLayerError: {
+                jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z");
+                hidl_vec<bool> layerErr = s.isLayerError();
+
+                jbooleanArray valObj = env->NewBooleanArray(layerErr.size());
+
+                for (size_t i = 0; i < layerErr.size(); i++) {
+                    jboolean x = layerErr[i];
+                    env->SetBooleanArrayRegion(valObj, i, 1, &x);
+                }
+                env->SetObjectField(statusObj, field, valObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::mer: {
+                jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.mer()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::freqOffset: {
+                jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.freqOffset()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::hierarchy: {
+                jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;");
+                jobject newIntegerObj = env->NewObject(
+                        intClazz, initInt, static_cast<jint>(s.hierarchy()));
+                env->SetObjectField(statusObj, field, newIntegerObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::isRfLocked: {
+                jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;");
+                jobject newBooleanObj = env->NewObject(
+                        booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked()));
+                env->SetObjectField(statusObj, field, newBooleanObj);
+                break;
+            }
+            case FrontendStatus::hidl_discriminator::plpInfo: {
+                jfieldID field = env->GetFieldID(clazz, "mPlpInfo",
+                        "[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;");
+                jclass plpClazz = env->FindClass(
+                        "android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo");
+                jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V");
+
+                hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo();
+
+                jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
+                for (int i = 0; i < plpInfos.size(); i++) {
+                    auto info = plpInfos[i];
+                    jint plpId = (jint) info.plpId;
+                    jboolean isLocked = (jboolean) info.isLocked;
+                    jint uec = (jint) info.uec;
+
+                    jobject plpObj = env->NewObject(plpClazz, initPlp, plpId, isLocked, uec);
+                    env->SetObjectArrayElement(valObj, i, plpObj);
+                }
+
+                env->SetObjectField(statusObj, field, valObj);
+                break;
+            }
+            default: {
+                break;
+            }
+        }
+    }
+
+    return statusObj;
+}
+
 }  // namespace android
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1990,8 +2269,6 @@
 
     gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
 
-    gFields.onLnbEventID = env->GetMethodID(clazz, "onLnbEvent", "(I)V");
-
     jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
     gFields.frontendInitID =
             env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
@@ -1999,6 +2276,8 @@
     jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
     gFields.lnbContext = env->GetFieldID(lnbClazz, "mNativeContext", "J");
     gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "(I)V");
+    gFields.onLnbEventID = env->GetMethodID(lnbClazz, "onEvent", "(I)V");
+    gFields.onLnbDiseqcMessageID = env->GetMethodID(lnbClazz, "onDiseqcMessage", "([B)V");
 
     jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter");
     gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
@@ -2086,8 +2365,10 @@
     return tuner->setLna(enable);
 }
 
-static jobject android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
-    return NULL;
+static jobject android_media_tv_Tuner_get_frontend_status(
+        JNIEnv* env, jobject thiz, jintArray types) {
+    sp<JTuner> tuner = getTuner(env, thiz);
+    return tuner->getFrontendStatus(types);
 }
 
 static jobject android_media_tv_Tuner_get_av_sync_hw_id(
@@ -2121,7 +2402,7 @@
     return tuner->getFrontendInfo(id);
 }
 
-static jobject android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
+static jintArray android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
     sp<JTuner> tuner = getTuner(env, thiz);
     return tuner->getLnbIds();
 }
@@ -2950,8 +3231,14 @@
     return (jint) r;
 }
 
-static int android_media_tv_Tuner_close_lnb(JNIEnv*, jobject) {
-    return 0;
+static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
+    sp<Lnb> lnbSp = getLnb(env, lnb);
+    Result r = lnbSp->getILnb()->close();
+    if (r == Result::SUCCESS) {
+        lnbSp->decStrong(lnb);
+        env->SetLongField(lnb, gFields.lnbContext, 0);
+    }
+    return (jint) r;
 }
 
 static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jobject jfd) {
@@ -3125,8 +3412,7 @@
             (void *)android_media_tv_Tuner_open_filter },
     { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/filter/TimeFilter;",
             (void *)android_media_tv_Tuner_open_time_filter },
-    { "nativeGetLnbIds", "()Ljava/util/List;",
-            (void *)android_media_tv_Tuner_get_lnb_ids },
+    { "nativeGetLnbIds", "()[I", (void *)android_media_tv_Tuner_get_lnb_ids },
     { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;",
             (void *)android_media_tv_Tuner_open_lnb_by_handle },
     { "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;",
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 7e860b9..73fc38d 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -70,7 +70,7 @@
     LnbCallback(jweak tunerObj, LnbId id);
     virtual Return<void> onEvent(LnbEventType lnbEventType);
     virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
-    jweak mObject;
+    jweak mLnb;
     LnbId mId;
 };
 
@@ -179,7 +179,7 @@
     int stopScan();
     int setLnb(int id);
     int setLna(bool enable);
-    jobject getLnbIds();
+    jintArray getLnbIds();
     jobject openLnbById(int id);
     jobject openLnbByName(jstring name);
     jobject openFilter(DemuxFilterType type, int bufferSize);
@@ -187,6 +187,7 @@
     jobject openDescrambler();
     jobject openDvr(DvrType type, jlong bufferSize);
     jobject getDemuxCaps();
+    jobject getFrontendStatus(jintArray types);
 
 protected:
     Result openDemux();
@@ -198,6 +199,7 @@
     static sp<ITuner> mTuner;
     hidl_vec<FrontendId> mFeIds;
     sp<IFrontend> mFe;
+    int mFeId;
     hidl_vec<LnbId> mLnbIds;
     sp<ILnb> mLnb;
     sp<IDemux> mDemux;
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
index f45114a..77e6a14 100644
--- a/media/packages/BluetoothMidiService/Android.bp
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -1,6 +1,35 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+    name: "BluetoothMidiLib",
+    srcs: [
+        "src/**/*.java",
+    ],
+    platform_apis: true,
+    plugins: ["java_api_finder"],
+    manifest: "AndroidManifestBase.xml",
+}
+
 android_app {
     name: "BluetoothMidiService",
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     platform_apis: true,
     certificate: "platform",
+    manifest: "AndroidManifest.xml",
 }
diff --git a/media/packages/BluetoothMidiService/AndroidManifest.xml b/media/packages/BluetoothMidiService/AndroidManifest.xml
index 1cfd55d..4042ce8 100644
--- a/media/packages/BluetoothMidiService/AndroidManifest.xml
+++ b/media/packages/BluetoothMidiService/AndroidManifest.xml
@@ -1,12 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
         package="com.android.bluetoothmidiservice"
+        android:versionCode="1"
+        android:versionName="R-initial"
         >
+    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
 
     <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
     <uses-feature android:name="android.software.midi" android:required="true"/>
     <uses-permission android:name="android.permission.BLUETOOTH"/>
 
     <application
+        tools:replace="android:label"
         android:label="@string/app_name">
         <service android:name=".BluetoothMidiService"
             android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE">
diff --git a/media/packages/BluetoothMidiService/AndroidManifestBase.xml b/media/packages/BluetoothMidiService/AndroidManifestBase.xml
new file mode 100644
index 0000000..ebe62b0
--- /dev/null
+++ b/media/packages/BluetoothMidiService/AndroidManifestBase.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.bluetoothmidiservice"
+          android:versionCode="1"
+          android:versionName="R-initial"
+          >
+    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+    <application
+        android:label="BluetoothMidi"
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
+    </application>
+</manifest>
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
index c51c8fa..8d18b77 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
@@ -70,7 +70,9 @@
         }
 
         byte header = buffer[0];
-        if ((header & 0xC0) != 0x80) {
+        // Check for the header bit 7.
+        // Ignore the reserved bit 6.
+        if ((header & 0x80) != 0x80) {
             Log.e(TAG, "packet does not start with header");
             return;
         }
diff --git a/media/packages/BluetoothMidiService/tests/unit/Android.bp b/media/packages/BluetoothMidiService/tests/unit/Android.bp
new file mode 100644
index 0000000..4d4ae9e
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+    name: "BluetoothMidiTests",
+    srcs: ["src/**/*.java"],
+    certificate: "platform",
+    static_libs: [
+        //"frameworks-base-testutils",
+        "android-support-test",
+        "androidx.test.core",
+        "androidx.test.ext.truth",
+        "androidx.test.runner",
+        "androidx.test.rules",
+        "platform-test-annotations",
+        "BluetoothMidiLib",
+    ],
+    test_suites: ["device-tests"],
+    libs: [
+        "framework-res",
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+}
diff --git a/media/packages/BluetoothMidiService/tests/unit/AndroidManifest.xml b/media/packages/BluetoothMidiService/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..4d27e1e
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="com.android.bluetoothmidiservice.tests.unit">
+    <uses-sdk
+        android:minSdkVersion="29"
+        android:targetSdkVersion="29" />
+
+    <application android:testOnly="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.bluetoothmidiservice.tests.unit"
+        android:label="Bluetooth MIDI Service tests">
+    </instrumentation>
+</manifest>
diff --git a/media/packages/BluetoothMidiService/tests/unit/AndroidTest.xml b/media/packages/BluetoothMidiService/tests/unit/AndroidTest.xml
new file mode 100644
index 0000000..02e7f0d
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Runs Bluetooth MIDI Service Tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="BluetoothMidiTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="BLEMidiTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.bluetoothmidiservice.tests.unit" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false" />
+    </test>
+</configuration>
diff --git a/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/AccumulatingMidiReceiver.java b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/AccumulatingMidiReceiver.java
new file mode 100644
index 0000000..57859bc
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/AccumulatingMidiReceiver.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetoothmidiservice;
+
+import android.media.midi.MidiReceiver;
+import android.util.Log;
+
+import com.android.internal.midi.MidiFramer;
+
+import java.util.ArrayList;
+
+class AccumulatingMidiReceiver extends MidiReceiver {
+    private static final String TAG = "AccumulatingMidiReceiver";
+    ArrayList<byte[]> mBuffers = new ArrayList<byte[]>();
+    ArrayList<Long> mTimestamps = new ArrayList<Long>();
+
+    public void onSend(byte[] buffer, int offset, int count, long timestamp) {
+        Log.d(TAG, "onSend() passed " + MidiFramer.formatMidiData(buffer, offset, count));
+        byte[] actualRow = new byte[count];
+        System.arraycopy(buffer, offset, actualRow, 0, count);
+        mBuffers.add(actualRow);
+        mTimestamps.add(timestamp);
+    }
+
+    byte[][] getBuffers() {
+        return mBuffers.toArray(new byte[mBuffers.size()][]);
+    }
+
+    Long[] getTimestamps() {
+        return mTimestamps.toArray(new Long[mTimestamps.size()]);
+    }
+}
+
diff --git a/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiCodecTest.java b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiCodecTest.java
new file mode 100644
index 0000000..3285f59
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiCodecTest.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetoothmidiservice;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiFramer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * End to end testing of the Bluetooth Encoder and Decoder
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothMidiCodecTest {
+
+    private static final String TAG = "BluetoothMidiCodecTest";
+    private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
+    private static final long NANOS_PER_MSEC = 1000000L;
+
+    static class EncoderDecoderChecker implements PacketEncoder.PacketReceiver {
+        BluetoothPacketEncoder mEncoder;
+        BluetoothPacketDecoder mDecoder;
+        AccumulatingMidiReceiver mReceiver;
+        MidiFramer mFramer;
+        AccumulatingMidiReceiver mBypassReceiver;
+        MidiFramer mBypassFramer;
+        int mMaxPacketsPerConnection;
+        int mConnectionIntervalMillis;
+        BlockingQueue<byte[]> mPacketQueue;
+        ScheduledExecutorService mScheduler;
+
+        EncoderDecoderChecker() {
+            this(2, 15, 20);
+        }
+
+        EncoderDecoderChecker(
+                int maxPacketsPerConnection,
+                int connectionIntervalMillis,
+                int maxBytesPerPacket) {
+            mMaxPacketsPerConnection = maxPacketsPerConnection;
+            mConnectionIntervalMillis = connectionIntervalMillis;
+            mEncoder = new BluetoothPacketEncoder(this, maxBytesPerPacket);
+            mDecoder = new BluetoothPacketDecoder(maxBytesPerPacket);
+            mReceiver = new AccumulatingMidiReceiver();
+            mFramer = new MidiFramer(mReceiver);
+            mBypassReceiver = new AccumulatingMidiReceiver();
+            mBypassFramer = new MidiFramer(mBypassReceiver);
+            mScheduler = Executors.newSingleThreadScheduledExecutor();
+            mPacketQueue = new LinkedBlockingDeque<>(maxPacketsPerConnection);
+        }
+
+        void processQueue() throws InterruptedException {
+            for (int i = 0; i < mMaxPacketsPerConnection; i++) {
+                byte[] packet = mPacketQueue.poll(0, TimeUnit.SECONDS);
+                if (packet == null) break;
+                Log.d(TAG, "decode " + MidiFramer.formatMidiData(packet, 0, packet.length));
+                mDecoder.decodePacket(packet, mFramer);
+            }
+            Log.d(TAG, "call writeComplete()");
+            mEncoder.writeComplete();
+        }
+
+        public void start() {
+            mScheduler.scheduleAtFixedRate(
+                    () -> {
+                        Log.d(TAG, "run scheduled task");
+                        try {
+                            processQueue();
+                        } catch (Exception e) {
+                            assertEquals(null, e);
+                        }
+                    },
+                    mConnectionIntervalMillis, // initial delay
+                    mConnectionIntervalMillis, // period
+                    TimeUnit.MILLISECONDS);
+        }
+
+        public void stop() {
+            // TODO wait for queue to empty
+            mScheduler.shutdown();
+        }
+
+        // TODO Should this block?
+        // Store the packets and then write them from a periodic task.
+        @Override
+        public void writePacket(byte[] buffer, int count) {
+            Log.d(TAG, "writePacket() passed " + MidiFramer.formatMidiData(buffer, 0, count));
+            byte[] packet = new byte[count];
+            System.arraycopy(buffer, 0, packet, 0, count);
+            try {
+                mPacketQueue.put(packet);
+            } catch (Exception e) {
+                assertEquals(null, e);
+            }
+            Log.d(TAG, "writePacket() returns");
+        }
+
+        void test(final byte[][] midi)
+                throws IOException, InterruptedException {
+            test(midi, 2);
+        }
+
+        // Send the MIDI messages through the encoder,
+        // then through the decoder,
+        // then gather the resulting MIDI and compare the results.
+        void test(final byte[][] midi, int intervalMillis)
+                throws IOException, InterruptedException {
+            start();
+            long timestamp = 0;
+            // Send all of the MIDI messages and gather the response.
+            for (int i = 0; i < midi.length; i++) {
+                byte[] outMessage = midi[i];
+                Log.d(TAG, "outMessage "
+                        + MidiFramer.formatMidiData(outMessage, 0, outMessage.length));
+                mEncoder.send(outMessage, 0, outMessage.length, timestamp);
+                timestamp += 2 * NANOS_PER_MSEC;
+                // Also send a copy through a MidiFramer to align the messages.
+                mBypassFramer.send(outMessage, 0, outMessage.length, timestamp);
+            }
+            Thread.sleep(200);
+            stop();
+
+            // Compare the gathered rows with the expected rows.
+            byte[][] expectedMessages = mBypassReceiver.getBuffers();
+            byte[][] inMessages = mReceiver.getBuffers();
+            Log.d(TAG, "expectedMessage length = " + expectedMessages.length
+                    + ", inMessages length = " + inMessages.length);
+            assertEquals(expectedMessages.length, inMessages.length);
+            Long[] actualTimestamps = mReceiver.getTimestamps();
+            long previousTime = 0;
+            for (int i = 0; i < expectedMessages.length; i++) {
+                byte[] expectedMessage = expectedMessages[i];
+                Log.d(TAG, "expectedMessage = "
+                        + MidiFramer.formatMidiData(expectedMessage,
+                        0, expectedMessage.length));
+                byte[] actualMessage = inMessages[i];
+                Log.d(TAG, "actualMessage   = "
+                        + MidiFramer.formatMidiData(actualMessage, 0, actualMessage.length));
+                assertArrayEquals(expectedMessage, actualMessage);
+                // Are the timestamps monotonic?
+                long currentTime =  actualTimestamps[i];
+                Log.d(TAG, "previousTime   = " + previousTime
+                        + ", currentTime   = " + currentTime);
+                assertTrue(currentTime >= previousTime);
+                previousTime = currentTime;
+            }
+        }
+    }
+
+    @Test
+    public void testOneNoteOn() throws IOException, InterruptedException {
+        final byte[][] midi = {
+                {(byte) 0x90, 0x40, 0x64}
+                };
+        EncoderDecoderChecker checker = new EncoderDecoderChecker();
+        checker.test(midi);
+    }
+
+    @Test
+    public void testTwoNoteOnSameTime() throws IOException, InterruptedException {
+        final byte[][] midi = {
+                {(byte) 0x90, 0x40, 0x64, (byte) 0x90, 0x47, 0x70}
+                };
+        EncoderDecoderChecker checker = new EncoderDecoderChecker();
+        checker.test(midi);
+    }
+
+    @Test
+    public void testTwoNoteOnStaggered() throws IOException, InterruptedException {
+        final byte[][] midi = {
+                {(byte) 0x90, 0x40, 0x64},
+                {(byte) 0x90, 0x47, 0x70}
+                };
+        EncoderDecoderChecker checker = new EncoderDecoderChecker();
+        checker.test(midi);
+    }
+
+    public void checkNoteBurst(int maxPacketsPerConnection,
+            int period,
+            int maxBytesPerPacket) throws IOException, InterruptedException {
+        final int numNotes = 100;
+        final byte[][] midi = new byte[numNotes][];
+        int channel = 2;
+        for (int i = 0; i < numNotes; i++) {
+            byte[] message = {(byte) (0x90 + channel), (byte) (i + 1), 0x64};
+            midi[i] = message;
+            channel ^= 1;
+        }
+        EncoderDecoderChecker checker = new EncoderDecoderChecker(
+                maxPacketsPerConnection, 15, maxBytesPerPacket);
+        checker.test(midi, period);
+    }
+
+    @Test
+    public void testNoteBurstM1P6() throws IOException, InterruptedException {
+        checkNoteBurst(1, 6, 20);
+    }
+    @Test
+    public void testNoteBurstM1P2() throws IOException, InterruptedException {
+        checkNoteBurst(1, 2, 20);
+    }
+    @Test
+    public void testNoteBurstM2P6() throws IOException, InterruptedException {
+        checkNoteBurst(2, 6, 20);
+    }
+    @Test
+    public void testNoteBurstM2P2() throws IOException, InterruptedException {
+        checkNoteBurst(2, 2, 20);
+    }
+    @Test
+    public void testNoteBurstM2P0() throws IOException, InterruptedException {
+        checkNoteBurst(2, 0, 20);
+    }
+    @Test
+    public void testNoteBurstM2P6B21() throws IOException, InterruptedException {
+        checkNoteBurst(2, 6, 21);
+    }
+    @Test
+    public void testNoteBurstM2P2B21() throws IOException, InterruptedException {
+        checkNoteBurst(2, 2, 21);
+    }
+    @Test
+    public void testNoteBurstM2P0B21() throws IOException, InterruptedException {
+        checkNoteBurst(2, 0, 21);
+    }
+}
diff --git a/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiDecoderTest.java b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiDecoderTest.java
new file mode 100644
index 0000000..6ecc539
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiDecoderTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetoothmidiservice;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiFramer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothMidiDecoderTest {
+
+    private static final String TAG = "BluetoothMidiDecoderTest";
+    private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
+    private static final long NANOS_PER_MSEC = 1000000L;
+
+    static class DecoderChecker {
+        AccumulatingMidiReceiver mReceiver;
+        BluetoothPacketDecoder mDecoder;
+
+        DecoderChecker() {
+            mReceiver = new AccumulatingMidiReceiver();
+            final int maxBytes = 20;
+            mDecoder = new BluetoothPacketDecoder(maxBytes);
+        }
+
+        void compareWithExpected(final byte[][] expectedMessages) {
+            byte[][] actualRows = mReceiver.getBuffers();
+            Long[] actualTimestamps = mReceiver.getTimestamps();
+            long previousTime = 0;
+            // Compare the gathered with the expected.
+            assertEquals(expectedMessages.length, actualRows.length);
+            for (int i = 0; i < expectedMessages.length; i++) {
+                byte[] expectedRow = expectedMessages[i];
+                Log.d(TAG, "expectedRow = "
+                        + MidiFramer.formatMidiData(expectedRow, 0, expectedRow.length));
+                byte[] actualRow = actualRows[i];
+                Log.d(TAG, "actualRow   = "
+                        + MidiFramer.formatMidiData(actualRow, 0, actualRow.length));
+                assertArrayEquals(expectedRow, actualRow);
+                // Are the timestamps monotonic?
+                long currentTime =  actualTimestamps[i];
+                Log.d(TAG, "previousTime   = " + previousTime + ", currentTime   = " + currentTime);
+                assertTrue(currentTime >= previousTime);
+                previousTime = currentTime;
+            }
+        }
+
+        void decodePacket(byte[] packet) throws IOException {
+            mDecoder.decodePacket(packet, mReceiver);
+        }
+
+        void decodePackets(byte[][] multiplePackets) throws IOException {
+            try {
+                for (int i = 0; i < multiplePackets.length; i++) {
+                    byte[] packet = multiplePackets[i];
+                    mDecoder.decodePacket(packet, mReceiver);
+                }
+            } catch (Exception e) {
+                assertEquals(null, e);
+            }
+        }
+
+        void test(byte[] encoded, byte[][] decoded) throws IOException {
+            decodePacket(encoded);
+            compareWithExpected(decoded);
+        }
+
+        void test(byte[][] encoded, byte[][] decoded) throws IOException {
+            decodePackets(encoded);
+            compareWithExpected(decoded);
+        }
+    }
+
+    @Test
+    public void testOneNoteOn() throws IOException {
+        final byte[] encoded = {
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x90, 0x40, 0x64
+                };
+        final byte[][] decoded = {
+                {(byte) 0x90, 0x40, 0x64}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testReservedHeaderBit() throws IOException {
+        final byte[] encoded = {
+                // Decoder should ignore the reserved bit.
+                (byte) (0x80 | 0x40), // set RESERVED bit in header!
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x90, 0x40, 0x64
+                };
+        final byte[][] decoded = {
+                {(byte) 0x90, 0x40, 0x64}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testTwoNotesOnRunning() throws IOException {
+        final byte[] encoded = {
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x90, 0x40, 0x64,
+                (byte) 0x85, // timestamp
+                (byte) 0x42, 0x70
+                };
+        final byte[][] decoded = {
+                {(byte) 0x90, 0x40, 0x64},
+                {(byte) 0x42, 0x70}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testTwoNoteOnsTwoChannels() throws IOException {
+        final byte[] encoded = {
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x93, 0x40, 0x60,
+                // two channels so no running status
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x95, 0x47, 0x64
+                };
+        final byte[][] decoded = {
+                {(byte) 0x93, 0x40, 0x60,  (byte) 0x95, 0x47, 0x64}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testTwoNoteOnsOverTime() throws IOException {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x98, 0x45, 0x60
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x82, // timestamp advanced by 2 msec
+                (byte) 0x90, 0x40, 0x64,
+                (byte) 0x84, // timestamp needed because of time delay
+                // encoder uses running status
+                0x47, 0x72
+                }};
+        final byte[][] decoded = {
+                {(byte) 0x98, 0x45, 0x60},
+                {(byte) 0x90, 0x40, 0x64},
+                {(byte) 0x47, 0x72}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testSysExBasic() throws IOException {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // timestamp
+                (byte) 0xF0, 0x7D, // Begin prototyping SysEx
+                0x01, 0x02, 0x03, 0x04, 0x05,
+                (byte) 0x80, // timestamp
+                (byte) 0xF7 // End SysEx
+                }};
+        final byte[][] decoded = {
+                {(byte) 0xF0, 0x7D, // experimental SysEx
+                0x01, 0x02, 0x03, 0x04, 0x05, (byte) 0xF7}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testSysExTwoPackets() throws IOException {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // timestamp
+                (byte) 0xF0, 0x7D, // Begin prototyping SysEx
+                0x01, 0x02
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                0x03, 0x04, 0x05,
+                (byte) 0x80, // timestamp
+                (byte) 0xF7 // End SysEx
+                }};
+        final byte[][] decoded = {
+            {(byte) 0xF0, 0x7D, 0x01, 0x02}, // experimental SysEx
+            {0x03, 0x04, 0x05, (byte) 0xF7}
+        };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+    @Test
+    public void testSysExThreePackets() throws IOException {
+        final byte[][] encoded = {
+                {(byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // timestamp
+                (byte) 0xF0, 0x7D, // Begin prototyping SysEx
+                0x01, 0x02
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                0x03, 0x04, 0x05,
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                0x06, 0x07, 0x08,
+                (byte) 0x80, // timestamp
+                (byte) 0xF7 // End SysEx
+                }};
+        final byte[][] decoded = {
+                {(byte) 0xF0, 0x7D, 0x01, 0x02}, // experimental SysEx
+                {0x03, 0x04, 0x05},
+                {0x06, 0x07, 0x08, (byte) 0xF7}
+                };
+        new DecoderChecker().test(encoded, decoded);
+    }
+
+}
diff --git a/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiEncoderTest.java b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiEncoderTest.java
new file mode 100644
index 0000000..a169c0d
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/BluetoothMidiEncoderTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetoothmidiservice;
+
+import static org.junit.Assert.assertEquals;
+
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiFramer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothMidiEncoderTest {
+
+    private static final String TAG = "BluetoothMidiEncoderTest";
+    private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
+    private static final long NANOS_PER_MSEC = 1000000L;
+
+    static class AccumulatingPacketReceiver implements PacketEncoder.PacketReceiver {
+        ArrayList<byte[]> mBuffers = new ArrayList<byte[]>();
+
+        public void writePacket(byte[] buffer, int count) {
+            byte[] actualRow = new byte[count];
+            Log.d(TAG, "writePacket() passed " + MidiFramer.formatMidiData(buffer, 0, count));
+            System.arraycopy(buffer, 0, actualRow, 0, count);
+            mBuffers.add(actualRow);
+        }
+
+        byte[][] getBuffers() {
+            return mBuffers.toArray(new byte[mBuffers.size()][]);
+        }
+    }
+
+    static class EncoderChecker {
+        AccumulatingPacketReceiver mReceiver;
+        BluetoothPacketEncoder mEncoder;
+
+        EncoderChecker() {
+            mReceiver = new AccumulatingPacketReceiver();
+            final int maxBytes = 20;
+            mEncoder = new BluetoothPacketEncoder(mReceiver, maxBytes);
+        }
+
+        void send(byte[] data) throws IOException {
+            send(data, 0);
+        }
+
+        void send(byte[] data, long timestamp) throws IOException {
+            Log.d(TAG, "send " + MidiFramer.formatMidiData(data, 0, data.length));
+            mEncoder.send(data, 0, data.length, timestamp);
+        }
+
+        void compareWithExpected(final byte[][] expected) {
+            byte[][] actualRows = mReceiver.getBuffers();
+            assertEquals(expected.length, actualRows.length);
+            // Compare the gathered rows with the expected rows.
+            for (int i = 0; i < expected.length; i++) {
+                byte[] expectedRow = expected[i];
+                Log.d(TAG, "expectedRow = "
+                        + MidiFramer.formatMidiData(expectedRow, 0, expectedRow.length));
+                byte[] actualRow = actualRows[i];
+                Log.d(TAG, "actualRow   = "
+                        + MidiFramer.formatMidiData(actualRow, 0, actualRow.length));
+                assertEquals(expectedRow.length, actualRow.length);
+                for (int k = 0; k < expectedRow.length; k++) {
+                    assertEquals(expectedRow[k], actualRow[k]);
+                }
+            }
+        }
+
+        void writeComplete() {
+            mEncoder.writeComplete();
+        }
+
+    }
+
+    @Test
+    public void testOneNoteOn() throws IOException  {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x90, 0x40, 0x64
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        checker.send(new byte[] {(byte) 0x90, 0x40, 0x64});
+        checker.compareWithExpected(encoded);
+    }
+
+    @Test
+    public void testTwoNoteOnsSameChannel() throws IOException  {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x90, 0x40, 0x64,
+                // encoder converts to running status
+                0x47, 0x72
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        checker.send(new byte[] {(byte) 0x90, 0x40, 0x64, (byte) 0x90, 0x47, 0x72});
+        checker.compareWithExpected(encoded);
+    }
+
+    @Test
+    public void testTwoNoteOnsTwoChannels() throws IOException  {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x93, 0x40, 0x60,
+                // two channels so no running status
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x95, 0x47, 0x64
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        checker.send(new byte[] {(byte) 0x93, 0x40, 0x60, (byte) 0x95, 0x47, 0x64});
+        checker.compareWithExpected(encoded);
+    }
+
+    @Test
+    public void testTwoNoteOnsOverTime() throws IOException  {
+        final byte[][] encoded = {
+                {
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // high bit of timestamp
+                (byte) 0x98, 0x45, 0x60
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x82, // timestamp advanced by 2 msec
+                (byte) 0x90, 0x40, 0x64,
+                (byte) 0x84, // timestamp needed because of time delay
+                // encoder converts to running status
+                0x47, 0x72
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        long timestamp = 0;
+        // Send one note. This will cause an immediate packet write
+        // because we don't know when the next one will arrive.
+        checker.send(new byte[] {(byte) 0x98, 0x45, 0x60}, timestamp);
+
+        // Send two notes. These should accumulate into the
+        // same packet because we do not yet have a writeComplete.
+        timestamp += 2 * NANOS_PER_MSEC;
+        checker.send(new byte[] {(byte) 0x90, 0x40, 0x64}, timestamp);
+        timestamp += 2 * NANOS_PER_MSEC;
+        checker.send(new byte[] {(byte) 0x90, 0x47, 0x72}, timestamp);
+        // Tell the encoder that the first packet has been written to the
+        // hardware. So it can flush the two pending notes.
+        checker.writeComplete();
+        checker.compareWithExpected(encoded);
+    }
+
+    @Test
+    public void testSysExBasic() throws IOException  {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // timestamp
+                (byte) 0xF0, 0x7D, // Begin prototyping SysEx
+                0x01, 0x02, 0x03, 0x04, 0x05,
+                (byte) 0x80, // timestamp
+                (byte) 0xF7 // End SysEx
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        checker.send(new byte[] {(byte) 0xF0, 0x7D, // experimental SysEx
+                0x01, 0x02, 0x03, 0x04, 0x05, (byte) 0xF7});
+        checker.compareWithExpected(encoded);
+    }
+
+    @Test
+    public void testSysExTwoPackets() throws IOException  {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // timestamp
+                (byte) 0xF0, 0x7D, // Begin prototyping SysEx
+                0x01, 0x02
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                0x03, 0x04, 0x05,
+                (byte) 0x80, // timestamp
+                (byte) 0xF7 // End SysEx
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        // Send in two messages.
+        checker.send(new byte[] {(byte) 0xF0, 0x7D, // experimental SysEx
+                0x01, 0x02});
+        checker.send(new byte[] {0x03, 0x04, 0x05, (byte) 0xF7});
+        // Tell the encoder that the first packet has been written to the
+        // hardware. So it can flush the remaining data.
+        checker.writeComplete();
+        checker.compareWithExpected(encoded);
+    }
+
+    @Test
+    public void testSysExThreePackets() throws IOException  {
+        final byte[][] encoded = {{
+                (byte) 0x80, // high bit of header must be set
+                (byte) 0x80, // timestamp
+                (byte) 0xF0, 0x7D, // Begin prototyping SysEx
+                0x01, 0x02
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                0x03, 0x04, 0x05,
+                },
+                {
+                (byte) 0x80, // high bit of header must be set
+                0x06, 0x07, 0x08,
+                (byte) 0x80, // timestamp
+                (byte) 0xF7 // End SysEx
+                }};
+        EncoderChecker checker = new EncoderChecker();
+        // Send in three messages.
+        checker.send(new byte[] {(byte) 0xF0, 0x7D, // experimental SysEx
+                0x01, 0x02});
+        checker.send(new byte[] {0x03, 0x04, 0x05});
+        checker.writeComplete();
+        checker.send(new byte[] {0x06, 0x07, 0x08, (byte) 0xF7});
+        checker.writeComplete();
+        checker.compareWithExpected(encoded);
+    }
+}
diff --git a/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/MidiFramerTest.java b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/MidiFramerTest.java
new file mode 100644
index 0000000..8cda6eb
--- /dev/null
+++ b/media/packages/BluetoothMidiService/tests/unit/src/com/android/bluetoothmidiservice/MidiFramerTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetoothmidiservice;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiFramer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MidiFramerTest {
+
+    private static final String TAG = "MidiFramerTest";
+    private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
+
+    // For testing MidiFramer
+    // TODO move MidiFramer tests to their own file
+    static class FramerChecker {
+        AccumulatingMidiReceiver mReceiver;
+        MidiFramer mFramer;
+
+        FramerChecker() {
+            mReceiver = new AccumulatingMidiReceiver();
+            mFramer = new MidiFramer(mReceiver);
+        }
+
+        void compareWithExpected(final byte[][] expected) {
+            byte[][] actualRows = mReceiver.getBuffers();
+            assertEquals(expected.length, actualRows.length);
+            // Compare the gathered rows with the expected rows.
+            for (int i = 0; i < expected.length; i++) {
+                byte[] expectedRow = expected[i];
+                Log.d(TAG, "expectedRow = "
+                        + MidiFramer.formatMidiData(expectedRow, 0, expectedRow.length));
+                byte[] actualRow = actualRows[i];
+                Log.d(TAG, "actualRow = "
+                        + MidiFramer.formatMidiData(actualRow, 0, actualRow.length));
+                assertArrayEquals(expectedRow, actualRow);
+            }
+        }
+
+        void send(byte[] data) throws IOException {
+            Log.d(TAG, "send " + MidiFramer.formatMidiData(data, 0, data.length));
+            mFramer.send(data, 0, data.length, 0);
+        }
+    }
+
+    @Test
+    public void testFramerTwoNoteOns() throws IOException {
+        final byte[][] expected = {
+                {(byte) 0x90, 0x40, 0x64},
+                {(byte) 0x90, 0x47, 0x50}
+                };
+        FramerChecker checker = new FramerChecker();
+        checker.send(new byte[] {(byte) 0x90, 0x40, 0x64, (byte) 0x90, 0x47, 0x50});
+        checker.compareWithExpected(expected);
+    }
+
+    @Test
+    public void testFramerTwoNoteOnsRunning() throws IOException {
+        final byte[][] expected = {
+                {(byte) 0x90, 0x40, 0x64},
+                {(byte) 0x90, 0x47, 0x70}
+                };
+        FramerChecker checker = new FramerChecker();
+        // Two notes with running status
+        checker.send(new byte[] {(byte) 0x90, 0x40, 0x64, 0x47, 0x70});
+        checker.compareWithExpected(expected);
+    }
+
+    @Test
+    public void testFramerPreGarbage() throws IOException {
+        final byte[][] expected = {
+                {(byte) 0x90, 0x40, 0x64},
+                {(byte) 0x90, 0x47, 0x70}
+                };
+        FramerChecker checker = new FramerChecker();
+        // Garbage can come before the first status byte if you connect
+        // a MIDI cable in the middle of a message.
+        checker.send(new byte[] {0x01, 0x02, // garbage bytes
+                (byte) 0x90, 0x40, 0x64, 0x47, 0x70});
+        checker.compareWithExpected(expected);
+    }
+}
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index 77e8f97..6ca564f 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -231,9 +231,10 @@
         addRouterCallback(new RouteCallback() {});
         addManagerCallback(new MediaRouter2Manager.Callback() {
             @Override
-            public void onSessionCreated(MediaRouter2Manager.RoutingController controller) {
-                if (TextUtils.equals(mPackageName, controller.getClientPackageName())
-                        && createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)) {
+            public void onTransferred(RoutingSessionInfo oldSessionInfo,
+                    RoutingSessionInfo newSessionInfo) {
+                if (TextUtils.equals(mPackageName, newSessionInfo.getClientPackageName())
+                        && newSessionInfo.getSelectedRoutes().contains(ROUTE_ID1)) {
                     latch.countDown();
                 }
             }
@@ -268,8 +269,9 @@
 
         addManagerCallback(new MediaRouter2Manager.Callback() {
             @Override
-            public void onSessionCreated(MediaRouter2Manager.RoutingController controller) {
-                assertNotNull(controller);
+            public void onTransferred(RoutingSessionInfo oldSessionInfo,
+                    RoutingSessionInfo newSessionInfo) {
+                assertNotNull(newSessionInfo);
                 onSessionCreatedLatch.countDown();
             }
         });
@@ -352,8 +354,9 @@
         // create a controller
         addManagerCallback(new MediaRouter2Manager.Callback() {
             @Override
-            public void onSessionCreated(MediaRouter2Manager.RoutingController controller) {
-                assertNotNull(controller);
+            public void onTransferred(RoutingSessionInfo oldSessionInfo,
+                    RoutingSessionInfo newSessionInfo) {
+                assertNotNull(newSessionInfo);
                 onSessionCreatedLatch.countDown();
             }
         });
@@ -383,13 +386,12 @@
 
         addManagerCallback(new MediaRouter2Manager.Callback() {
             @Override
-            public void onSessionsUpdated() {
-                List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
-                if (sessions.size() != 2) {
+            public void onSessionUpdated(RoutingSessionInfo updatedSessionInfo) {
+                if (!TextUtils.equals(sessionInfo.getId(), updatedSessionInfo.getId())) {
                     return;
                 }
 
-                if (sessions.get(1).getVolume() == targetVolume) {
+                if (updatedSessionInfo.getVolume() == targetVolume) {
                     volumeChangedLatch.countDown();
                 }
             }
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 43e2918..0b56d05 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -32,6 +32,10 @@
     <!-- Disable normal notification rendering; we handle that ourselves -->
     <bool name="config_renderNotifications">false</bool>
 
+    <!-- Whether navigationBar touch events should be consumed before reaching the CarFacetButton \
+         when the notification panel is open. -->
+    <bool name="config_consumeNavigationBarTouchWhenNotificationPanelOpen">false</bool>
+
     <!-- Whether heads-up notifications should be shown when shade is open. -->
     <bool name="config_enableHeadsUpNotificationWhenNotificationShadeOpen">true</bool>
     <!-- Whether heads-up notifications should be shown on the bottom. If false, heads-up
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java
index f11eff8..d84b2f9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java
@@ -28,7 +28,6 @@
 @Module(includes = {
         DefaultActivityBinder.class,
         DefaultBroadcastReceiverBinder.class,
-        DefaultServiceBinder.class,
-        CarSystemUIBinder.class})
+        DefaultServiceBinder.class})
 public class CarComponentBinder {
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 5547fee..c275536 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -65,7 +65,7 @@
 import dagger.Provides;
 
 @Module(includes = {DividerModule.class})
-abstract class CarSystemUIModule {
+public abstract class CarSystemUIModule {
 
     @Singleton
     @Provides
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
index 7d544c9..0e923f71 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
@@ -40,6 +40,6 @@
                 CarSystemUIModule.class,
                 CarSystemUIBinder.class
         })
-interface CarSystemUIRootComponent extends SystemUIRootComponent {
+public interface CarSystemUIRootComponent extends SystemUIRootComponent {
 
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index f6679c0..1901a2d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -219,6 +219,9 @@
 
         mNavBarNotificationTouchListener =
                 (v, event) -> {
+                    if (!isInflated()) {
+                        return true;
+                    }
                     boolean consumed = navBarCloseNotificationGestureDetector.onTouchEvent(event);
                     if (consumed) {
                         return true;
@@ -596,6 +599,11 @@
         }
     }
 
+    /** Returns {@code true} if the notification panel is expanded. */
+    public boolean isPanelExpanded() {
+        return mPanelExpanded;
+    }
+
     /** Sets the unseen count listener. */
     public void setOnUnseenCountUpdateListener(OnUnseenCountUpdateListener listener) {
         mUnseenCountUpdateListener = listener;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java
index 1cfc832..110c2ee 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewMediator.java
@@ -20,7 +20,6 @@
 import android.content.res.Configuration;
 
 import com.android.systemui.car.CarDeviceProvisionedController;
-import com.android.systemui.car.CarServiceProvider;
 import com.android.systemui.navigationbar.car.CarNavigationBarController;
 import com.android.systemui.statusbar.car.PowerManagerHelper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -36,7 +35,6 @@
 
     private final CarNavigationBarController mCarNavigationBarController;
     private final NotificationPanelViewController mNotificationPanelViewController;
-    private final CarServiceProvider mCarServiceProvider;
     private final PowerManagerHelper mPowerManagerHelper;
     private final CarDeviceProvisionedController mCarDeviceProvisionedController;
     private final ConfigurationController mConfigurationController;
@@ -46,7 +44,6 @@
             CarNavigationBarController carNavigationBarController,
             NotificationPanelViewController notificationPanelViewController,
 
-            CarServiceProvider carServiceProvider,
             PowerManagerHelper powerManagerHelper,
 
             CarDeviceProvisionedController carDeviceProvisionedController,
@@ -54,7 +51,6 @@
     ) {
         mCarNavigationBarController = carNavigationBarController;
         mNotificationPanelViewController = notificationPanelViewController;
-        mCarServiceProvider = carServiceProvider;
         mPowerManagerHelper = powerManagerHelper;
         mCarDeviceProvisionedController = carDeviceProvisionedController;
         mConfigurationController = configurationController;
@@ -72,7 +68,17 @@
                 mNotificationPanelViewController.getNavBarNotificationTouchListener());
 
         mCarNavigationBarController.registerNotificationController(
-                () -> mNotificationPanelViewController.toggle());
+                new CarNavigationBarController.NotificationsShadeController() {
+                    @Override
+                    public void togglePanel() {
+                        mNotificationPanelViewController.toggle();
+                    }
+
+                    @Override
+                    public boolean isNotificationPanelOpen() {
+                        return mNotificationPanelViewController.isPanelExpanded();
+                    }
+                });
     }
 
     @Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
index 67e9da4..fbcd878 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
@@ -314,6 +314,9 @@
     public interface NotificationsShadeController {
         /** Toggles the visibility of the notifications shade. */
         void togglePanel();
+
+        /** Returns {@code true} if the panel is open. */
+        boolean isNotificationPanelOpen();
     }
 
     private void checkAllBars(boolean isSetUp) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
index 28da169..5b99f53 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
@@ -35,10 +35,11 @@
  * in a linear layout.
  */
 public class CarNavigationBarView extends LinearLayout {
+    private final boolean mConsumeTouchWhenPanelOpen;
+
     private View mNavButtons;
     private CarNavigationButton mNotificationsButton;
     private NotificationsShadeController mNotificationsShadeController;
-    private Context mContext;
     private View mLockScreenButtons;
     // used to wire in open/close gestures for notifications
     private OnTouchListener mStatusBarWindowTouchListener;
@@ -46,7 +47,8 @@
 
     public CarNavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mContext = context;
+        mConsumeTouchWhenPanelOpen = getResources().getBoolean(
+                R.bool.config_consumeNavigationBarTouchWhenNotificationPanelOpen);
     }
 
     @Override
@@ -77,9 +79,16 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mStatusBarWindowTouchListener != null) {
+            boolean shouldConsumeEvent = mNotificationsShadeController == null ? false
+                    : mNotificationsShadeController.isNotificationPanelOpen();
+
             // Forward touch events to the status bar window so it can drag
             // windows if required (Notification shade)
             mStatusBarWindowTouchListener.onTouch(this, ev);
+
+            if (mConsumeTouchWhenPanelOpen && shouldConsumeEvent) {
+                return true;
+            }
         }
         return super.onInterceptTouchEvent(ev);
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 02604d8..cd45fc9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -65,6 +65,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
@@ -225,6 +226,7 @@
             KeyguardIndicationController keyguardIndicationController,
             DismissCallbackRegistry dismissCallbackRegistry,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
+            Lazy<NotificationShadeDepthController> depthControllerLazy,
             /* Car Settings injected components. */
             CarNavigationBarController carNavigationBarController) {
         super(
@@ -304,6 +306,7 @@
                 phoneStatusBarPolicy,
                 keyguardIndicationController,
                 dismissCallbackRegistry,
+                depthControllerLazy,
                 statusBarTouchableRegionManager);
         mUserSwitcherController = userSwitcherController;
         mScrimController = scrimController;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index 1baa1f6..e163173 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -51,6 +51,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
@@ -200,6 +201,7 @@
             KeyguardIndicationController keyguardIndicationController,
             DismissCallbackRegistry dismissCallbackRegistry,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
+            Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
             CarNavigationBarController carNavigationBarController) {
         return new CarStatusBar(
                 context,
@@ -278,6 +280,7 @@
                 keyguardIndicationController,
                 dismissCallbackRegistry,
                 statusBarTouchableRegionManager,
+                notificationShadeDepthControllerLazy,
                 carNavigationBarController);
     }
 }
diff --git a/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml b/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml
new file mode 100644
index 0000000..b0ca8dc
--- /dev/null
+++ b/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml
@@ -0,0 +1,58 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<com.android.systemui.navigationbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/system_bar_background"
+    android:orientation="vertical">
+    <!--The 20dp padding is the difference between the background selected icon size and the ripple
+        that was chosen, thus it's a hack to make it look pretty and not an official margin value-->
+    <LinearLayout
+        android:id="@id/nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingStart="20dp"
+        android:paddingEnd="20dp"
+        android:gravity="center">
+
+        <com.android.systemui.navigationbar.car.CarNavigationButton
+            android:id="@+id/home"
+            style="@style/NavigationBarButton"
+            systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+            systemui:icon="@drawable/car_ic_overview"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+            systemui:selectedIcon="@drawable/car_ic_overview_selected"
+            systemui:highlightWhenSelected="true"
+        />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/lock_screen_nav_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingStart="@dimen/car_keyline_1"
+        android:paddingEnd="@dimen/car_keyline_1"
+        android:gravity="center"
+        android:visibility="gone"
+    />
+
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarViewTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarViewTest.java
new file mode 100644
index 0000000..9e2131c
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarViewTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.navigationbar.car;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+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;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class CarNavigationBarViewTest extends SysuiTestCase {
+
+    private CarNavigationBarView mNavBarView;
+
+    @Mock
+    private CarNavigationBarController.NotificationsShadeController mNotificationsShadeController;
+
+    @Mock
+    private View.OnTouchListener mNavBarTouchListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @After
+    public void tearDown() {
+        getContext().getOrCreateTestableResources().addOverride(
+                R.bool.config_consumeNavigationBarTouchWhenNotificationPanelOpen, false);
+    }
+
+    @Test
+    public void dispatchTouch_shadeOpen_flagOff_doesNotConsumeTouch() {
+        getContext().getOrCreateTestableResources().addOverride(
+                R.bool.config_consumeNavigationBarTouchWhenNotificationPanelOpen, false);
+        when(mNotificationsShadeController.isNotificationPanelOpen()).thenReturn(true);
+        mNavBarView = (CarNavigationBarView) LayoutInflater.from(getContext()).inflate(
+                R.layout.car_navigation_bar_view_test, /* root= */ null);
+        mNavBarView.setNotificationsPanelController(mNotificationsShadeController);
+        mNavBarView.setStatusBarWindowTouchListener(mNavBarTouchListener);
+
+        boolean consume = mNavBarView.onInterceptTouchEvent(
+                MotionEvent.obtain(/* downTime= */ 200, /* eventTime= */ 300,
+                        MotionEvent.ACTION_MOVE, mNavBarView.getX(),
+                        mNavBarView.getY(), /* metaState= */ 0));
+
+        assertThat(consume).isFalse();
+    }
+
+    @Test
+    public void dispatchTouch_shadeOpen_flagOn_consumesTouch() {
+        getContext().getOrCreateTestableResources().addOverride(
+                R.bool.config_consumeNavigationBarTouchWhenNotificationPanelOpen, true);
+        when(mNotificationsShadeController.isNotificationPanelOpen()).thenReturn(true);
+        mNavBarView = (CarNavigationBarView) LayoutInflater.from(getContext()).inflate(
+                R.layout.car_navigation_bar_view_test, /* root= */ null);
+        mNavBarView.setNotificationsPanelController(mNotificationsShadeController);
+        mNavBarView.setStatusBarWindowTouchListener(mNavBarTouchListener);
+
+        boolean consume = mNavBarView.onInterceptTouchEvent(
+                MotionEvent.obtain(/* downTime= */ 200, /* eventTime= */ 300,
+                        MotionEvent.ACTION_MOVE, mNavBarView.getX(),
+                        mNavBarView.getY(), /* metaState= */ 0));
+
+        assertThat(consume).isTrue();
+    }
+}
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index 37a3de8..5328a03 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -6,9 +6,7 @@
     <string name="portal_notification_id" msgid="5155057562457079297">"داده تلفن همراه تمام شده است"</string>
     <string name="no_data_notification_id" msgid="668400731803969521">"داده شبکه تلفن همراه شما غیرفعال شده است"</string>
     <string name="portal_notification_detail" msgid="2295729385924660881">"‏برای رفتن به وب‌سایت %s، ضربه بزنید"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for no_data_notification_detail (3112125343857014825) -->
-    <skip />
+    <string name="no_data_notification_detail" msgid="3112125343857014825">"‏لطفاً با ارائه‌دهنده خدمات %s خود تماس بگیرید"</string>
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"بدون اتصال داده دستگاه همراه"</string>
     <string name="no_mobile_data_connection" msgid="544980465184147010">"‏افزودن طرح داده یا فراگردی ازطریق %s"</string>
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"وضعیت داده تلفن همراه"</string>
diff --git a/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml b/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml
index 2e9381a..5f84587 100644
--- a/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml
+++ b/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml
@@ -14,9 +14,7 @@
   ~ limitations under the License.
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.apk.cts.shim"
-          android:versionCode="2"
-          android:versionName="2.0" >
+          package="com.android.cts.ctsshim">
 
-    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="P" />
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="P.123" />
 </manifest>
\ No newline at end of file
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 4d5dc4e..30a193f 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -9,14 +9,14 @@
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Ingelesa (AEB), Colemak estiloa"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Ingelesa (AEB), Dvorak estiloa"</string>
     <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Ingelesa (AEB), Workman estiloa"</string>
-    <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Alemaniarra"</string>
+    <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Alemana"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Frantsesa"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Frantsesa (Kanada)"</string>
     <string name="keyboard_layout_russian_label" msgid="8724879775815042968">"Errusiarra"</string>
     <string name="keyboard_layout_russian_mac_label" msgid="3795866869038264796">"Errusiarra, Mac estiloa"</string>
     <string name="keyboard_layout_spanish_label" msgid="7091555148131908240">"Espainiarra"</string>
     <string name="keyboard_layout_swiss_french_label" msgid="4659191025396371684">"Frantsesa (Suitza)"</string>
-    <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemaniarra (Suitza)"</string>
+    <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Alemana (Suitza)"</string>
     <string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgikarra"</string>
     <string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bulgariarra"</string>
     <string name="keyboard_layout_italian" msgid="6497079660449781213">"Italiarra"</string>
@@ -36,8 +36,8 @@
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkiarra"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainarra"</string>
     <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabiarra"</string>
-    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greziera"</string>
-    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreera"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greziarra"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrearra"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituaniera"</string>
     <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espainiera (Latinoamerika)"</string>
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letoniera"</string>
diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml
index 44069a2..220dd67 100644
--- a/packages/InputDevices/res/values-mk/strings.xml
+++ b/packages/InputDevices/res/values-mk/strings.xml
@@ -3,12 +3,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="8016145283189546017">"Влезни уреди"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Тастатура за Android"</string>
-    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Англиски (О.К.)"</string>
-    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Англиски (САД)"</string>
-    <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Англиски (САД), меѓународен стил"</string>
-    <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Англиски (САД), Colemak стил"</string>
-    <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Англиски (САД), Dvorak стил"</string>
-    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Англиски (САД), Workman стил"</string>
+    <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"англиски (О.К.)"</string>
+    <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"англиски (САД)"</string>
+    <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"англиски (САД), меѓународен стил"</string>
+    <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"англиски (САД), Colemak стил"</string>
+    <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"англиски (САД), Dvorak стил"</string>
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"англиски (САД), Workman стил"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Германски"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Француски"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Француски (Канада)"</string>
diff --git a/packages/OsuLogin/res/values-af/strings.xml b/packages/OsuLogin/res/values-af/strings.xml
new file mode 100644
index 0000000..bfeee10
--- /dev/null
+++ b/packages/OsuLogin/res/values-af/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Sluit aanlyn aan"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Kon nie aanmeld nie"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-am/strings.xml b/packages/OsuLogin/res/values-am/strings.xml
new file mode 100644
index 0000000..e27c578
--- /dev/null
+++ b/packages/OsuLogin/res/values-am/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"የመስመር ላይ ምዝገባ"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ምዝገባ አልተሳካም"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ar/strings.xml b/packages/OsuLogin/res/values-ar/strings.xml
new file mode 100644
index 0000000..b72d7c1
--- /dev/null
+++ b/packages/OsuLogin/res/values-ar/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"الاشتراك على الإنترنت"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"تعذّر الاشتراك."</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-as/strings.xml b/packages/OsuLogin/res/values-as/strings.xml
new file mode 100644
index 0000000..422de32
--- /dev/null
+++ b/packages/OsuLogin/res/values-as/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"অনলাইনত ছাই আপ কৰক"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ছাইন আপ কৰিব পৰা নগ’ল"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-az/strings.xml b/packages/OsuLogin/res/values-az/strings.xml
new file mode 100644
index 0000000..977f939
--- /dev/null
+++ b/packages/OsuLogin/res/values-az/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Onlayn Qeydiyyat"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Qeydiyyat alınmadı"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-b+sr+Latn/strings.xml b/packages/OsuLogin/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..6eb2cc1
--- /dev/null
+++ b/packages/OsuLogin/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Onlajn registracija"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspela"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-be/strings.xml b/packages/OsuLogin/res/values-be/strings.xml
new file mode 100644
index 0000000..158c3f2
--- /dev/null
+++ b/packages/OsuLogin/res/values-be/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Зарэгістравацца ў інтэрнэце"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Не ўдалося зарэгістравацца"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-bg/strings.xml b/packages/OsuLogin/res/values-bg/strings.xml
new file mode 100644
index 0000000..ea3145d
--- /dev/null
+++ b/packages/OsuLogin/res/values-bg/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Онлайн регистрация"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Регистрацията не бе успешна"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-bn/strings.xml b/packages/OsuLogin/res/values-bn/strings.xml
new file mode 100644
index 0000000..c9f615e
--- /dev/null
+++ b/packages/OsuLogin/res/values-bn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"অনলাইনে সাইন-আপ করুন"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"সাইন-আপ করা যায়নি"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-bs/strings.xml b/packages/OsuLogin/res/values-bs/strings.xml
new file mode 100644
index 0000000..e9b9751
--- /dev/null
+++ b/packages/OsuLogin/res/values-bs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online registracija"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspjela"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ca/strings.xml b/packages/OsuLogin/res/values-ca/strings.xml
new file mode 100644
index 0000000..7d93096
--- /dev/null
+++ b/packages/OsuLogin/res/values-ca/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Registre en línia"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Ha fallat el registre"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-cs/strings.xml b/packages/OsuLogin/res/values-cs/strings.xml
new file mode 100644
index 0000000..b9cb794
--- /dev/null
+++ b/packages/OsuLogin/res/values-cs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online registrace"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registrace selhala"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-da/strings.xml b/packages/OsuLogin/res/values-da/strings.xml
new file mode 100644
index 0000000..68c93b7
--- /dev/null
+++ b/packages/OsuLogin/res/values-da/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online registrering"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registrering mislykkedes"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-de/strings.xml b/packages/OsuLogin/res/values-de/strings.xml
new file mode 100644
index 0000000..7e5a310
--- /dev/null
+++ b/packages/OsuLogin/res/values-de/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online-Registrierung"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registrierung fehlgeschlagen"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-el/strings.xml b/packages/OsuLogin/res/values-el/strings.xml
new file mode 100644
index 0000000..a58e481
--- /dev/null
+++ b/packages/OsuLogin/res/values-el/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Εγγραφή στο διαδίκτυο"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Αποτυχία εγγραφής"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-en-rAU/strings.xml b/packages/OsuLogin/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/packages/OsuLogin/res/values-en-rAU/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-en-rCA/strings.xml b/packages/OsuLogin/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/packages/OsuLogin/res/values-en-rCA/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-en-rGB/strings.xml b/packages/OsuLogin/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/packages/OsuLogin/res/values-en-rGB/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-en-rIN/strings.xml b/packages/OsuLogin/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/packages/OsuLogin/res/values-en-rIN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-en-rXC/strings.xml b/packages/OsuLogin/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..af7ff67
--- /dev/null
+++ b/packages/OsuLogin/res/values-en-rXC/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎OsuLogin‎‏‎‎‏‎"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎Online Sign Up‎‏‎‎‏‎"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎Sign-up failed‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-es-rUS/strings.xml b/packages/OsuLogin/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..144804c
--- /dev/null
+++ b/packages/OsuLogin/res/values-es-rUS/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Registrarse en línea"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Se produjo un error de registro"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-es/strings.xml b/packages/OsuLogin/res/values-es/strings.xml
new file mode 100644
index 0000000..3ad95cd
--- /dev/null
+++ b/packages/OsuLogin/res/values-es/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Registro online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Error al completar el registro"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-et/strings.xml b/packages/OsuLogin/res/values-et/strings.xml
new file mode 100644
index 0000000..94c5cea
--- /dev/null
+++ b/packages/OsuLogin/res/values-et/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Veebis registreerimine"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registreerimine ebaõnnestus"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-eu/strings.xml b/packages/OsuLogin/res/values-eu/strings.xml
new file mode 100644
index 0000000..30caa87
--- /dev/null
+++ b/packages/OsuLogin/res/values-eu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Sarean izen-ematea"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Ezin izan da eman izena"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-fa/strings.xml b/packages/OsuLogin/res/values-fa/strings.xml
new file mode 100644
index 0000000..3005203
--- /dev/null
+++ b/packages/OsuLogin/res/values-fa/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ثبت‌نام آنلاین"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ثبت‌نام انجام نشد"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-fi/strings.xml b/packages/OsuLogin/res/values-fi/strings.xml
new file mode 100644
index 0000000..24eac8a
--- /dev/null
+++ b/packages/OsuLogin/res/values-fi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Rekisteröidy verkossa"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Rekisteröityminen ei onnistunut"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-fr-rCA/strings.xml b/packages/OsuLogin/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..bcaa662
--- /dev/null
+++ b/packages/OsuLogin/res/values-fr-rCA/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Inscription en ligne"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Échec de l\'inscription"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-fr/strings.xml b/packages/OsuLogin/res/values-fr/strings.xml
new file mode 100644
index 0000000..bcaa662
--- /dev/null
+++ b/packages/OsuLogin/res/values-fr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Inscription en ligne"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Échec de l\'inscription"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-gl/strings.xml b/packages/OsuLogin/res/values-gl/strings.xml
new file mode 100644
index 0000000..5fc4444
--- /dev/null
+++ b/packages/OsuLogin/res/values-gl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Rexistro en liña"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Produciuse un erro co rexistro"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-gu/strings.xml b/packages/OsuLogin/res/values-gu/strings.xml
new file mode 100644
index 0000000..8449963
--- /dev/null
+++ b/packages/OsuLogin/res/values-gu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ઑનલાઇન સાઇન અપ કરો"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"સાઇન અપ નિષ્ફળ"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-hi/strings.xml b/packages/OsuLogin/res/values-hi/strings.xml
new file mode 100644
index 0000000..9e07438
--- /dev/null
+++ b/packages/OsuLogin/res/values-hi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ऑनलाइन साइन अप करें"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"साइन अप नहीं किया जा सका"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-hr/strings.xml b/packages/OsuLogin/res/values-hr/strings.xml
new file mode 100644
index 0000000..e9b9751
--- /dev/null
+++ b/packages/OsuLogin/res/values-hr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online registracija"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspjela"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-hu/strings.xml b/packages/OsuLogin/res/values-hu/strings.xml
new file mode 100644
index 0000000..cb0e036
--- /dev/null
+++ b/packages/OsuLogin/res/values-hu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online regisztráció"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"A regisztráció nem sikerült"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-hy/strings.xml b/packages/OsuLogin/res/values-hy/strings.xml
new file mode 100644
index 0000000..ae1c36a
--- /dev/null
+++ b/packages/OsuLogin/res/values-hy/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Առցանց գրանցում"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Չհաջողվեց գրանցվել"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-in/strings.xml b/packages/OsuLogin/res/values-in/strings.xml
new file mode 100644
index 0000000..6aaf694
--- /dev/null
+++ b/packages/OsuLogin/res/values-in/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Pendaftaran Online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Pendaftaran gagal"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-is/strings.xml b/packages/OsuLogin/res/values-is/strings.xml
new file mode 100644
index 0000000..f1ae520
--- /dev/null
+++ b/packages/OsuLogin/res/values-is/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Skráning á netinu"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Skráning mistókst"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-it/strings.xml b/packages/OsuLogin/res/values-it/strings.xml
new file mode 100644
index 0000000..fbff7b0
--- /dev/null
+++ b/packages/OsuLogin/res/values-it/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Registrazione online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registrazione non riuscita"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-iw/strings.xml b/packages/OsuLogin/res/values-iw/strings.xml
new file mode 100644
index 0000000..866ef88
--- /dev/null
+++ b/packages/OsuLogin/res/values-iw/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"הרשמה אונליין"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ההרשמה נכשלה"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ja/strings.xml b/packages/OsuLogin/res/values-ja/strings.xml
new file mode 100644
index 0000000..8a220d6
--- /dev/null
+++ b/packages/OsuLogin/res/values-ja/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"オンライン登録"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"登録できませんでした"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ka/strings.xml b/packages/OsuLogin/res/values-ka/strings.xml
new file mode 100644
index 0000000..bf08006
--- /dev/null
+++ b/packages/OsuLogin/res/values-ka/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ონლაინ რეგისტრაცია"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"რეგისტრაცია ვერ მოხერხდა"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-kk/strings.xml b/packages/OsuLogin/res/values-kk/strings.xml
new file mode 100644
index 0000000..8b87356
--- /dev/null
+++ b/packages/OsuLogin/res/values-kk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Онлайн тіркелу"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Тіркелмеді."</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-km/strings.xml b/packages/OsuLogin/res/values-km/strings.xml
new file mode 100644
index 0000000..f58ccc3
--- /dev/null
+++ b/packages/OsuLogin/res/values-km/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ការចុះឈ្មោះ​លើអ៊ីនធឺណិត"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ការចុះឈ្មោះ​មិនបានសម្រេច"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-kn/strings.xml b/packages/OsuLogin/res/values-kn/strings.xml
new file mode 100644
index 0000000..49a6562
--- /dev/null
+++ b/packages/OsuLogin/res/values-kn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ಆನ್‌ಲೈನ್ ಸೈನ್ ಅಪ್"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ಸೈನ್ ಅಪ್ ವಿಫಲವಾಗಿದೆ"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ko/strings.xml b/packages/OsuLogin/res/values-ko/strings.xml
new file mode 100644
index 0000000..e647ca0
--- /dev/null
+++ b/packages/OsuLogin/res/values-ko/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"온라인 가입"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"가입에 실패했습니다."</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ky/strings.xml b/packages/OsuLogin/res/values-ky/strings.xml
new file mode 100644
index 0000000..42da248
--- /dev/null
+++ b/packages/OsuLogin/res/values-ky/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Интернет аркылуу катталуу"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Катталган жоксуз"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-lo/strings.xml b/packages/OsuLogin/res/values-lo/strings.xml
new file mode 100644
index 0000000..9ff2241
--- /dev/null
+++ b/packages/OsuLogin/res/values-lo/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ສະໝັກອອນລາຍ"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ສະໝັກບໍ່ສຳເລັດ"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-lt/strings.xml b/packages/OsuLogin/res/values-lt/strings.xml
new file mode 100644
index 0000000..1a4c06e
--- /dev/null
+++ b/packages/OsuLogin/res/values-lt/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Internetinis prisiregistravimas"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Nepavyko prisiregistruoti"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-lv/strings.xml b/packages/OsuLogin/res/values-lv/strings.xml
new file mode 100644
index 0000000..11cdb97
--- /dev/null
+++ b/packages/OsuLogin/res/values-lv/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Reģistrācija tiešsaistē"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Reģistrācija neizdevās."</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-mk/strings.xml b/packages/OsuLogin/res/values-mk/strings.xml
new file mode 100644
index 0000000..de608e1
--- /dev/null
+++ b/packages/OsuLogin/res/values-mk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Онлајн регистрација"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Регистрацијата не успеа"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ml/strings.xml b/packages/OsuLogin/res/values-ml/strings.xml
new file mode 100644
index 0000000..8e797c8
--- /dev/null
+++ b/packages/OsuLogin/res/values-ml/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ഓൺലെെൻ സെെൻ അപ്പ്"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"സൈൻ അപ്പ് ചെയ്യാനായില്ല"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-mn/strings.xml b/packages/OsuLogin/res/values-mn/strings.xml
new file mode 100644
index 0000000..59d79d0
--- /dev/null
+++ b/packages/OsuLogin/res/values-mn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Онлайнаар бүртгүүлэх"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Бүртгүүлж чадсангүй"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-mr/strings.xml b/packages/OsuLogin/res/values-mr/strings.xml
new file mode 100644
index 0000000..15479a6
--- /dev/null
+++ b/packages/OsuLogin/res/values-mr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ऑनलाइन साइन अप करा"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"साइन-अप करता आले नाही"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ms/strings.xml b/packages/OsuLogin/res/values-ms/strings.xml
new file mode 100644
index 0000000..7e1cf95
--- /dev/null
+++ b/packages/OsuLogin/res/values-ms/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Pendaftaran Dalam Talian"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Pendaftaran gagal"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-my/strings.xml b/packages/OsuLogin/res/values-my/strings.xml
new file mode 100644
index 0000000..1bd992e
--- /dev/null
+++ b/packages/OsuLogin/res/values-my/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"အွန်လိုင်း အကောင့်ဖွင့်ရန်"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"အကောင့်ဖွင့်၍ မရပါ"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-nb/strings.xml b/packages/OsuLogin/res/values-nb/strings.xml
new file mode 100644
index 0000000..2e0c47a1
--- /dev/null
+++ b/packages/OsuLogin/res/values-nb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Registrering på nettet"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registreringen mislyktes"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ne/strings.xml b/packages/OsuLogin/res/values-ne/strings.xml
new file mode 100644
index 0000000..16bd92f
--- /dev/null
+++ b/packages/OsuLogin/res/values-ne/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"अनलाइन साइन अप"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"साइन अप गर्न सकिएन"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-nl/strings.xml b/packages/OsuLogin/res/values-nl/strings.xml
new file mode 100644
index 0000000..7cf8bd2
--- /dev/null
+++ b/packages/OsuLogin/res/values-nl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online aanmelding"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Aanmelding mislukt"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-or/strings.xml b/packages/OsuLogin/res/values-or/strings.xml
new file mode 100644
index 0000000..e0584d7
--- /dev/null
+++ b/packages/OsuLogin/res/values-or/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ଅନଲାଇନ୍ ସାଇନ୍ ଅପ୍ କରନ୍ତୁ"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ସାଇନ୍ ଅପ୍ ବିଫଳ ହୋଇଛି"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-pa/strings.xml b/packages/OsuLogin/res/values-pa/strings.xml
new file mode 100644
index 0000000..7e47d0e
--- /dev/null
+++ b/packages/OsuLogin/res/values-pa/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ਆਨਲਾਈਨ ਸਾਈਨ-ਅੱਪ ਕਰੋ"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ਸਾਈਨ-ਅੱਪ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-pl/strings.xml b/packages/OsuLogin/res/values-pl/strings.xml
new file mode 100644
index 0000000..c0722ab
--- /dev/null
+++ b/packages/OsuLogin/res/values-pl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Rejestracja online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Nie udało się zarejestrować"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-pt-rBR/strings.xml b/packages/OsuLogin/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..c9fe377
--- /dev/null
+++ b/packages/OsuLogin/res/values-pt-rBR/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Inscrição on-line"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-pt-rPT/strings.xml b/packages/OsuLogin/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..0059281
--- /dev/null
+++ b/packages/OsuLogin/res/values-pt-rPT/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Inscrição online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição."</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-pt/strings.xml b/packages/OsuLogin/res/values-pt/strings.xml
new file mode 100644
index 0000000..c9fe377
--- /dev/null
+++ b/packages/OsuLogin/res/values-pt/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Inscrição on-line"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ro/strings.xml b/packages/OsuLogin/res/values-ro/strings.xml
new file mode 100644
index 0000000..eead127
--- /dev/null
+++ b/packages/OsuLogin/res/values-ro/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Înscriere online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Nu s-a înscris"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ru/strings.xml b/packages/OsuLogin/res/values-ru/strings.xml
new file mode 100644
index 0000000..a271ef7
--- /dev/null
+++ b/packages/OsuLogin/res/values-ru/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Регистрация в Интернете"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Не удалось зарегистрироваться."</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-si/strings.xml b/packages/OsuLogin/res/values-si/strings.xml
new file mode 100644
index 0000000..52e5979
--- /dev/null
+++ b/packages/OsuLogin/res/values-si/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"සබැඳි ලියාපදිංචිය"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ලියාපදිංචිය අසාර්ථක විය"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-sk/strings.xml b/packages/OsuLogin/res/values-sk/strings.xml
new file mode 100644
index 0000000..f6b9f70
--- /dev/null
+++ b/packages/OsuLogin/res/values-sk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online registrácia"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registrácia zlyhala"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-sl/strings.xml b/packages/OsuLogin/res/values-sl/strings.xml
new file mode 100644
index 0000000..6e6b95c
--- /dev/null
+++ b/packages/OsuLogin/res/values-sl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Spletna registracija"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registracija ni uspela"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-sq/strings.xml b/packages/OsuLogin/res/values-sq/strings.xml
new file mode 100644
index 0000000..f67a238
--- /dev/null
+++ b/packages/OsuLogin/res/values-sq/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Regjistrimi në linjë"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Regjistrimi dështoi"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-sr/strings.xml b/packages/OsuLogin/res/values-sr/strings.xml
new file mode 100644
index 0000000..14e0828
--- /dev/null
+++ b/packages/OsuLogin/res/values-sr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Онлајн регистрација"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Регистрација није успела"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-sv/strings.xml b/packages/OsuLogin/res/values-sv/strings.xml
new file mode 100644
index 0000000..ea5fdfd
--- /dev/null
+++ b/packages/OsuLogin/res/values-sv/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Registrering online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registreringen misslyckades"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-sw/strings.xml b/packages/OsuLogin/res/values-sw/strings.xml
new file mode 100644
index 0000000..c20a402
--- /dev/null
+++ b/packages/OsuLogin/res/values-sw/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Kujisajili Mtandaoni"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Imeshindwa kukusajili"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ta/strings.xml b/packages/OsuLogin/res/values-ta/strings.xml
new file mode 100644
index 0000000..e2eb567
--- /dev/null
+++ b/packages/OsuLogin/res/values-ta/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ஆன்லைனில் பதிவு செய்"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"பதிவு செய்ய முடியவில்லை"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-te/strings.xml b/packages/OsuLogin/res/values-te/strings.xml
new file mode 100644
index 0000000..56b0b44
--- /dev/null
+++ b/packages/OsuLogin/res/values-te/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"ఆన్‌లైన్ సైన్ అప్"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"సైన్-అప్ విఫలమయ్యింది"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-th/strings.xml b/packages/OsuLogin/res/values-th/strings.xml
new file mode 100644
index 0000000..552dca2
--- /dev/null
+++ b/packages/OsuLogin/res/values-th/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"การลงชื่อสมัครใช้ออนไลน์"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"ลงชื่อสมัครใช้ไม่สำเร็จ"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-tl/strings.xml b/packages/OsuLogin/res/values-tl/strings.xml
new file mode 100644
index 0000000..ba89e96
--- /dev/null
+++ b/packages/OsuLogin/res/values-tl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Pag-sign Up Online"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Hindi nakapag-sign up"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-tr/strings.xml b/packages/OsuLogin/res/values-tr/strings.xml
new file mode 100644
index 0000000..1d927fe
--- /dev/null
+++ b/packages/OsuLogin/res/values-tr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Online Kaydolma"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Kaydolma işlemi başarısız oldu"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-uk/strings.xml b/packages/OsuLogin/res/values-uk/strings.xml
new file mode 100644
index 0000000..6e60ff0
--- /dev/null
+++ b/packages/OsuLogin/res/values-uk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Онлайн-реєстрація"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Не вдалося зареєструватись"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-ur/strings.xml b/packages/OsuLogin/res/values-ur/strings.xml
new file mode 100644
index 0000000..eed7686
--- /dev/null
+++ b/packages/OsuLogin/res/values-ur/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"آن لائن سائن اپ کریں"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"سائن اپ ناکام ہو گیا"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-uz/strings.xml b/packages/OsuLogin/res/values-uz/strings.xml
new file mode 100644
index 0000000..152d129
--- /dev/null
+++ b/packages/OsuLogin/res/values-uz/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Onlayn registratsiya"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Registratsiya qilinmadi"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-vi/strings.xml b/packages/OsuLogin/res/values-vi/strings.xml
new file mode 100644
index 0000000..84558076
--- /dev/null
+++ b/packages/OsuLogin/res/values-vi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Đăng ký trực tuyến"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Không đăng ký được"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-zh-rCN/strings.xml b/packages/OsuLogin/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..7f13647
--- /dev/null
+++ b/packages/OsuLogin/res/values-zh-rCN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"在线注册"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"注册失败"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-zh-rHK/strings.xml b/packages/OsuLogin/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..8731791
--- /dev/null
+++ b/packages/OsuLogin/res/values-zh-rHK/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"網上申請"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"無法申請"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-zh-rTW/strings.xml b/packages/OsuLogin/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..79208c8
--- /dev/null
+++ b/packages/OsuLogin/res/values-zh-rTW/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"線上註冊"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"註冊失敗"</string>
+</resources>
diff --git a/packages/OsuLogin/res/values-zu/strings.xml b/packages/OsuLogin/res/values-zu/strings.xml
new file mode 100644
index 0000000..27ac6bb
--- /dev/null
+++ b/packages/OsuLogin/res/values-zu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="8288271429327488421">"I-OsuLogin"</string>
+    <string name="action_bar_label" msgid="550995560341508693">"Ukubhalisa Okuku-inthanethi"</string>
+    <string name="sign_up_failed" msgid="837216244603867568">"Ukubhalisa kuhlulekile"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 1681fdb..126efcc 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -206,11 +206,11 @@
     <string name="enable_adb" msgid="8072776357237289039">"የUSB አራሚ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB ሲያያዝ የአርም ሁኔታ"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"የዩ ኤስ ቢ ስህተት ማረም ፈቀዳዎችን ይሻሩ"</string>
-    <string name="enable_adb_wireless" msgid="6973226350963971018">"ገመድ-አልባ ማረም"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ገመድ-አልባ debugging"</string>
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi ሲገናኝ የማረም ሁነታ"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"ስህተት"</string>
-    <string name="adb_wireless_settings" msgid="2295017847215680229">"ገመድ-አልባ ማረም"</string>
-    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"የሚገኙ መሣሪያዎችን ለመመልከትና ለመጠቀም ገመድ-አልባ ማረምን ያብሩ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ገመድ-አልባ debugging"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"የሚገኙ መሣሪያዎችን ለመመልከትና ለመጠቀም ገመድ-አልባ debuggingን ያብሩ"</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"የQR ኮድን በመጠቀም መሣሪያን ያጣምሩ"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"የQR ኮድ መቃኛን በመጠቀም አዲስ መሣሪያዎችን ያጣምሩ"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"የማጣመሪያ ኮድን በመጠቀም መሣሪያን ያጣምሩ"</string>
@@ -300,8 +300,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"የሃርድዌር ማቀላጠፊያን ማስተሳሰርን የሚገኝ ከሆነ ይጠቀሙ"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"የUSB ማረሚያ ይፈቀድ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"የUSB አድስ ለግንባታ አላማ ብቻ የታሰበ ነው። ከኮምፒዩተርህ ወደ መሳሪያህ ውሂብ ለመገልበጥ፣ መሣሪያህ ላይ ያለ ማሳወቂያ መተግበሪያዎችን መጫን፣ እና ማስታወሻ ውሂብ ማንበብ ለመጠቀም ይቻላል።"</string>
-    <string name="adbwifi_warning_title" msgid="727104571653031865">"ገመድ-አልባ ማረም ይፈቀድ?"</string>
-    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ገመድ-አልባ ማረም ለግንባታ አላማዎች ብቻ የታሰበ ነው። ውሂብን ከኮምፒዩተርዎ ወደ መሳሪያዎ ለመቅዳት፣ መሣሪያዎ ላይ ያለማሳወቂያ መተግበሪያዎችን ለመጫን እና የምዝግብ ማስታወሻ ውሂብን ለማንበብ ይጠቀሙበት።"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ገመድ-አልባ debugging ይፈቀድ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ገመድ-አልባ debugging ለግንባታ አላማዎች ብቻ የታሰበ ነው። ውሂብን ከኮምፒዩተርዎ ወደ መሳሪያዎ ለመቅዳት፣ መሣሪያዎ ላይ ያለማሳወቂያ መተግበሪያዎችን ለመጫን እና የምዝግብ ማስታወሻ ውሂብን ለማንበብ ይጠቀሙበት።"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"የዩ ኤስ ቢ ማረም መዳረሻ ከዚህ ቀደም ፍቃድ ከሰጧቸው ኮምፒውተሮች ላይ ይሻሩ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"የግንባታ ቅንብሮችን ፍቀድ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"እነዚህ ቅንብሮች  የታሰቡት ለግንባታ አጠቃቀም ብቻ ናቸው። መሳሪያህን እና በሱ ላይ ያሉትን መተግበሪያዎች እንዲበለሹ ወይም በትክክል እንዳይሰሩ ሊያደርጉ ይችላሉ።"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index abd1e03..88d4c03 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -232,8 +232,7 @@
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏عنوان IP والمنفذ"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"المسح الضوئي لرمز الاستجابة السريعة"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"‏إقران الجهاز من خلال شبكة Wi‑Fi عن طريق المسح الضوئي لرمز استجابة سريعة"</string>
-    <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
-    <skip />
+    <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"‏يُرجى الاتصال بشبكة Wi-Fi."</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"‏adb، تصحيح الأخطاء، مطور برامج"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"اختصار تقرير الأخطاء"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"عرض زر في قائمة خيارات التشغيل لإعداد تقرير بالأخطاء"</string>
@@ -432,8 +431,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g>."</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"حتى <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
-    <skip />
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"قد ينفد شحن البطارية قبل <xliff:g id="TIME">%1$s</xliff:g>."</string>
     <string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
@@ -515,32 +513,21 @@
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"مكبر صوت الهاتف"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
-    <!-- no translation found for help_label (3528360748637781274) -->
-    <skip />
-    <!-- no translation found for storage_category (2287342585424631813) -->
-    <skip />
-    <!-- no translation found for shared_data_title (1017034836800864953) -->
-    <skip />
-    <!-- no translation found for shared_data_summary (5516326713822885652) -->
-    <skip />
+    <string name="help_label" msgid="3528360748637781274">"المساعدة والتعليقات"</string>
+    <string name="storage_category" msgid="2287342585424631813">"مساحة التخزين"</string>
+    <string name="shared_data_title" msgid="1017034836800864953">"البيانات المشتركة"</string>
+    <string name="shared_data_summary" msgid="5516326713822885652">"عرض البيانات المشتركة وتعديلها"</string>
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ما مِن بيانات مشتركة لهذا المستخدم."</string>
     <string name="shared_data_query_failure_text" msgid="3489828881998773687">"حدث خطأ أثناء جلب البيانات المشتركة. يُرجى إعادة المحاولة."</string>
-    <!-- no translation found for blob_id_text (8680078988996308061) -->
-    <skip />
-    <!-- no translation found for blob_expires_text (7882727111491739331) -->
-    <skip />
+    <string name="blob_id_text" msgid="8680078988996308061">"معرّف البيانات المشتركة: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+    <string name="blob_expires_text" msgid="7882727111491739331">"تنتهي صلاحيتها في <xliff:g id="DATE">%s</xliff:g>."</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"حدث خطأ أثناء حذف البيانات المشتركة."</string>
     <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"ما مِن عمليات تأجير مطلوبة لهذه المعلومات المشتركة. هل تريد حذفها؟"</string>
-    <!-- no translation found for accessor_info_title (8289823651512477787) -->
-    <skip />
-    <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
-    <skip />
-    <!-- no translation found for accessor_expires_text (4625619273236786252) -->
-    <skip />
-    <!-- no translation found for delete_blob_text (2819192607255625697) -->
-    <skip />
-    <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
-    <skip />
+    <string name="accessor_info_title" msgid="8289823651512477787">"التطبيقات التي تشارك البيانات"</string>
+    <string name="accessor_no_description_text" msgid="7510967452505591456">"لم يوفّر التطبيق وصفًا."</string>
+    <string name="accessor_expires_text" msgid="4625619273236786252">"تنتهي صلاحية العقد في <xliff:g id="DATE">%s</xliff:g>."</string>
+    <string name="delete_blob_text" msgid="2819192607255625697">"حذف البيانات المشتركة"</string>
+    <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"هل فعلاً تريد حذف هذه البيانات المشتركة؟"</string>
     <string name="user_add_user_item_summary" msgid="5748424612724703400">"المستخدمون لديهم تطبيقات ومحتوى خاص بهم"</string>
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"يمكنك تقييد الدخول إلى التطبيقات والمحتوى من حسابك"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"المستخدم"</string>
@@ -560,12 +547,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"معلومات الملف الشخصي"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"قبل أن تتمكن من إنشاء ملف شخصي مقيد، يلزمك إعداد تأمين للشاشة لحماية تطبيقاتك وبياناتك الشخصية."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"تعيين التأمين"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"التبديل إلى <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"إضافة ضيف"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"إزالة جلسة الضيف"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ضيف"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index a1c00a3..73a5e7c 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"প্ৰ\'ফাইলৰ তথ্য"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ\'ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপবিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীণ লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>লৈ সলনি কৰক"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 50451e1..4cb4017 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profil info"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Məhdudlaşdırılmış profil yaratmadan öncə, Siz tətbiqlərinizi və şəxsi datanızı qorumaq üçün ekran kilidi quraşdırmalısınız."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Kilid ayarlayın"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> adlı istifadəçiyə keçin"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Qonağı silin"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Qonaq"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 0e39d7f..839b85a 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -544,12 +544,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Podaci o profilu"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Da biste mogli da napravite ograničeni profil, treba da podesite zaključavanje ekrana da biste zaštitili aplikacije i lične podatke."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Podesi zaključavanje"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Pređi na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 328762c..cc0d286 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Звесткi профiлю"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Перш чым вы зможаце стварыць профіль з абмежаваннямi, вам трэба наладзіць блакiроўку экрана для абароны сваiх дадаткаў і асабістай інфармацыі."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Усталёўка блакiроўкi"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Пераключыцца на карыстальніка <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Дадаць госця"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Выдаліць госця"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Госць"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 690cc49..ef0951c 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Инф. за потр. профил"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Преди да можете да създадете потребителски профил с ограничена функционалност, трябва да настроите заключения екран, за да защитите приложенията и личните си данни."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Задаване на заключване"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Превключване към <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Добавяне на гост"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Премахване на госта"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 017936f..1cd8eea 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"প্রোফাইল তথ্য"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"আপনি একটি সীমাবদ্ধযুক্ত প্রোফাইল তৈরি করার আগে, আপনাকে আপনার অ্যাপ্লিকেশন এবং ব্যক্তিগত ডেটা সুরক্ষিত করার জন্য একটি স্ক্রিন লক সেট-আপ করতে হবে।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"লক সেট করুন"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-এ পাল্টান"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি সরান"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index a1b1afc..c72411c 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -544,8 +544,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Podaci o profilu"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Prije nego vam se omogući kreiranje ograničenog profila, morate postaviti zaključavanje ekrana da biste zaštitili svoje aplikacije i lične podatke."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Postaviti zaključavanje"</string>
-    <string name="user_switch_to_user" msgid="6975428297154968543">"Prelazak na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
-    <string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string>
-    <string name="guest_exit_guest" msgid="5908239569510734136">"Uklanjanje gosta"</string>
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Prebaci na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index a1b2da8..765d442 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informació de perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Per crear un perfil restringit, has de configurar una pantalla de bloqueig per protegir les aplicacions i les dades personals."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Defineix un bloqueig"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Canvia a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Suprimeix el convidat"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Convidat"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index bbf29bb..ed2db3a 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informace o profilu"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Před vytvořením omezeného profilu je nutné nejprve nastavit zámek obrazovky k ochraně aplikací a dat."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavit zámek"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Přepnout na uživatele <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Odstranit hosta"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Host"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 20b7ae1..f682b15 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profiloplysninger"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan oprette en begrænset profil, skal du oprette en skærmlås for at beskytte dine apps og personlige data."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurer låseskærmen"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Skift til <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Tilføj gæsten"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gæsten"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gæst"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 1a28985..7918022 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profilinformationen"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Vor dem Erstellen eines eingeschränkten Profils musst du eine Displaysperre einrichten, um deine Apps und personenbezogenen Daten zu schützen."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Sperre einrichten"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Zu <xliff:g id="USER_NAME">%s</xliff:g> wechseln"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Gast hinzufügen"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Gast entfernen"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 9c1842a..b4d7c87 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Πληροφορίες προφίλ"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Προκειμένου να μπορέσετε να δημιουργήσετε ένα περιορισμένο προφίλ, θα πρέπει να δημιουργήσετε ένα κλείδωμα οθόνης για την προστασία των εφαρμογών και των προσωπικών δεδομένων σας."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Ορισμός κλειδώματος"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Εναλλαγή σε <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Κατάργηση επισκέπτη"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Επισκέπτης"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index cc3cd11..6cb975f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Datos del perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar un bloqueo de pantalla que proteja tus aplicaciones y datos personales."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Configurar bloqueo"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Agregar invitado"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index e85187b..d777723 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Información del perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar una pantalla de bloqueo que proteja tus aplicaciones y datos personales."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Añadir invitado"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index c9bd7a0..1fa4159 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profiili teave"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Enne piiratud profiili loomist peate seadistama lukustusekraani, et oma rakendusi ja isiklikke andmeid kaitsta."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Määra lukk"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Lülita kasutajale <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Külaline"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 42c702a..2700162 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -235,7 +235,7 @@
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Konektatu wifi-sare batera"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, araztu, gailua"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Akatsen txostenerako lasterbidea"</string>
-    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Bateriaren menuan, erakutsi akatsen txostena sortzeko botoia"</string>
+    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Pizteko menuan, erakutsi akatsen txostena sortzeko botoia"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Mantendu aktibo"</string>
     <string name="keep_screen_on_summary" msgid="1510731514101925829">"Pantaila ez da ezarriko inoiz inaktibo kargatu bitartean"</string>
     <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Gaitu Bluetooth HCI miatze-erregistroa"</string>
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profileko informazioa"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Profil murriztua sortu aurretik, aplikazioak eta datu pertsonalak babesteko, pantaila blokeatzeko metodo bat konfiguratu beharko duzu."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Ezarri blokeoa"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Aldatu <xliff:g id="USER_NAME">%s</xliff:g> erabiltzailera"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatua"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gonbidatua"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 2a284ee..1c32926 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"اطلاعات نمایه"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"قبل از ایجاد یک نمایه محدود، باید یک قفل صفحه را برای محافظت از برنامه‌ها و داده‌های شخصی خود تنظیم کنید."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"تنظیم قفل"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"رفتن به <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"افزودن مهمان"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"حذف مهمان"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"مهمان"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 76e8f5b..765e08e 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profiilin tiedot"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Ennen kuin voit luoda rajoitetun profiilin, määritä näytön lukitus, joka suojelee sovelluksiasi ja henkilökohtaisia tietojasi."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Aseta lukitus"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Vaihda tähän: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 4c599f0..d118e1f 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informations de profil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 8e8f09d..f2dcbba 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informations de profil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index e17da89..9ee490f 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Información do perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restrinxido, precisarás configurar un bloqueo da pantalla para protexer as túas aplicacións e datos persoais."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Quitar convidado"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 207e07f..2fced2b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"પ્રોફાઇલ માહિતી"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"તમે પ્રતિબંધિત પ્રોફાઇલ બનાવી શકો તે પહેલાં, તમારે તમારી ઍપ્લિકેશનો અને વ્યક્તિગત ડેટાની સુરક્ષા માટે એક લૉક સ્ક્રીન સેટ કરવાની જરૂર પડશે."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"લૉક સેટ કરો"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> પર સ્વિચ કરો"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"અતિથિને કાઢી નાખો"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"અતિથિ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 0c95313..cb41100 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -514,7 +514,7 @@
     <string name="shared_data_title" msgid="1017034836800864953">"शेयर किया गया डेटा"</string>
     <string name="shared_data_summary" msgid="5516326713822885652">"शेयर किए गए डेटा को देखें और उसमें बदलाव करें"</string>
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"इस उपयोगकर्ता के साथ किसी तरह का डेटा शेयर नहीं किया गया है."</string>
-    <string name="shared_data_query_failure_text" msgid="3489828881998773687">"शेयर किए गए इस डेटा को लाने में कोई गड़बड़ी हुई है. फिर से कोशिश करें."</string>
+    <string name="shared_data_query_failure_text" msgid="3489828881998773687">"शेयर किए गए डेटा को लाने में कोई गड़बड़ी हुई है. फिर से कोशिश करें."</string>
     <string name="blob_id_text" msgid="8680078988996308061">"शेयर किए गए डेटा का आईडी: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
     <string name="blob_expires_text" msgid="7882727111491739331">"डेटा का ऐक्सेस <xliff:g id="DATE">%s</xliff:g> को खत्म हो जाएगा"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"शेयर किए गए डेटा को मिटाने में कोई गड़बड़ी हुई."</string>
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफ़ाइल की जानकारी"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"इससे पहले कि आप कोई प्रतिबंधित प्रोफ़ाइल बनाएं, आपको अपने ऐप्लिकेशन  और व्यक्तिगत डेटा की सुरक्षा करने के लिए एक स्क्रीन लॉक सेट करना होगा."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करें"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> पर जाएं"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान हटाएं"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"मेहमान"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index d0fff21..bb2f17c 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profiladatok"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Mielőtt létrehozhatna egy korlátozott profilt, be kell állítania egy képernyőzárat, hogy megvédje alkalmazásait és személyes adatait."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Képernyőzár beállítása"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Váltás erre: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Vendég munkamenet eltávolítása"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Vendég"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a884c84..9cc883a 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Պրոֆիլի տեղեկություններ"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Նախքան դուք կկարողանաք ստեղծել սահմանափակ պրոֆիլ, դուք պետք է կարգավորեք էկրանի կողպումը` ձեր ծրագրերը և անձնական տվյալները պաշտպանելու համար:"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Կարգավորել կողպումը"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Անցնել <xliff:g id="USER_NAME">%s</xliff:g> պրոֆիլին"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Ավելացնել հյուր"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Հեռացնել հյուրին"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Հյուր"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 4022bab..d80eba2 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -88,7 +88,7 @@
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"Berbagi kontak"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"Gunakan untuk berbagi kontak"</string>
-    <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Berbagi sambungan internet"</string>
+    <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Berbagi koneksi internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
@@ -103,7 +103,7 @@
     <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Tidak tersambung kepada server transfer file"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"Terhubung ke perangkat masukan"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Terhubung ke perangkat untuk akses internet"</string>
-    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Berbagi sambungan internet lokal dengan perangkat"</string>
+    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Berbagi koneksi internet lokal dengan perangkat"</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="7422039765025340313">"Digunakan untuk akses internet"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="4453622103977592583">"Gunakan untuk peta"</string>
     <string name="bluetooth_sap_profile_summary_use_for" msgid="6204902866176714046">"Gunakan untuk akses SIM"</string>
@@ -169,11 +169,11 @@
     <string name="tts_install_data_title" msgid="1829942496472751703">"Instal data suara"</string>
     <string name="tts_install_data_summary" msgid="3608874324992243851">"Instal data suara yang dibutuhkan untuk sintesis suara"</string>
     <string name="tts_engine_security_warning" msgid="3372432853837988146">"Mesin sintesis suara ini mungkin dapat mengumpulkan semua teks yang akan diucapkan, termasuk di antaranya data pribadi seperti sandi dan nomor kartu kredit. Berasal dari <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> aplikasi. Gunakan metode masukan ini?"</string>
-    <string name="tts_engine_network_required" msgid="8722087649733906851">"Bahasa ini perlu sambungan jaringan yang bekerja untuk keluaran text-to-speech."</string>
+    <string name="tts_engine_network_required" msgid="8722087649733906851">"Bahasa ini perlu koneksi jaringan yang bekerja untuk keluaran text-to-speech."</string>
     <string name="tts_default_sample_string" msgid="6388016028292967973">"Ini adalah contoh sintesis suara"</string>
     <string name="tts_status_title" msgid="8190784181389278640">"Status bahasa default"</string>
     <string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> didukung sepenuhnya"</string>
-    <string name="tts_status_requires_network" msgid="8327617638884678896">"<xliff:g id="LOCALE">%1$s</xliff:g> membutuhkan sambungan jaringan"</string>
+    <string name="tts_status_requires_network" msgid="8327617638884678896">"<xliff:g id="LOCALE">%1$s</xliff:g> membutuhkan koneksi jaringan"</string>
     <string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> tidak didukung"</string>
     <string name="tts_status_checking" msgid="8026559918948285013">"Memeriksa…"</string>
     <string name="tts_engine_settings_title" msgid="7849477533103566291">"Setelan untuk <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
@@ -514,11 +514,11 @@
     <string name="shared_data_title" msgid="1017034836800864953">"Data bersama"</string>
     <string name="shared_data_summary" msgid="5516326713822885652">"Lihat dan ubah data bersama"</string>
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Tidak ada data yang dibagikan untuk pengguna ini."</string>
-    <string name="shared_data_query_failure_text" msgid="3489828881998773687">"Terjadi kesalahan saat mengambil data yang dibagikan. Coba lagi."</string>
+    <string name="shared_data_query_failure_text" msgid="3489828881998773687">"Terjadi error saat mengambil data yang dibagikan. Coba lagi."</string>
     <string name="blob_id_text" msgid="8680078988996308061">"ID data bersama: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
     <string name="blob_expires_text" msgid="7882727111491739331">"Berlaku sampai <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"Terjadi error saat menghapus data yang dibagikan."</string>
-    <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"Tidak ada sewa yang diperoleh dari data yang dibagikan. Apakah Anda ingin menghapusnya?"</string>
+    <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"Tidak ada lease yang diperoleh dari data yang dibagikan ini. Apakah Anda ingin menghapusnya?"</string>
     <string name="accessor_info_title" msgid="8289823651512477787">"Aplikasi yang berbagi data"</string>
     <string name="accessor_no_description_text" msgid="7510967452505591456">"Tidak ada deskripsi yang disediakan oleh aplikasi."</string>
     <string name="accessor_expires_text" msgid="4625619273236786252">"Lease akan berakhir pada <xliff:g id="DATE">%s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 437e826..2e96446 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Upplýsingar um snið"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Áður en þú getur búið til takmarkað snið þarftu að setja upp skjálás til að vernda forritin þín og persónuleg gögn."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Velja lás"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Skipta yfir í <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Fjarlægja gest"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gestur"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 86374f4..61f35ab 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"פרטי פרופיל"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"לפני שתוכל ליצור פרופיל מוגבל, תצטרך להגדיר נעילת מסך כדי להגן על האפליקציות ועל הנתונים האישיים שלך."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"הגדרת נעילה"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"מעבר אל <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"אורח"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index ba8418b..ea9cfd8 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"プロファイル情報"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"制限付きプロファイルを作成する場合は、アプリや個人データを保護するように画面ロックを設定しておく必要があります。"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"ロックを設定"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> に切り替え"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"ゲストを追加"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"ゲストを削除"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ゲスト"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index da5ff9b..106bc18 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ინფორმაცია პროფილზე"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"შეზღუდული პროფილის შექმნამდე, საკუთარი აპლიკაციებისა და პირადი მონაცემების დასაცავად, უნდა დაბლოკოთ ეკრანი."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"საკეტის დაყენება"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-ზე გადართვა"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"სტუმრის დამატება"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"სტუმრის ამოშლა"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"სტუმარი"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index e74f52b..0ef83bb 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Профильдік ақпарат"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Шектелген профайл жасақтауға дейін қолданбалар мен жеке деректерді қорғау үшін экран бекітпесін тағайындау қажет."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Бекітпе тағайындау"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> атты пайдаланушыға ауысу"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Қонақты енгізу"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты өшіру"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index c51f9a6..4cf8bed 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -518,7 +518,7 @@
     <string name="blob_id_text" msgid="8680078988996308061">"លេខសម្គាល់​ទិន្នន័យ​ដែលបាន​ចែករំលែក៖ <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
     <string name="blob_expires_text" msgid="7882727111491739331">"ផុតកំណត់​នៅថ្ងៃទី <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"មានបញ្ហា​ក្នុងការលុប​ទិន្នន័យ​ដែលបានចែករំលែក។"</string>
-    <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"មិនមានការជួល​ដែលបានទទួល​សម្រាប់​ទិន្នន័យដែលបានចែករំលែក​នេះទេ។ តើអ្នកចង់​លុបទិន្នន័យ​នេះដែរទេ?"</string>
+    <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"មិនមានភតិសន្យា​ដែលបានទទួល​សម្រាប់​ទិន្នន័យដែលបានចែករំលែក​នេះទេ។ តើអ្នកចង់​លុបទិន្នន័យ​នេះដែរទេ?"</string>
     <string name="accessor_info_title" msgid="8289823651512477787">"កម្មវិធី​ដែលកំពុង​ចែករំលែក​ទិន្នន័យ"</string>
     <string name="accessor_no_description_text" msgid="7510967452505591456">"គ្មាន​ការពណ៌នា​ដែលផ្ដល់ដោយ​កម្មវិធីទេ។"</string>
     <string name="accessor_expires_text" msgid="4625619273236786252">"ភតិសន្យា​ផុតកំណត់​នៅថ្ងៃទី <xliff:g id="DATE">%s</xliff:g>"</string>
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ព័ត៌មាន​ប្រវត្តិរូប"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"មុន​ពេល​អ្នក​អាច​បង្កើត​ប្រវត្តិ​រូប​បាន​ដាក់​កម្រិត អ្នក​ត្រូវ​រៀបចំ​ការ​ចាក់​សោ​អេក្រង់ ដើម្បី​ការពារ​កម្មវិធី និង​ទិន្នន័យ​ផ្ទាល់ខ្លួន​របស់​អ្នក។"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"កំណត់​ការ​ចាក់​សោ"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"ប្ដូរទៅ <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូល​ភ្ញៀវ"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"លុប​​​ភ្ញៀវ"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ភ្ញៀវ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 9e37fbc..ed854ac 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -232,8 +232,7 @@
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ವಿಳಾಸ ಮತ್ತು ಪೋರ್ಟ್"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡುವ ಮೂಲಕ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
-    <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
-    <skip />
+    <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ಡೀಬಗ್, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ದೋಷ ವರದಿಯ ಶಾರ್ಟ್‌ಕಟ್‌‌"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ದೋಷ ವರದಿ ಮಾಡಲು ಪವರ್ ಮೆನುನಲ್ಲಿ ಬಟನ್ ತೋರಿಸು"</string>
@@ -432,8 +431,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ಸಮಯದವರೆಗೆ ಫೋನ್‌ ರನ್‌ ಆಗಬೇಕು"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"<xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ಫೋನ್‌ ರನ್‌ ಆಗಬೇಕು"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> ರವರೆಗೆ"</string>
-    <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
-    <skip />
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> ಗಳಲ್ಲಿ ಬ್ಯಾಟರಿ ಮುಕ್ತಾಯವಾಗಬಹುದು"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ನಿಮಿಷಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ"</string>
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ (<xliff:g id="LEVEL">%2$s</xliff:g>) ಬಾಕಿ"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು (<xliff:g id="LEVEL">%2$s</xliff:g>) ಬಾಕಿ"</string>
@@ -511,32 +509,21 @@
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ಫೋನ್ ಸ್ಪೀಕರ್"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
-    <!-- no translation found for help_label (3528360748637781274) -->
-    <skip />
-    <!-- no translation found for storage_category (2287342585424631813) -->
-    <skip />
-    <!-- no translation found for shared_data_title (1017034836800864953) -->
-    <skip />
-    <!-- no translation found for shared_data_summary (5516326713822885652) -->
-    <skip />
+    <string name="help_label" msgid="3528360748637781274">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
+    <string name="storage_category" msgid="2287342585424631813">"ಸಂಗ್ರಹಣೆ"</string>
+    <string name="shared_data_title" msgid="1017034836800864953">"ಹಂಚಿಕೊಳ್ಳಲಾದ ಡೇಟಾ"</string>
+    <string name="shared_data_summary" msgid="5516326713822885652">"ಹಂಚಿಕೊಳ್ಳಲಾದ ಡೇಟಾವನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ಈ ಬಳಕೆದಾರರಿಗೆ ಯಾವುದೇ ಹಂಚಿದ ಡೇಟಾ ಇಲ್ಲ."</string>
     <string name="shared_data_query_failure_text" msgid="3489828881998773687">"ಹಂಚಿದ ಡೇಟಾವನ್ನು ಪಡೆಯುವಲ್ಲಿ ದೋಷ ಕಂಡುಬಂದಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <!-- no translation found for blob_id_text (8680078988996308061) -->
-    <skip />
-    <!-- no translation found for blob_expires_text (7882727111491739331) -->
-    <skip />
+    <string name="blob_id_text" msgid="8680078988996308061">"ಹಂಚಿಕೊಳ್ಳಲಾದ ಡೇಟಾ ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+    <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g> ರಂದು ಅವಧಿ ಮುಕ್ತಾಯವಾಗಲಿದೆ"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"ಹಂಚಿದ ಡೇಟಾವನ್ನು ಅಳಿಸುವಾಗ ದೋಷ ಕಂಡುಬಂದಿದೆ."</string>
     <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"ಈ ಹಂಚಿದ ಡೇಟಾವನ್ನು ಗುತ್ತಿಗೆಗೆ ಪಡೆದಿಲ್ಲ. ನೀವು ಅದನ್ನು ಅಳಿಸಲು ಬಯಸುವಿರಾ?"</string>
-    <!-- no translation found for accessor_info_title (8289823651512477787) -->
-    <skip />
-    <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
-    <skip />
-    <!-- no translation found for accessor_expires_text (4625619273236786252) -->
-    <skip />
-    <!-- no translation found for delete_blob_text (2819192607255625697) -->
-    <skip />
-    <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
-    <skip />
+    <string name="accessor_info_title" msgid="8289823651512477787">"ಹಂಚಿಕೊಂಡ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸುವ ಆ್ಯಪ್‌ಗಳು"</string>
+    <string name="accessor_no_description_text" msgid="7510967452505591456">"ಆ್ಯಪ್‌ನಿಂದ ಯಾವುದೇ ವಿವರಣೆಯನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ."</string>
+    <string name="accessor_expires_text" msgid="4625619273236786252">"<xliff:g id="DATE">%s</xliff:g> ರಂದು ಗುತ್ತಿಗೆ ಅವಧಿ ಮುಗಿಯುತ್ತದೆ"</string>
+    <string name="delete_blob_text" msgid="2819192607255625697">"ಹಂಚಿಕೊಳ್ಳಲಾದ ಡೇಟಾವನ್ನು ಅಳಿಸಿ"</string>
+    <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"ಈ ಹಂಚಿಕೊಳ್ಳಲಾದ ಡೇಟಾವನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?"</string>
     <string name="user_add_user_item_summary" msgid="5748424612724703400">"ಬಳಕೆದಾರರು ತಮ್ಮದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವಿಷಯವನ್ನು ಹೊಂದಿದ್ದಾರೆ"</string>
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ನಿಮ್ಮ ಖಾತೆಯಿಂದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವಿಷಯಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ನೀವು ನಿರ್ಬಂಧಿಸಬಹುದು"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"ಬಳಕೆದಾರ"</string>
@@ -556,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ಪ್ರೊಫೈಲ್‌‌ ಮಾಹಿತಿ"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ನೀವು ನಿರ್ಬಂಧಿತ ಪ್ರೊಫೈಲ್ ಅನ್ನು ರಚಿಸಬಹುದಾದರ ಮೊದಲು, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು ನೀವು ಪರದೆಯ ಲಾಕ್‌ ಹೊಂದಿಸುವ ಅಗತ್ಯವಿದೆ."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"ಲಾಕ್ ಹೊಂದಿಸಿ"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> ಗೆ ಬದಲಿಸಿ"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index cd69dd6..6f642c3 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"프로필 정보"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"제한된 프로필을 만들기 전에 화면 잠금을 설정하여 앱과 개인 데이터를 보호해야 합니다."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"잠금 설정"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>(으)로 전환"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"게스트 추가"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"게스트 삭제"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"게스트"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index c05fd66..417e511 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Профилдин чоо-жайы"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Чектелген профайл түзөөрдөн мурун, сиз өзүңүздүн колдонмолоруңузду жана жеке маалыматтарыңызды коргош үчүн, бөгөттөө көшөгөсүн орнотушуңуз керек болот."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Бөгөт коюу"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> аккаунтуна которулуу"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Конокту өчүрүү"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Конок"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 4591ca0..94800ea 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profilio informacija"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Prieš kuriant apribotą profilį reikės nustatyti ekrano užraktą, kad apsaugotumėte programas ir asmeninius duomenis."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Nustatyti užraktą"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Perjungti į <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Pašalinti svečią"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Svečias"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index c36b7f4..d7816aa 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -544,12 +544,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profila informācija"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Lai varētu izveidot ierobežotu profilu, jums jāiestata ekrāna bloķēšana, kas aizsargās jūsu lietotni un personas datus."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Iestatīt bloķēšanu"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Pārslēgties uz: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Noņemt viesi"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Viesis"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index bde3e92..c593bee 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"പ്രൊഫൈൽ വിവരം"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ഒരു നിയന്ത്രിത പ്രൊഫൈൽ സൃഷ്‌ടിക്കുന്നതിനുമുമ്പ്, നിങ്ങളുടെ അപ്ലിക്കേഷനുകളും വ്യക്തിഗത ഡാറ്റയും പരിരക്ഷിക്കുന്നതിന് ഒരു സ്‌ക്രീൻ ലോക്ക് സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"ലോക്ക് സജ്ജീകരിക്കുക"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> എന്നതിലേക്ക് മാറുക"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 38c8b86..d3e41f7 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Профайлын мэдээлэл"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Та хязгаарлагдсан профайл үүсгэхийн өмнө өөрийн апп-ууд болон хувийн өгөгдлийг хамгаалахын тулд дэлгэцийн түгжээг тохируулах шаардлагатай."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Түгжээг тохируулах"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> руу сэлгэх"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Зочин нэмэх"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Зочин хасах"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Зочин"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 746ef57..c222bd3 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफाइल माहिती"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"तुम्ही एक प्रतिबंधित प्रोफाईल तयार करु शकण्यापूर्वी तुम्हाला तुमचे अ‍ॅप्स आणि वैयक्तिक डेटा संरक्षित करण्यासाठी एक स्क्रीन लॉक सेट करण्याची आवश्यकता राहील."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करा"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> वर स्विच करा"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 5e400e3..1dc3dc4 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Maklumat profil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum anda boleh membuat profil yang terhad, anda perlu menyediakan kunci skrin untuk melindungi apl dan data peribadi anda."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Tetapkan kunci"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Tukar kepada <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Tetamu"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index b71f842..58213a7 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profilinformasjon"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan opprette en begrenset profil, må du konfigurere skjermlåsen for å beskytte appene og de personlige dataene dine."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Angi lås"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Bytt til <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gjest"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 79fd469..cc26483 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -431,7 +431,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"ब्याट्री लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> सम्म"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"ब्याट्री <xliff:g id="TIME">%1$s</xliff:g> बजेभित्र सकिन सक्छ"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"ब्याट्री <xliff:g id="TIME">%1$s</xliff:g> बजेसम्ममा सकिन सक्छ"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी छ"</string>
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> भन्दा बढी समय बाँकी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,16 +513,12 @@
     <string name="storage_category" msgid="2287342585424631813">"भण्डारण"</string>
     <string name="shared_data_title" msgid="1017034836800864953">"साझा डेटा"</string>
     <string name="shared_data_summary" msgid="5516326713822885652">"साझा डेटा हेर्नुहोस् र परिमार्जन गर्नुहोस्"</string>
-    <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
-    <skip />
-    <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
-    <skip />
+    <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"यो प्रयोगकर्तासँग कुनै पनि डेटा सेयर गरिएको छैन।"</string>
+    <string name="shared_data_query_failure_text" msgid="3489828881998773687">"सेयर गरिएको डेटा प्राप्त गर्ने क्रममा कुनै त्रुटि भयो। फेरि प्रयास गर्नुहोस्।"</string>
     <string name="blob_id_text" msgid="8680078988996308061">"साझा डेटाको ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
     <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g> मा म्याद सकिन्छ"</string>
-    <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
-    <skip />
-    <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
-    <skip />
+    <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"सेयर गरिएको डेटा मेट्ने क्रममा त्रुटि भयो।"</string>
+    <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"सेयर गरिएको यो डेटाका लागि कुनै ठेक्का पट्टा लिएको छैन। तपाईं यसलाई मेट्न चाहनुहुन्छ?"</string>
     <string name="accessor_info_title" msgid="8289823651512477787">"साझा डेटा प्रयोग गर्ने अनुप्रयोगहरू"</string>
     <string name="accessor_no_description_text" msgid="7510967452505591456">"यो अनुप्रयोगले कुनै विवरण प्रदान गरेको छैन।"</string>
     <string name="accessor_expires_text" msgid="4625619273236786252">"लिजको म्याद <xliff:g id="DATE">%s</xliff:g> मा सकिन्छ"</string>
@@ -547,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफाइल जानकारी"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"निषेधयुक्त प्रोफाइल बनाउनु अघि तपाईँको अनुप्रयोग र व्यक्तिगत डेटा सुरक्षा गर्नाका लागि तपाईँले स्क्रिन लक सेटअप गर्नु पर्दछ ।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"लक सेट गर्नुहोस्"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"प्रयोगकर्ता बदलेर <xliff:g id="USER_NAME">%s</xliff:g> पार्नुहोस्"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"अतिथि हटाउनुहोस्"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"अतिथि"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index c780d6a..57fc87a 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profielinfo"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Voordat je een beperkt profiel kunt maken, moet je een schermvergrendeling instellen om je apps en persoonsgegevens te beschermen."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Vergrendeling instellen"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Overschakelen naar <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Gast toevoegen"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Gast verwijderen"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 82cfbe3..3a7f2c5 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -232,8 +232,7 @@
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ଠିକଣା ଓ ପୋର୍ଟ"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR କୋଡ୍ ସ୍କାନ୍ କରନ୍ତୁ"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"ଏକ QR କୋଡ୍ ସ୍କାନ୍ କରି ୱାଇ-ଫାଇରେ ଡିଭାଇସ୍ ପେୟାର୍ କରନ୍ତୁ"</string>
-    <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
-    <skip />
+    <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"ଦୟାକରି ଏକ ୱାଇ-ଫାଇ ନେଟୱାର୍କରେ ସଂଯୋଗ କରନ୍ତୁ"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ଡିବଗ୍, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ବଗ୍ ରିପୋର୍ଟ ସର୍ଟକଟ୍‌"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ବଗ୍ ରିପୋର୍ଟ ଦେବାପାଇଁ ପାୱାର୍‌ ମେନୁରେ ଏକ ବଟନ୍‌ ଦେଖନ୍ତୁ"</string>
@@ -432,8 +431,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"ବ୍ୟାଟେରୀ ପାଖାପାଖି <xliff:g id="TIME">%1$s</xliff:g> ଚାଲିବ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"ବ୍ୟାଟେରୀ <xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ ଚାଲିବ"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
-    <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
-    <skip />
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> ସୁଦ୍ଧା ବ୍ୟାଟେରୀର ଚାର୍ଜ ଶେଷ ହୋଇ ଯାଇପାରେ"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ରୁ କମ୍ ସମୟ ବଳକା ଅଛି"</string>
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ରୁ କମ୍ ସମୟ ବଳକା ଅଛି (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ରୁ ଅଧିକ ସମୟ ବଳକା ଅଛି(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,32 +509,21 @@
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ଫୋନ୍ ସ୍ପିକର୍"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string>
-    <!-- no translation found for help_label (3528360748637781274) -->
-    <skip />
-    <!-- no translation found for storage_category (2287342585424631813) -->
-    <skip />
-    <!-- no translation found for shared_data_title (1017034836800864953) -->
-    <skip />
-    <!-- no translation found for shared_data_summary (5516326713822885652) -->
-    <skip />
+    <string name="help_label" msgid="3528360748637781274">"ସାହାଯ୍ୟ ଓ ମତାମତ"</string>
+    <string name="storage_category" msgid="2287342585424631813">"ଷ୍ଟୋରେଜ୍"</string>
+    <string name="shared_data_title" msgid="1017034836800864953">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା"</string>
+    <string name="shared_data_summary" msgid="5516326713822885652">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ଦେଖନ୍ତୁ ଏବଂ ଏହାକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ କୌଣସି ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ନାହିଁ।"</string>
     <string name="shared_data_query_failure_text" msgid="3489828881998773687">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ଫେଚ୍ କରିବା ସମୟରେ ଏକ ତ୍ରୁଟି ହୋଇଥିଲା। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <!-- no translation found for blob_id_text (8680078988996308061) -->
-    <skip />
-    <!-- no translation found for blob_expires_text (7882727111491739331) -->
-    <skip />
+    <string name="blob_id_text" msgid="8680078988996308061">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+    <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g>ରେ ମିଆଦ ଶେଷ ହେଉଛି"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ଡିଲିଟ୍ କରିବା ସମୟରେ ଏକ ତ୍ରୁଟି ହୋଇଥିଲା।"</string>
     <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"ସେୟାର୍ କରାଯାଇଥିବା ଏହି ଡାଟା ପାଇଁ କୌଣସି ଲିଜ୍ ପ୍ରାପ୍ତ ହୋଇନାହିଁ। ଆପଣ ଏହା ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି?"</string>
-    <!-- no translation found for accessor_info_title (8289823651512477787) -->
-    <skip />
-    <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
-    <skip />
-    <!-- no translation found for accessor_expires_text (4625619273236786252) -->
-    <skip />
-    <!-- no translation found for delete_blob_text (2819192607255625697) -->
-    <skip />
-    <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
-    <skip />
+    <string name="accessor_info_title" msgid="8289823651512477787">"ଡାଟା ସେୟାର୍ କରୁଥିବା ଆପଗୁଡ଼ିକ"</string>
+    <string name="accessor_no_description_text" msgid="7510967452505591456">"ଆପ୍ ଦ୍ୱାରା କୌଣସି ବର୍ଣ୍ଣନା ପ୍ରଦାନ କରାଯାଇନାହିଁ।"</string>
+    <string name="accessor_expires_text" msgid="4625619273236786252">"<xliff:g id="DATE">%s</xliff:g>ରେ ଲିଜର ମିଆଦ ଶେଷ ହେଉଛି"</string>
+    <string name="delete_blob_text" msgid="2819192607255625697">"ସେୟାର୍ କରାଯାଇଥିବା ଡାଟା ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+    <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"ଆପଣ ସେୟାର୍ କରାଯାଇଥିବା ଏହି ଡାଟା ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଥିବା ନିଶ୍ଚିତ କି?"</string>
     <string name="user_add_user_item_summary" msgid="5748424612724703400">"ଉପଯୋଗକର୍ତ୍ତାମାନଙ୍କ ପାଖରେ ନିଜର ଆପ୍‌ ଓ କଣ୍ଟେଣ୍ଟ ଅଛି"</string>
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ନିଜ ଆକାଉଣ୍ଟରୁ ଆପ୍‌ ତଥା କଣ୍ଟେଣ୍ଟକୁ ଆପଣ ଆକ୍ସେସ୍ ରୋକିପାରିବେ"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"ଉପଯୋଗକର୍ତ୍ତା"</string>
@@ -556,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ପ୍ରୋଫାଇଲ୍ ସୂଚନା"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ପ୍ରତିବନ୍ଧିତ ପ୍ରୋଫାଇଲ୍‌ ତିଆରି କରିବାବେଳେ, ନିଜ ଆପ୍‌ ଓ ବ୍ୟକ୍ତିଗତ ତଥ୍ୟର ସୁରକ୍ଷା ପାଇଁ ଏକ ସ୍କ୍ରୀନ୍‌ ଲକ୍‌ ସେଟ୍‌ କରନ୍ତୁ।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"ଲକ୍‌ ସେଟ୍‌ କରନ୍ତୁ"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>କୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"ଅତିଥିଙ୍କୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ଅତିଥି"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 52ba604..9802257 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ਪ੍ਰੋਫਾਈਲ ਜਾਣਕਾਰੀ"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਤਿਬੰਧਿਤ ਪ੍ਰੋਫਾਈਲ ਬਣਾ ਸਕੋ, ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਐਪਾਂ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਇੱਕ ਸਕ੍ਰੀਨ  ਲਾਕ  ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">" ਲਾਕ  ਸੈੱਟ ਕਰੋ"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> \'ਤੇ ਜਾਓ"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"ਮਹਿਮਾਨ ਹਟਾਓ"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ਮਹਿਮਾਨ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 602e179..734b257 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informacje o profilu"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Zanim utworzysz profil z ograniczeniami, musisz skonfigurować ekran blokady, by chronić aplikacje i osobiste dane."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Ustaw blokadę"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Przełącz na: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Usuń gościa"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gość"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 90ce2a9..5860409 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -544,12 +544,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informații de profil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Înainte de a putea crea un profil cu permisiuni limitate, va trebui să configurați blocarea ecranului pentru a vă proteja aplicațiile și datele personale."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Configurați blocarea"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Comutați la <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Invitat"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 71b231c..ab230b7 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -278,7 +278,7 @@
     <string name="private_dns_mode_off" msgid="7065962499349997041">"Отключено"</string>
     <string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"Автоматический режим"</string>
     <string name="private_dns_mode_provider" msgid="3619040641762557028">"Имя хоста поставщика персонального DNS-сервера"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Введите имя хоста поставщика услуг DNS"</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Введите имя хоста поставщика DNS"</string>
     <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Ошибка подключения"</string>
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Показывать параметры сертификации беспроводных мониторов"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Вести подробный журнал, показывать RSSI для каждого SSID при выборе сети"</string>
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Информация о профиле"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Чтобы создать профиль с ограниченным доступом, необходимо предварительно настроить блокировку экрана для защиты приложений и личных данных"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Включить блокировку"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Переключиться на этот аккаунт: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Добавить аккаунт гостя"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Удалить аккаунт гостя"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Гость"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 0e2cd84..73cfce1 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Informácie o profile"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Pred vytvorením obmedzeného profilu je nutné najprv nastaviť zámku obrazovky na ochranu aplikácií a osobných údajov."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Nastaviť uzamknutie"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Prepnúť na používateľa <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Odobrať hosťa"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Hosť"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index f3bba52..8e3782c 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Podatki za profil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Preden lahko ustvarite profil z omejitvami, morate nastaviti zaklepanje zaslona, da zaščitite aplikacije in osebne podatke."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavi zaklepanje"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Preklop na račun <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Odstranitev gosta"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2cd2393..6d1e80a 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Inform. i profilit"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Para se të mund të krijosh një profil të kufizuar, duhet të konfigurosh një kyçje të ekranit për të mbrojtur aplikacionet dhe të dhënat e tua personale."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Cakto kyçjen"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Kalo te <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Shto të ftuar"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Hiq të ftuarin"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"I ftuar"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 102d925..775b7d5 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -544,12 +544,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Подаци о профилу"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Да бисте могли да направите ограничени профил, треба да подесите закључавање екрана да бисте заштитили апликације и личне податке."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Подеси закључавање"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Пређи на корисника <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Уклони госта"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 50297a7..e40ba29 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profilinfo"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Innan du skapar en begränsad profil måste du konfigurera ett skärmlås för att skydda dina appar och personliga data."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurera lås"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Byt till <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Ta bort gäst"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Gäst"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index bfa1208..815896d 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Maelezo ya wasifu"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Kabla uunde wasifu uliowekekwa vikwazo, utahitajika kuweka skrini iliyofungwa ili kulinda programu zako na data binafsi."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Weka ufunguo"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Badili utumie <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Weka mgeni"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Ondoa mgeni"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Mgeni"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 98bb0ca..5080c31 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -418,8 +418,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"நிறம் அடையாளங்காண முடியாமை (சிவப்பு-பச்சை)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"நிறம் அடையாளங்காண முடியாமை (நீலம்-மஞ்சள்)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"வண்ணத்திருத்தம்"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"வண்ணத் திருத்தத்தைப் பயன்படுத்தி உங்கள் சாதனத்தில் வண்ணம் காண்பிக்கப்படும் விதத்தைச் சரிசெய்யலாம்"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index a36b6a3..0e763dd 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -232,8 +232,7 @@
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP చిరునామా &amp; పోర్ట్"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR కోడ్‌ను స్కాన్ చేయండి"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"పరికరాన్ని Wi-Fi ద్వారా పెయిర్ చేయడానికి QR కోడ్‌ను స్కాన్ చేయండి"</string>
-    <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
-    <skip />
+    <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"దయచేసి Wi-Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయండి"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, డీబగ్, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"బగ్ నివేదిక షార్ట్‌కట్"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"బగ్ నివేదికను తీసుకోవడానికి పవర్ మెనూలో బటన్‌ను చూపు"</string>
@@ -418,7 +417,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"రంగు సవరణ"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"రంగుల సరి చేసే ఫీచర్‌తో మీరు మీ పరికరంలో రంగులో కనిపించే పద్ధతిని సర్దుబాటు చేయగలుగుతారు"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"రంగులు సరి చేసే ఫీచర్ సాయంతో, మీ పరికరంలో రంగులు కనిపించే పద్ధతిని మీరు సర్దుబాటు చేయగలుగుతారు"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
@@ -432,8 +431,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> వరకు"</string>
-    <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
-    <skip />
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"బ్యాటరీ <xliff:g id="TIME">%1$s</xliff:g> సమయానికి ఖాళీ అవ్వచ్చు"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది"</string>
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,32 +509,21 @@
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ఫోన్ స్పీకర్"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
-    <!-- no translation found for help_label (3528360748637781274) -->
-    <skip />
-    <!-- no translation found for storage_category (2287342585424631813) -->
-    <skip />
-    <!-- no translation found for shared_data_title (1017034836800864953) -->
-    <skip />
-    <!-- no translation found for shared_data_summary (5516326713822885652) -->
-    <skip />
+    <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; అభిప్రాయం"</string>
+    <string name="storage_category" msgid="2287342585424631813">"నిల్వ"</string>
+    <string name="shared_data_title" msgid="1017034836800864953">"షేర్ చేసిన డేటా"</string>
+    <string name="shared_data_summary" msgid="5516326713822885652">"షేర్ చేసిన డేటాను చూసి, సవరించండి"</string>
     <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ఈ యూజర్ కోసం షేర్ చేసిన డేటా ఏదీ లేదు."</string>
     <string name="shared_data_query_failure_text" msgid="3489828881998773687">"షేర్ చేసిన డేటా పొందడంలో ఎర్రర్ ఏర్పడింది. మళ్లీ ట్రై చేయండి."</string>
-    <!-- no translation found for blob_id_text (8680078988996308061) -->
-    <skip />
-    <!-- no translation found for blob_expires_text (7882727111491739331) -->
-    <skip />
+    <string name="blob_id_text" msgid="8680078988996308061">"షేర్ చేసిన డేటా ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+    <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g>న గడువు ముగుస్తుంది"</string>
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"షేర్ చేసిన డేటాను తొలగించడంలో ఎర్రర్ ఏర్పడింది."</string>
     <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"ఈ షేర్ చేసిన డేటాకు సేకరించబడిన లీజులు ఏవీ లేవు. దీన్ని మీరు తొలగించాలనుకుంటున్నారా?"</string>
-    <!-- no translation found for accessor_info_title (8289823651512477787) -->
-    <skip />
-    <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
-    <skip />
-    <!-- no translation found for accessor_expires_text (4625619273236786252) -->
-    <skip />
-    <!-- no translation found for delete_blob_text (2819192607255625697) -->
-    <skip />
-    <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
-    <skip />
+    <string name="accessor_info_title" msgid="8289823651512477787">"యాప్‌ల షేరింగ్ డేటా"</string>
+    <string name="accessor_no_description_text" msgid="7510967452505591456">"యాప్ ద్వారా ఎలాంటి వివరణ అందించబడలేదు."</string>
+    <string name="accessor_expires_text" msgid="4625619273236786252">"లీజు గడువు <xliff:g id="DATE">%s</xliff:g>తో ముగుస్తుంది"</string>
+    <string name="delete_blob_text" msgid="2819192607255625697">"షేర్ చేసిన డేటాను తొలగించు"</string>
+    <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"మీరు ఖచ్చితంగా ఈ షేర్ చేసిన డేటాను తొలగించాలనుకుంటున్నారా?"</string>
     <string name="user_add_user_item_summary" msgid="5748424612724703400">"వినియోగదారులు వారి స్వంత అనువర్తనాలను మరియు కంటెంట్‌ను కలిగి ఉన్నారు"</string>
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"మీరు మీ ఖాతా నుండి అనువర్తనాలకు మరియు కంటెంట్‌కు ప్రాప్యతను పరిమితం చేయవచ్చు"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"వినియోగదారు"</string>
@@ -556,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ప్రొఫైల్ సమాచారం"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్‌ను సృష్టించడానికి ముందు, మీ అనువర్తనాలు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్‌ను సెటప్ చేయాల్సి ఉంటుంది."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"లాక్‌ను సెట్ చేయి"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>కు మార్చు"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"అతిథిని జోడించండి"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"అతిథిని తీసివేయండి"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"అతిథి"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 765c5dd..b24f006d 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -513,16 +513,12 @@
     <string name="storage_category" msgid="2287342585424631813">"พื้นที่เก็บข้อมูล"</string>
     <string name="shared_data_title" msgid="1017034836800864953">"ข้อมูลที่แชร์"</string>
     <string name="shared_data_summary" msgid="5516326713822885652">"ดูและแก้ไขข้อมูลที่แชร์"</string>
-    <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
-    <skip />
-    <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
-    <skip />
+    <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ไม่มีข้อมูลที่แชร์สำหรับผู้ใช้รายนี้"</string>
+    <string name="shared_data_query_failure_text" msgid="3489828881998773687">"เกิดข้อผิดพลาดขณะดึงข้อมูลที่แชร์ ลองใหม่"</string>
     <string name="blob_id_text" msgid="8680078988996308061">"รหัสข้อมูลที่แชร์: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
     <string name="blob_expires_text" msgid="7882727111491739331">"จะหมดอายุในวันที่ <xliff:g id="DATE">%s</xliff:g>"</string>
-    <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
-    <skip />
-    <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
-    <skip />
+    <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"เกิดข้อผิดพลาดขณะลบข้อมูลที่แชร์"</string>
+    <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"ไม่มีสัญญาเช่าที่ได้มาสำหรับข้อมูลที่แชร์นี้ คุณต้องการลบข้อมูลนี้ไหม"</string>
     <string name="accessor_info_title" msgid="8289823651512477787">"แอปที่แชร์ข้อมูล"</string>
     <string name="accessor_no_description_text" msgid="7510967452505591456">"แอปไม่ได้ให้คำอธิบายไว้"</string>
     <string name="accessor_expires_text" msgid="4625619273236786252">"เวลาได้รับสิทธิ์จะสิ้นสุดในวันที่ <xliff:g id="DATE">%s</xliff:g>"</string>
@@ -547,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"ข้อมูลโปรไฟล์"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ก่อนที่คุณจะสามารถสร้างโปรไฟล์ที่ถูกจำกัดได้ คุณจะต้องตั้งค่าล็อกหน้าจอเพื่อปกป้องแอปและข้อมูลส่วนตัวของคุณ"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"ตั้งค่าล็อก"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"เปลี่ยนเป็น <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"เพิ่มผู้เข้าร่วม"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"นำผู้เข้าร่วมออก"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"ผู้เข้าร่วม"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 1146619..8d70718 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Info sa profile"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Bago ka makakalikha ng pinaghihigpitang profile, kakailanganin mong mag-set up ng screen lock upang protektahan ang iyong apps at personal na data."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Itakda ang lock"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Lumipat sa <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Magdagdag ng bisita"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Alisin ang bisita"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Bisita"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 3853331..3579957 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profil bilgisi"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Kısıtlanmış bir profil oluşturabilmeniz için uygulamalarınızı ve kişisel verilerinizi korumak üzere bir ekran kilidi oluşturmanız gerekir."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Kilidi ayarla"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> hesabına geç"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Misafir ekle"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Misafir oturumunu kaldır"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Misafir"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 2eeda18..5dae4f0 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -545,12 +545,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Інформація профілю"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Перш ніж створювати обмежений профіль, потрібно налаштувати блокування екрана, щоб захистити свої програми та особисті дані."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Налаштувати блокування"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Перейти до користувача <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Видалити гостя"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Гість"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index f802ebc..ce25f2f 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -300,8 +300,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"اگر دستیاب ہو تو ٹیدرنگ ہارڈویئر سرعت کاری کا استعمال کریں"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"‏USB ڈیبگ کرنے کی اجازت دیں؟"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"‏USB ڈیبگ کرنا صرف ڈیولپمنٹ کے مقاصد کیلئے ہے۔ اپنے کمپیوٹر اور اپنے آلہ کے درمیان ڈیٹا کاپی کرنے کیلئے اسے استعمال کریں، بغیر اطلاع کے اپنے آلہ پر ایپس انسٹال کریں اور لاگ ڈیٹا پڑھیں۔"</string>
-    <string name="adbwifi_warning_title" msgid="727104571653031865">"وائرلیس ڈیبگ کرنے کی اجازت دیں؟"</string>
-    <string name="adbwifi_warning_message" msgid="8005936574322702388">"وائرلیس ڈیبگ کرنا صرف ڈیولپمنٹ کے مقاصد کے لیے ہے۔ اپنے کمپیوٹر اور اپنے آلہ کے درمیان ڈیٹا کاپی کرنے کے لیے اسے استعمال کریں، بغیر اطلاع کے اپنے آلہ پر ایپس انسٹال کریں اور لاگ ڈیٹا پڑھیں۔"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"وائرلیس ڈیبگنگ کی اجازت دیں؟"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"وائرلیس ڈیبگنگ صرف ڈیولپمنٹ کے مقاصد کے لیے ہے۔ اپنے کمپیوٹر اور اپنے آلہ کے درمیان ڈیٹا کاپی کرنے کے لیے اسے استعمال کریں، بغیر اطلاع کے اپنے آلہ پر ایپس انسٹال کریں اور لاگ ڈیٹا پڑھیں۔"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"‏اپنے ذریعہ پہلے سے اجازت یافتہ سبھی کمپیوٹرز سے USB ڈیبگ کرنے کی رسائی کو کالعدم کریں؟"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"ڈویلپمنٹ ترتیبات کی اجازت دیں؟"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"یہ ترتیبات صرف ڈویلپمنٹ استعمال کے ارادے سے ہیں۔ ان سے آپ کا آلہ اور اس پر موجود ایپلیکیشنز بریک ہو سکتی یا غلط برتاؤ کر سکتی ہیں۔"</string>
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"پروفائل کی معلومات"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"ایک محدود پروفائل بنانے سے پہلے، آپ کو اپنی ایپس اور ذاتی ڈیٹا کو محفوظ کرنے کیلئے ایک اسکرین لاک سیٹ اپ کرنا ہوگا۔"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"لاک سیٹ کریں"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> پر سوئچ کریں"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"مہمان کو ہٹائیں"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"مہمان"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 52fe395..07f3a6e 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -520,8 +520,8 @@
     <string name="shared_data_delete_failure_text" msgid="3842701391009628947">"Umumiy maʼlumotlarni oʻchirishda xatolik yuz berdi."</string>
     <string name="shared_data_no_accessors_dialog_text" msgid="8903738462570715315">"Bu umumiy maʼlumotlar yuzasidan kelgan soʻrov topilmadi. Oʻchirib tashlansinmi?"</string>
     <string name="accessor_info_title" msgid="8289823651512477787">"Umumiy maʼlumotlar bor ilovalar"</string>
-    <string name="accessor_no_description_text" msgid="7510967452505591456">"Ilova hech qanday tavsif bermagan."</string>
-    <string name="accessor_expires_text" msgid="4625619273236786252">"Ruxsat eskirish sanasi: <xliff:g id="DATE">%s</xliff:g>"</string>
+    <string name="accessor_no_description_text" msgid="7510967452505591456">"Ilovaga hech qanday tavsif bermagan."</string>
+    <string name="accessor_expires_text" msgid="4625619273236786252">"Ruxsat tugash sanasi: <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="delete_blob_text" msgid="2819192607255625697">"Umumiy maʼlumotlarni oʻchirish"</string>
     <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Umumiy maʼlumotlarni oʻchirishni xohlaysizmi?"</string>
     <string name="user_add_user_item_summary" msgid="5748424612724703400">"Foydalanuvchilar o‘zlarining ilovalari va kontenlariga egalar"</string>
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Profil haqida axborot"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Cheklangan profil yaratish uchun, shaxsiy ilovlar va ma‘lumotlarni himoyalash maqsadida avval ekran qulfini yaratish lozim."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Qulf o‘rnatish"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Bunga almashish: <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Mehmon kiritish"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Mehmon rejimini olib tashlash"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Mehmon"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index eb22f7d..10ac60d 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -206,11 +206,11 @@
     <string name="enable_adb" msgid="8072776357237289039">"Gỡ lỗi qua USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Bật chế độ gỡ lỗi khi kết nối USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Thu hồi ủy quyền gỡ lỗi USB"</string>
-    <string name="enable_adb_wireless" msgid="6973226350963971018">"Gỡ lỗi không dây"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Gỡ lỗi qua Wi-Fi"</string>
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Chế độ gỡ lỗi khi có kết nối Wi-Fi"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Lỗi"</string>
-    <string name="adb_wireless_settings" msgid="2295017847215680229">"Gỡ lỗi không dây"</string>
-    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Để xem và sử dụng các thiết bị có sẵn, hãy bật tính năng gỡ lỗi không dây"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Gỡ lỗi qua Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Để xem và sử dụng các thiết bị có sẵn, hãy bật tính năng gỡ lỗi qua Wi-Fi"</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Ghép nối thiết bị bằng mã QR"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Ghép nối các thiết bị mới bằng Trình quét mã QR"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Ghép nối thiết bị bằng mã ghép nối"</string>
@@ -300,8 +300,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Sử dụng tính năng tăng tốc phần cứng khi chia sẻ kết nối nếu có"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Cho phép gỡ lỗi qua USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Gỡ lỗi USB chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị của bạn mà không thông báo và đọc dữ liệu nhật ký."</string>
-    <string name="adbwifi_warning_title" msgid="727104571653031865">"Bật tính năng gỡ lỗi không dây?"</string>
-    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Tính năng gỡ lỗi không dây chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị mà không thông báo và đọc dữ liệu nhật ký."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Bật tính năng gỡ lỗi qua Wi-Fi?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Tính năng gỡ lỗi qua Wi-Fi chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị mà không thông báo và đọc dữ liệu nhật ký."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Thu hồi quyền truy cập gỡ lỗi USB từ tất cả máy tính mà bạn đã ủy quyền trước đó?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Cho phép cài đặt phát triển?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Những cài đặt này chỉ dành cho mục đích phát triển. Chúng có thể làm cho thiết bị và ứng dụng trên thiết bị của bạn bị lỗi và hoạt động sai."</string>
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"Thông tin hồ sơ"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Trước khi bạn có thể tạo tiểu sử bị hạn chế, bạn sẽ cần thiết lập một màn hình khóa để bảo vệ các ứng dụng và dữ liệu cá nhân của bạn."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Thiết lập khóa"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"Chuyển sang <xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"Thêm khách"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"Xóa phiên khách"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"Khách"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index a4727ca..c24f72d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"个人资料信息"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"您需要先设置锁定屏幕来保护您的应用和个人数据,然后才可以创建受限个人资料。"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"设置屏幕锁定方式"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"切换到<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"添加访客"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"移除访客"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"访客"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index b3f28fa..a4c2336 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"個人檔案資料"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"建立限制存取的個人檔案前,您必須先設定上鎖畫面來保護您的應用程式和個人資料。"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"設定上鎖畫面"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 05d4d46..5183df3 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -543,12 +543,8 @@
     <string name="profile_info_settings_title" msgid="105699672534365099">"設定檔資訊"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"如要建立設有限制的個人資料,你必須先設定螢幕鎖定來保護你的應用程式和個人資料。"</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"設定鎖定"</string>
-    <!-- no translation found for user_switch_to_user (6975428297154968543) -->
-    <skip />
-    <!-- no translation found for guest_new_guest (3482026122932643557) -->
-    <skip />
-    <!-- no translation found for guest_exit_guest (5908239569510734136) -->
-    <skip />
-    <!-- no translation found for guest_nickname (6332276931583337261) -->
-    <skip />
+    <string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string>
+    <string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
+    <string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string>
+    <string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 9112602..53e7921 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -566,7 +566,7 @@
     <!-- [CHAR LIMIT=50] Title for adb wireless pair by QR code preference -->
     <string name="adb_pair_method_qrcode_title">Pair device with QR code</string>
     <!-- [CHAR LIMIT=NONE] Summary for adb wireless pair by QR code preference -->
-    <string name="adb_pair_method_qrcode_summary">Pair new devices using QR code Scanner</string>
+    <string name="adb_pair_method_qrcode_summary">Pair new devices using QR code scanner</string>
     <!-- [CHAR LIMIT=50] Title for adb wireless pair by pairing code preference -->
     <string name="adb_pair_method_code_title">Pair device with pairing code</string>
     <!-- [CHAR LIMIT=NONE] Summary for adb wireless pair by pairing code preference -->
@@ -604,7 +604,7 @@
     <!-- [CHAR LIMIT=NONE] Adb Wireless QR code pairing scanner title -->
     <string name="adb_wireless_qrcode_pairing_title">Scan QR code</string>
     <!-- [CHAR LIMIT=NONE] Adb Wireless QR code pairing description -->
-    <string name="adb_wireless_qrcode_pairing_description">Pair device over Wi\u2011Fi by scanning a QR Code</string>
+    <string name="adb_wireless_qrcode_pairing_description">Pair device over Wi\u2011Fi by scanning a QR code</string>
     <!-- [CHAR LIMIT=NONE] Toast message when trying to enable Wi-Fi debugging and no Wi-Fi network connected -->
     <string name="adb_wireless_no_network_msg">Please connect to a Wi\u2011Fi network</string>
     <!--Adb wireless search Keywords [CHAR LIMIT=NONE]-->
@@ -928,11 +928,15 @@
     <!-- UI debug setting: show all ANRs summary [CHAR LIMIT=100] -->
     <string name="show_all_anrs_summary">Display App Not Responding dialog for background apps</string>
 
-    <!-- UI debug setting: show all ANRs? [CHAR LIMIT=25] -->
+    <!-- UI debug setting: show missing channel toasts? [CHAR LIMIT=25] -->
     <string name="show_notification_channel_warnings">Show notification channel warnings</string>
-    <!-- UI debug setting: show all ANRs summary [CHAR LIMIT=50] -->
+    <!-- UI debug setting: show missing channel toasts summary [CHAR LIMIT=50] -->
     <string name="show_notification_channel_warnings_summary">Displays on-screen warning when an app posts a notification without a valid channel</string>
 
+    <!-- UI debug setting: enforce shortcut requirements for conversation space [CHAR LIMIT=25] -->
+    <string name="enforce_shortcuts_for_conversations">Enforce shortcuts for conversation notifications</string>
+    <!-- UI debug setting: enforce shortcut requirements for conversation space summary [CHAR LIMIT=50] -->
+    <string name="enforce_shortcuts_for_conversations_summary">Require notifications to be backed by a long-lived sharing shortcut in order to appear in the conversation section</string>
 
     <!-- UI debug setting: force allow apps on external storage [CHAR LIMIT=50] -->
     <string name="force_allow_on_external">Force allow apps on external</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index fb8a0b7..3024b84 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -146,6 +146,7 @@
                     ((BluetoothMediaDevice) device).getCachedDevice();
             if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
                 mOnTransferBluetoothDevice = connectDevice;
+                device.setState(MediaDeviceState.STATE_CONNECTING);
                 cachedDevice.connect();
                 return;
             }
@@ -220,7 +221,7 @@
      */
     public MediaDevice getMediaDeviceById(List<MediaDevice> devices, String id) {
         for (MediaDevice mediaDevice : devices) {
-            if (mediaDevice.getId().equals(id)) {
+            if (TextUtils.equals(mediaDevice.getId(), id)) {
                 return mediaDevice;
             }
         }
@@ -236,7 +237,7 @@
      */
     public MediaDevice getMediaDeviceById(String id) {
         for (MediaDevice mediaDevice : mMediaDevices) {
-            if (mediaDevice.getId().equals(id)) {
+            if (TextUtils.equals(mediaDevice.getId(), id)) {
                 return mediaDevice;
             }
         }
@@ -394,6 +395,7 @@
             dispatchDeviceListUpdate();
             if (mOnTransferBluetoothDevice != null && mOnTransferBluetoothDevice.isConnected()) {
                 connectDevice(mOnTransferBluetoothDevice);
+                mOnTransferBluetoothDevice.setState(MediaDeviceState.STATE_CONNECTED);
                 mOnTransferBluetoothDevice = null;
             }
         }
@@ -539,6 +541,14 @@
 
         @Override
         public void onDeviceAttributesChanged() {
+            if (mOnTransferBluetoothDevice != null
+                    && !((BluetoothMediaDevice) mOnTransferBluetoothDevice).getCachedDevice()
+                    .isBusy()
+                    && !mOnTransferBluetoothDevice.isConnected()) {
+                // Failed to connect
+                mOnTransferBluetoothDevice.setState(MediaDeviceState.STATE_DISCONNECTED);
+                mOnTransferBluetoothDevice = null;
+            }
             dispatchDeviceAttributesChanged();
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
index 19e3808..65c7786 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
@@ -65,5 +65,17 @@
         }
         return savedConfigs;
     }
+
+    /**
+     * Returns the count of the saved configurations on the device, including both Wi-Fi networks
+     * and Passpoint profiles.
+     *
+     * @param context The application context
+     * @param wifiManager An instance of {@link WifiManager}
+     * @return count of saved Wi-Fi networks
+     */
+    public static int getAllConfigsCount(Context context, WifiManager wifiManager) {
+        return getAllConfigs(context, wifiManager).size();
+    }
 }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 1c69072..7ddd64c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -218,6 +218,26 @@
     }
 
     @Test
+    public void getMediaDeviceById_idIsNull_shouldReturnNull() {
+        final MediaDevice device1 = mock(MediaDevice.class);
+        final MediaDevice device2 = mock(MediaDevice.class);
+        mLocalMediaManager.mMediaDevices.add(device1);
+        mLocalMediaManager.mMediaDevices.add(device2);
+
+        when(device1.getId()).thenReturn(null);
+        when(device2.getId()).thenReturn(null);
+
+        MediaDevice device = mLocalMediaManager
+                .getMediaDeviceById(mLocalMediaManager.mMediaDevices, TEST_CURRENT_DEVICE_ID);
+
+        assertThat(device).isNull();
+
+        device = mLocalMediaManager.getMediaDeviceById(TEST_CURRENT_DEVICE_ID);
+
+        assertThat(device).isNull();
+    }
+
+    @Test
     public void onDeviceAdded_addDevice() {
         final MediaDevice device = mock(MediaDevice.class);
 
@@ -464,6 +484,26 @@
     }
 
     @Test
+    public void onDeviceAttributesChanged_failingTransferring_shouldResetState() {
+        final MediaDevice currentDevice = mock(MediaDevice.class);
+        final MediaDevice device = mock(BluetoothMediaDevice.class);
+        final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
+        mLocalMediaManager.mMediaDevices.add(device);
+        mLocalMediaManager.mMediaDevices.add(currentDevice);
+        when(device.getId()).thenReturn(TEST_DEVICE_ID_1);
+        when(currentDevice.getId()).thenReturn(TEST_CURRENT_DEVICE_ID);
+        when(((BluetoothMediaDevice) device).getCachedDevice()).thenReturn(cachedDevice);
+        when(cachedDevice.isConnected()).thenReturn(false);
+        when(cachedDevice.isBusy()).thenReturn(false);
+
+        mLocalMediaManager.registerCallback(mCallback);
+        mLocalMediaManager.connectDevice(device);
+
+        mLocalMediaManager.mDeviceAttributeChangeCallback.onDeviceAttributesChanged();
+        verify(device).setState(LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED);
+    }
+
+    @Test
     public void onRequestFailed_checkDevicesState() {
         mLocalMediaManager.mMediaDevices.add(mInfoMediaDevice1);
         mLocalMediaManager.mMediaDevices.add(mInfoMediaDevice2);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 2fde87c..d3d04e5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2813,6 +2813,7 @@
                 if (settingsState.isNewConfigBannedLocked(prefix, keyValues)) {
                     return false;
                 }
+                settingsState.unbanAllConfigIfBannedConfigUpdatedLocked(prefix);
                 List<String> changedSettings =
                         settingsState.setSettingsLocked(prefix, keyValues, packageName);
                 if (!changedSettings.isEmpty()) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index d93c015..6b8219e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -459,6 +459,16 @@
     }
 
     @GuardedBy("mLock")
+    public void unbanAllConfigIfBannedConfigUpdatedLocked(String prefix) {
+        // If the prefix updated is a banned namespace, clear mNamespaceBannedHashes
+        // to unban all unbanned namespaces.
+        if (mNamespaceBannedHashes.get(prefix) != null) {
+            mNamespaceBannedHashes.clear();
+            scheduleWriteIfNeededLocked();
+        }
+    }
+
+    @GuardedBy("mLock")
     public void banConfigurationLocked(String prefix, Map<String, String> keyValues) {
         if (prefix == null || keyValues.isEmpty()) {
             return;
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 86ba8bb..01a2b69 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -418,6 +418,7 @@
                     Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
                     Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
                     Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
+                    Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS,
                     Settings.Global.SAFE_BOOT_DISALLOWED,
                     Settings.Global.SELINUX_STATUS,
                     Settings.Global.SELINUX_UPDATE_CONTENT_URL,
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index 7d04eeb..18ab908 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -30,7 +30,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"Le segnalazioni di bug contengono dati recuperati da vari file di log del sistema e potrebbero includere dati considerati riservati (ad esempio dati relativi alla posizione e all\'utilizzo delle app). Condividi le segnalazioni di bug solo con persone e app attendibili."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Non mostrare più"</string>
-    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapporti sui bug"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Segnalazioni di bug"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Impossibile leggere il file relativo alla segnalazione di bug"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Impossibile aggiungere i dettagli della segnalazione di bug al file zip"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"senza nome"</string>
diff --git a/packages/Shell/res/values-or/strings.xml b/packages/Shell/res/values-or/strings.xml
index bd2b6cd..5171839 100644
--- a/packages/Shell/res/values-or/strings.xml
+++ b/packages/Shell/res/values-or/strings.xml
@@ -35,7 +35,7 @@
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"ଜିପ୍‍ ଫାଇଲରେ ବଗ୍‍ ରିପୋର୍ଟ ବିବରଣୀ ଯୋଡ଼ାଯାଇପାରିଲା ନାହିଁ"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"ବେନାମୀ"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"ବିବରଣୀ"</string>
-    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"ସ୍କ୍ରୀନ୍‌ଶଟ୍‌"</string>
+    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"ସ୍କ୍ରିନ୍‌ସଟ୍‌"</string>
     <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"ସଫଳତାପୂର୍ବକ ସ୍କ୍ରୀନଶଟ୍‍ ନିଆଗଲା"</string>
     <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ସ୍କ୍ରୀନ୍‍ଶଟ୍‍ ନିଆଯାଇପାରିଲା ନାହିଁ।"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ବଗ୍‍ ରିପୋର୍ଟ <xliff:g id="ID">#%d</xliff:g>ର ବିବରଣୀ"</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 5d363f3..c2015ed 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -351,9 +351,6 @@
         @Override
         public void onProgress(float progress) {
             synchronized (mLock) {
-                if (progress == 0) {
-                    trackInfoWithIdLocked();
-                }
                 checkProgressUpdatedLocked(mInfo, (int) progress);
             }
         }
@@ -365,8 +362,8 @@
         @Override
         public void onError(@BugreportErrorCode int errorCode) {
             synchronized (mLock) {
-                trackInfoWithIdLocked();
                 stopProgressLocked(mInfo.id);
+                mInfo.deleteEmptyFiles();
             }
             Log.e(TAG, "Bugreport API callback onError() errorCode = " + errorCode);
             return;
@@ -382,10 +379,10 @@
         }
 
         /**
-         * Reads bugreport id and links it to the bugreport info to track the bugreport's
-         * progress/completion/error. id is incremented in dumpstate code. This function is called
-         * when dumpstate calls one of the callback functions (onProgress, onFinished, onError)
-         * after the id has been incremented.
+         * Reads bugreport id and links it to the bugreport info to track a bugreport that is in
+         * process. id is incremented in the dumpstate code.
+         * We do not track a bugreport if there is already a bugreport with the same id being
+         * tracked.
          */
         @GuardedBy("mLock")
         private void trackInfoWithIdLocked() {
@@ -408,7 +405,6 @@
                 sendRemoteBugreportFinishedBroadcast(mContext, bugreportFilePath,
                         mInfo.bugreportFile);
             } else {
-                trackInfoWithIdLocked();
                 cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE, mBugreportsDir);
                 final Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
                 intent.putExtra(EXTRA_BUGREPORT, bugreportFilePath);
@@ -638,8 +634,11 @@
 
         BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(info);
         try {
-            mBugreportManager.startBugreport(bugreportFd, screenshotFd,
-                    new BugreportParams(bugreportType), executor, bugreportCallback);
+            synchronized (mLock) {
+                mBugreportManager.startBugreport(bugreportFd, screenshotFd,
+                        new BugreportParams(bugreportType), executor, bugreportCallback);
+                bugreportCallback.trackInfoWithIdLocked();
+            }
         } catch (RuntimeException e) {
             Log.i(TAG, "Error in generating bugreports: ", e);
             // The binder call didn't go through successfully, so need to close the fds.
@@ -756,7 +755,7 @@
                 != (info.lastProgress.intValue() / LOG_PROGRESS_STEP))) {
             Log.d(TAG, "Progress #" + info.id + ": " + percentageText);
         }
-        info.lastProgress = new AtomicInteger(progress);
+        info.lastProgress.set(progress);
 
         sendForegroundabledNotification(info.id, builder.build());
     }
@@ -1025,7 +1024,7 @@
         }
         Log.d(TAG, "Bugreport finished with title: " + info.getTitle()
                 + " and shareDescription: " + info.shareDescription);
-        info.finished = new AtomicBoolean(true);
+        info.finished.set(true);
 
         synchronized (mLock) {
             // Stop running on foreground, otherwise share notification cannot be dismissed.
@@ -1809,18 +1808,18 @@
          * Current value of progress (in percentage) of the bugreport generation as
          * displayed by the UI.
          */
-        AtomicInteger progress = new AtomicInteger(0);
+        final AtomicInteger progress = new AtomicInteger(0);
 
         /**
          * Last value of progress (in percentage) of the bugreport generation for which
          * system notification was updated.
          */
-        AtomicInteger lastProgress = new AtomicInteger(0);
+        final AtomicInteger lastProgress = new AtomicInteger(0);
 
         /**
          * Time of the last progress update.
          */
-        AtomicLong lastUpdate = new AtomicLong(System.currentTimeMillis());
+        final AtomicLong lastUpdate = new AtomicLong(System.currentTimeMillis());
 
         /**
          * Time of the last progress update when Parcel was created.
@@ -1840,7 +1839,7 @@
         /**
          * Whether dumpstate sent an intent informing it has finished.
          */
-        AtomicBoolean finished = new AtomicBoolean(false);
+        final AtomicBoolean finished = new AtomicBoolean(false);
 
         /**
          * Whether the details entries have been added to the bugreport yet.
@@ -1982,6 +1981,22 @@
         }
 
         /**
+         * Deletes empty files for a given bugreport.
+         */
+        private void deleteEmptyFiles() {
+            if (bugreportFile.length() == 0) {
+                Log.i(TAG, "Deleting empty bugreport file: " + bugreportFile);
+                bugreportFile.delete();
+            }
+            for (File file : screenshotFiles) {
+                if (file.length() == 0) {
+                    Log.i(TAG, "Deleting empty screenshot file: " + file);
+                    file.delete();
+                }
+            }
+        }
+
+        /**
          * Rename all screenshots files so that they contain the new {@code name} instead of the
          * {@code initialName} if user has changed it.
          */
@@ -2075,8 +2090,8 @@
             initialName = in.readString();
             title = in.readString();
             description = in.readString();
-            progress = new AtomicInteger(in.readInt());
-            lastUpdate = new AtomicLong(in.readLong());
+            progress.set(in.readInt());
+            lastUpdate.set(in.readLong());
             formattedLastUpdate = in.readString();
             bugreportFile = readFile(in);
 
@@ -2085,7 +2100,7 @@
                   screenshotFiles.add(readFile(in));
             }
 
-            finished = new AtomicBoolean(in.readInt() == 1);
+            finished.set(in.readInt() == 1);
             screenshotCounter = in.readInt();
             shareDescription = in.readString();
             shareTitle = in.readString();
@@ -2157,8 +2172,8 @@
                         + ") from " + info.progress.intValue() + " to " + progress);
             }
         }
-        info.progress = new AtomicInteger(progress);
-        info.lastUpdate = new AtomicLong(System.currentTimeMillis());
+        info.progress.set(progress);
+        info.lastUpdate.set(System.currentTimeMillis());
 
         updateProgress(info);
     }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 791b832..c6f0327 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -255,6 +255,9 @@
     <!-- Query all packages on device on R+ -->
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 
+    <!-- Permission to register process observer -->
+    <uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER"/>
+
     <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index 022726e..d956a79 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -98,7 +98,7 @@
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-картанын PIN-кодун ачуу кыйрады!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-картанын PUK-кодун ачуу кыйрады!"</string>
     <string name="kg_pin_accepted" msgid="1625501841604389716">"Код кабыл алынды!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Байланыш жок."</string>
+    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Интернет жок."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Киргизүү ыкмасын өзгөртүү"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Учак режими"</string>
     <string name="kg_prompt_reason_prepare_for_update_pin" msgid="8878724145347297575">"Жаңыртууга даярдоо үчүн PIN код талап кылынат"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 34633d3..5f1df3e 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -54,7 +54,7 @@
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Miejsce na kod PIN karty SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Miejsce na kod PUK karty SIM"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Następny alarm ustawiony na: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
-    <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Usuwanie"</string>
+    <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Usuń"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Wyłącz eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nie można wyłączyć karty eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Nie można wyłączyć karty eSIM z powodu błędu."</string>
diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml b/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml
similarity index 87%
copy from packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
copy to packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml
index 344859c..b16d038 100644
--- a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
+++ b/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml
@@ -17,6 +17,6 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true" android:color="?android:attr/colorAccent" />
+    <item android:state_activated="true" android:color="@color/kg_user_switcher_activated_background_color" />
     <item android:color="@android:color/transparent" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml b/packages/SystemUI/res/color/qs_user_avatar_frame.xml
similarity index 92%
rename from packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
rename to packages/SystemUI/res/color/qs_user_avatar_frame.xml
index 344859c..0c816b4 100644
--- a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
+++ b/packages/SystemUI/res/color/qs_user_avatar_frame.xml
@@ -18,5 +18,5 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_activated="true" android:color="?android:attr/colorAccent" />
-    <item android:color="@android:color/transparent" />
+    <item android:color="@color/qs_user_switcher_avatar_background" />
 </selector>
\ No newline at end of file
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml b/packages/SystemUI/res/drawable/bg_avatar_selected.xml
similarity index 65%
copy from core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml
copy to packages/SystemUI/res/drawable/bg_avatar_selected.xml
index 896993e..84d3416 100644
--- a/core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml
+++ b/packages/SystemUI/res/drawable/bg_avatar_selected.xml
@@ -15,10 +15,14 @@
   ~ limitations under the License.
   -->
 
-<resources>
-    <dimen name="test">400dp</dimen>
-    <string name="test">Four</string>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="100"
+        android:viewportHeight="100">
 
-    <string name="additional">Four</string>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
\ No newline at end of file
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:pathData="M50,50m-50,0a50,50 0,1 1,100 0a50,50 0,1 1,-100 0"/>
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/control_background_ripple.xml b/packages/SystemUI/res/drawable/control_background_ripple.xml
index 37914e2..27e3da9 100644
--- a/packages/SystemUI/res/drawable/control_background_ripple.xml
+++ b/packages/SystemUI/res/drawable/control_background_ripple.xml
@@ -17,7 +17,10 @@
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
         android:color="?android:attr/colorControlHighlight">
     <item android:id="@android:id/mask">
-        <color android:color="@android:color/white" />
+        <shape android:shape="rectangle">
+            <solid android:color="@android:color/white" />
+            <corners android:radius="@dimen/control_corner_radius" />
+        </shape>
     </item>
     <item android:drawable="@drawable/control_background" />
 </ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_add_circle.xml b/packages/SystemUI/res/drawable/ic_add_circle.xml
new file mode 100644
index 0000000..79ea707
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_add_circle.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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:viewportWidth="48"
+        android:viewportHeight="48">
+
+    <path
+        android:pathData="M23.9998,10.667C16.6398,10.667 10.6665,16.6403 10.6665,24.0003C10.6665,31.3603 16.6398,37.3337 23.9998,37.3337C31.3598,37.3337 37.3332,31.3603 37.3332,24.0003C37.3332,16.6403 31.3598,10.667 23.9998,10.667ZM22.6665,17.3337V22.667H17.3332V25.3337H22.6665V30.667H25.3332V25.3337H30.6665V22.667H25.3332V17.3337H22.6665ZM13.3332,24.0003C13.3332,29.8803 18.1198,34.667 23.9998,34.667C29.8798,34.667 34.6665,29.8803 34.6665,24.0003C34.6665,18.1203 29.8798,13.3337 23.9998,13.3337C18.1198,13.3337 13.3332,18.1203 13.3332,24.0003Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_add_circle_qs.xml b/packages/SystemUI/res/drawable/ic_add_circle_qs.xml
deleted file mode 100644
index 8e93344..0000000
--- a/packages/SystemUI/res/drawable/ic_add_circle_qs.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-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="48.0dp"
-        android:height="48.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorForeground">
-    <group
-            android:scaleX="1.2"
-            android:scaleY="1.2"
-            android:pivotX="12.0"
-            android:pivotY="12.0">
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM17.000000,13.000000l-4.000000,0.000000l0.000000,4.000000l-2.000000,0.000000l0.000000,-4.000000L7.000000,13.000000l0.000000,-2.000000l4.000000,0.000000L11.000000,7.000000l2.000000,0.000000l0.000000,4.000000l4.000000,0.000000L17.000000,13.000000z"/>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_avatar_guest_user.xml b/packages/SystemUI/res/drawable/ic_avatar_guest_user.xml
new file mode 100644
index 0000000..e3a83a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_avatar_guest_user.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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:viewportWidth="48"
+        android:viewportHeight="48">
+
+    <path
+        android:pathData="M23.9998,10.667C16.6398,10.667 10.6665,16.6403 10.6665,24.0003C10.6665,31.3603 16.6398,37.3337 23.9998,37.3337C31.3598,37.3337 37.3332,31.3603 37.3332,24.0003C37.3332,16.6403 31.3598,10.667 23.9998,10.667ZM17.4265,32.3737C17.9998,31.1737 21.4932,30.0003 23.9998,30.0003C26.5065,30.0003 30.0132,31.1737 30.5732,32.3737C28.7598,33.8137 26.4798,34.667 23.9998,34.667C21.5198,34.667 19.2398,33.8137 17.4265,32.3737ZM23.9998,27.3337C25.9465,27.3337 30.5732,28.1203 32.4798,30.4403C33.8398,28.6537 34.6665,26.427 34.6665,24.0003C34.6665,18.1203 29.8798,13.3337 23.9998,13.3337C18.1198,13.3337 13.3332,18.1203 13.3332,24.0003C13.3332,26.427 14.1598,28.6537 15.5198,30.4403C17.4265,28.1203 22.0532,27.3337 23.9998,27.3337ZM23.9998,16.0003C21.4132,16.0003 19.3332,18.0803 19.3332,20.667C19.3332,23.2537 21.4132,25.3337 23.9998,25.3337C26.5865,25.3337 28.6665,23.2537 28.6665,20.667C28.6665,18.0803 26.5865,16.0003 23.9998,16.0003ZM21.9998,20.667C21.9998,21.7737 22.8932,22.667 23.9998,22.667C25.1065,22.667 25.9998,21.7737 25.9998,20.667C25.9998,19.5603 25.1065,18.667 23.9998,18.667C22.8932,18.667 21.9998,19.5603 21.9998,20.667Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_avatar_user.xml b/packages/SystemUI/res/drawable/ic_avatar_user.xml
new file mode 100644
index 0000000..b4a4a88
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_avatar_user.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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:viewportWidth="48"
+        android:viewportHeight="48">
+
+    <path
+        android:pathData="M23.9998,10.667C16.6398,10.667 10.6665,16.6403 10.6665,24.0003C10.6665,31.3603 16.6398,37.3337 23.9998,37.3337C31.3598,37.3337 37.3332,31.3603 37.3332,24.0003C37.3332,16.6403 31.3598,10.667 23.9998,10.667ZM32.4798,30.4403C30.5732,28.1203 25.9465,27.3337 23.9998,27.3337C22.0532,27.3337 17.4265,28.1203 15.5198,30.4403C14.1598,28.6537 13.3332,26.427 13.3332,24.0003C13.3332,18.1203 18.1198,13.3337 23.9998,13.3337C29.8798,13.3337 34.6665,18.1203 34.6665,24.0003C34.6665,26.427 33.8398,28.6537 32.4798,30.4403ZM19.3332,20.667C19.3332,18.0803 21.4132,16.0003 23.9998,16.0003C26.5865,16.0003 28.6665,18.0803 28.6665,20.667C28.6665,23.2537 26.5865,25.3337 23.9998,25.3337C21.4132,25.3337 19.3332,23.2537 19.3332,20.667Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_empty_bubble_overflow_dark.xml b/packages/SystemUI/res/drawable/ic_empty_bubble_overflow_dark.xml
new file mode 100644
index 0000000..8f8f1b6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_empty_bubble_overflow_dark.xml
@@ -0,0 +1,162 @@
+<!--
+Copyright (C) 2020 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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="412dp"
+    android:height="300dp"
+    android:viewportWidth="412"
+    android:viewportHeight="300">
+  <group>
+    <clip-path
+        android:pathData="M206,150m-150,0a150,150 0,1 1,300 0a150,150 0,1 1,-300 0"/>
+    <path
+        android:pathData="M296,105.2h-9.6l-3.1,-2.5l-3.1,2.5H116c-1.7,0 -3,1.3 -3,3v111.7c0,1.7 1.3,3 3,3h180c1.7,0 3,-1.3 3,-3V108.2C299,106.6 297.7,105.2 296,105.2C296,105.2 296,105.2 296,105.2z"
+        android:fillColor="#3C4043"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M252.4,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#D2E3FC"
+        android:strokeColor="#4285F4"/>
+    <path
+        android:pathData="M261.9,95.7m-4.5,0a4.5,4.5 0,1 1,9 0a4.5,4.5 0,1 1,-9 0"
+        android:fillColor="#4285F4"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M160.6,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#FAD2CF"
+        android:strokeColor="#EA4335"/>
+    <path
+        android:pathData="M170.1,95.7m-4.6,0a4.6,4.6 0,1 1,9.2 0a4.6,4.6 0,1 1,-9.2 0"
+        android:fillColor="#EA4335"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M192.1,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#FEEFC3"
+        android:strokeColor="#FBBC04"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M221.8,85.4m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#CEEAD6"
+        android:strokeColor="#34A853"/>
+    <path
+        android:pathData="M201.6,95.7m-4.6,0a4.6,4.6 0,1 1,9.2 0a4.6,4.6 0,1 1,-9.2 0"
+        android:fillColor="#FBBC04"/>
+    <path
+        android:pathData="M231.4,95.7m-4.6,0a4.6,4.6 0,1 1,9.2 0a4.6,4.6 0,1 1,-9.2 0"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M282.8,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#3C4043"/>
+    <path
+        android:pathData="M278.7,85.7m-1.2,0a1.2,1.2 0,1 1,2.4 0a1.2,1.2 0,1 1,-2.4 0"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M282.8,85.7m-1.2,0a1.2,1.2 0,1 1,2.4 0a1.2,1.2 0,1 1,-2.4 0"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M286.9,85.7m-1.2,0a1.2,1.2 0,1 1,2.4 0a1.2,1.2 0,1 1,-2.4 0"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M129.2,72.9h-3.4l0.3,1c1,-0.3 2.1,-0.4 3.2,-0.4v-1V72.9zM122.6,74.8c-0.5,0.3 -1,0.6 -1.4,1l0,0l0,0l0,0l0,0h-0.6l0,0l0,0l0,0l0,0l0,0l0,0c-0.2,0.2 -0.3,0.3 -0.4,0.5l0.8,0.7c0.7,-0.8 1.5,-1.5 2.4,-2.1l-0.5,-0.8L122.6,74.8zM118,80L118,80L118,80L118,80L118,80L118,80L118,80L118,80c-0.5,1 -0.8,2 -1,3l1,0.2c0.2,-1 0.5,-2 1,-3L118,80zM117.8,86.7l-1,0.1c0.1,0.6 0.2,1.1 0.3,1.7l0,0l0,0h0.1l0,0l0,0l0,0l0,0c0.1,0.5 0.3,0.9 0.5,1.4l0.9,-0.4c-0.4,-1 -0.7,-2 -0.8,-3.1L117.8,86.7zM120.2,92.5l-0.8,0.6l0.2,0.3l0,0l0,0l0,0l0,0h0.3l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0.4,0.4l0,0l0,0l0,0l0,0h0.1l0,0l0,0l0,0l0,0l0,0h0.5l0,0l0,0l0,0l0,0l0,0l0,0l0.6,0.4l0.6,-0.8c-0.9,-0.6 -1.7,-1.4 -2.3,-2.2L120.2,92.5zM125.4,96.2l-0.3,0.9c1.1,0.4 2.2,0.6 3.4,0.7l0.1,-1C127.5,96.7 126.4,96.5 125.4,96.2zM134.7,95.4c-0.9,0.5 -2,0.9 -3,1.1l0.2,1h0.4c1,-0.3 2,-0.6 2.9,-1.2l-0.5,-0.9L134.7,95.4zM139.2,90.9c-0.5,0.9 -1.2,1.8 -1.9,2.5l0.7,0.7v-0.1h0.2l0,0l0,0c0.7,-0.7 1.3,-1.6 1.8,-2.4l-0.9,-0.5L139.2,90.9zM141.6,84.7h-1c0,0.2 0,0.4 0,0.6c0,0.9 -0.1,1.7 -0.3,2.6l1,0.2c0.1,-0.4 0.2,-0.8 0.2,-1.2l0,0v-0.1l0,0v-0.1l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0c0,-0.2 0,-0.3 0,-0.5l0,0L141.6,84.7zM139.3,78.2l-0.8,0.6c0.6,0.9 1.1,1.8 1.5,2.8l0.9,-0.3c-0.1,-0.2 -0.2,-0.4 -0.2,-0.7l0,0l0,0h-0.1l0,0l0,0l0,0l0,0l0,0l0,0c-0.3,-0.7 -0.7,-1.4 -1.1,-2l0,0l0,0l0,0l0,0l0,0l0,0l0,0L139.3,78.2zM134,73.9l-0.4,0.9c1,0.4 1.9,1 2.7,1.6l0.6,-0.8l0,0l0,0l0,0l0,0l0,0c-0.3,-0.3 -0.7,-0.5 -1,-0.7l0,0h-0.1h-0.6c-0.4,-0.2 -0.8,-0.4 -1.2,-0.6L134,73.9zM129.2,72.9v1c0.4,0 0.9,0 1.3,0.1l0.1,-1l-0.9,-0.1L129.2,72.9L129.2,72.9z"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M206,252m-11.7,0a11.7,11.7 0,1 1,23.4 0a11.7,11.7 0,1 1,-23.4 0"
+        android:fillColor="#F1F3F4"/>
+    <path
+        android:pathData="M201.7,247.7L210.3,256.3"
+        android:strokeWidth="2"
+        android:fillColor="#00000000"
+        android:strokeColor="#202124"
+        android:strokeLineCap="round"/>
+    <path
+        android:pathData="M210.3,247.7L201.7,256.3"
+        android:strokeWidth="2"
+        android:fillColor="#00000000"
+        android:strokeColor="#202124"
+        android:strokeLineCap="round"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M205.3,221.9m-10.4,0a10.4,10.4 0,1 1,20.8 0a10.4,10.4 0,1 1,-20.8 0"
+        android:fillColor="#CEEAD6"
+        android:strokeColor="#34A853"/>
+    <path
+        android:pathData="M481.4,292.2c48,58.3 119.8,125.8 58.6,162.9c-38.7,23.5 -53.9,24 -98.3,33.2c-43.8,9.1 -93.6,-89.8 -101.1,-134.5C329.6,288.6 452.6,257.2 481.4,292.2z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M458.2,320.7l-21.1,-71.4L400.5,193c-2.7,-5.1 -1.2,-11.4 3.5,-14.7l0,0c2.8,-2 6.6,-1.5 8.8,1.1c0,0 40.6,38.4 53.2,61.1l81.5,134.8l-69.9,-39.1L458.2,320.7z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M403.8,184.8l5.4,6.9c1.2,1.5 3.3,1.9 4.9,0.9l3,-1.8"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M420.9,325.8l-37.8,-88.6l-58.4,-37.8c-5.7,-5.4 -7.4,-13.8 -4.2,-21l0,0c2,-4.6 7.4,-6.7 12,-4.6c0.2,0.1 0.4,0.2 0.7,0.3c0,0 70.7,36.3 81.5,48.3l59.8,95.5l-49.9,24.9L420.9,325.8z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M324.6,183.9l8,6.2c2.1,1.7 5.2,1.4 7,-0.6l2.9,-3.3"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M392.4,231c3.8,-5.1 9.1,-8.9 15.1,-10.9"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+    <path
+        android:pathData="M401.3,283.8L405.8,292.6"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+    <path
+        android:pathData="M378.2,346.9l-34.7,-75.6l-60,-61.2c-6.3,-4.7 -9,-12.8 -6.7,-20.4l0,0c1.5,-4.8 6.5,-7.5 11.3,-6c0.2,0.1 0.4,0.1 0.7,0.2c0,0 73.5,48.2 82.6,61.7l64.1,95.7l-40.3,23.5L378.2,346.9z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M280.8,196.6l7.6,4.6c2.6,1.6 5.9,1.1 7.9,-1.1l4.1,-4.5"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M347.5,251c3.8,-5.1 9.1,-8.9 15.1,-10.9"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+    <path
+        android:pathData="M207.2,234.1c-8.8,-11 4.7,-31.5 19.8,-19c17.7,14.7 74.7,64.3 74.7,64.3l103.8,101.8c0,0 -36.4,53.8 -44.5,42.3C287.8,319.3 234.4,267.9 207.2,234.1z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M209.6,226.2l9.3,9.5c1,0.8 3,0.4 3.1,-1c0.2,-2.2 4.6,-6.2 7,-6.6c1.1,-0.3 1.7,-1.4 1.4,-2.4c-0.1,-0.2 -0.2,-0.4 -0.3,-0.6l-4.4,-3.9"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M284.1,296.2c3.1,-5.5 7.8,-10 13.5,-12.8"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+  </group>
+  <path
+      android:pathData="M206,4c80.6,0 146,65.4 146,146c0,38.7 -15.4,75.9 -42.8,103.2c-57,57 -149.5,57 -206.5,0s-57,-149.5 0,-206.5C130.1,19.3 167.3,3.9 206,4M206,0C123.2,0 56,67.2 56,150s67.2,150 150,150s150,-67.2 150,-150S288.8,0 206,0z"
+      android:fillColor="#D2E3FC"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_empty_bubble_overflow_light.xml b/packages/SystemUI/res/drawable/ic_empty_bubble_overflow_light.xml
new file mode 100644
index 0000000..5e02f67
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_empty_bubble_overflow_light.xml
@@ -0,0 +1,162 @@
+<!--
+Copyright (C) 2020 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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="412dp"
+    android:height="300dp"
+    android:viewportWidth="412"
+    android:viewportHeight="300">
+  <group>
+    <clip-path
+        android:pathData="M206,150m-150,0a150,150 0,1 1,300 0a150,150 0,1 1,-300 0"/>
+    <path
+        android:pathData="M296,105.2h-9.6l-3.1,-2.5l-3.1,2.5H116c-1.7,0 -3,1.3 -3,3v111.7c0,1.7 1.3,3 3,3h180c1.7,0 3,-1.3 3,-3V108.2C299,106.6 297.7,105.2 296,105.2L296,105.2z"
+        android:fillColor="#F1F3F4"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M252.4,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#D2E3FC"
+        android:strokeColor="#4285F4"/>
+    <path
+        android:pathData="M261.9,95.7m-4.5,0a4.5,4.5 0,1 1,9 0a4.5,4.5 0,1 1,-9 0"
+        android:fillColor="#4285F4"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M160.6,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#FAD2CF"
+        android:strokeColor="#EA4335"/>
+    <path
+        android:pathData="M170.1,95.7m-4.6,0a4.6,4.6 0,1 1,9.2 0a4.6,4.6 0,1 1,-9.2 0"
+        android:fillColor="#EA4335"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M192.1,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#FEEFC3"
+        android:strokeColor="#FBBC04"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M221.8,85.4m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#CEEAD6"
+        android:strokeColor="#34A853"/>
+    <path
+        android:pathData="M201.6,95.7m-4.6,0a4.6,4.6 0,1 1,9.2 0a4.6,4.6 0,1 1,-9.2 0"
+        android:fillColor="#FBBC04"/>
+    <path
+        android:pathData="M231.4,95.7m-4.6,0a4.6,4.6 0,1 1,9.2 0a4.6,4.6 0,1 1,-9.2 0"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M282.8,85.3m-12.4,0a12.4,12.4 0,1 1,24.8 0a12.4,12.4 0,1 1,-24.8 0"
+        android:fillColor="#F1F3F4"/>
+    <path
+        android:pathData="M278.7,85.7m-1.2,0a1.2,1.2 0,1 1,2.4 0a1.2,1.2 0,1 1,-2.4 0"
+        android:fillColor="#3474E0"/>
+    <path
+        android:pathData="M282.8,85.7m-1.2,0a1.2,1.2 0,1 1,2.4 0a1.2,1.2 0,1 1,-2.4 0"
+        android:fillColor="#3474E0"/>
+    <path
+        android:pathData="M286.9,85.7m-1.2,0a1.2,1.2 0,1 1,2.4 0a1.2,1.2 0,1 1,-2.4 0"
+        android:fillColor="#3474E0"/>
+    <path
+        android:pathData="M129.2,72.9h-3.4l0.3,1c1,-0.3 2.1,-0.4 3.2,-0.4v-1v0.4H129.2zM122.6,74.8c-0.5,0.3 -1,0.6 -1.4,1l0,0l0,0l0,0l0,0h-0.6l0,0l0,0l0,0l0,0l0,0l0,0c-0.2,0.2 -0.3,0.3 -0.4,0.5L121,77c0.7,-0.8 1.5,-1.5 2.4,-2.1l-0.5,-0.8L122.6,74.8zM118,80L118,80L118,80L118,80L118,80L118,80L118,80L118,80c-0.5,1 -0.8,2 -1,3l1,0.2c0.2,-1 0.5,-2 1,-3L118,80zM117.8,86.7l-1,0.1c0.1,0.6 0.2,1.1 0.3,1.7l0,0l0,0h0.1l0,0l0,0l0,0l0,0c0.1,0.5 0.3,0.9 0.5,1.4l0.9,-0.4c-0.4,-1 -0.7,-2 -0.8,-3.1V86.7zM120.2,92.5l-0.8,0.6l0.2,0.3l0,0l0,0l0,0l0,0h0.3l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0.4,0.4l0,0l0,0l0,0l0,0h0.1l0,0l0,0l0,0l0,0l0,0h0.5l0,0l0,0l0,0l0,0l0,0l0,0l0.6,0.4l0.6,-0.8c-0.9,-0.6 -1.7,-1.4 -2.3,-2.2L120.2,92.5zM125.4,96.2l-0.3,0.9c1.1,0.4 2.2,0.6 3.4,0.7l0.1,-1C127.5,96.7 126.4,96.5 125.4,96.2zM134.7,95.4c-0.9,0.5 -2,0.9 -3,1.1l0.2,1h0.4c1,-0.3 2,-0.6 2.9,-1.2L134.7,95.4L134.7,95.4zM139.2,90.9c-0.5,0.9 -1.2,1.8 -1.9,2.5l0.7,0.7V94h0.2l0,0l0,0c0.7,-0.7 1.3,-1.6 1.8,-2.4l-0.9,-0.5L139.2,90.9zM141.6,84.7h-1c0,0.2 0,0.4 0,0.6c0,0.9 -0.1,1.7 -0.3,2.6l1,0.2c0.1,-0.4 0.2,-0.8 0.2,-1.2l0,0v-0.1l0,0v-0.1l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0c0,-0.2 0,-0.3 0,-0.5l0,0L141.6,84.7zM139.3,78.2l-0.8,0.6c0.6,0.9 1.1,1.8 1.5,2.8l0.9,-0.3c-0.1,-0.2 -0.2,-0.4 -0.2,-0.7l0,0l0,0h-0.1l0,0l0,0l0,0l0,0l0,0l0,0c-0.3,-0.7 -0.7,-1.4 -1.1,-2l0,0l0,0l0,0l0,0l0,0l0,0l0,0L139.3,78.2zM134,73.9l-0.4,0.9c1,0.4 1.9,1 2.7,1.6l0.6,-0.8l0,0l0,0l0,0l0,0l0,0c-0.3,-0.3 -0.7,-0.5 -1,-0.7l0,0h-0.1h-0.6c-0.4,-0.2 -0.8,-0.4 -1.2,-0.6V73.9zM129.2,72.9v1c0.4,0 0.9,0 1.3,0.1l0.1,-1l-0.9,-0.1H129.2L129.2,72.9z"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M206,252m-11.7,0a11.7,11.7 0,1 1,23.4 0a11.7,11.7 0,1 1,-23.4 0"
+        android:fillColor="#9AA0A6"/>
+    <path
+        android:pathData="M201.7,247.7L210.3,256.3"
+        android:strokeWidth="2"
+        android:fillColor="#00000000"
+        android:strokeColor="#F1F3F4"
+        android:strokeLineCap="round"/>
+    <path
+        android:pathData="M210.3,247.7L201.7,256.3"
+        android:strokeWidth="2"
+        android:fillColor="#00000000"
+        android:strokeColor="#F1F3F4"
+        android:strokeLineCap="round"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M205.3,221.9m-10.4,0a10.4,10.4 0,1 1,20.8 0a10.4,10.4 0,1 1,-20.8 0"
+        android:fillColor="#CEEAD6"
+        android:strokeColor="#34A853"/>
+    <path
+        android:pathData="M481.4,292.2c48,58.3 119.8,125.8 58.6,162.9c-38.7,23.5 -53.9,24 -98.3,33.2c-43.8,9.1 -93.6,-89.8 -101.1,-134.5C329.6,288.6 452.6,257.2 481.4,292.2z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M458.2,320.7l-21.1,-71.4L400.5,193c-2.7,-5.1 -1.2,-11.4 3.5,-14.7l0,0c2.8,-2 6.6,-1.5 8.8,1.1c0,0 40.6,38.4 53.2,61.1l81.5,134.8l-69.9,-39.1L458.2,320.7z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M403.8,184.8l5.4,6.9c1.2,1.5 3.3,1.9 4.9,0.9l3,-1.8"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M420.9,325.8l-37.8,-88.6l-58.4,-37.8c-5.7,-5.4 -7.4,-13.8 -4.2,-21l0,0c2,-4.6 7.4,-6.7 12,-4.6c0.2,0.1 0.4,0.2 0.7,0.3c0,0 70.7,36.3 81.5,48.3l59.8,95.5l-49.9,24.9L420.9,325.8z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M324.6,183.9l8,6.2c2.1,1.7 5.2,1.4 7,-0.6l2.9,-3.3"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M392.4,231c3.8,-5.1 9.1,-8.9 15.1,-10.9"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+    <path
+        android:pathData="M401.3,283.8L405.8,292.6"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+    <path
+        android:pathData="M378.2,346.9l-34.7,-75.6l-60,-61.2c-6.3,-4.7 -9,-12.8 -6.7,-20.4l0,0c1.5,-4.8 6.5,-7.5 11.3,-6c0.2,0.1 0.4,0.1 0.7,0.2c0,0 73.5,48.2 82.6,61.7l64.1,95.7l-40.3,23.5L378.2,346.9z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M280.8,196.6l7.6,4.6c2.6,1.6 5.9,1.1 7.9,-1.1l4.1,-4.5"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M347.5,251c3.8,-5.1 9.1,-8.9 15.1,-10.9"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+    <path
+        android:pathData="M207.2,234.1c-8.8,-11 4.7,-31.5 19.8,-19c17.7,14.7 74.7,64.3 74.7,64.3l103.8,101.8c0,0 -36.4,53.8 -44.5,42.3C287.8,319.3 234.4,267.9 207.2,234.1z"
+        android:fillColor="#D2E3FC"/>
+    <path
+        android:pathData="M209.6,226.2l9.3,9.5c1,0.8 3,0.4 3.1,-1c0.2,-2.2 4.6,-6.2 7,-6.6c1.1,-0.3 1.7,-1.4 1.4,-2.4c-0.1,-0.2 -0.2,-0.4 -0.3,-0.6l-4.4,-3.9"
+        android:strokeLineJoin="bevel"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"
+        android:strokeLineCap="square"/>
+    <path
+        android:pathData="M284.1,296.2c3.1,-5.5 7.8,-10 13.5,-12.8"
+        android:strokeWidth="1.75"
+        android:fillColor="#00000000"
+        android:strokeColor="#A0C2F9"/>
+  </group>
+  <path
+      android:pathData="M206,4c80.6,0 146,65.4 146,146c0,38.7 -15.4,75.9 -42.8,103.2c-57,57 -149.5,57 -206.5,0s-57,-149.5 0,-206.5C130.1,19.3 167.3,3.9 206,4M206,0C123.2,0 56,67.2 56,150s67.2,150 150,150s150,-67.2 150,-150S288.8,0 206,0z"
+      android:fillColor="#D2E3FC"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/rounded_user_switcher_bg.xml b/packages/SystemUI/res/drawable/kg_user_switcher_rounded_bg.xml
similarity index 69%
rename from packages/SystemUI/res/drawable/rounded_user_switcher_bg.xml
rename to packages/SystemUI/res/drawable/kg_user_switcher_rounded_bg.xml
index e3d010e..13c5fe0 100644
--- a/packages/SystemUI/res/drawable/rounded_user_switcher_bg.xml
+++ b/packages/SystemUI/res/drawable/kg_user_switcher_rounded_bg.xml
@@ -16,17 +16,17 @@
   -->
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
         android:color="?android:attr/colorControlHighlight">
-   <item>
-      <shape>
-         <solid android:color="@color/qs_user_detail_avatar_frame" />
+    <item>
+        <shape>
+            <solid android:color="@color/kg_user_switcher_rounded_background_color" />
 
-         <padding
-                 android:left="1dp"
-                 android:right="1dp"
-                 android:bottom="1dp"
-                 android:top="1dp" />
+            <padding
+                android:left="8dp"
+                android:right="8dp"
+                android:bottom="8dp"
+                android:top="8dp" />
 
-         <corners android:radius="48dp" />
-      </shape>
-   </item>
+            <corners android:radius="48dp" />
+        </shape>
+    </item>
 </ripple>
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml b/packages/SystemUI/res/drawable/qs_bg_avatar.xml
similarity index 64%
copy from core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml
copy to packages/SystemUI/res/drawable/qs_bg_avatar.xml
index 896993e..41176a8 100644
--- a/core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml
+++ b/packages/SystemUI/res/drawable/qs_bg_avatar.xml
@@ -15,10 +15,14 @@
   ~ limitations under the License.
   -->
 
-<resources>
-    <dimen name="test">400dp</dimen>
-    <string name="test">Four</string>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="100"
+        android:viewportHeight="100">
 
-    <string name="additional">Four</string>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
\ No newline at end of file
+    <path
+        android:fillColor="@color/qs_user_switcher_avatar_background"
+        android:pathData="M50,50m-50,0a50,50 0,1 1,100 0a50,50 0,1 1,-100 0"/>
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
index 1f38b1e..4413b1e 100644
--- a/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
@@ -20,24 +20,24 @@
 <com.android.systemui.statusbar.policy.KeyguardUserDetailItemView
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:sysui="http://schemas.android.com/apk/res-auto"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:padding="8dp"
-        android:layout_marginEnd="8dp"
+        android:layout_marginEnd="32dp"
         android:gravity="end|center_vertical"
         android:clickable="true"
-        android:background="@drawable/rounded_user_switcher_bg"
-        sysui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
-        sysui:activatedTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.Activated">
+        android:background="@drawable/kg_user_switcher_rounded_bg"
+        sysui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher">
     <TextView android:id="@+id/user_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginEnd="13dp"
+            android:layout_marginStart="25dp"
+            android:layout_marginEnd="12dp"
             android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
             />
     <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
-            android:layout_width="@dimen/framed_avatar_size"
-            android:layout_height="@dimen/framed_avatar_size"
+            android:layout_width="@dimen/kg_framed_avatar_size"
+            android:layout_height="@dimen/kg_framed_avatar_size"
             android:contentDescription="@null"
             sysui:badgeDiameter="18dp"
             sysui:badgeMargin="1dp" />
diff --git a/packages/SystemUI/res/layout/bubble_dismiss_target.xml b/packages/SystemUI/res/layout/bubble_dismiss_target.xml
index ca085b6..f5cd727 100644
--- a/packages/SystemUI/res/layout/bubble_dismiss_target.xml
+++ b/packages/SystemUI/res/layout/bubble_dismiss_target.xml
@@ -17,7 +17,7 @@
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="@dimen/pip_dismiss_gradient_height"
+    android:layout_height="@dimen/floating_dismiss_gradient_height"
     android:layout_gravity="bottom|center_horizontal">
 
     <FrameLayout
diff --git a/packages/SystemUI/res/layout/bubble_overflow_activity.xml b/packages/SystemUI/res/layout/bubble_overflow_activity.xml
index 65b04fd..3060619 100644
--- a/packages/SystemUI/res/layout/bubble_overflow_activity.xml
+++ b/packages/SystemUI/res/layout/bubble_overflow_activity.xml
@@ -20,6 +20,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingTop="@dimen/bubble_overflow_padding"
+    android:paddingLeft="@dimen/bubble_overflow_padding"
+    android:paddingRight="@dimen/bubble_overflow_padding"
     android:orientation="vertical"
     android:layout_gravity="center_horizontal">
 
@@ -39,6 +41,13 @@
         android:orientation="vertical"
         android:gravity="center">
 
+        <ImageView
+            android:layout_width="@dimen/bubble_empty_overflow_image_height"
+            android:layout_height="@dimen/bubble_empty_overflow_image_height"
+            android:id="@+id/bubble_overflow_empty_state_image"
+            android:scaleType="fitCenter"
+            android:layout_gravity="center"/>
+
         <TextView
             android:id="@+id/bubble_overflow_empty_title"
             android:text="@string/bubble_overflow_empty_title"
@@ -57,6 +66,7 @@
             android:text="@string/bubble_overflow_empty_subtitle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:paddingBottom="@dimen/bubble_empty_overflow_subtitle_padding"
             android:gravity="center"/>
     </LinearLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/bubble_overflow_view.xml b/packages/SystemUI/res/layout/bubble_overflow_view.xml
index d67c81d..88a05ec 100644
--- a/packages/SystemUI/res/layout/bubble_overflow_view.xml
+++ b/packages/SystemUI/res/layout/bubble_overflow_view.xml
@@ -37,5 +37,6 @@
         android:layout_height="wrap_content"
         android:maxLines="1"
         android:layout_gravity="center"
+        android:paddingTop="@dimen/bubble_overflow_text_padding"
         android:gravity="center"/>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index b83e500..db81e23 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -40,29 +40,20 @@
 
     <TextView
         android:id="@+id/status"
-        android:layout_width="wrap_content"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:textAppearance="@style/TextAppearance.Control.Status"
         android:paddingTop="@dimen/control_padding_adjustment"
         android:paddingStart="@dimen/control_status_padding"
-        android:clickable="false"
+        android:clickable="true"
         android:focusable="false"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:marqueeRepeatLimit = "marquee_forever"
+        app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintBottom_toBottomOf="@+id/icon"
         app:layout_constraintStart_toEndOf="@+id/icon" />
 
-
-    <TextView
-        android:id="@+id/status_extra"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Control.Status"
-        android:paddingTop="@dimen/control_padding_adjustment"
-        android:paddingStart="@dimen/control_status_padding"
-        android:clickable="false"
-        android:focusable="false"
-        app:layout_constraintBottom_toBottomOf="@+id/icon"
-        app:layout_constraintStart_toEndOf="@+id/status" />
-
     <TextView
         android:id="@+id/title"
         android:layout_width="match_parent"
@@ -109,6 +100,10 @@
         android:layout_height="wrap_content"
         android:layout_gravity="bottom|end"
         android:button="@drawable/controls_btn_star"
+        android:background="@android:color/transparent"
+        android:clickable="false"
+        android:selectable="false"
+        android:importantForAccessibility="no"
         android:layout_marginTop="4dp"
         android:layout_marginStart="4dp"
         app:layout_constraintStart_toEndOf="@id/subtitle"
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
index 50aa212..cb53fe6 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
@@ -27,7 +27,7 @@
     android:paddingRight="@dimen/global_actions_grid_item_side_margin"
     android:layout_marginRight="3dp"
     android:layout_marginLeft="3dp"
-    android:background="@drawable/rounded_bg_full">
+    android:background="@drawable/control_background">
     <LinearLayout
         android:layout_width="@dimen/global_actions_grid_item_width"
         android:layout_height="@dimen/global_actions_grid_item_height"
@@ -42,7 +42,7 @@
             android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
             android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
             android:scaleType="centerInside"
-            android:tint="@color/global_actions_text" />
+            android:tint="@color/control_default_foreground" />
 
         <TextView
             android:id="@*android:id/message"
@@ -53,7 +53,7 @@
             android:singleLine="true"
             android:gravity="center"
             android:textSize="12dp"
-            android:textColor="@color/global_actions_text"
+            android:textColor="@color/control_default_foreground"
             android:textAppearance="?android:attr/textAppearanceSmall" />
 
         <TextView
@@ -62,7 +62,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center"
-            android:textColor="@color/global_actions_text"
+            android:textColor="@color/control_default_foreground"
             android:textAppearance="?android:attr/textAppearanceSmall" />
     </LinearLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
index 92ae1b9..620e2e6 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
@@ -67,9 +67,7 @@
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical"
-          android:layout_marginRight="@dimen/global_actions_grid_horizontal_padding"
-          android:layout_marginLeft="@dimen/global_actions_grid_horizontal_padding"
       />
     </LinearLayout>
   </com.android.systemui.globalactions.MinHeightScrollView>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
index b1e5165..626951c 100644
--- a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
@@ -36,8 +36,8 @@
             android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
             />
     <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
-            android:layout_width="@dimen/framed_avatar_size"
-            android:layout_height="@dimen/framed_avatar_size"
+            android:layout_width="@dimen/kg_framed_avatar_size"
+            android:layout_height="@dimen/kg_framed_avatar_size"
             android:contentDescription="@null"
             android:backgroundTint="@color/qs_user_detail_avatar_tint"
             android:backgroundTintMode="src_atop"
@@ -45,5 +45,5 @@
             sysui:framePadding="2.5dp"
             sysui:badgeDiameter="18dp"
             sysui:badgeMargin="1dp"
-            sysui:frameColor="@color/qs_user_detail_avatar_frame" />
+            sysui:frameColor="@color/kg_user_switcher_rounded_background_color" />
 </com.android.systemui.statusbar.policy.KeyguardUserDetailItemView>
diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml
index 7dcc46c..ec00429 100644
--- a/packages/SystemUI/res/layout/people_strip.xml
+++ b/packages/SystemUI/res/layout/people_strip.xml
@@ -43,6 +43,7 @@
             android:forceHasOverlappingRendering="false">
 
             <TextView
+                android:id="@+id/header_label"
                 style="@style/TextAppearance.NotificationSectionHeaderButton"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/pip_dismiss_view.xml b/packages/SystemUI/res/layout/pip_dismiss_view.xml
deleted file mode 100644
index 2cc4b22..0000000
--- a/packages/SystemUI/res/layout/pip_dismiss_view.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/pip_dismiss_gradient_height"
-    android:alpha="0">
-
-    <TextView
-        android:id="@+id/pip_dismiss_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom|center_horizontal"
-        android:text="@string/pip_phone_dismiss_hint"
-        android:textColor="#FFFFFFFF"
-        android:textSize="14sp"
-        android:shadowColor="@android:color/black"
-        android:shadowDx="-2"
-        android:shadowDy="2"
-        android:shadowRadius="0.01" />
-
-</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_media_panel.xml b/packages/SystemUI/res/layout/qs_media_panel.xml
index fe8557b..fc3bf94 100644
--- a/packages/SystemUI/res/layout/qs_media_panel.xml
+++ b/packages/SystemUI/res/layout/qs_media_panel.xml
@@ -136,6 +136,47 @@
             </LinearLayout>
         </LinearLayout>
 
+        <!-- Seek Bar -->
+        <SeekBar
+            android:id="@+id/media_progress_bar"
+            android:clickable="true"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:maxHeight="3dp"
+            android:paddingTop="24dp"
+            android:paddingBottom="24dp"
+            android:layout_marginBottom="-24dp"
+            android:layout_marginTop="-24dp"
+            android:splitTrack="false"
+        />
+
+        <FrameLayout
+            android:id="@+id/notification_media_progress_time"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            >
+            <!-- width is set to "match_parent" to avoid extra layout calls -->
+            <TextView
+                android:id="@+id/media_elapsed_time"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentLeft="true"
+                android:fontFamily="@*android:string/config_bodyFontFamily"
+                android:textSize="14sp"
+                android:gravity="left"
+            />
+            <TextView
+                android:id="@+id/media_total_time"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:fontFamily="@*android:string/config_bodyFontFamily"
+                android:layout_alignParentRight="true"
+                android:textSize="14sp"
+                android:gravity="right"
+            />
+        </FrameLayout>
+
         <!-- Controls -->
         <LinearLayout
             android:id="@+id/media_actions"
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 5c03e309..0608685 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -30,21 +30,20 @@
         android:clipToPadding="false"
         android:focusable="true"
         android:background="@drawable/ripple_drawable"
-        systemui:regularTextAppearance="@style/TextAppearance.QS.UserSwitcher"
-        systemui:activatedTextAppearance="@style/TextAppearance.QS.UserSwitcher.Activated">
+        systemui:regularTextAppearance="@style/TextAppearance.QS.UserSwitcher">
 
     <com.android.systemui.statusbar.phone.UserAvatarView
             android:id="@+id/user_picture"
-            android:layout_width="@dimen/framed_avatar_size"
-            android:layout_height="@dimen/framed_avatar_size"
+            android:layout_width="@dimen/qs_framed_avatar_size"
+            android:layout_height="@dimen/qs_framed_avatar_size"
             android:layout_marginBottom="7dp"
             android:backgroundTint="@color/qs_user_detail_avatar_tint"
             android:backgroundTintMode="src_atop"
-            systemui:frameWidth="2dp"
-            systemui:framePadding="2.5dp"
+            systemui:frameWidth="6dp"
             systemui:badgeDiameter="18dp"
             systemui:badgeMargin="1dp"
-            systemui:frameColor="@color/qs_user_detail_avatar_frame"/>
+            systemui:framePadding="-1dp"
+            systemui:frameColor="@color/qs_user_avatar_frame"/>
 
     <LinearLayout
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2220b36..ca1af67 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -154,8 +154,7 @@
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"نقش غير صحيح"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"كلمة مرور غير صحيحة"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"تم إجراء عدد كبير جدًا من المحاولات غير الصحيحة.\nأعد المحاولة خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
-    <!-- no translation found for biometric_dialog_credential_attempts_before_wipe (6751859711975516999) -->
-    <skip />
+    <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"يُرجى إعادة المحاولة. المحاولة <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> من <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>"</string>
     <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"سيتم حذف بياناتك"</string>
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف بيانات هذا الجهاز."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف بيانات هذا الجهاز."</string>
@@ -166,14 +165,10 @@
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"عند إدخال نقش غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_device (6585503524026243042) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_user (7015008539146949115) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_profile (5239378521440749682) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_now_wiping_dialog_dismiss (7189432882125106154) -->
-    <skip />
+    <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف بيانات هذا الجهاز."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف هذا المستخدم."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"لقد استنفدت عدد المحاولات غير الصحيحة وسيتم حذف الملف الشخصي للعمل وبياناته."</string>
+    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"إغلاق"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"المس زر استشعار بصمة الإصبع"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"رمز بصمة الإصبع"</string>
     <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"جارٍ البحث عن وجهك…"</string>
@@ -725,17 +720,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"يساعدك هذا الإشعار على التركيز بدون صوت أو اهتزاز."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"يلفت هذا الإشعار انتباهك باستخدام الصوت والاهتزاز."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"يلفِت هذا الإشعار انتباهك لهذا المحتوى باستخدام اختصار عائم."</string>
-    <!-- no translation found for notification_channel_summary_priority (7415770044553264622) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_all_bubble (5389290797101635297) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_settings (2409977688430606835) -->
-    <skip />
-    <!-- no translation found for notification_priority_title (2079708866333537093) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"تظهر كفقاعة في أعلى قسم المحادثات"</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"تظهر كل المحادثات من تطبيق <xliff:g id="APP_NAME_0">%1$s</xliff:g> كفقاعات تلقائيًا. يمكنك إدارة هذا الإعداد في <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
+    <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"الإعدادات"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"الأولوية"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"ليس هناك فقاعات حديثة"</string>
-    <!-- no translation found for bubble_overflow_empty_subtitle (2030874469510497397) -->
-    <skip />
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"ستظهر هنا أحدث الفقاعات والفقاعات التي تم إغلاقها."</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"يتعذّر تعديل هذه الإشعارات."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"يتعذّر ضبط مجموعة الإشعارات هذه هنا."</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"إشعار مستند إلى خادم وكيل"</string>
@@ -942,7 +932,7 @@
     <string name="pip_pause" msgid="1139598607050555845">"إيقاف مؤقت"</string>
     <string name="pip_skip_to_next" msgid="3864212650579956062">"التخطي إلى التالي"</string>
     <string name="pip_skip_to_prev" msgid="3742589641443049237">"التخطي إلى السابق"</string>
-    <string name="thermal_shutdown_title" msgid="2702966892682930264">"تم إيقاف تفعيل الهاتف بسبب الحرارة"</string>
+    <string name="thermal_shutdown_title" msgid="2702966892682930264">"تم إيقاف الهاتف بسبب الحرارة"</string>
     <string name="thermal_shutdown_message" msgid="7432744214105003895">"يعمل هاتفك الآن بشكل طبيعي"</string>
     <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"ارتفعت درجة حرارة هاتفك بشدة، لذا تم إيقاف تشغيله لخفض درجة حرارته. يعمل هاتفك الآن بشكل طبيعي.\n\nقد ترتفع بشدة درجة حرارة هاتفك إذا:\n	• استخدمت تطبيقات كثيفة الاستخدام لموارد الجهاز (مثل الألعاب أو الفيديو أو تطبيقات التنقل)\n	• نزَّلت أو حمَّلت ملفات كبيرة الحجم\n	• استخدمت هاتفك وسط أجواء مرتفعة الحرارة"</string>
     <string name="high_temp_title" msgid="2218333576838496100">"تزداد درجة حرارة الهاتف"</string>
@@ -1023,17 +1013,12 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"نقل إلى أسفل يمين الشاشة"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"نقل إلى أسفل اليسار"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"تجاهل"</string>
-    <!-- no translation found for bubbles_dont_bubble_conversation (1033040343437428822) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_title (5547017089271445797) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_description (1160281719576715211) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_manage_title (2848511858160342320) -->
-    <skip />
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"عدم عرض المحادثة كفقاعة"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"الدردشة باستخدام الفقاعات"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"تظهر المحادثات الجديدة كرموز عائمة أو فقاعات. انقر عليها لفتحها كفقاعة أو اسحبها لتحريكها."</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"التحكّم في الفقاعات في أي وقت"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"انقر على \"إدارة\" لإيقاف الفقاعات من هذا التطبيق."</string>
-    <!-- no translation found for bubbles_user_education_got_it (8282812431953161143) -->
-    <skip />
+    <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"حسنًا"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"تم تحديث التنقل داخل النظام. لإجراء التغييرات، يُرجى الانتقال إلى \"الإعدادات\"."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"الانتقال إلى \"الإعدادات\" لتعديل التنقل داخل النظام"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"وضع الاستعداد"</string>
@@ -1041,8 +1026,7 @@
     <string name="magnification_window_title" msgid="4863914360847258333">"نافذة التكبير"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"عناصر التحكم في نافذة التكبير"</string>
     <string name="quick_controls_title" msgid="1686913115679255053">"عناصر التحكّم السريعة"</string>
-    <!-- no translation found for quick_controls_subtitle (1667408093326318053) -->
-    <skip />
+    <string name="quick_controls_subtitle" msgid="1667408093326318053">"إضافة عناصر تحكّم لأجهزتك المتصلة"</string>
     <string name="quick_controls_setup_title" msgid="9079435969373471268">"إعداد عناصر التحكّم السريعة"</string>
     <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"اضغط مع الاستمرار على زر التشغيل للوصول إلى عناصر التحكّم"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"اختيار تطبيق لإضافة عناصر التحكّم"</string>
@@ -1055,45 +1039,28 @@
       <item quantity="one">تمت إضافة عنصر تحكّم واحد (<xliff:g id="NUMBER_0">%s</xliff:g>).</item>
     </plurals>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"عناصر التحكّم"</string>
-    <!-- no translation found for controls_favorite_subtitle (6604402232298443956) -->
-    <skip />
-    <!-- no translation found for controls_favorite_rearrange (7364147066539766260) -->
-    <skip />
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"اختيار عناصر التحكّم التي تريد الوصول إليها من قائمة التشغيل"</string>
+    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"اضغط مع الاستمرار على عنصر تحكّم واسحبه لتحريكه."</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"تعذّر تحميل قائمة كل عناصر التحكّم."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"غير ذلك"</string>
-    <!-- no translation found for controls_dialog_title (3475025327938684220) -->
-    <skip />
+    <string name="controls_dialog_title" msgid="3475025327938684220">"إضافة إلى عناصر التحكم السريعة"</string>
     <string name="controls_dialog_ok" msgid="7011816381344485651">"إضافة إلى الإعدادات المفضّلة"</string>
     <string name="controls_dialog_message" msgid="6292099631702047540">"اقترح تطبيق <xliff:g id="APP">%s</xliff:g> إضافة عنصر التحكّم هذا إلى الإعدادات المفضّلة."</string>
-    <!-- no translation found for controls_dialog_confirmation (586517302736263447) -->
-    <skip />
+    <string name="controls_dialog_confirmation" msgid="586517302736263447">"تم تعديل عناصر التحكّم."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"يشتمل رقم التعريف الشخصي على أحرف أو رموز."</string>
-    <!-- no translation found for controls_pin_verify (3452778292918877662) -->
-    <skip />
-    <!-- no translation found for controls_pin_verifying (3755045989392131746) -->
-    <skip />
+    <string name="controls_pin_verify" msgid="3452778292918877662">"إثبات ملكية <xliff:g id="DEVICE">%s</xliff:g>"</string>
+    <string name="controls_pin_verifying" msgid="3755045989392131746">"جارٍ التحقّق…"</string>
     <string name="controls_pin_instructions" msgid="6363309783822475238">"إدخال رقم التعريف الشخصي"</string>
-    <!-- no translation found for controls_pin_instructions_retry (1566667581012131046) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_confirming (2596071302617310665) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_message (7744104992609594859) -->
-    <skip />
-    <!-- no translation found for controls_structure_tooltip (4355922222944447867) -->
-    <skip />
+    <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"حاوِل إدخال رقم تعريف شخصي آخر"</string>
+    <string name="controls_confirmation_confirming" msgid="2596071302617310665">"جارٍ التأكيد…"</string>
+    <string name="controls_confirmation_message" msgid="7744104992609594859">"تأكيد التغيير لـ <xliff:g id="DEVICE">%s</xliff:g>"</string>
+    <string name="controls_structure_tooltip" msgid="4355922222944447867">"مرّر سريعًا لرؤية المزيد."</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string>
-    <!-- no translation found for controls_media_close_session (9023534788828414585) -->
-    <skip />
-    <!-- no translation found for controls_error_timeout (794197289772728958) -->
-    <skip />
-    <!-- no translation found for controls_error_failed (960228639198558525) -->
-    <skip />
-    <!-- no translation found for controls_in_progress (4421080500238215939) -->
-    <skip />
-    <!-- no translation found for controls_added_tooltip (4842812921719153085) -->
-    <skip />
-    <!-- no translation found for controls_menu_add (4447246119229920050) -->
-    <skip />
-    <!-- no translation found for controls_menu_edit (890623986951347062) -->
-    <skip />
+    <string name="controls_media_close_session" msgid="9023534788828414585">"إغلاق جلسة تشغيل الوسائط هذه"</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
+    <string name="controls_error_failed" msgid="960228639198558525">"حدث خطأ، يُرجى إعادة المحاولة."</string>
+    <string name="controls_in_progress" msgid="4421080500238215939">"قيد التقدم"</string>
+    <string name="controls_added_tooltip" msgid="4842812921719153085">"اضغط مع الاستمرار على زر التشغيل لعرض عناصر التحكّم الجديدة."</string>
+    <string name="controls_menu_add" msgid="4447246119229920050">"إضافة عناصر تحكّم"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"تعديل عناصر التحكّم"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 4e3b899..17dba43 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -155,26 +155,16 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ভুল পাছৱৰ্ড"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"বহুসংখ্যক ভুল প্ৰয়াস।\n<xliff:g id="NUMBER">%d</xliff:g>ছেকেণ্ডত পুনৰ চেষ্টা কৰক।"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"আকৌ চেষ্টা কৰক। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> টাৰ প্ৰয়াসৰ ভিতৰত <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> টা প্ৰয়াস।"</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"আপোনাৰ ডেটা মচি পেলোৱা হ’ব"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল আৰ্হি দিলে, এই ডিভাইচটোৰ ডেটা মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পিন দিলে, এই ডিভাইচটোৰ ডেটা মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পাছৱৰ্ড দিলে, এই ডিভাইচটোৰ ডেটা মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল আৰ্হি দিলে, এই ব্যৱহাৰকাৰীক মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পিন দিলে, এই ব্যৱহাৰকাৰীক মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পাছৱৰ্ড দিলে, এই ব্যৱহাৰকাৰীক মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল আৰ্হি দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পিন দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পাছৱৰ্ড দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"বহুসংখ্যক ভুল প্ৰয়াস। এই ডিভাইচটোৰ ডেটা মচা হ\'ব।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"বহুসংখ্যক ভুল প্ৰয়াস। এই ব্যৱহাৰকাৰীক মচা হ\'ব।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"বহুসংখ্যক ভুল প্ৰয়াস। এই কৰ্মস্থানৰ প্ৰ\'ফাইলটো আৰু তাৰ লগত জড়িত ডেটা মচা হ\'ব।"</string>
@@ -813,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"এছএমএছ"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"সংগীত"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"কেলেণ্ডাৰ"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"ভলিউম নিয়ন্ত্ৰণৰ সৈতে দেখুৱাওক"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"অসুবিধা নিদিব"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বুটামসমূহৰ শ্বৰ্টকাট"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c67291e..047d00b 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -155,26 +155,16 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ভুল পাসওয়ার্ড"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"অনেকবার ভুল চেষ্টা করা হয়েছে। \n<xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"আবার চেষ্টা করুন। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> বারের মধ্যে <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> বার চেষ্টা করা হয়েছে।"</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"আপনার ডেটা মুছে দেওয়া হবে"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"আপনি পরের বারও ভুল প্যাটার্ন আঁকলে এই ডিভাইসের ডেটা মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"আপনি পরের বারও ভুল পিন দিলে এই ডিভাইসের ডেটা মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"আপনি পরের বারও ভুল পাসওয়ার্ড দিলে এই ডিভাইসের ডেটা মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"আপনি পরের বারও ভুল প্যাটার্ন আঁকলে আপনাকে ব্যবহারকারীর তালিকা থেকে মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"আপনি পরের বারও ভুল পিন দিলে আপনাকে ব্যবহারকারীর তালিকা থেকে মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"আপনি পরের বারও ভুল পাসওয়ার্ড দিলে আপনাকে ব্যবহারকারীর তালিকা থেকে মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"আপনি পরের বারও ভুল প্যাটার্ন দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"আপনি পরের বারও ভুল পিন দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"আপনি পরের বারও ভুল পাসওয়ার্ড দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"বহুবার ভুল লেখা হয়েছে। এই ডিভাইসের ডেটা মুছে যাবে।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"বহুবার ভুল লেখা হয়েছে। এই ব্যবহারকারীর ডেটা মুছে যাবে।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"বহুবার ভুল লেখা হয়েছে। এই অফিসের প্রোফাইল ও সংশ্লিষ্ট ডেটা মুছে যাবে।"</string>
@@ -813,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"সংগীত"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ক্যালেন্ডার"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"ভলিউম নিয়ন্ত্রণ সহ দেখান"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"বিরক্ত করবে না"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বোতামের শর্টকাট"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 16121c3..9e7bfb9 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -168,7 +168,7 @@
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"Hubo demasiados intentos incorrectos. Se borrarán los datos del dispositivo."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"Hubo demasiados intentos incorrectos. Se borrará este usuario."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"Hubo demasiados intentos incorrectos. Se borrarán este perfil de trabajo y sus datos."</string>
-    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"Ignorar"</string>
+    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"Descartar"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícono de huella digital"</string>
     <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Autenticando tu rostro…"</string>
@@ -508,7 +508,7 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificaciones silenciosas"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificaciones que alertan"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificaciones de alerta"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borrar todas las notificaciones silenciosas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificaciones pausadas por el modo \"No interrumpir\""</string>
@@ -708,12 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Te ayuda a concentrarte sin sonar ni vibrar."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Capta tu atención con sonido o vibración."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Retiene tu atención con un acceso directo flotante a este contenido."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Aparece como una burbuja en la parte superior de la sección de conversación."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Aparece como una burbuja en la parte superior de la sección de la conversación."</string>
     <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Todas las conversaciones de <xliff:g id="APP_NAME_0">%1$s</xliff:g> se muestran como burbujas de forma predeterminada. Administra esta opción en <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"No hay burbujas recientes"</string>
-    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Las burbujas recientes y las descartadas aparecerán aquí"</string>
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Las burbujas recientes y las que se descartaron aparecerán aquí"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"No se pueden modificar estas notificaciones."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"No se puede configurar aquí este grupo de notificaciones"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"Notificación almacenada en proxy"</string>
@@ -993,9 +993,9 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Ubicar abajo a la izquierda"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Ubicar abajo a la derecha"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ignorar"</string>
-    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No colocar la conversación en burbuja"</string>
-    <string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat mediante burbujas"</string>
-    <string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como íconos flotantes o burbujas. Pulsa para abrir la burbuja. Arrástrala para moverla."</string>
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostrar la conversación en burbujas"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat con burbujas"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como elementos flotantes o burbujas. Presiona para abrir la burbuja. Arrástrala para moverla."</string>
     <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla las burbujas en todo momento"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Presiona Administrar para desactivar las burbujas de esta app"</string>
     <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Entendido"</string>
@@ -1033,10 +1033,10 @@
     <string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más elementos"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
     <string name="controls_media_close_session" msgid="9023534788828414585">"Cerrar esta sesión multimedia"</string>
-    <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, verifica la app"</string>
-    <string name="controls_error_failed" msgid="960228639198558525">"Se produjo un error, vuelve a intentarlo."</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
+    <string name="controls_error_failed" msgid="960228639198558525">"Error. Vuelve a intentarlo."</string>
     <string name="controls_in_progress" msgid="4421080500238215939">"En curso"</string>
-    <string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén pulsado el botón de encendido para ver los nuevos controles"</string>
+    <string name="controls_added_tooltip" msgid="4842812921719153085">"Mantén presionado el botón de encendido para ver los nuevos controles"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Agregar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 645d2bd..d670023 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -88,7 +88,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Cerrar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="669177537416980449">"Abrir captura de pantalla"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"Grabadora de pantalla"</string>
+    <string name="screenrecord_name" msgid="2596401223859996572">"Grabación de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"¿Empezar a grabar?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Mientras grabas, el sistema Android puede capturar información sensible que se muestre o se reproduzca en tu dispositivo, como contraseñas, datos de pago, fotos, mensajes y audios."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1adf7c7..1688fc3 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -780,8 +780,8 @@
     <string name="keyboard_key_media_previous" msgid="5637875709190955351">"Aurrekoa"</string>
     <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Atzeratu"</string>
     <string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"Aurreratu"</string>
-    <string name="keyboard_key_page_up" msgid="173914303254199845">"Orria gora"</string>
-    <string name="keyboard_key_page_down" msgid="9035902490071829731">"Orria behera"</string>
+    <string name="keyboard_key_page_up" msgid="173914303254199845">"Orrian gora"</string>
+    <string name="keyboard_key_page_down" msgid="9035902490071829731">"Orrian behera"</string>
     <string name="keyboard_key_forward_del" msgid="5325501825762733459">"Ezabatu"</string>
     <string name="keyboard_key_move_home" msgid="3496502501803911971">"Hasiera"</string>
     <string name="keyboard_key_move_end" msgid="99190401463834854">"Amaitu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index c5f18974..e719c53 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -708,12 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"به شما کمک می‌کند بدون صدا یا لرزش تمرکز کنید."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"با صدا یا لرزش توجه شما را جلب می‌کند."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"با میان‌بری شناور به این محتوا، توجه‌تان را جلب می‌کند."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"در بالای بخش مکالمه نمایش داده می‌شود و به‌صورت حباب نمایان می‌شود."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"در بالای بخش مکالمه نمایش داده می‌شود و به‌صورت ابزارک اعلان نمایان می‌شود."</string>
     <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"همه مکالمه‌های <xliff:g id="APP_NAME_0">%1$s</xliff:g>، به‌طور پیش‌فرض در حباب نمایش داده می‌شوند. در <xliff:g id="APP_NAME_1">%2$s</xliff:g> مدیریت کنید."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"تنظیمات"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"اولویت"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"هیچ ابزارک اعلان جدیدی وجود ندارد"</string>
-    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"حباب‌های اخیر و حباب‌های ردشده اینجا ظاهر خواهند شد"</string>
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"ابزارک اعلان اخیر و ابزارک اعلان ردشده اینجا ظاهر خواهند شد"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"این اعلان‌ها قابل اصلاح نیستند."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"نمی‌توانید این گروه اعلان‌ها را در اینجا پیکربندی کنید"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"اعلان‌های دارای پراکسی"</string>
@@ -994,10 +994,10 @@
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"انتقال به پایین سمت چپ"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"رد کردن"</string>
     <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"مکالمه در حباب نشان داده نشود"</string>
-    <string name="bubbles_user_education_title" msgid="5547017089271445797">"گپ بااستفاده از حباب‌ها"</string>
-    <string name="bubbles_user_education_description" msgid="1160281719576715211">"مکالمه‌های جدید به‌صورت نمادهای شناور یا حباب نشان داده شوند. برای باز کردن حباب ضربه بزنید. برای جابه‌جایی، آن را بکشید."</string>
-    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"کنترل حباب‌ها در هرزمانی"</string>
-    <string name="bubbles_user_education_manage" msgid="1391639189507036423">"برای خاموش کردن «حباب‌ها» از این برنامه، روی «مدیریت» ضربه بزنید"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"گپ بااستفاده از ابزارک اعلان"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"مکالمه‌های جدید به‌صورت نمادهای شناور یا ابزارک اعلان نشان داده شوند. برای باز کردن ابزارک اعلان ضربه بزنید. برای جابه‌جایی، آن را بکشید."</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"کنترل ابزارک اعلان در هرزمانی"</string>
+    <string name="bubbles_user_education_manage" msgid="1391639189507036423">"برای خاموش کردن «ابزارک اعلان» از این برنامه، روی «مدیریت» ضربه بزنید"</string>
     <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"متوجه‌ام"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"پیمایش سیستم به‌روزرسانی شد. برای انجام تغییرات به «تنظیمات» بروید."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"برای به‌روزرسانی پیمایش سیستم، به «تنظیمات» بروید"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 663ad0f..bd86b08 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -847,7 +847,7 @@
     <string name="right_keycode" msgid="2480715509844798438">"Code de touche droit"</string>
     <string name="left_icon" msgid="5036278531966897006">"Icône à gauche"</string>
     <string name="right_icon" msgid="1103955040645237425">"Icône droite"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Maint. doigt sur écran, puis glissez-le pour ajouter tuiles"</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Sélectionnez et faites glisser les tuiles pour les ajouter"</string>
     <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Maint. doigt sur l\'écran, puis glissez-le pour réorg. tuiles"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Faites glisser les tuiles ici pour les supprimer"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"Vous avez besoin d\'au moins <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tuiles"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 26128d1..f781c3f 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -154,36 +154,21 @@
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ખોટી પૅટર્ન"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ખોટો પાસવર્ડ"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ઘણા વધારે ખોટા પ્રયત્નો. \n <xliff:g id="NUMBER">%d</xliff:g> સેકંડમાં ફરી પ્રયાસ કરો."</string>
-    <!-- no translation found for biometric_dialog_credential_attempts_before_wipe (6751859711975516999) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_device (6585503524026243042) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_user (7015008539146949115) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_profile (5239378521440749682) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_now_wiping_dialog_dismiss (7189432882125106154) -->
-    <skip />
+    <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ફરી પ્રયાસ કરો. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> માંથી <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> પ્રયત્ન."</string>
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"તમારો ડેટા ડિલીટ કરવામાં આવશે"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"જો તમે આગલા પ્રયત્નમાં ખોટી પૅટર્ન દાખલ કરશો, તો આ ડિવાઇસનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"જો તમે આગલા પ્રયત્નમાં ખોટો પિન દાખલ કરશો, તો આ ડિવાઇસનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"જો તમે આગલા પ્રયત્નમાં ખોટો પાસવર્ડ દાખલ કરશો, તો આ ડિવાઇસનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"જો તમે આગલા પ્રયત્નમાં ખોટી પૅટર્ન દાખલ કરશો, તો આ વપરાશકર્તાને ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"જો તમે આગલા પ્રયત્નમાં ખોટો પિન દાખલ કરશો, તો આ વપરાશકર્તાને ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"જો તમે આગલા પ્રયત્નમાં ખોટો પાસવર્ડ દાખલ કરશો, તો આ વપરાશકર્તાને ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"જો તમે આગલા પ્રયત્નમાં ખોટી પૅટર્ન દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"જો તમે આગલા પ્રયત્નમાં ખોટો પિન દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"જો તમે આગલા પ્રયત્નમાં ખોટો પાસવર્ડ દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"ઘણા બધા ખોટા પ્રયત્નો. આ ડિવાઇસનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"ઘણા બધા ખોટા પ્રયત્નો. આ વપરાશકર્તાને ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"ઘણા બધા ખોટા પ્રયત્નો. આ કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
+    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"છોડી દો"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ફિંગરપ્રિન્ટનું આઇકન"</string>
     <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"તમારા માટે શોધી રહ્યાં છે..."</string>
@@ -723,17 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"તમને સાઉન્ડ અથવા વાઇબ્રેશન વિના ફોકસ કરવામાં સહાય કરે છે."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"સાઉન્ડ અથવા વાઇબ્રેશન વિના તમારું ધ્યાન દોરે છે."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ફ્લોટિંગ શૉર્ટકટથી આ કન્ટેન્ટ પર તમારું ધ્યાન દોરી રાખે છે."</string>
-    <!-- no translation found for notification_channel_summary_priority (7415770044553264622) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_all_bubble (5389290797101635297) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_settings (2409977688430606835) -->
-    <skip />
-    <!-- no translation found for notification_priority_title (2079708866333537093) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"વાતચીત વિભાગની ટોચ પર બતાવે છે અને બબલ તરીકે દેખાય છે."</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>ની બધી વાતચીતને ડિફૉલ્ટ તરીકે બબલ કરવામાં આવે છે. <xliff:g id="APP_NAME_1">%2$s</xliff:g>માં મેનેજ કરો."</string>
+    <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"સેટિંગ"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"પ્રાધાન્યતા"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"તાજેતરના કોઈ બબલ નથી"</string>
-    <!-- no translation found for bubble_overflow_empty_subtitle (2030874469510497397) -->
-    <skip />
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"એકદમ નવા બબલ અને છોડી દીધેલા બબલ અહીં દેખાશે"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"આ નોટિફિકેશનમાં કોઈ ફેરફાર થઈ શકશે નહીં."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"નોટિફિકેશનના આ ગ્રૂપની ગોઠવણી અહીં કરી શકાશે નહીં"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"પ્રૉક્સી નોટિફિકેશન"</string>
@@ -823,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"સંગીત"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"કૅલેન્ડર"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"વૉલ્યૂમ નિયંત્રણ સાથે બતાવો"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ખલેલ પાડશો નહીં"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"વૉલ્યૂમ બટન્સ શૉર્ટકટ"</string>
@@ -1013,77 +993,50 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"નીચે ડાબે ખસેડો"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"નીચે જમણે ખસેડો"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"છોડી દો"</string>
-    <!-- no translation found for bubbles_dont_bubble_conversation (1033040343437428822) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_title (5547017089271445797) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_description (1160281719576715211) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_manage_title (2848511858160342320) -->
-    <skip />
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"વાતચીતને બબલ કરશો નહીં"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"બબલનો ઉપયોગ કરીને ચેટ કરો"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"નવી વાતચીત ફ્લોટિંગ આઇકન અથવા બબલ જેવી દેખાશે. બબલને ખોલવા માટે ટૅપ કરો. તેને ખસેડવા માટે ખેંચો."</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"બબલને કોઈપણ સમયે નિયંત્રિત કરો"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"આ ઍપમાંથી બબલને બંધ કરવા માટે મેનેજ કરો પર ટૅપ કરો"</string>
-    <!-- no translation found for bubbles_user_education_got_it (8282812431953161143) -->
-    <skip />
+    <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"સમજાઈ ગયું"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"સિસ્ટમ નૅવિગેશન અપડેટ કર્યું. ફેરફારો કરવા માટે, સેટિંગ પર જાઓ."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"સિસ્ટમ નૅવિગેશનને અપડેટ કરવા માટે સેટિંગ પર જાઓ"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"સ્ટૅન્ડબાય"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"વિસ્તૃતીકરણ ઓવરલે વિંડો"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
-    <!-- no translation found for quick_controls_title (1686913115679255053) -->
-    <skip />
-    <!-- no translation found for quick_controls_subtitle (1667408093326318053) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_title (9079435969373471268) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_subtitle (1681506617879773824) -->
-    <skip />
-    <!-- no translation found for controls_providers_title (6879775889857085056) -->
-    <skip />
+    <string name="quick_controls_title" msgid="1686913115679255053">"ઝડપી નિયંત્રણો"</string>
+    <string name="quick_controls_subtitle" msgid="1667408093326318053">"તમારા કનેક્ટ કરેલા ડિવાઇસ માટે નિયંત્રણો ઉમેરો"</string>
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"ઝડપી નિયંત્રણો સેટઅપ કરો"</string>
+    <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"તમારા નિયંત્રણોને ઍક્સેસ કરવા માટે પાવર બટન દબાવી રાખો"</string>
+    <string name="controls_providers_title" msgid="6879775889857085056">"નિયંત્રણો ઉમેરવા માટે ઍપ પસંદ કરો"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> નિયંત્રણ ઉમેર્યું.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> નિયંત્રણો ઉમેર્યા.</item>
     </plurals>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"નિયંત્રણો"</string>
-    <!-- no translation found for controls_favorite_subtitle (6604402232298443956) -->
-    <skip />
-    <!-- no translation found for controls_favorite_rearrange (7364147066539766260) -->
-    <skip />
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"પાવર મેનૂમાંથી ઍક્સેસ કરવા માટેના નિયંત્રણોને પસંદ કરો"</string>
+    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"નિયંત્રણને ખસેડવા માટે તેના પર આંગળી દબાવીને ખેંચો"</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"બધા નિયંત્રણોની સૂચિ લોડ કરી શકાઈ નથી."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"અન્ય"</string>
-    <!-- no translation found for controls_dialog_title (3475025327938684220) -->
-    <skip />
+    <string name="controls_dialog_title" msgid="3475025327938684220">"ઝડપી નિયંત્રણોમાં ઉમેરો"</string>
     <string name="controls_dialog_ok" msgid="7011816381344485651">"મનપસંદમાં ઉમેરો"</string>
     <string name="controls_dialog_message" msgid="6292099631702047540">"<xliff:g id="APP">%s</xliff:g> એ આ નિયંત્રણને તમારા મનપસંદમાં ઉમેરવાનું સૂચવ્યું છે."</string>
-    <!-- no translation found for controls_dialog_confirmation (586517302736263447) -->
-    <skip />
+    <string name="controls_dialog_confirmation" msgid="586517302736263447">"નિયંત્રણ અપડેટ કર્યા"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"પિનમાં અક્ષરો અથવા પ્રતીકોનો સમાવેશ થાય છે"</string>
-    <!-- no translation found for controls_pin_verify (3452778292918877662) -->
-    <skip />
-    <!-- no translation found for controls_pin_verifying (3755045989392131746) -->
-    <skip />
+    <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>ને ચકાસો"</string>
+    <string name="controls_pin_verifying" msgid="3755045989392131746">"ચકાસી રહ્યાં છીએ…"</string>
     <string name="controls_pin_instructions" msgid="6363309783822475238">"પિન દાખલ કરો"</string>
-    <!-- no translation found for controls_pin_instructions_retry (1566667581012131046) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_confirming (2596071302617310665) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_message (7744104992609594859) -->
-    <skip />
-    <!-- no translation found for controls_structure_tooltip (4355922222944447867) -->
-    <skip />
+    <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"બીજા પિનને અજમાવી જુઓ"</string>
+    <string name="controls_confirmation_confirming" msgid="2596071302617310665">"કન્ફર્મ કરી રહ્યાં છે…"</string>
+    <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> માટે ફેરફાર કન્ફર્મ કરો"</string>
+    <string name="controls_structure_tooltip" msgid="4355922222944447867">"વધુ જોવા માટે સ્વાઇપ કરો"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string>
-    <!-- no translation found for controls_media_close_session (9023534788828414585) -->
-    <skip />
-    <!-- no translation found for controls_error_timeout (794197289772728958) -->
-    <skip />
-    <!-- no translation found for controls_error_failed (960228639198558525) -->
-    <skip />
-    <!-- no translation found for controls_in_progress (4421080500238215939) -->
-    <skip />
-    <!-- no translation found for controls_added_tooltip (4842812921719153085) -->
-    <skip />
-    <!-- no translation found for controls_menu_add (4447246119229920050) -->
-    <skip />
-    <!-- no translation found for controls_menu_edit (890623986951347062) -->
-    <skip />
+    <string name="controls_media_close_session" msgid="9023534788828414585">"આ મીડિયા સત્રને બંધ કરો"</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
+    <string name="controls_error_failed" msgid="960228639198558525">"ભૂલ, ફરીથી પ્રયાસ કરો"</string>
+    <string name="controls_in_progress" msgid="4421080500238215939">"પ્રક્રિયા ચાલુ છે"</string>
+    <string name="controls_added_tooltip" msgid="4842812921719153085">"નવા નિયંત્રણ જોવા માટે પાવર બટનને દબાવી રાખો"</string>
+    <string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index fcba17a..107edb8 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -159,9 +159,9 @@
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"अगर आप फिर से गलत पैटर्न डालते हैं, तो इस डिवाइस का डेटा मिटा दिया जाएगा."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"अगर आप फिर से गलत पिन डालते हैं, तो इस डिवाइस का डेटा मिटा दिया जाएगा."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"अगर आप फिर से गलत पासवर्ड डालते हैं, तो इस डिवाइस का डेटा मिटा दिया जाएगा."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"अगर आप फिर से गलत पैटर्न डालते हैं, तो इस उपयोगकर्ता का डेटा मिटा दिया जाएगा."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"अगर आप फिर से गलत पिन डालते हैं, तो इस उपयोगकर्ता का डेटा मिटा दिया जाएगा."</string>
-    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"अगर आप फिर से गलत पासवर्ड डालते हैं, तो इस उपयोगकर्ता का डेटा मिटा दिया जाएगा."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"अगर आप फिर से गलत पैटर्न डालते हैं, तो इस उपयोगकर्ता को हटा दिया जाएगा."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"अगर आप फिर से गलत पिन डालते हैं, तो इस उपयोगकर्ता को हटा दिया जाएगा."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"अगर आप फिर से गलत पासवर्ड डालते हैं, तो इस उपयोगकर्ता को हटा दिया जाएगा."</string>
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"अगर आप फिर से गलत पैटर्न डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"अगर आप फिर से गलत पिन डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"अगर आप फिर से गलत पासवर्ड डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
@@ -1007,9 +1007,9 @@
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Magnification Overlay Window"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"स्क्रीन को बड़ा करके दिखाने वाली विंडो"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"स्क्रीन को बड़ा करके दिखाने वाली विंडो के नियंत्रण"</string>
-    <string name="quick_controls_title" msgid="1686913115679255053">"फटाफट कंट्रोल"</string>
+    <string name="quick_controls_title" msgid="1686913115679255053">"क्विक कंट्रोल"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"कनेक्ट किए गए डिवाइस के लिए कंट्रोल जोड़ें"</string>
-    <string name="quick_controls_setup_title" msgid="9079435969373471268">"फटाफट कंट्रोल सेट अप करें"</string>
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"क्विक कंट्रोल सेट अप करें"</string>
     <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"कंट्रोल ऐक्सेस करने के लिए पावर बटन को दबाकर रखें"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"कंट्रोल जोड़ने के लिए ऐप्लिकेशन चुनें"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c3220e3..875bc4f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -708,7 +708,7 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Favorisce la tua concentrazione grazie all\'assenza di suono o vibrazione."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Richiama la tua attenzione con suono o vibrazione."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantiene la tua attenzione con una scorciatoia mobile a questi contenuti."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Visualizzata nella parte superiore della sezione della conversazione e viene mostrata come bolla."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Appare in cima alla sezione delle conversazioni sotto forma di bolla."</string>
     <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Per impostazione predefinita, tutte le conversazioni di <xliff:g id="APP_NAME_0">%1$s</xliff:g> vengono mostrate come bolle. Gestisci in <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Impostazioni"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 1ddecfb..5c3dabb 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -154,36 +154,21 @@
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ಪಾಸ್‌ವರ್ಡ್ ತಪ್ಪಾಗಿದೆ"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ಹಲವಾರು ತಪ್ಪು ಪ್ರಯತ್ನಗಳು.\nಮತ್ತೆ <xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <!-- no translation found for biometric_dialog_credential_attempts_before_wipe (6751859711975516999) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_device (6585503524026243042) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_user (7015008539146949115) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_profile (5239378521440749682) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_now_wiping_dialog_dismiss (7189432882125106154) -->
-    <skip />
+    <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ. <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>/<xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ಪ್ರಯತ್ನಗಳು."</string>
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪ್ಯಾಟರ್ನ್‌ ನಮೂದಿಸಿದರೆ, ಈ ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಿನ್ ನಮೂದಿಸಿದರೆ, ಈ ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನಮೂದಿಸಿದರೆ, ಈ ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪ್ಯಾಟರ್ನ್ ನಮೂದಿಸಿದರೆ, ಈ ಬಳಕೆದಾರರನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಿನ್ ನಮೂದಿಸಿದರೆ, ಈ ಬಳಕೆದಾರರನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿದರೆ, ಈ ಬಳಕೆದಾರರನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪ್ಯಾಟರ್ನ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಿನ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"ಹಲವಾರು ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"ಹಲವಾರು ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಬಳಕೆದಾರರನ್ನು ಅಳಿಸಲಾಗುವುದು."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"ಹಲವಾರು ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಈ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"ವಜಾಗೊಳಿಸಿ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ನಿಮಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
@@ -723,17 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"ಶಬ್ದ ಅಥವಾ ವೈಬ್ರೇಷನ್ ಇರದಂತೆ ನಿಮಗೆ ಗಮನಹರಿಸಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"ಧ್ವನಿ ಅಥವಾ ವೈಬ್ರೇಷನ್ ಮೂಲಕ ನಿಮ್ಮ ಗಮನವನ್ನು ಸೆಳೆಯುತ್ತದೆ."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ಈ ವಿಷಯಕ್ಕೆ ಲಿಂಕ್ ಮಾಡಿ ಕೊಂಡೊಯ್ಯುವ ಶಾರ್ಟ್‌ಕಟ್‌ ಕಡೆಗೆ ಗಮನ ಇರಿಸಿ."</string>
-    <!-- no translation found for notification_channel_summary_priority (7415770044553264622) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_all_bubble (5389290797101635297) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_settings (2409977688430606835) -->
-    <skip />
-    <!-- no translation found for notification_priority_title (2079708866333537093) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"ಸಂಭಾಷಣೆ ವಿಭಾಗದ ಮೇಲ್ಬಾಗದಲ್ಲಿ ಕಾಣಿಸುತ್ತದೆ ಮತ್ತು ಬಬಲ್‌ನಂತೆ ಗೋಚರಿಸುತ್ತದೆ."</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"ಡೀಫಾಲ್ಟ್ ಆಗಿ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ನ ಎಲ್ಲಾ ಸಂಭಾಷಣೆಗಳನ್ನು ಬಬಲ್‌ ಆಗಿ ತೋರಿಸಿ. <xliff:g id="APP_NAME_1">%2$s</xliff:g> ನಲ್ಲಿ ನಿರ್ವಹಿಸಿ."</string>
+    <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"ಆದ್ಯತೆ"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಬಬಲ್‌ಗಳಿಲ್ಲ"</string>
-    <!-- no translation found for bubble_overflow_empty_subtitle (2030874469510497397) -->
-    <skip />
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"ಇತ್ತೀಚಿನ ಬಬಲ್ಸ್ ಮತ್ತು ವಜಾಗೊಳಿಸಿದ ಬಬಲ್ಸ್ ಇಲ್ಲಿ ಗೋಚರಿಸುತ್ತವೆ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ಈ ಗುಂಪಿನ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇಲ್ಲಿ ಕಾನ್ಫಿಗರ್‌ ಮಾಡಲಾಗಿರುವುದಿಲ್ಲ"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"ಪ್ರಾಕ್ಸಿ ಮಾಡಿದ ಅಧಿಸೂಚನೆಗಳು"</string>
@@ -823,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"ಎಸ್ಎಂಎಸ್"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ಸಂಗೀತ"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ಕ್ಯಾಲೆಂಡರ್"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳ ಜೊತೆಗೆ ತೋರಿಸು"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ಅಡಚಣೆ ಮಾಡಬೇಡ"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳ ಶಾರ್ಟ್‌ಕಟ್‌"</string>
@@ -1013,77 +993,50 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ಸ್ಕ್ರೀನ್‌ನ ಎಡ ಕೆಳಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ಕೆಳಗಿನ ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"ವಜಾಗೊಳಿಸಿ"</string>
-    <!-- no translation found for bubbles_dont_bubble_conversation (1033040343437428822) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_title (5547017089271445797) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_description (1160281719576715211) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_manage_title (2848511858160342320) -->
-    <skip />
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ಸಂಭಾಷಣೆಯನ್ನು ಬಬಲ್ ಮಾಡಬೇಡಿ"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"ಬಬಲ್ಸ್ ಬಳಸಿ ಚಾಟ್ ಮಾಡಿ"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"ಹೊಸ ಸಂಭಾಷಣೆಗಳು ತೇಲುವ ಐಕಾನ್‌ಗಳು ಅಥವಾ ಬಬಲ್ಸ್ ಆಗಿ ಗೋಚರಿಸುತ್ತವೆ. ಬಬಲ್ ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಅದನ್ನು ಡ್ರ್ಯಾಗ್ ಮಾಡಲು ಎಳೆಯಿರಿ."</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಬಬಲ್ಸ್ ಅನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"ಈ ಆ್ಯಪ್‌ನಿಂದ ಬಬಲ್‌ಗಳನ್ನು ಆಫ್ ಮಾಡಲು ನಿರ್ವಹಿಸಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <!-- no translation found for bubbles_user_education_got_it (8282812431953161143) -->
-    <skip />
+    <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"ಅರ್ಥವಾಯಿತು"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿದೆ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಲು, ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ್ ಅಪ್‌ಡೇಟ್ ಮಾಡಲು ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ಸ್ಟ್ಯಾಂಡ್‌ಬೈ"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"ವರ್ಧನೆಯ ಓವರ್‌ಲೇ ವಿಂಡೋ"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
-    <!-- no translation found for quick_controls_title (1686913115679255053) -->
-    <skip />
-    <!-- no translation found for quick_controls_subtitle (1667408093326318053) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_title (9079435969373471268) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_subtitle (1681506617879773824) -->
-    <skip />
-    <!-- no translation found for controls_providers_title (6879775889857085056) -->
-    <skip />
+    <string name="quick_controls_title" msgid="1686913115679255053">"ತ್ವರಿತ ನಿಯಂತ್ರಣಗಳು"</string>
+    <string name="quick_controls_subtitle" msgid="1667408093326318053">"ನಿಮ್ಮ ಸಂಪರ್ಕಿತ ಸಾಧನಗಳಿಗೆ ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"ತ್ವರಿತ ನಿಯಂತ್ರಣಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
+    <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"ನಿಮ್ಮ ನಿಯಂತ್ರಣಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="controls_providers_title" msgid="6879775889857085056">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲು ಆ್ಯಪ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.</item>
     </plurals>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ನಿಯಂತ್ರಣಗಳು"</string>
-    <!-- no translation found for controls_favorite_subtitle (6604402232298443956) -->
-    <skip />
-    <!-- no translation found for controls_favorite_rearrange (7364147066539766260) -->
-    <skip />
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ಪವರ್ ಮೆನುವಿನಿಂದ ಪ್ರವೇಶಿಸಲು ನಿಯಂತ್ರಣಗಳನ್ನು ಆರಿಸಿ"</string>
+    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"ಅದನ್ನು ಸರಿಸಲು ನಿಯಂತ್ರಣವೊಂದನ್ನು ಹಿಡಿದುಕೊಂಡು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"ಎಲ್ಲಾ ನಿಯಂತ್ರಣಗಳ ಪಟ್ಟಿಯನ್ನು ಲೋಡ್ ಮಾಡಲು ಆಗಲಿಲ್ಲ."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ಇತರ"</string>
-    <!-- no translation found for controls_dialog_title (3475025327938684220) -->
-    <skip />
+    <string name="controls_dialog_title" msgid="3475025327938684220">"ತ್ವರಿತ ನಿಯಂತ್ರಣಗಳಿಗೆ ಸೇರಿಸಿ"</string>
     <string name="controls_dialog_ok" msgid="7011816381344485651">"ಮೆಚ್ಚಿನವುಗಳಿಗೆ ಸೇರಿಸಿ"</string>
     <string name="controls_dialog_message" msgid="6292099631702047540">"ಈ ನಿಯಂತ್ರಣವನ್ನು ನಿಮ್ಮ ಮೆಚ್ಚಿನವುಗಳಿಗೆ ಸೇರಿಸಲು <xliff:g id="APP">%s</xliff:g> ಸೂಚಿಸಿದೆ."</string>
-    <!-- no translation found for controls_dialog_confirmation (586517302736263447) -->
-    <skip />
+    <string name="controls_dialog_confirmation" msgid="586517302736263447">"ನಿಯಂತ್ರಣಗಳನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ಪಿನ್ ಅಕ್ಷರಗಳು ಅಥವಾ ಸಂಕೇತಗಳನ್ನು ಒಳಗೊಂಡಿದೆ"</string>
-    <!-- no translation found for controls_pin_verify (3452778292918877662) -->
-    <skip />
-    <!-- no translation found for controls_pin_verifying (3755045989392131746) -->
-    <skip />
+    <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ಅನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
+    <string name="controls_pin_verifying" msgid="3755045989392131746">"ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="controls_pin_instructions" msgid="6363309783822475238">"ಪಿನ್ ನಮೂದಿಸಿ"</string>
-    <!-- no translation found for controls_pin_instructions_retry (1566667581012131046) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_confirming (2596071302617310665) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_message (7744104992609594859) -->
-    <skip />
-    <!-- no translation found for controls_structure_tooltip (4355922222944447867) -->
-    <skip />
+    <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ಮತ್ತೊಂದು ಪಿನ್ ಅನ್ನು ಪ್ರಯತ್ನಿಸಿ"</string>
+    <string name="controls_confirmation_confirming" msgid="2596071302617310665">"ಖಚಿತಪಡಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ಸಾಧನಕ್ಕಾಗಿ ಬದಲಾವಣೆಯನ್ನು ದೃಢೀಕರಿಸಿ"</string>
+    <string name="controls_structure_tooltip" msgid="4355922222944447867">"ಇನ್ನಷ್ಟು ನೋಡಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string>
-    <!-- no translation found for controls_media_close_session (9023534788828414585) -->
-    <skip />
-    <!-- no translation found for controls_error_timeout (794197289772728958) -->
-    <skip />
-    <!-- no translation found for controls_error_failed (960228639198558525) -->
-    <skip />
-    <!-- no translation found for controls_in_progress (4421080500238215939) -->
-    <skip />
-    <!-- no translation found for controls_added_tooltip (4842812921719153085) -->
-    <skip />
-    <!-- no translation found for controls_menu_add (4447246119229920050) -->
-    <skip />
-    <!-- no translation found for controls_menu_edit (890623986951347062) -->
-    <skip />
+    <string name="controls_media_close_session" msgid="9023534788828414585">"ಈ ಮಾಧ್ಯಮ ಸೆಶನ್ ಅನ್ನು ಮುಚ್ಚಿರಿ"</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
+    <string name="controls_error_failed" msgid="960228639198558525">"ದೋಷ, ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
+    <string name="controls_in_progress" msgid="4421080500238215939">"ಪ್ರಗತಿಯಲ್ಲಿದೆ"</string>
+    <string name="controls_added_tooltip" msgid="4842812921719153085">"ಹೊಸ ನಿಯಂತ್ರಣಗಳನ್ನು ನೋಡಲು ಪವರ್ ಬಟನ್ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="controls_menu_add" msgid="4447246119229920050">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"ನಿಯಂತ್ರಣಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index 63bbe62..da5819c 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -31,4 +31,7 @@
 
     <!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
     <integer name="navigation_bar_deadzone_orientation">1</integer>
+
+    <!-- Max number of columns for quick controls area -->
+    <integer name="controls_max_columns">4</integer>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 03cb324..07c2edd 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -155,26 +155,16 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"നിരവധി തെറ്റായ ശ്രമങ്ങൾ. \n<xliff:g id="NUMBER">%d</xliff:g> സെക്കൻഡിൽ വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"വീണ്ടും ശ്രമിക്കുക. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ശ്രമങ്ങളിൽ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ശ്രമം."</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"നിങ്ങളുടെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാറ്റേൺ നൽകിയാൽ, ഈ ഉപകരണത്തിലെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പിൻ നൽകിയാൽ, ഈ ഉപകരണത്തിലെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാസ്‌വേഡ് നൽകിയാൽ, ഈ ഉപകരണത്തിലെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാറ്റേൺ നൽകിയാൽ, ഈ ഉപയോക്താവ് ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പിൻ നൽകിയാൽ, ഈ ഉപയോക്താവ് ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാസ്‌വേഡ് നൽകിയാൽ, ഈ ഉപയോക്താവ് ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാറ്റേൺ നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പിൻ നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാസ്‌വേഡ് നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"ഒരുപാട് തെറ്റായ ശ്രമങ്ങൾ. ഈ ഉപകരണത്തിലെ ഡാറ്റ ഇല്ലാതാക്കപ്പെടും."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"ഒരുപാട് തെറ്റായ ശ്രമങ്ങൾ. ഈ ഉപയോക്താവ് ഇല്ലാതാക്കപ്പെടും."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"ഒരുപാട് തെറ്റായ ശ്രമങ്ങൾ. ഈ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
@@ -813,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS:"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"സംഗീതം"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"കലണ്ടർ"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"വോളിയം നിയന്ത്രണങ്ങളോടൊപ്പം കാണിക്കുക"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ശല്യപ്പെടുത്തരുത്"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"വോളിയം ബട്ടൺ കുറുക്കുവഴി"</string>
@@ -1015,15 +1005,11 @@
     <string name="magnification_overlay_title" msgid="6584179429612427958">"മാഗ്നിഫിക്കേഷൻ ഓവർലേ വിൻഡോ"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
-    <!-- no translation found for quick_controls_title (1686913115679255053) -->
-    <skip />
+    <string name="quick_controls_title" msgid="1686913115679255053">"ദ്രുത നിയന്ത്രണങ്ങൾ"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"നിങ്ങളുടെ കണക്റ്റ് ചെയ്ത ഉപകരണങ്ങൾക്ക് നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
-    <!-- no translation found for quick_controls_setup_title (9079435969373471268) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_subtitle (1681506617879773824) -->
-    <skip />
-    <!-- no translation found for controls_providers_title (6879775889857085056) -->
-    <skip />
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"ദ്രുത നിയന്ത്രണങ്ങൾ സജ്ജീകരിക്കുക"</string>
+    <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"നിങ്ങളുടെ നിയന്ത്രണങ്ങൾ ആക്‌സസ് ചെയ്യാൻ പവർ ബട്ടണിൽ പിടിക്കുക"</string>
+    <string name="controls_providers_title" msgid="6879775889857085056">"നിയന്ത്രണങ്ങൾ ചേർക്കാൻ ആപ്പ് തിരഞ്ഞെടുക്കുക"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> നിയന്ത്രണങ്ങൾ ചേർത്തു.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> നിയന്ത്രണം ചേർത്തു.</item>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 4b6cf07..c2ebfcd 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -155,26 +155,16 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"चुकीचा पासवर्ड"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"बरेच चुकीचे प्रयत्न. \n <xliff:g id="NUMBER">%d</xliff:g> सेकंदांमध्‍ये पुन्हा प्रयत्न करा."</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"पुन्हा प्रयत्न करा. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> पैकी <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> प्रयत्न."</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"तुमचा डेटा हटवला जाईल"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पॅटर्न एंटर केल्यास, या डिव्‍हाइसचा डेटा हटवला जाईल."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पिन एंटर केल्यास, या डिव्‍हाइसचा डेटा हटवला जाईल."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पासवर्ड एंटर केल्यास, या डिव्‍हाइसचा डेटा हटवला जाईल."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पॅटर्न एंटर केल्यास, हा वापरकर्ता हटवला जाईल."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पिन एंटर केल्यास, हा वापरकर्ता हटवला जाईल."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पासवर्ड एंटर केल्यास, हा वापरकर्ता हटवला जाईल."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पॅटर्न एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पिन एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पासवर्ड एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"बरेच चुकीचे प्रयत्‍न. या डिव्‍हाइसचा डेटा हटवला जाईल."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"बरेच चुकीचे प्रयत्‍न. हा वापरकर्ता हटवला जाईल."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"बरेच चुकीचे प्रयत्‍न. ही कार्य प्रोफाइल आणि त्यामधील डेटा हटवला जाईल."</string>
@@ -813,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"संगीत"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"कॅलेंडर"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"आवाज नियंत्रणांसह दर्शवा"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"व्यत्यय आणू नका"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"आवाजाच्या बटणांचा शार्टकट"</string>
@@ -1015,15 +1005,11 @@
     <string name="magnification_overlay_title" msgid="6584179429612427958">"मॅग्निफिकेशन ओव्हरले विंडो"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"मॅग्निफिकेशन विंडो"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"मॅग्निफिकेशन विंडो नियंत्रणे"</string>
-    <!-- no translation found for quick_controls_title (1686913115679255053) -->
-    <skip />
+    <string name="quick_controls_title" msgid="1686913115679255053">"क्विक नियंत्रणे"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"तुमच्या कनेक्ट केलेल्या डिव्हाइससाठी नियंत्रणे जोडा"</string>
-    <!-- no translation found for quick_controls_setup_title (9079435969373471268) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_subtitle (1681506617879773824) -->
-    <skip />
-    <!-- no translation found for controls_providers_title (6879775889857085056) -->
-    <skip />
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"क्विक नियंत्रणे सेट करा"</string>
+    <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"तुमची नियंत्रणे अ‍ॅक्सेस करण्यासाठी पॉवर बटण दाबून ठेवा"</string>
+    <string name="controls_providers_title" msgid="6879775889857085056">"नियंत्रणे जोडण्यासाठी ॲप निवडा"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> नियंत्रणे जोडली.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> नियंत्रण जोडले.</item>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 46c93a7..e9f2c07 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -155,29 +155,19 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"पासवर्ड मिलेन"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"अत्यन्तै धेरै पटक गलत प्रयास गरिए। \n <xliff:g id="NUMBER">%d</xliff:g>सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"फेरि प्रयास गर्नुहोस्। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> मध्ये <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> प्रयास।"</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"तपाईंको डेटा मेटाइने छ"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"तपाईंले अर्को पटक पनि गलत ढाँचा प्रविष्टि गर्नुभयो भने यो यन्त्रको डेटा मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"तपाईंले अर्को पटक पनि गलत PIN प्रविष्टि गर्नुभयो भने यो यन्त्रको डेटा मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"तपाईंले अर्को पटक पनि गलत पासवर्ड प्रविष्टि गर्नुभयो भने यो यन्त्रको डेटा मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"तपाईंले अर्को पटक पनि गलत ढाँचा प्रविष्टि गर्नुभयो भने यी प्रयोगकर्तालाई मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"तपाईंले अर्को पटक पनि गलत PIN प्रविष्टि गर्नुभयो भने यी प्रयोगकर्तालाई मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"तपाईंले अर्को पटक पनि गलत पासवर्ड प्रविष्टि गर्नुभयो भने यी प्रयोगकर्तालाई मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"तपाईंले अर्को पटक पनि गलत ढाँचा प्रविष्टि गर्नुभयो भने यो कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"तपाईंले अर्को पटक पनि गलत PIN प्रविष्टि गर्नुभयो भने तपाईंको कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"तपाईंले अर्को पटक पनि गलत पासवर्ड प्रविष्टि गर्नुभयो भने तपाईंको कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"अनलक गर्ने अत्याधिक गलत प्रयासहरू भए। यो यन्त्रको डेटा मेटाइने छ।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"अनलक गर्ने अत्याधिक गलत प्रयासहरू भए। यो प्रयोगकर्तालाई हटाइने छ।"</string>
-    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"अनलक गर्ने अत्यधिक गलत प्रयासहरू भए। यो कार्य प्रोफाइल र यसको डेटा मेटाइने छ।"</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"अनलक गर्ने अत्यधिक गलत प्रयासहरू भए। यो कार्यलयको प्रोफाइल र यसको डेटा मेटाइने छ।"</string>
     <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"हटाउनुहोस्"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्‌"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फिंगरप्रिन्ट जनाउने आइकन"</string>
@@ -718,8 +708,8 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"तपाईंलाई आवाज वा कम्पनविना ध्यान केन्द्रित गर्न मद्दत गर्छ।"</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"ध्वनि वा कम्पनमार्फत तपाईंको ध्यान आकर्षित गर्छ।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"वार्तालापको खण्डको सिरानमा बबलका रूपमा देखा पर्छ।"</string>
-    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> मार्फत भएका सबै वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखिन्छन्। <xliff:g id="APP_NAME_1">%2$s</xliff:g> मा व्यवस्थापन गर्नुहोस्।"</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"वार्तालाप खण्डको सिरानमा बबलका रूपमा देखा पर्छ।"</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> मार्फत भएका सबै वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखिन्छन्। <xliff:g id="APP_NAME_1">%2$s</xliff:g> मा गई व्यवस्थापन गर्नुहोस्।"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिङ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"हालसालै खारेज गरिएको कुनै पनि बबल छैन"</string>
@@ -1015,22 +1005,18 @@
     <string name="magnification_overlay_title" msgid="6584179429612427958">"म्याग्निफिकेसन ओभरले विन्डो"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"म्याग्निफिकेसन विन्डो"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"म्याग्निफिकेसन विन्डोका नियन्त्रणहरू"</string>
-    <!-- no translation found for quick_controls_title (1686913115679255053) -->
-    <skip />
+    <string name="quick_controls_title" msgid="1686913115679255053">"द्रुत नियन्त्रणहरू"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"आफ्ना जोडिएका यन्त्रहरूका लागि नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
-    <!-- no translation found for quick_controls_setup_title (9079435969373471268) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_subtitle (1681506617879773824) -->
-    <skip />
-    <!-- no translation found for controls_providers_title (6879775889857085056) -->
-    <skip />
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"द्रुत नियन्त्रणहरू सेटअप गर्नुहोस्"</string>
+    <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"आफ्ना नियन्त्रणहरूमाथि पहुँच राख्न पावर बटन थिचिराख्नुहोस्"</string>
+    <string name="controls_providers_title" msgid="6879775889857085056">"नियन्त्रणहरू थप्न अनुप्रयोग छनौट गर्नुहोस्"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <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="controls_favorite_default_title" msgid="967742178688938137">"नियन्त्रणहरू"</string>
-    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"पावर मेनुबाट प्रयोग गर्न मिल्ने नियन्त्रण सुविधाहरू छान्नुहोस्"</string>
-    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"कुनै नियन्त्रण सुविधा सार्न त्यसलाई थिचिराखेर ड्र्याग गर्नुहोस्"</string>
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"पावर मेनुबाट प्रयोग गर्न चाहेका नियन्त्रण सुविधाहरू छान्नुहोस्"</string>
+    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"कुनै नियन्त्रण सुविधा सार्न त्यसलाई थिचेर ड्र्याग गर्नुहोस्"</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"सबै नियन्त्रणहरूको सूची लोड गर्न सकिएन।"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
     <string name="controls_dialog_title" msgid="3475025327938684220">"द्रुत नियन्त्रणहरूमा थप्नुहोस्"</string>
@@ -1047,7 +1033,7 @@
     <string name="controls_structure_tooltip" msgid="4355922222944447867">"थप हेर्न स्वाइप गर्नुहोस्"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string>
     <string name="controls_media_close_session" msgid="9023534788828414585">"यो मिडिया सत्र बन्द गर्नुहोस्"</string>
-    <string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, अनुप्रयोगको जाँच गर्नु…"</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, अनुप्रयोग जाँच गर्नु…"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"त्रुटि भयो, फेरि प्रयास गर्नु…"</string>
     <string name="controls_in_progress" msgid="4421080500238215939">"कार्य हुँदै छ"</string>
     <string name="controls_added_tooltip" msgid="4842812921719153085">"नयाँ नियन्त्रण सुविधाहरू हेर्न पावर बटन थिचिराख्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 9b0fe46..93aa270 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -86,4 +86,15 @@
     <color name="GM2_red_500">#E25142</color>
     <color name="GM2_yellow_500">#F5C518</color>
 
+    <!-- Icon color for user avatars in keyguard user switcher -->
+    <color name="kg_user_switcher_avatar_icon_color">@android:color/background_light</color>
+    <!-- Icon color for selected user avatars in keyguard user switcher -->
+    <color name="kg_user_switcher_selected_avatar_icon_color">#202124</color>
+    <!-- Icon color for user avatars in quick settings user switcher  -->
+    <color name="qs_user_switcher_avatar_icon_color">@android:color/background_light</color>
+    <!-- Icon color for selected user avatars in quick settings user switcher  -->
+    <color name="qs_user_switcher_selected_avatar_icon_color">#202124</color>
+    <!-- Color of background circle of user avatars in quick settings user switcher -->
+    <color name="qs_user_switcher_avatar_background">#3C4043</color>
+
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 4adc1ff..d4796d6 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -154,36 +154,21 @@
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ଭୁଲ ପାଟର୍ନ"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ଭୁଲ ପାସ୍‌ୱାର୍ଡ"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ଅନେକ ଥର ଭୁଲ ଚେଷ୍ଟା। \n <xliff:g id="NUMBER">%d</xliff:g>ସେକେଣ୍ଡରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <!-- no translation found for biometric_dialog_credential_attempts_before_wipe (6751859711975516999) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_device (6585503524026243042) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_user (7015008539146949115) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_profile (5239378521440749682) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_now_wiping_dialog_dismiss (7189432882125106154) -->
-    <skip />
+    <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>ଟିରୁ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g>ଟି ପ୍ରଚେଷ୍ଟା।"</string>
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ଆପଣଙ୍କ ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାଟର୍ନ ପ୍ରବେଶ କଲେ, ଏହି ଡିଭାଇସର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ PIN ଲେଖିଲେ, ଏହି ଡିଭାଇସର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାସୱାର୍ଡ ଲେଖିଲେ, ଏହି ଡିଭାଇସର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାଟର୍ନ ପ୍ରବେଶ କଲେ, ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ PIN ଲେଖିଲେ, ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାସୱାର୍ଡ ଲେଖିଲେ, ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାଟର୍ନ ପ୍ରବେଶ କଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଏବଂ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ PIN ଲେଖିଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଏବଂ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାସୱାର୍ଡ ଲେଖିଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଓ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପ୍ରଚେଷ୍ଟା। ଏହି ଡିଭାଇସର ଡାଟା ଡିଲିଟ୍ ହୋଇଯିବ।"</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପ୍ରଚେଷ୍ଟା। ଏହି ଉପଯୋଗକର୍ତ୍ତା ଡିଲିଟ୍ ହୋଇଯିବ।"</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପ୍ରଚେଷ୍ଟା। ଏହି ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଏବଂ ଏହାର ଡାଟା ଡିଲିଟ୍ ହୋଇଯିବ।"</string>
+    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"ଖାରଜ କରନ୍ତୁ"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରୁଛି…"</string>
@@ -723,17 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"ବିନା ସାଉଣ୍ଡ କିମ୍ବା ଭାଇବ୍ରେସନ୍‌ରେ ଆପଣଙ୍କୁ ଫୋକସ୍ କରିବାରେ ସାହାଯ୍ୟ କରେ।"</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"ସାଉଣ୍ଡ କିମ୍ବା ଭାଇବ୍ରେସନ୍ ମାଧ୍ୟମରେ ଆପଣଙ୍କର ଧ୍ୟାନ ଆକର୍ଷିତ କରିଥାଏ।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ଏହି ବିଷୟବସ୍ତୁ ପାଇଁ ଏକ ଭାସମାନ ସର୍ଟକଟ୍ ସହ ଆପଣଙ୍କର ଧ୍ୟାନ ଦିଅନ୍ତୁ।"</string>
-    <!-- no translation found for notification_channel_summary_priority (7415770044553264622) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_all_bubble (5389290797101635297) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_settings (2409977688430606835) -->
-    <skip />
-    <!-- no translation found for notification_priority_title (2079708866333537093) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"ଏହା ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ।"</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>ରୁ ସମସ୍ତ ବାର୍ତ୍ତାଳାପ ଡିଫଲ୍ଟ ରୂପେ ବବଲରେ ଦେଖାଯାଏ। <xliff:g id="APP_NAME_1">%2$s</xliff:g>ରେ ପରିଚାଳନା କରନ୍ତୁ।"</string>
+    <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ସେଟିଂସ୍"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"ପ୍ରାଥମିକତା"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"ବର୍ତ୍ତମାନ କୌଣସି ବବଲ୍ ନାହିଁ"</string>
-    <!-- no translation found for bubble_overflow_empty_subtitle (2030874469510497397) -->
-    <skip />
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"ବର୍ତ୍ତମାନର ଏବଂ ଖାରଜ କରାଯାଇଥିବା ବବଲଗୁଡ଼ିକ ଏଠାରେ ଦେଖାଯିବ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିବର୍ତ୍ତନ କରିହେବ ନାହିଁ।"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ଏଠାରେ ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଗ୍ରୁପ୍ କନଫ୍ୟୁଗର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"ବିଜ୍ଞପ୍ତି ପ୍ରକ୍ସୀ ହୋଇଛି"</string>
@@ -1013,17 +993,12 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ତଳ ବାମକୁ ନିଅନ୍ତୁ"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ତଳ ଡାହାଣକୁ ନିଅନ୍ତୁ"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"ଖାରଜ କରନ୍ତୁ"</string>
-    <!-- no translation found for bubbles_dont_bubble_conversation (1033040343437428822) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_title (5547017089271445797) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_description (1160281719576715211) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_manage_title (2848511858160342320) -->
-    <skip />
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ବାର୍ତ୍ତାଳାପକୁ ବବଲ୍ କରନ୍ତୁ ନାହିଁ"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"ବବଲଗୁଡ଼ିକୁ ବ୍ୟବହାର କରି ଚାଟ୍ କରନ୍ତୁ"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"ନୂଆ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଫ୍ଲୋଟିଂ ଆଇକନ୍ କିମ୍ବା ବବଲ୍ ଭାବେ ଦେଖାଯିବ। ବବଲ୍ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ। ଏହାକୁ ମୁଭ୍ କରିବାକୁ ଟାଣନ୍ତୁ।"</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"ଯେ କୌଣସି ସମୟରେ ବବଲଗୁଡ଼ିକ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"ଏହି ଆପର ବବଲଗୁଡ଼ିକ ବନ୍ଦ କରିବା ପାଇଁ \'ପରିଚାଳନା କରନ୍ତୁ\' ବଟନରେ ଟାପ୍ କରନ୍ତୁ"</string>
-    <!-- no translation found for bubbles_user_education_got_it (8282812431953161143) -->
-    <skip />
+    <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"ବୁଝିଗଲି"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ ହୋଇଛି। ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ, ସେଟିଂସ୍‌କୁ ଯାଆନ୍ତୁ।"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ସିଷ୍ଟମ୍ ନାଭିଗେସନ୍ ଅପ୍‌ଡେଟ୍ କରିବା ପାଇଁ ସେଟିଂସ୍‍କୁ ଯାଆନ୍ତୁ"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ଷ୍ଟାଣ୍ଡବାଏ"</string>
@@ -1031,8 +1006,7 @@
     <string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
     <string name="quick_controls_title" msgid="1686913115679255053">"ଦ୍ରୁତ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
-    <!-- no translation found for quick_controls_subtitle (1667408093326318053) -->
-    <skip />
+    <string name="quick_controls_subtitle" msgid="1667408093326318053">"ଆପଣଙ୍କ ସଂଯୁକ୍ତ ଥିବା ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="quick_controls_setup_title" msgid="9079435969373471268">"ଦ୍ରୁତ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
     <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"ଆପଣଙ୍କ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଯୋଗ କରିବାକୁ ଆପ୍ ବାଛନ୍ତୁ"</string>
@@ -1041,45 +1015,28 @@
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g>ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।</item>
     </plurals>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
-    <!-- no translation found for controls_favorite_subtitle (6604402232298443956) -->
-    <skip />
-    <!-- no translation found for controls_favorite_rearrange (7364147066539766260) -->
-    <skip />
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ପାୱାର ମେନୁରୁ ଆକ୍ସେସ୍ କରିବାକୁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ବାଛନ୍ତୁ"</string>
+    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"ଏକ ନିୟନ୍ତ୍ରଣକୁ ମୁଭ୍ କରିବାକୁ ଏହାକୁ ଧରି ଟାଣନ୍ତୁ"</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"ସବୁ ନିୟନ୍ତ୍ରଣର ତାଲିକା ଲୋଡ୍ କରିପାରିଲା ନାହିଁ।"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ଅନ୍ୟ"</string>
-    <!-- no translation found for controls_dialog_title (3475025327938684220) -->
-    <skip />
+    <string name="controls_dialog_title" msgid="3475025327938684220">"ଦ୍ରୁତ ନିୟନ୍ତ୍ରଣରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="controls_dialog_ok" msgid="7011816381344485651">"ପସନ୍ଦଗୁଡ଼ିକରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="controls_dialog_message" msgid="6292099631702047540">"ଏହି ନିୟନ୍ତ୍ରଣକୁ ଆପଣଙ୍କ ପସନ୍ଦଗୁଡ଼ିକରେ ଯୋଗ କରିବାକୁ <xliff:g id="APP">%s</xliff:g> ପ୍ରସ୍ତାବ ଦେଇଛି।"</string>
-    <!-- no translation found for controls_dialog_confirmation (586517302736263447) -->
-    <skip />
+    <string name="controls_dialog_confirmation" msgid="586517302736263447">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଅପଡେଟ୍ କରାଯାଇଛି"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PINରେ ଅକ୍ଷର କିମ୍ୱା ସଙ୍କେତଗୁଡ଼ିକ ଥାଏ"</string>
-    <!-- no translation found for controls_pin_verify (3452778292918877662) -->
-    <skip />
-    <!-- no translation found for controls_pin_verifying (3755045989392131746) -->
-    <skip />
+    <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ଯାଞ୍ଚ କରନ୍ତୁ"</string>
+    <string name="controls_pin_verifying" msgid="3755045989392131746">"ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
     <string name="controls_pin_instructions" msgid="6363309783822475238">"PIN ଲେଖନ୍ତୁ"</string>
-    <!-- no translation found for controls_pin_instructions_retry (1566667581012131046) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_confirming (2596071302617310665) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_message (7744104992609594859) -->
-    <skip />
-    <!-- no translation found for controls_structure_tooltip (4355922222944447867) -->
-    <skip />
+    <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"ଅନ୍ୟ ଏକ PIN ଚେଷ୍ଟା କରି ଦେଖନ୍ତୁ"</string>
+    <string name="controls_confirmation_confirming" msgid="2596071302617310665">"ସୁନିଶ୍ଚିତ କରାଯାଉଛି…"</string>
+    <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g> ପାଇଁ ପରିବର୍ତ୍ତନ ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+    <string name="controls_structure_tooltip" msgid="4355922222944447867">"ଅଧିକ ଦେଖିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string>
-    <!-- no translation found for controls_media_close_session (9023534788828414585) -->
-    <skip />
-    <!-- no translation found for controls_error_timeout (794197289772728958) -->
-    <skip />
-    <!-- no translation found for controls_error_failed (960228639198558525) -->
-    <skip />
-    <!-- no translation found for controls_in_progress (4421080500238215939) -->
-    <skip />
-    <!-- no translation found for controls_added_tooltip (4842812921719153085) -->
-    <skip />
-    <!-- no translation found for controls_menu_add (4447246119229920050) -->
-    <skip />
-    <!-- no translation found for controls_menu_edit (890623986951347062) -->
-    <skip />
+    <string name="controls_media_close_session" msgid="9023534788828414585">"ଏହି ମିଡିଆ ସେସନ୍ ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
+    <string name="controls_error_failed" msgid="960228639198558525">"ତ୍ରୁଟି ହୋଇଛି, ପୁଣି ଚେଷ୍ଟା କର"</string>
+    <string name="controls_in_progress" msgid="4421080500238215939">"ପ୍ରଗତିରେ ଅଛି"</string>
+    <string name="controls_added_tooltip" msgid="4842812921719153085">"ନୂଆ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string>
+    <string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 89eee64..9a7201b 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -155,26 +155,16 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"ਗਲਤ ਪਾਸਵਰਡ"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"ਬਹੁਤ ਸਾਰੀਆਂ ਗ਼ਲਤ ਕੋਸ਼ਿਸ਼ਾਂ।\n<xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ। <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ਕੋਸ਼ਿਸ਼।"</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"ਤੁਹਾਡਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪੈਟਰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਿੰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪੈਟਰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਿੰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪੈਟਰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਿੰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"ਬਹੁਤ ਸਾਰੀਆਂ ਗਲਤ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"ਬਹੁਤ ਸਾਰੀਆਂ ਗਲਤ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"ਬਹੁਤ ਸਾਰੀਆਂ ਗਲਤ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਹ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।"</string>
@@ -719,7 +709,7 @@
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"ਧੁਨੀ ਅਤੇ ਥਰਥਰਾਹਟ ਨਾਲ ਤੁਹਾਡਾ ਧਿਆਨ ਖਿੱਚਦੀ ਹੈ।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ਇਸ ਸਮੱਗਰੀ ਦੇ ਅਸਥਿਰ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਆਪਣਾ ਧਿਆਨ ਕੇਂਦਰਿਤ ਰੱਖੋ।"</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਦੇ ਉੱਪਰ ਅਤੇ ਬੁਲਬੁਲਿਆਂ ਦੇ ਤੌਰ \'ਤੇ ਦਿਖਾਉਂਦਾ ਹੈ।"</string>
-    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਵੱਲੋਂ ਸਾਰੀਆਂ ਗੱਲਾਂਬਾਤਾਂ \'ਤੇ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ \'ਤੇ ਬੁਲਬੁਲੇ ਲਾਏ ਗਏ ਹਨ। <xliff:g id="APP_NAME_1">%2$s</xliff:g> ਵਿੱਚ ਪ੍ਰਬੰਧਨ ਕਰੋ।"</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਵੱਲੋਂ ਸਾਰੀਆਂ ਗੱਲਾਂਬਾਤਾਂ \'ਤੇ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ \'ਤੇ ਬੁਲਬੁਲੇ ਲਾਏ ਜਾਂਦੇ ਹਨ। <xliff:g id="APP_NAME_1">%2$s</xliff:g> ਵਿੱਚ ਪ੍ਰਬੰਧਨ ਕਰੋ।"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ਤਰਜੀਹ"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"ਕੋਈ ਹਾਲੀਆ ਬੁਲਬੁਲਾ ਨਹੀਂ"</string>
@@ -813,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ਸੰਗੀਤ"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ਕੈਲੰਡਰ"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"ਵੌਲਿਊਮ ਕੰਟਰੋਲਾਂ ਨਾਲ  ਦਿਖਾਓ"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ਵੌਲਿਊਮ ਬਟਨ ਸ਼ਾਰਟਕੱਟ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f1c1d8b..bf5a581 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -88,7 +88,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zamknij zrzut ekranu"</string>
     <string name="screenshot_preview_description" msgid="669177537416980449">"Otwórz zrzut ekranu"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"Rejestrator ekranu"</string>
+    <string name="screenrecord_name" msgid="2596401223859996572">"Nagrywanie ekranu"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Rozpocząć rejestrowanie?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Podczas nagrywania system Android może rejestrować wszelkie informacji poufne wyświetlane na ekranie lub odtwarzane na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
@@ -714,8 +714,8 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Pomaga Ci się skupić, nie sygnalizując niczego dźwiękiem ani wibracjami."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Przyciąga uwagę dźwiękiem lub wibracjami."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Przyciąga uwagę dzięki pływającym skrótom do treści."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Wyświetla się u góry sekcji wątków i ma postać dymku."</string>
-    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Wszystkie wątki z aplikacji <xliff:g id="APP_NAME_0">%1$s</xliff:g> są domyślnie wyświetlane jako dymki. Zarządzaj w aplikacji <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Wyświetla się u góry sekcji rozmów i ma postać dymku."</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Wszystkie rozmowy z aplikacji <xliff:g id="APP_NAME_0">%1$s</xliff:g> są domyślnie wyświetlane jako dymki. Zarządzaj w aplikacji <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ustawienia"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorytet"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Brak ostatnich dymków"</string>
@@ -741,7 +741,7 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Dostosuj"</string>
     <string name="notification_done" msgid="6215117625922713976">"Gotowe"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Cofnij"</string>
-    <string name="demote" msgid="6225813324237153980">"Nie oznaczaj tego powiadomienia jako wątku"</string>
+    <string name="demote" msgid="6225813324237153980">"Nie oznaczaj tego powiadomienia jako rozmowy"</string>
     <string name="notification_conversation_favorite" msgid="1905240206975921907">"Ważne rozmowy"</string>
     <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Rozmowa nieoznaczona jako ważna"</string>
     <string name="notification_conversation_mute" msgid="268951550222925548">"Wyciszone"</string>
@@ -1003,9 +1003,9 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Przenieś w lewy dolny róg"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Przenieś w prawy dolny róg"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"Zamknij"</string>
-    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj wątków jako dymków."</string>
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj rozmowy jako dymku"</string>
     <string name="bubbles_user_education_title" msgid="5547017089271445797">"Czatuj, korzystając z dymków"</string>
-    <string name="bubbles_user_education_description" msgid="1160281719576715211">"Nowe wątki będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"Nowe rozmowy będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string>
     <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Zarządzaj dymkami w dowolnym momencie"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Kliknij Zarządzaj, aby wyłączyć dymki z tej aplikacji"</string>
     <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index c338f46..27e9dc3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -156,15 +156,15 @@
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Слишком много неудачных попыток.\nПовторите через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"Попробуйте ещё раз. Попытка <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> из <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>."</string>
     <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"Осталась одна попытка"</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Если вы неправильно введете графический ключ, с устройства будут удалены все данные."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"Если вы неправильно введете PIN-код, с устройства будут удалены все данные."</string>
-    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"Если вы неправильно введете пароль, с устройства будут удалены все данные."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"Если вы неправильно введете графический ключ, этот пользователь будет удален."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"Если вы неправильно введете PIN-код, этот пользователь будет удален."</string>
-    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"Если вы неправильно введете пароль, этот пользователь будет удален."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Если вы неправильно введете графический ключ, ваш рабочий профиль и его данные будут удалены."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Если вы неправильно введете PIN-код, ваш рабочий профиль и его данные будут удалены."</string>
-    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Если вы неправильно введете пароль, ваш рабочий профиль и его данные будут удалены."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"Если вы неправильно введете графический ключ ещё раз, с устройства будут удалены все данные."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"Если вы неправильно введете PIN-код ещё раз, с устройства будут удалены все данные."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"Если вы неправильно введете пароль ещё раз, с устройства будут удалены все данные."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"Если вы неправильно введете графический ключ ещё раз, этот пользователь будет удален."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"Если вы неправильно введете PIN-код ещё раз, этот пользователь будет удален."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"Если вы неправильно введете пароль ещё раз, этот пользователь будет удален."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Если вы неправильно введете графический ключ ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Если вы неправильно введете PIN-код ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Если вы неправильно введете пароль ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"Слишком много неудачных попыток. С устройства будут удалены все данные."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"Слишком много неудачных попыток. Этот пользователь будет удален."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"Слишком много неудачных попыток. Этот рабочий профиль и его данные будут удалены."</string>
@@ -514,7 +514,7 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Настроить"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Беззвучные уведомления"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Уведомления со звуком или вибрацией"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Оповещения"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Чаты"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Отклонить все беззвучные уведомления"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"В режиме \"Не беспокоить\" уведомления заблокированы"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f7b948a..e742ec0 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -88,7 +88,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zavrieť snímku obrazovky"</string>
     <string name="screenshot_preview_description" msgid="669177537416980449">"Otvoriť snímku obrazovky"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"Nahrávanie obrazovky"</string>
+    <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Chcete spustiť nahrávanie?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Počas nahrávania zaznamená systém Android všetky citlivé údaje, ktoré sa zobrazia na obrazovke alebo prehrajú v zariadení. Zahrnuje to heslá, platobné údaje, fotky, správy a zvuky."</string>
@@ -715,7 +715,7 @@
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Upúta vás zvukom alebo vibráciami."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Upúta vás plávajúcim odkazom na tento obsah."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Zobrazuje sa v hornej časti konverzácie ako bublina."</string>
-    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Predvolene zahrnúť všetky konverzácie z bubliny <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Spravujte v aplikácii <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Predvolene zobrazovať všetky konverzácie z aplikácie <xliff:g id="APP_NAME_0">%1$s</xliff:g> ako bubliny. Spravujte v aplikácii <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavenia"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Žiadne nedávne bubliny"</string>
diff --git a/packages/SystemUI/res/values-sw320dp/dimens.xml b/packages/SystemUI/res/values-sw320dp/dimens.xml
index 2774554..47a2a09 100644
--- a/packages/SystemUI/res/values-sw320dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw320dp/dimens.xml
@@ -30,5 +30,7 @@
     <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
     <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
 
+    <!-- Home Controls -->
+    <dimen name="controls_list_side_margin">10dp</dimen>
 </resources>
 
diff --git a/packages/SystemUI/res/values-sw360dp/dimens.xml b/packages/SystemUI/res/values-sw360dp/dimens.xml
index dfd9743..35a6536 100644
--- a/packages/SystemUI/res/values-sw360dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw360dp/dimens.xml
@@ -26,5 +26,7 @@
          navigation_extra_key_width -->
     <dimen name="navigation_side_padding">40dip</dimen>
 
+    <!-- Home Controls -->
+    <dimen name="controls_list_side_margin">12dp</dimen>
 </resources>
 
diff --git a/packages/SystemUI/res/values-sw392dp/dimens.xml b/packages/SystemUI/res/values-sw392dp/dimens.xml
index be1d952..308bc69 100644
--- a/packages/SystemUI/res/values-sw392dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw392dp/dimens.xml
@@ -30,5 +30,7 @@
     <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
     <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
 
+    <!-- Home Controls -->
+    <dimen name="controls_list_side_margin">16dp</dimen>
 </resources>
 
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 8934183..8f73d23 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -45,6 +45,11 @@
     <!-- Height of the status bar header bar when on Keyguard -->
     <dimen name="status_bar_header_height_keyguard">60dp</dimen>
 
+    <!-- Size of user icon + frame in the qs user picker (incl. frame) -->
+    <dimen name="qs_framed_avatar_size">60dp</dimen>
+    <!-- Size of user icon + frame in the keyguard user picker (incl. frame) -->
+    <dimen name="kg_framed_avatar_size">48dp</dimen>
+
     <!-- The width of user avatar when on Keyguard -->
     <dimen name="multi_user_switch_width_keyguard">48dp</dimen>
 
@@ -88,4 +93,7 @@
 
     <!-- Keyboard shortcuts helper -->
     <dimen name="ksh_layout_width">488dp</dimen>
+
+    <!-- Text size for user name in user switcher -->
+    <dimen name="kg_user_switcher_text_size">18sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index b375364..02bd602 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -30,20 +30,10 @@
         <item name="android:textColor">?attr/wallpaperTextColor</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.Activated">
-        <item name="android:fontWeight">700</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
-    </style>
-
     <style name="TextAppearance.QS.UserSwitcher">
-        <item name="android:textSize">@dimen/qs_detail_item_primary_text_size</item>
+        <item name="android:textSize">@dimen/kg_user_switcher_text_size</item>
         <item name="android:textColor">?android:attr/textColorSecondary</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
     </style>
 
-    <style name="TextAppearance.QS.UserSwitcher.Activated">
-        <item name="android:fontWeight">700</item>
-        <item name="android:textStyle">bold</item>
-    </style>
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 7cbecf4..2d904e7 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -86,10 +86,8 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string>
     <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
-    <!-- no translation found for screenshot_dismiss_ui_description (934736855340147968) -->
-    <skip />
-    <!-- no translation found for screenshot_preview_description (669177537416980449) -->
-    <skip />
+    <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ஸ்கிரீன்ஷாட்டை நிராகரி"</string>
+    <string name="screenshot_preview_description" msgid="669177537416980449">"ஸ்கிரீன்ஷாட்டைத் திற"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ஸ்கிரீன் ரெக்கார்டர்"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ரெக்கார்டிங்கைத் தொடங்கவா?"</string>
@@ -825,7 +823,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"மியூசிக்"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"கேலெண்டர்"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"ஒலிக் கட்டுப்பாடுகளுடன் காட்டு"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"தொந்தரவு செய்ய வேண்டாம்"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ஒலியளவுப் பொத்தான்களுக்கான ஷார்ட்கட்"</string>
@@ -1073,8 +1071,7 @@
     <skip />
     <!-- no translation found for controls_structure_tooltip (4355922222944447867) -->
     <skip />
-    <!-- no translation found for controls_seeding_in_progress (3033855341410264148) -->
-    <skip />
+    <string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string>
     <!-- no translation found for controls_media_close_session (9023534788828414585) -->
     <skip />
     <!-- no translation found for controls_error_timeout (794197289772728958) -->
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index eba3ae5..92162ae 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -154,36 +154,21 @@
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"ఆకృతి తప్పు"</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"పాస్‌వర్డ్ తప్పు"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు.\n<xliff:g id="NUMBER">%d</xliff:g> సెకన్ల తర్వాత మళ్లీ ప్రయత్నించండి."</string>
-    <!-- no translation found for biometric_dialog_credential_attempts_before_wipe (6751859711975516999) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_device (6585503524026243042) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_user (7015008539146949115) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_failed_attempts_now_wiping_profile (5239378521440749682) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_now_wiping_dialog_dismiss (7189432882125106154) -->
-    <skip />
+    <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"మళ్లీ ప్రయత్నించండి. <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>లో <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> ప్రయత్నం చేశారు."</string>
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"మీ డేటా తొలగించబడుతుంది"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు ఆకృతిని ఎంటర్ చేస్తే, ఈ పరికరం యొక్క డేటా తొలగించబడుతుంది."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పిన్‌ను ఎంటర్ చేస్తే, ఈ పరికరం యొక్క డేటా తొలగించబడుతుంది."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పాస్‌వర్డ్‌ను ఎంటర్ చేస్తే, ఈ పరికరం యొక్క డేటా తొలగించబడుతుంది."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు ఆకృతిని ఎంటర్ చేస్తే, ఈ యూజర్ తొలగించబడతారు."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పిన్‌ను ఎంటర్ చేస్తే, ఈ యూజర్ తొలగించబడతారు."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పాస్‌వర్డ్‌ను ఎంటర్ చేస్తే, ఈ యూజర్ తొలగించబడతారు."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు ఆకృతిని ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పిన్‌ను ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పాస్‌వర్డ్‌ను ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు. ఈ పరికరం యొక్క డేటా తొలగించబడుతుంది."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు. ఈ యూజర్ తొలగించబడతారు."</string>
+    <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు. ఈ కార్యాలయ ప్రొఫైల్ మరియు దీని డేటా తొలగించబడతాయి."</string>
+    <string name="biometric_dialog_now_wiping_dialog_dismiss" msgid="7189432882125106154">"తీసివేయి"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"వేలిముద్ర సెన్సార్‌ను తాకండి"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"వేలిముద్ర చిహ్నం"</string>
     <string name="face_dialog_looking_for_face" msgid="2656848512116189509">"మీ కోసం చూస్తోంది…"</string>
@@ -723,17 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"శబ్దం లేదా వైబ్రేషన్ లేకుండా దృష్టి కేంద్రీకరించడానికి మీకు సహాయపడుతుంది."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"శబ్దం లేదా వైబ్రేషన్‌తో మీరు దృష్టి సారించేలా చేస్తుంది."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ఫ్లోటింగ్ షార్ట్‌కట్‌తో మీ దృష్టిని ఈ కంటెంట్‌పై నిలిపి ఉంచుతుంది."</string>
-    <!-- no translation found for notification_channel_summary_priority (7415770044553264622) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_all_bubble (5389290797101635297) -->
-    <skip />
-    <!-- no translation found for notification_conversation_channel_settings (2409977688430606835) -->
-    <skip />
-    <!-- no translation found for notification_priority_title (2079708866333537093) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"సంభాషణ విభాగానికి ఎగువున ఉంటుంది, బబుల్‌లాగా కనిపిస్తుంది."</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> నుండి అన్ని సంభాషణలు డిఫాల్ట్‌గా బబుల్‌గా ఉంటాయి. <xliff:g id="APP_NAME_1">%2$s</xliff:g>లో మేనేజ్ చేయండి"</string>
+    <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"సెట్టింగ్‌లు"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"ఇటీవల బబుల్‌లు ఏవీ లేవు"</string>
-    <!-- no translation found for bubble_overflow_empty_subtitle (2030874469510497397) -->
-    <skip />
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"ఇటీవలి బబుల్‌లు, తీసివేసిన బబుల్‌లు ఇక్కడ కనిపిస్తాయి"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ఈ నోటిఫికేషన్‌లను సవరించడం వీలుపడదు."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ఈ నోటిఫికేషన్‌ల సమూహాన్ని ఇక్కడ కాన్ఫిగర్ చేయలేము"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"ప్రాక్సీ చేయబడిన నోటిఫికేషన్"</string>
@@ -823,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"సంగీతం"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
-    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"క్యాలెండర్"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="5120366354224404511">"వాల్యూమ్ నియంత్రణలతో చూపు"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"అంతరాయం కలిగించవద్దు"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"వాల్యూమ్ బటన్‌ల షార్ట్‌కట్"</string>
@@ -1013,17 +993,12 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"దిగువ ఎడమవైపునకు తరలించు"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"దిగవు కుడివైపునకు జరుపు"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"విస్మరించు"</string>
-    <!-- no translation found for bubbles_dont_bubble_conversation (1033040343437428822) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_title (5547017089271445797) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_description (1160281719576715211) -->
-    <skip />
-    <!-- no translation found for bubbles_user_education_manage_title (2848511858160342320) -->
-    <skip />
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"సంభాషణను బబుల్ చేయవద్దు"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"బబుల్‌లను ఉపయోగించి చాట్ చేయండి"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"కొత్త సంభాషణలు తేలియాడే చిహ్నాలుగా లేదా బబుల్‌లు లాగా కనిపిస్తాయి. బబుల్‌ని తెరవడానికి నొక్కండి. తరలించడానికి లాగండి."</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"బబుల్‌లను ఎప్పుడైనా నియంత్రించండి"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"ఈ యాప్ నుండి వచ్చే బబుల్‌లను ఆఫ్ చేయడానికి మేనేజ్ బటన్‌ను ట్యాప్ చేయండి"</string>
-    <!-- no translation found for bubbles_user_education_got_it (8282812431953161143) -->
-    <skip />
+    <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"అర్థమైంది"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"సిస్టమ్ నావిగేషన్ అప్‌డేట్ చేయబడింది. మార్పులు చేయడానికి, సెట్టింగ్‌లకు వెళ్లండి."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"సిస్టమ్ నావిగేషన్‌ను అప్‌డేట్ చేయడానికి సెట్టింగ్‌లకు వెళ్లండి"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"స్టాండ్‌బై"</string>
@@ -1031,8 +1006,7 @@
     <string name="magnification_window_title" msgid="4863914360847258333">"మాగ్నిఫికేషన్ విండో"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"మాగ్నిఫికేషన్ నియంత్రణల విండో"</string>
     <string name="quick_controls_title" msgid="1686913115679255053">"త్వరిత నియంత్రణలు"</string>
-    <!-- no translation found for quick_controls_subtitle (1667408093326318053) -->
-    <skip />
+    <string name="quick_controls_subtitle" msgid="1667408093326318053">"మీ కనెక్ట్ అయిన పరికరాలకు నియంత్రణలను జోడించండి"</string>
     <string name="quick_controls_setup_title" msgid="9079435969373471268">"త్వరిత నియంత్రణలను సెటప్ చేయండి"</string>
     <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"మీ నియంత్రణలను యాక్సెస్ చేయడానికి పవర్ బటన్‌ను నొక్కి పట్టుకోండి"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"నియంత్రణలను యాడ్ చేయడానికి యాప్‌ను ఎంచుకోండి"</string>
@@ -1041,45 +1015,28 @@
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> కంట్రోల్ యాడ్ అయింది.</item>
     </plurals>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"నియంత్రణలు"</string>
-    <!-- no translation found for controls_favorite_subtitle (6604402232298443956) -->
-    <skip />
-    <!-- no translation found for controls_favorite_rearrange (7364147066539766260) -->
-    <skip />
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"పవర్ మెనూ నుండి యాక్సెస్ చేయడానికి నియంత్రణలను ఎంచుకోండి"</string>
+    <string name="controls_favorite_rearrange" msgid="7364147066539766260">"తరలించడానికి నియంత్రణను పట్టుకొని, లాగండి"</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"అన్ని నియంత్రణలు గల జాబితాను లోడ్ చేయలేకపోయాము."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ఇతరం"</string>
-    <!-- no translation found for controls_dialog_title (3475025327938684220) -->
-    <skip />
+    <string name="controls_dialog_title" msgid="3475025327938684220">"త్వరిత నియంత్రణలకు జోడించండి"</string>
     <string name="controls_dialog_ok" msgid="7011816381344485651">"ఇష్టమైనవాటికి జోడించు"</string>
     <string name="controls_dialog_message" msgid="6292099631702047540">"మీ ఇష్టమైనవాటికి జోడించడానికి <xliff:g id="APP">%s</xliff:g> ఈ కంట్రోల్‌ను సూచించింది."</string>
-    <!-- no translation found for controls_dialog_confirmation (586517302736263447) -->
-    <skip />
+    <string name="controls_dialog_confirmation" msgid="586517302736263447">"నియంత్రణలు అప్‌డేట్ అయ్యాయి"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"పిన్ అక్షరాలను లేదా చిహ్నాలను కలిగి ఉంది"</string>
-    <!-- no translation found for controls_pin_verify (3452778292918877662) -->
-    <skip />
-    <!-- no translation found for controls_pin_verifying (3755045989392131746) -->
-    <skip />
+    <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>ను వెరిఫై చేయండి"</string>
+    <string name="controls_pin_verifying" msgid="3755045989392131746">"వెరిఫై చేస్తోంది..."</string>
     <string name="controls_pin_instructions" msgid="6363309783822475238">"పిన్‌ని ఎంటర్ చేయండి"</string>
-    <!-- no translation found for controls_pin_instructions_retry (1566667581012131046) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_confirming (2596071302617310665) -->
-    <skip />
-    <!-- no translation found for controls_confirmation_message (7744104992609594859) -->
-    <skip />
-    <!-- no translation found for controls_structure_tooltip (4355922222944447867) -->
-    <skip />
+    <string name="controls_pin_instructions_retry" msgid="1566667581012131046">"మరొక పిన్‌ని ప్రయత్నించండి"</string>
+    <string name="controls_confirmation_confirming" msgid="2596071302617310665">"నిర్ధారిస్తోంది..."</string>
+    <string name="controls_confirmation_message" msgid="7744104992609594859">"<xliff:g id="DEVICE">%s</xliff:g>కి సంబంధించి మార్పును నిర్ధారించండి"</string>
+    <string name="controls_structure_tooltip" msgid="4355922222944447867">"మరిన్నింటిని చూడటం కోసం స్వైప్ చేయండి"</string>
     <string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
-    <!-- no translation found for controls_media_close_session (9023534788828414585) -->
-    <skip />
-    <!-- no translation found for controls_error_timeout (794197289772728958) -->
-    <skip />
-    <!-- no translation found for controls_error_failed (960228639198558525) -->
-    <skip />
-    <!-- no translation found for controls_in_progress (4421080500238215939) -->
-    <skip />
-    <!-- no translation found for controls_added_tooltip (4842812921719153085) -->
-    <skip />
-    <!-- no translation found for controls_menu_add (4447246119229920050) -->
-    <skip />
-    <!-- no translation found for controls_menu_edit (890623986951347062) -->
-    <skip />
+    <string name="controls_media_close_session" msgid="9023534788828414585">"ఈ మీడియా సెషన్‌ని మూసివేయండి"</string>
+    <string name="controls_error_timeout" msgid="794197289772728958">"ఇన్‌యాక్టివ్, యాప్ చెక్ చేయండి"</string>
+    <string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string>
+    <string name="controls_in_progress" msgid="4421080500238215939">"పురోగతిలో ఉంది"</string>
+    <string name="controls_added_tooltip" msgid="4842812921719153085">"కొత్త నియంత్రణలను చూడడానికి పవర్ బటన్‌ని నొక్కి పట్టుకోండి"</string>
+    <string name="controls_menu_add" msgid="4447246119229920050">"నియంత్రణలను జోడించండి"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"నియంత్రణలను ఎడిట్ చేయండి"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 1a95fcfa9de..3cf00dd 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -88,7 +88,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"اسکرین شاٹ برخاست کریں"</string>
     <string name="screenshot_preview_description" msgid="669177537416980449">"اسکرین شاٹ کھولیں"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"اسکرین ریکارڈر"</string>
+    <string name="screenrecord_name" msgid="2596401223859996572">"سکرین ریکارڈر"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ریکارڈنگ شروع کریں؟"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"‏ریکارڈ کرنے کے دوران، Android سسٹم آپ کی اسکرین پر نظر آنے والی یا آپ کے آلہ پر چلنے والی کسی بھی حساس معلومات کو کیپچر کر سکتا ہے۔ اس میں پاس ورڈز، ادائیگی کی معلومات، تصاویر، پیغامات اور آڈیو شامل ہیں۔"</string>
@@ -155,26 +155,16 @@
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"غلط پاس ورڈ"</string>
     <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"کافی زیادہ غلط کوششیں کی گئیں۔\n <xliff:g id="NUMBER">%d</xliff:g> سیکنڈ بعد دوبارہ کوشش کریں۔"</string>
     <string name="biometric_dialog_credential_attempts_before_wipe" msgid="6751859711975516999">"دوبارہ کوشش کریں۔ کوشش <xliff:g id="ATTEMPTS_0">%1$d</xliff:g> از <xliff:g id="MAX_ATTEMPTS">%2$d</xliff:g>۔"</string>
-    <!-- no translation found for biometric_dialog_last_attempt_before_wipe_dialog_title (2874250099278693477) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_device (6562299244825817598) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_device (9151756675698215723) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_device (2363778585575998317) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_user (8400180746043407270) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_user (4159878829962411168) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_user (4695682515465063885) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pattern_attempt_before_wipe_profile (6045224069529284686) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_pin_attempt_before_wipe_profile (545567685899091757) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_last_password_attempt_before_wipe_profile (8538032972389729253) -->
-    <skip />
+    <string name="biometric_dialog_last_attempt_before_wipe_dialog_title" msgid="2874250099278693477">"آپ کا ڈیٹا حذف کر دیا جائے گا"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_device" msgid="6562299244825817598">"اگر آپ نے اگلی کوشش میں غلط پیٹرن درج کیا تو اس آلے کا ڈیٹا حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_device" msgid="9151756675698215723">"‏اگر آپ نے اگلی کوشش میں غلط PIN درج کیا تو اس آلے کا ڈیٹا حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_device" msgid="2363778585575998317">"اگر آپ نے اگلی کوشش میں غلط پاس ورڈ درج کیا تو اس آلے کا ڈیٹا حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"اگر آپ نے اگلی کوشش میں غلط پیٹرن درج کیا تو اس صارف کو حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"‏اگر آپ نے اگلی کوشش میں غلط PIN درج کیا تو اس صارف کو حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"اگر آپ نے اگلی کوشش میں غلط پاس ورڈ درج کیا تو اس صارف کو حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"اگر آپ نے اگلی کوشش میں غلط پیٹرن درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"‏اگر آپ نے اگلی کوشش میں غلط PIN درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"اگر آپ نے اگلی کوشش میں غلط پاس ورڈ درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"بہت زیادہ غلط کوششیں۔ اس آلے کا ڈیٹا حذف کر دیا جائے گا۔"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"بہت زیادہ غلط کوششیں۔ اس صارف کو حذف کر دیا جائے گا۔"</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"بہت زیادہ غلط کوششیں۔ یہ دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
@@ -1005,7 +995,7 @@
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"برخاست کریں"</string>
     <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"بلبلہ گفتگو نہ کریں"</string>
     <string name="bubbles_user_education_title" msgid="5547017089271445797">"بلبلے کے ذریعے چیٹ کریں"</string>
-    <string name="bubbles_user_education_description" msgid="1160281719576715211">"نئی گفتگو فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہو گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"نئی گفتگوئیں فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہوں گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
     <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"کسی بھی وقت بلبلے کو کنٹرول کریں"</string>
     <string name="bubbles_user_education_manage" msgid="1391639189507036423">"اس ایپ سے بلبلوں کو آف کرنے کے لیے نظم کریں پر تھپتھپائیں"</string>
     <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"سمجھ آ گئی"</string>
@@ -1015,15 +1005,11 @@
     <string name="magnification_overlay_title" msgid="6584179429612427958">"میگنیفیکیشن اوورلے ونڈو"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
-    <!-- no translation found for quick_controls_title (1686913115679255053) -->
-    <skip />
+    <string name="quick_controls_title" msgid="1686913115679255053">"فوری کنٹرولز"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"اپنے منسلک آلات کے لیے کنٹرولز شامل کریں"</string>
-    <!-- no translation found for quick_controls_setup_title (9079435969373471268) -->
-    <skip />
-    <!-- no translation found for quick_controls_setup_subtitle (1681506617879773824) -->
-    <skip />
-    <!-- no translation found for controls_providers_title (6879775889857085056) -->
-    <skip />
+    <string name="quick_controls_setup_title" msgid="9079435969373471268">"فوری کنٹرولز سیٹ اپ کریں"</string>
+    <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"اپنے کنٹرول تک رسائی حاصل کرنے کے ليے پاور بٹن کو دبائیں رکھیں"</string>
+    <string name="controls_providers_title" msgid="6879775889857085056">"کنٹرولز شامل کرنے کے لیے ایپ منتخب کریں"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> کنٹرولز شامل کر دیے گئے۔</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> کنٹرول شامل کر دیا گیا۔</item>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 0429135..b88c874 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -162,9 +162,9 @@
     <string name="biometric_dialog_last_pattern_attempt_before_wipe_user" msgid="8400180746043407270">"Agar grafik kalitni xato kiritsangiz, bu foydalanuvchi oʻchirib tashlanadi."</string>
     <string name="biometric_dialog_last_pin_attempt_before_wipe_user" msgid="4159878829962411168">"Agar PIN kodni xato kiritsangiz, bu foydalanuvchi oʻchirib tashlanadi."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_user" msgid="4695682515465063885">"Agar parolni xato kiritsangiz, bu foydalanuvchi oʻchirib tashlanadi."</string>
-    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Agar grafik kalitni xato kiritsangiz, ishchi profil va undagi maʼlumotlar oʻchirib tashlanadi."</string>
-    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Agar PIN kodni xato kiritsangiz, ishchi profil va undagi maʼlumotlar oʻchirib tashlanadi."</string>
-    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Agar parolni xato kiritsangiz, ishchi profil va undagi maʼlumotlar oʻchirib tashlanadi."</string>
+    <string name="biometric_dialog_last_pattern_attempt_before_wipe_profile" msgid="6045224069529284686">"Agar grafik kalitni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
+    <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Agar PIN kodni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
+    <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Agar parolni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_device" msgid="6585503524026243042">"Juda koʻp marta muvaffaqiyatsiz urindingiz. Bu qurilmadagi maʼlumotlar oʻchirib tashlanadi."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_user" msgid="7015008539146949115">"Juda koʻp marta muvaffaqiyatsiz urindingiz. Bu foydalanuvchi oʻchirib tashlanadi."</string>
     <string name="biometric_dialog_failed_attempts_now_wiping_profile" msgid="5239378521440749682">"Juda koʻp marta muvaffaqiyatsiz urindingiz. Bu ishchi profil va undagi maʼlumotlar oʻchirib tashlanadi."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index eb6c825..957bbd6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -63,12 +63,12 @@
     <string name="usb_debugging_allow" msgid="1722643858015321328">"Cho phép"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Không cho phép chế độ gỡ lỗi qua USB"</string>
     <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi USB. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string>
-    <string name="wifi_debugging_title" msgid="7300007687492186076">"Cho phép gỡ lỗi không dây trên mạng này?"</string>
+    <string name="wifi_debugging_title" msgid="7300007687492186076">"Cho phép gỡ lỗi qua Wi-Fi trên mạng này?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"Tên mạng (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nĐịa chỉ Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
     <string name="wifi_debugging_always" msgid="2968383799517975155">"Luôn cho phép trên mạng này"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"Cho phép"</string>
-    <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Không cho phép gỡ lỗi không dây"</string>
-    <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi không dây. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string>
+    <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Không cho phép gỡ lỗi qua Wi-Fi"</string>
+    <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi qua Wi-Fi. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string>
     <string name="usb_contaminant_title" msgid="894052515034594113">"Đã tắt cổng USB"</string>
     <string name="usb_contaminant_message" msgid="7730476585174719805">"Để bảo vệ thiết bị của bạn khỏi chất lỏng hay mảnh vỡ, cổng USB sẽ tắt và không phát hiện được bất kỳ phụ kiện nào.\n\nBạn sẽ nhận được thông báo khi có thể sử dụng lại cổng USB."</string>
     <string name="usb_port_enabled" msgid="531823867664717018">"Đã bật cổng USB để phát hiện bộ sạc và phụ kiện"</string>
@@ -712,8 +712,8 @@
     <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"Theo mặc định, tất cả các cuộc trò chuyện từ ứng dụng <xliff:g id="APP_NAME_0">%1$s</xliff:g> được phép hiển thị dưới dạng bong bóng. Quản lý trong phần <xliff:g id="APP_NAME_1">%2$s</xliff:g>."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cài đặt"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Mức độ ưu tiên"</string>
-    <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Không có bong bóng nào gần đây"</string>
-    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Bong bóng đã đóng và bong bóng gần đây sẽ xuất hiện ở đây"</string>
+    <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Không có bong bóng trò chuyện nào gần đây"</string>
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Bong bóng trò chuyện đã đóng và bong bóng trò chuyện gần đây sẽ xuất hiện ở đây"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Không thể sửa đổi các thông báo này."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Không thể định cấu hình nhóm thông báo này tại đây"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"Thông báo đã xử lý qua máy chủ proxy"</string>
@@ -741,7 +741,7 @@
     <string name="notification_conversation_mute" msgid="268951550222925548">"Bị tắt tiếng"</string>
     <string name="notification_conversation_unmute" msgid="2692255619510896710">"Thông báo"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"Hiển thị bong bóng"</string>
-    <string name="notification_conversation_unbubble" msgid="6908427185031099868">"Xóa bong bóng"</string>
+    <string name="notification_conversation_unbubble" msgid="6908427185031099868">"Xóa bong bóng trò chuyện"</string>
     <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Thêm vào màn hình chính"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<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="6429668976593634862">"điều khiển thông báo"</string>
@@ -983,7 +983,7 @@
     <string name="device_services" msgid="1549944177856658705">"Dịch vụ cho thiết bị"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Nhấn để khởi động lại ứng dụng này và xem ở chế độ toàn màn hình."</string>
-    <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Tùy chọn cài đặt cho bong bóng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Tùy chọn cài đặt cho bong bóng trò chuyện <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Quản lý"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> của <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> từ <xliff:g id="APP_NAME">%2$s</xliff:g> và <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> bong bóng khác"</string>
@@ -994,10 +994,10 @@
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Chuyển tới dưới cùng bên phải"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"Loại bỏ"</string>
     <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Dừng trò chuyện bằng bong bóng"</string>
-    <string name="bubbles_user_education_title" msgid="5547017089271445797">"Trò chuyện bằng bong bóng"</string>
-    <string name="bubbles_user_education_description" msgid="1160281719576715211">"Các cuộc trò chuyện mới hiển thị dưới dạng biểu tượng nổi hoặc bong bóng. Nhấn để mở bong bóng. Kéo để di chuyển bong bóng."</string>
-    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Kiểm soát các tùy chọn cài đặt bong bóng bất cứ lúc nào"</string>
-    <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Nhấn vào nút Quản lý để tắt bong bóng từ ứng dụng này"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"Trò chuyện bằng bong bóng trò chuyện"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"Các cuộc trò chuyện mới hiển thị dưới dạng biểu tượng nổi hoặc bong bóng trò chuyện. Nhấn để mở bong bóng trò chuyện. Kéo để di chuyển bong bóng trò chuyện."</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Kiểm soát tùy chọn cài đặt bong bóng trò chuyện bất mọi lúc"</string>
+    <string name="bubbles_user_education_manage" msgid="1391639189507036423">"Nhấn vào nút Quản lý để tắt bong bóng trò chuyện từ ứng dụng này"</string>
     <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"OK"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Đã cập nhật chế độ di chuyển trên hệ thống. Để thay đổi, hãy chuyển đến phần Cài đặt."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Chuyển đến phần Cài đặt để cập nhật chế độ di chuyển trên hệ thống"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3dfc3bf..791fe8d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -88,7 +88,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"此应用或您所在的单位不允许进行屏幕截图"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"关闭屏幕截图"</string>
     <string name="screenshot_preview_description" msgid="669177537416980449">"打开屏幕截图"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制工具"</string>
+    <string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制器"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"要开始录制吗?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"在录制内容时,Android 系统可以捕捉到您屏幕上显示或设备中播放的敏感信息,其中包括密码、付款信息、照片、消息和音频。"</string>
@@ -708,12 +708,12 @@
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"不会发出提示音或振动,可帮助您保持专注。"</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"通过提示音或振动吸引您的注意。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"通过可链接到这项内容的浮动快捷方式吸引您的注意。"</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"以气泡形式显示在会话部分顶部。"</string>
-    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"默认情况下,<xliff:g id="APP_NAME_0">%1$s</xliff:g>中的所有会话都会以气泡形式显示。在“<xliff:g id="APP_NAME_1">%2$s</xliff:g>”中管理。"</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"以对话泡形式显示在对话部分顶部。"</string>
+    <string name="notification_conversation_channel_all_bubble" msgid="5389290797101635297">"默认情况下,<xliff:g id="APP_NAME_0">%1$s</xliff:g>中的所有对话都会以对话泡形式显示。在“<xliff:g id="APP_NAME_1">%2$s</xliff:g>”中管理。"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"设置"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"优先级"</string>
-    <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"最近没有气泡"</string>
-    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"此处会显示最近的气泡和已关闭的气泡"</string>
+    <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"最近没有对话泡"</string>
+    <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"此处会显示最近的对话泡和已关闭的对话泡"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"无法修改这些通知。"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"您无法在此处配置这组通知"</string>
     <string name="notification_delegate_header" msgid="1264510071031479920">"代理通知"</string>
@@ -741,7 +741,7 @@
     <string name="notification_conversation_mute" msgid="268951550222925548">"已静音"</string>
     <string name="notification_conversation_unmute" msgid="2692255619510896710">"提醒"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"显示气泡"</string>
-    <string name="notification_conversation_unbubble" msgid="6908427185031099868">"移除气泡"</string>
+    <string name="notification_conversation_unbubble" msgid="6908427185031099868">"移除对话泡"</string>
     <string name="notification_conversation_home_screen" msgid="8347136037958438935">"添加到主屏幕"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<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="6429668976593634862">"通知设置"</string>
@@ -983,7 +983,7 @@
     <string name="device_services" msgid="1549944177856658705">"设备服务"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"点按即可重启此应用并进入全屏模式。"</string>
-    <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g>气泡的相关设置"</string>
+    <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g>对话泡的设置"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"管理"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>:<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g>和另外 <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> 个应用:<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -993,11 +993,11 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"移至左下角"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"移至右下角"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"关闭"</string>
-    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"不以气泡形式显示会话"</string>
-    <string name="bubbles_user_education_title" msgid="5547017089271445797">"使用气泡聊天"</string>
-    <string name="bubbles_user_education_description" msgid="1160281719576715211">"新会话会以浮动图标或气泡形式显示。点按即可打开气泡。拖动即可移动气泡。"</string>
-    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"随时控制气泡"</string>
-    <string name="bubbles_user_education_manage" msgid="1391639189507036423">"点按“管理”按钮,可关闭来自此应用的气泡"</string>
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"不以对话泡形式显示对话"</string>
+    <string name="bubbles_user_education_title" msgid="5547017089271445797">"使用对话泡聊天"</string>
+    <string name="bubbles_user_education_description" msgid="1160281719576715211">"新对话会以浮动图标或对话泡形式显示。点按即可打开对话泡。拖动即可移动对话泡。"</string>
+    <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"随时控制对话泡"</string>
+    <string name="bubbles_user_education_manage" msgid="1391639189507036423">"点按“管理”按钮,可关闭来自此应用的对话泡"</string>
     <string name="bubbles_user_education_got_it" msgid="8282812431953161143">"知道了"</string>
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"系统导航已更新。要进行更改,请转到“设置”。"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"转到“设置”即可更新系统导航"</string>
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/packages/SystemUI/res/values/arrays_tv.xml
index 95716c8..3343a84 100644
--- a/packages/SystemUI/res/values/arrays_tv.xml
+++ b/packages/SystemUI/res/values/arrays_tv.xml
@@ -35,7 +35,5 @@
     </string-array>
 
     <string-array name="audio_recording_disclosure_exempt_apps" translatable="false">
-      <item>com.google.android.katniss</item>
-      <item>com.google.android.apps.mediashell</item>
     </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 74bbee6..288487a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -58,6 +58,19 @@
     <!-- Shadows under the clock, date and other keyguard text fields -->
     <color name="keyguard_shadow_color">#B2000000</color>
 
+    <!-- Color for rounded background for activated user in keyguard user switcher -->
+    <color name="kg_user_switcher_activated_background_color">#26000000</color>
+    <!-- Icon color for user avatars in keyguard user switcher -->
+    <color name="kg_user_switcher_avatar_icon_color">@android:color/background_light</color>
+    <!-- Icon color for selected user avatars in keyguard user switcher -->
+    <color name="kg_user_switcher_selected_avatar_icon_color">@android:color/background_light</color>
+    <!-- Icon color for user avatars in user switcher quick settings -->
+    <color name="qs_user_switcher_avatar_icon_color">#3C4043</color>
+    <!-- Icon color for selected user avatars in user switcher quick settings -->
+    <color name="qs_user_switcher_selected_avatar_icon_color">@android:color/background_light</color>
+    <!-- Color of background circle of user avatars in quick settings -->
+    <color name="qs_user_switcher_avatar_background">#DADCE0</color>
+
     <!-- The color of the legacy notification background -->
     <color name="notification_legacy_background_color">#ff1a1a1a</color>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 922acff..f549a32 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -533,4 +533,12 @@
          This config value should contain the package name of that preferred application.
     -->
     <string translatable="false" name="config_controlsPreferredPackage"></string>
+
+    <!-- Max number of columns for quick controls area -->
+    <integer name="controls_max_columns">2</integer>
+    <!-- If the dp width of the available space is <= this value, potentially adjust the number
+         of columns-->
+    <integer name="controls_max_columns_adjust_below_width_dp">320</integer>
+    <!-- If the config font scale is >= this value, potentially adjust the number of columns-->
+    <item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 23be78b..bce5fac 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -477,6 +477,7 @@
     <dimen name="qs_tile_height">106dp</dimen>
     <dimen name="qs_tile_layout_margin_side">6dp</dimen>
     <dimen name="qs_tile_margin_horizontal">18dp</dimen>
+    <dimen name="qs_tile_margin_horizontal_two_line">2dp</dimen>
     <dimen name="qs_tile_margin_vertical">24dp</dimen>
     <dimen name="qs_tile_margin_top_bottom">12dp</dimen>
     <dimen name="qs_tile_margin_top_bottom_negative">-12dp</dimen>
@@ -751,8 +752,10 @@
          quick settings header -->
     <dimen name="max_avatar_size">48dp</dimen>
 
-    <!-- Size of user icon + frame in the qs/keyguard user picker (incl. frame) -->
-    <dimen name="framed_avatar_size">54dp</dimen>
+    <!-- Size of user icon + frame in the qs user picker (incl. frame) -->
+    <dimen name="qs_framed_avatar_size">54dp</dimen>
+    <!-- Size of user icon + frame in the keyguard user picker (incl. frame) -->
+    <dimen name="kg_framed_avatar_size">54dp</dimen>
 
     <!-- Margin on the left side of the carrier text on Keyguard -->
     <dimen name="keyguard_carrier_text_margin">16dp</dimen>
@@ -952,7 +955,7 @@
     <dimen name="recents_quick_scrub_onboarding_margin_start">8dp</dimen>
 
     <!-- The height of the gradient indicating the dismiss edge when moving a PIP. -->
-    <dimen name="pip_dismiss_gradient_height">176dp</dimen>
+    <dimen name="floating_dismiss_gradient_height">176dp</dimen>
 
     <!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
     <dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
@@ -1147,11 +1150,17 @@
     <!-- Default (and minimum) height of the expanded view shown when the bubble is expanded -->
     <dimen name="bubble_expanded_default_height">180dp</dimen>
     <!-- Default height of bubble overflow -->
-    <dimen name="bubble_overflow_height">380dp</dimen>
+    <dimen name="bubble_overflow_height">460dp</dimen>
     <!-- Bubble overflow padding when there are no bubbles  -->
     <dimen name="bubble_overflow_empty_state_padding">16dp</dimen>
     <!-- Padding of container for overflow bubbles -->
-    <dimen name="bubble_overflow_padding">5dp</dimen>
+    <dimen name="bubble_overflow_padding">15dp</dimen>
+    <!-- Padding of label for bubble overflow view -->
+    <dimen name="bubble_overflow_text_padding">7dp</dimen>
+    <!-- Height of bubble overflow empty state illustration -->
+    <dimen name="bubble_empty_overflow_image_height">200dp</dimen>
+    <!-- Padding of bubble overflow empty state subtitle -->
+    <dimen name="bubble_empty_overflow_subtitle_padding">50dp</dimen>
     <!-- Height of the triangle that points to the expanded bubble -->
     <dimen name="bubble_pointer_height">4dp</dimen>
     <!-- Width of the triangle that points to the expanded bubble -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d17b81d..566d143 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2647,15 +2647,15 @@
     <!-- Title for Magnification Controls Window [CHAR LIMIT=NONE] -->
     <string name="magnification_controls_title">Magnification Window Controls</string>
 
-    <!-- Quick Controls strings -->
-    <!-- Quick Controls empty state, title [CHAR LIMIT=30] -->
-    <string name="quick_controls_title">Quick controls</string>
-    <!-- Quick Controls empty state, subtitle [CHAR LIMIT=100] -->
+    <!-- Device Controls strings -->
+    <!-- Device Controls empty state, title [CHAR LIMIT=30] -->
+    <string name="quick_controls_title">Device controls</string>
+    <!-- Device Controls empty state, subtitle [CHAR LIMIT=100] -->
     <string name="quick_controls_subtitle">Add controls for your connected devices</string>
 
-    <!-- Quick Controls setup, title [CHAR LIMIT=50] -->
-    <string name="quick_controls_setup_title">Set up quick controls</string>
-    <!-- Quick Controls setup, subtitle [CHAR LIMIT=100] -->
+    <!-- Device Controls setup, title [CHAR LIMIT=50] -->
+    <string name="quick_controls_setup_title">Set up device controls</string>
+    <!-- Device Controls setup, subtitle [CHAR LIMIT=100] -->
     <string name="quick_controls_setup_subtitle">Hold the Power button to access your controls</string>
 
     <!-- Controls management providers screen title [CHAR LIMIT=60]-->
@@ -2679,7 +2679,7 @@
     <string name="controls_favorite_other_zone_header">Other</string>
 
     <!-- Controls dialog title [CHAR LIMIT=40] -->
-    <string name="controls_dialog_title">Add to quick controls</string>
+    <string name="controls_dialog_title">Add to device controls</string>
     <!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
     <string name="controls_dialog_ok">Add to favorites</string>
     <!-- Controls dialog message [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 1598465..aabee1c 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -249,6 +249,7 @@
     <style name="TextAppearance.DeviceManagementDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"/>
 
     <style name="TextAppearance.AuthCredential">
+        <item name="android:accessibilityLiveRegion">polite</item>
         <item name="android:gravity">center_horizontal</item>
         <item name="android:textAlignment">gravity</item>
         <item name="android:layout_gravity">top</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 80fd826..35ad422 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -26,7 +26,7 @@
 
 /**
  * Temporary callbacks into SystemUI.
- * Next id = 25
+ * Next id = 26
  */
 interface ISystemUiProxy {
 
@@ -140,4 +140,10 @@
      * Sets listener to get pinned stack animation callbacks.
      */
     void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) = 24;
+
+    /**
+     * Notifies that quickstep will switch to a new task
+     * @param rotation indicates which Surface.Rotation the gesture was started in
+     */
+    void onQuickSwitchToNewTask(int rotation) = 25;
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
index 29100ef..8bd7c79 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.util.Size;
@@ -59,6 +60,7 @@
         if (mSurfaceControlViewHost != null) {
             mSurfaceControlViewHost.die();
         }
+
         SurfaceControl surfaceControl = SurfaceViewRequestUtils.getSurfaceControl(bundle);
         if (surfaceControl != null) {
             if (viewSize == null) {
@@ -70,8 +72,10 @@
             WindowlessWindowManager windowlessWindowManager =
                     new WindowlessWindowManager(context.getResources().getConfiguration(),
                             surfaceControl, hostToken);
+            DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
             mSurfaceControlViewHost = new SurfaceControlViewHost(context,
-                    context.getDisplayNoVerify(), windowlessWindowManager);
+                    dm.getDisplay(SurfaceViewRequestUtils.getDisplayId(bundle)),
+                    windowlessWindowManager);
             WindowManager.LayoutParams layoutParams =
                     new WindowManager.LayoutParams(
                             viewSize.getWidth(),
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java
index 4409276..6742a4d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java
@@ -26,30 +26,38 @@
 public class SurfaceViewRequestUtils {
     private static final String KEY_HOST_TOKEN = "host_token";
     private static final String KEY_SURFACE_CONTROL = "surface_control";
+    private static final String KEY_DISPLAY_ID = "display_id";
 
     /** Creates a SurfaceView based bundle that stores the input host token and surface control. */
     public static Bundle createSurfaceBundle(SurfaceView surfaceView) {
         Bundle bundle = new Bundle();
         bundle.putBinder(KEY_HOST_TOKEN, surfaceView.getHostToken());
         bundle.putParcelable(KEY_SURFACE_CONTROL, surfaceView.getSurfaceControl());
+        bundle.putInt(KEY_DISPLAY_ID, surfaceView.getDisplay().getDisplayId());
         return bundle;
     }
 
     /**
      * Retrieves the SurfaceControl from a bundle created by
      * {@link #createSurfaceBundle(SurfaceView)}.
-     **/
+     */
     public static SurfaceControl getSurfaceControl(Bundle bundle) {
         return bundle.getParcelable(KEY_SURFACE_CONTROL);
     }
 
     /**
-     * Retrieves the input token from a bundle created by
-     * {@link #createSurfaceBundle(SurfaceView)}.
-     **/
+     * Retrieves the input token from a bundle created by {@link #createSurfaceBundle(SurfaceView)}.
+     */
     public static @Nullable IBinder getHostToken(Bundle bundle) {
         return bundle.getBinder(KEY_HOST_TOKEN);
     }
 
+    /**
+     * Retrieves the display id from a bundle created by {@link #createSurfaceBundle(SurfaceView)}.
+     */
+    public static int getDisplayId(Bundle bundle) {
+        return bundle.getInt(KEY_DISPLAY_ID);
+    }
+
     private SurfaceViewRequestUtils() {}
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index caee8cc..88f4176 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -34,6 +34,7 @@
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockscreenCredential;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
 /**
@@ -50,6 +51,7 @@
     private boolean mDismissing;
     protected boolean mResumed;
     private CountDownTimer mCountdownTimer = null;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     // To avoid accidental lockout due to events while the device in in the pocket, ignore
     // any passwords with length less than or equal to this length.
@@ -61,6 +63,7 @@
 
     public KeyguardAbsKeyInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
     }
 
     @Override
@@ -151,6 +154,8 @@
             LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
             LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
         }
+
+        mKeyguardUpdateMonitor.setCredentialAttempted();
         mPendingLockCheck = LockPatternChecker.checkCredential(
                 mLockPatternUtils,
                 password,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
index d154434..af5196f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
@@ -24,6 +24,8 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
 import android.util.Log;
 import android.view.View;
 import android.widget.ImageButton;
@@ -40,6 +42,7 @@
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.media.MediaControllerFactory;
 import com.android.systemui.statusbar.notification.MediaNotificationProcessor;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.stack.MediaHeaderView;
@@ -71,10 +74,11 @@
     private KeyguardMediaObserver mObserver;
 
     @Inject
-    public KeyguardMediaPlayer(Context context, @Background Executor backgroundExecutor) {
+    public KeyguardMediaPlayer(Context context, MediaControllerFactory factory,
+            @Background Executor backgroundExecutor) {
         mContext = context;
         mBackgroundExecutor = backgroundExecutor;
-        mViewModel = new KeyguardMediaViewModel(context);
+        mViewModel = new KeyguardMediaViewModel(context, factory);
     }
 
     /** Binds media controls to a view hierarchy. */
@@ -139,14 +143,16 @@
     private static final class KeyguardMediaViewModel {
 
         private final Context mContext;
+        private final MediaControllerFactory mMediaControllerFactory;
         private final MutableLiveData<KeyguardMedia> mMedia = new MutableLiveData<>();
         private final Object mActionsLock = new Object();
         private List<PendingIntent> mActions;
         private float mAlbumArtRadius;
         private int mAlbumArtSize;
 
-        KeyguardMediaViewModel(Context context) {
+        KeyguardMediaViewModel(Context context, MediaControllerFactory factory) {
             mContext = context;
+            mMediaControllerFactory = factory;
             loadDimens();
         }
 
@@ -162,6 +168,17 @@
         public void updateControls(NotificationEntry entry, Icon appIcon,
                 MediaMetadata mediaMetadata) {
 
+            // Check the playback state of the media controller. If it is null, then the session was
+            // probably destroyed. Don't update in this case.
+            final MediaSession.Token token = entry.getSbn().getNotification().extras
+                    .getParcelable(Notification.EXTRA_MEDIA_SESSION);
+            final MediaController controller = token != null
+                    ? mMediaControllerFactory.create(token) : null;
+            if (controller != null && controller.getPlaybackState() == null) {
+                clearControls();
+                return;
+            }
+
             // Foreground and Background colors computed from album art
             Notification notif = entry.getSbn().getNotification();
             int fgColor = notif.color;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 48c6bd1..ad92f8f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -282,6 +282,7 @@
 
         @Override
         public void onPatternDetected(final List<LockPatternView.Cell> pattern) {
+            mKeyguardUpdateMonitor.setCredentialAttempted();
             mLockPatternView.disableInput();
             if (mPendingLockCheck != null) {
                 mPendingLockCheck.cancel(false);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 7cbc840af..88d6943 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -223,6 +223,7 @@
     private int mRingMode;
     private int mPhoneState;
     private boolean mKeyguardIsVisible;
+    private boolean mCredentialAttempted;
     private boolean mKeyguardGoingAway;
     private boolean mGoingToSleep;
     private boolean mBouncer;
@@ -498,11 +499,21 @@
     }
 
     /**
+     * Updates KeyguardUpdateMonitor's internal state to know if credential was attempted on
+     * bouncer. Note that this does not care if the credential was correct/incorrect. This is
+     * cleared when the user leaves the bouncer (unlocked, screen off, back to lockscreen, etc)
+     */
+    public void setCredentialAttempted() {
+        mCredentialAttempted = true;
+        updateBiometricListeningState();
+    }
+
+    /**
      * Updates KeyguardUpdateMonitor's internal state to know if keyguard is goingAway
      */
     public void setKeyguardGoingAway(boolean goingAway) {
         mKeyguardGoingAway = goingAway;
-        updateFingerprintListeningState();
+        updateBiometricListeningState();
     }
 
     /**
@@ -664,6 +675,8 @@
             updateFingerprintListeningState();
         } else {
             setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
+            mFingerprintCancelSignal = null;
+            mFaceCancelSignal = null;
         }
 
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
@@ -679,6 +692,11 @@
                     getCurrentUser());
         }
 
+        if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
+                || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+            mFingerprintLockedOut = true;
+        }
+
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -688,6 +706,7 @@
     }
 
     private void handleFingerprintLockoutReset() {
+        mFingerprintLockedOut = false;
         updateFingerprintListeningState();
     }
 
@@ -971,13 +990,16 @@
         boolean changed = false;
 
         if (enabled && (oldIntent == null)) {
-            ComponentName poComponent = mDevicePolicyManager.getProfileOwnerAsUser(userId);
-            if (poComponent == null) {
-                Log.e(TAG, "No profile owner found for User " + userId);
+            ComponentName supervisorComponent =
+                    mDevicePolicyManager.getProfileOwnerOrDeviceOwnerSupervisionComponent(
+                            UserHandle.of(userId));
+            if (supervisorComponent == null) {
+                Log.e(TAG, "No Profile Owner or Device Owner supervision app found for User "
+                        + userId);
             } else {
                 Intent intent =
                         new Intent(DevicePolicyManager.ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE)
-                                .setPackage(poComponent.getPackageName());
+                                .setPackage(supervisorComponent.getPackageName());
                 ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent, 0);
                 if (resolveInfo != null && resolveInfo.serviceInfo != null) {
                     Intent launchIntent =
@@ -1271,6 +1293,7 @@
     private CancellationSignal mFaceCancelSignal;
     private FingerprintManager mFpm;
     private FaceManager mFaceManager;
+    private boolean mFingerprintLockedOut;
 
     /**
      * When we receive a
@@ -1817,13 +1840,17 @@
     }
 
     private boolean shouldListenForFingerprint() {
+        final boolean allowedOnBouncer =
+                !(mFingerprintLockedOut && mBouncer && mCredentialAttempted);
+
         // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
         final boolean shouldListen = (mKeyguardIsVisible || !mDeviceInteractive ||
                 (mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
                 shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
                 && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
-                && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser;
+                && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser
+                && allowedOnBouncer;
         return shouldListen;
     }
 
@@ -2369,6 +2396,8 @@
             // camera requests dismiss keyguard (tapping on photos for example). When these happen,
             // face auth should resume.
             mSecureCameraLaunched = false;
+        } else {
+            mCredentialAttempted = false;
         }
 
         for (int i = 0; i < mCallbacks.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index fc29f5c..2f10394 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -57,27 +57,27 @@
     /**
      * Called when the device started going to sleep.
      */
-    void onStartedGoingToSleep();
+    default void onStartedGoingToSleep() {};
 
     /**
      * Called when the device has finished going to sleep.
      */
-    void onFinishedGoingToSleep();
+    default void onFinishedGoingToSleep() {};
 
     /**
      * Called when the device started waking up.
      */
-    void onStartedWakingUp();
+    default void onStartedWakingUp() {};
 
     /**
      * Called when the device started turning on.
      */
-    void onScreenTurningOn();
+    default void onScreenTurningOn() {};
 
     /**
      * Called when the device has finished turning on.
      */
-    void onScreenTurnedOn();
+    default void onScreenTurnedOn() {};
 
     /**
      * Sets whether the Keyguard needs input.
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 23fa645..5442299 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -120,7 +120,7 @@
         private void init(DozeParameters dozeParameters) {
             mIsHighEndGfx = ActivityManager.isHighEndGfx();
             mDisplayNeedsBlanking = dozeParameters.getDisplayNeedsBlanking();
-            mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking;
+            mNeedTransition = false;
 
             // We will preserve EGL context when we are in lock screen or aod
             // to avoid janking in following transition, we need to release when back to home.
@@ -137,7 +137,7 @@
             mRenderer = getRendererInstance();
             getDisplayContext().getDisplay().getDisplayInfo(mDisplayInfo);
             setFixedSizeAllowed(true);
-            setOffsetNotificationsEnabled(true);
+            setOffsetNotificationsEnabled(mNeedTransition);
             updateSurfaceSize();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index 6923079..13d6a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -49,6 +49,8 @@
     public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
     public static final Interpolator HEADS_UP_APPEAR = new HeadsUpAppearInterpolator();
     public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
+    public static final Interpolator SHADE_ANIMATION =
+            new PathInterpolator(0.6f, 0.02f, 0.4f, 0.98f);
     public static final Interpolator ICON_OVERSHOT_LESS
             = new PathInterpolator(0.4f, 0f, 0.2f, 1.1f);
     public static final Interpolator PANEL_CLOSE_ACCELERATED
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index cc4ee89..a876dee 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -109,7 +109,7 @@
     protected static final String CONSTRAINED_KEY = "should_constrain";
 
     public static final int INVOCATION_TYPE_GESTURE = 1;
-    public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2;
+    public static final int INVOCATION_TYPE_OTHER = 2;
     public static final int INVOCATION_TYPE_VOICE = 3;
     public static final int INVOCATION_TYPE_QUICK_SEARCH_BAR = 4;
     public static final int INVOCATION_HOME_BUTTON_LONG_PRESS = 5;
@@ -482,8 +482,12 @@
     }
 
     public void onLockscreenShown() {
-        // TODO(b/140052478)
-        whitelistIpcs(mAssistUtils::onLockscreenShown);
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                mAssistUtils.onLockscreenShown();
+            }
+        });
     }
 
     public long getAssistHandleShowAndGoRemainingDurationMs() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
index b006bc1..8bf2591 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
@@ -214,9 +214,11 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
-        setText(mTitleView, getTitle(mBiometricPromptBundle));
+        final CharSequence title = getTitle(mBiometricPromptBundle);
+        setText(mTitleView, title);
         setTextOrHide(mSubtitleView, getSubtitle(mBiometricPromptBundle));
         setTextOrHide(mDescriptionView, getDescription(mBiometricPromptBundle));
+        announceForAccessibility(title);
 
         final boolean isManagedProfile = Utils.isManagedProfile(mContext, mEffectiveUserId);
         final Drawable image;
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index e89c66e..74b94e7 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -166,7 +166,7 @@
 
     @VisibleForTesting
     protected open fun createUBRForUser(userId: Int) =
-            UserBroadcastDispatcher(context, userId, mainHandler, bgLooper)
+            UserBroadcastDispatcher(context, userId, bgLooper)
 
     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
         pw.println("Broadcast dispatcher:")
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index 0c631aa..4e84f06 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -27,7 +27,6 @@
 import android.util.ArrayMap
 import android.util.ArraySet
 import android.util.Log
-import androidx.annotation.MainThread
 import androidx.annotation.VisibleForTesting
 import com.android.internal.util.Preconditions
 import com.android.systemui.Dumpable
@@ -46,11 +45,13 @@
  *
  * Created by [BroadcastDispatcher] as needed by users. The value of [userId] can be
  * [UserHandle.USER_ALL].
+ *
+ * Each instance of this class will register itself exactly once with [Context]. Updates to the
+ * [IntentFilter] will be done in the background thread.
  */
 class UserBroadcastDispatcher(
     private val context: Context,
     private val userId: Int,
-    private val mainHandler: Handler,
     private val bgLooper: Looper
 ) : BroadcastReceiver(), Dumpable {
 
@@ -168,7 +169,7 @@
     // Only call this from a BG thread
     private fun createFilterAndRegisterReceiverBG() {
         val intentFilter = createFilter()
-        mainHandler.post(RegisterReceiverRunnable(intentFilter))
+        bgHandler.post(RegisterReceiverRunnable(intentFilter))
     }
 
     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
@@ -207,10 +208,7 @@
 
         /*
          * Registers and unregisters the BroadcastReceiver
-         *
-         * Must be called from Main Thread
          */
-        @MainThread
         override fun run() {
             if (registered.get()) {
                 context.unregisterReceiver(this@UserBroadcastDispatcher)
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 1c69594..be9cd5f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -549,6 +549,7 @@
                 Log.e(TAG, "Attempt to expand stack without selected bubble!");
                 return;
             }
+            mSelectedBubble.markUpdatedAt(mTimeSource.currentTimeMillis());
             mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
             mStateChange.orderChanged |= repackAll();
         } else if (!mBubbles.isEmpty()) {
@@ -662,7 +663,7 @@
 
     /**
      * This applies a full sort and group pass to all existing bubbles. The bubbles are grouped
-     * by groupId. Each group is then sorted by the max(lastUpdated) time of it's bubbles. Bubbles
+     * by groupId. Each group is then sorted by the max(lastUpdated) time of its bubbles. Bubbles
      * within each group are then sorted by lastUpdated descending.
      *
      * @return true if the position of any bubbles changed as a result
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index 2231d11..37841f2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -21,18 +21,17 @@
 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.app.Activity;
-import android.app.Notification;
-import android.app.Person;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.os.Bundle;
-import android.os.Parcelable;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -55,6 +54,7 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleOverflowActivity" : TAG_BUBBLES;
 
     private LinearLayout mEmptyState;
+    private ImageView mEmptyStateImage;
     private BubbleController mBubbleController;
     private BubbleOverflowAdapter mAdapter;
     private RecyclerView mRecyclerView;
@@ -73,6 +73,7 @@
 
         mEmptyState = findViewById(R.id.bubble_overflow_empty_state);
         mRecyclerView = findViewById(R.id.bubble_overflow_recycler);
+        mEmptyStateImage = findViewById(R.id.bubble_overflow_empty_state_image);
 
         Resources res = getResources();
         final int columns = res.getInteger(R.integer.bubbles_overflow_columns);
@@ -81,11 +82,15 @@
 
         DisplayMetrics displayMetrics = new DisplayMetrics();
         getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
-        final int viewWidth = displayMetrics.widthPixels / columns;
+        final int recyclerViewWidth = (displayMetrics.widthPixels
+                - res.getDimensionPixelSize(R.dimen.bubble_overflow_padding));
+        final int viewWidth = recyclerViewWidth / columns;
 
         final int maxOverflowBubbles = res.getInteger(R.integer.bubbles_max_overflow);
         final int rows = (int) Math.ceil((double) maxOverflowBubbles / columns);
-        final int viewHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height) / rows;
+        final int recyclerViewHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height)
+                - res.getDimensionPixelSize(R.dimen.bubble_overflow_padding);
+        final int viewHeight = recyclerViewHeight / rows;
 
         mAdapter = new BubbleOverflowAdapter(mOverflowBubbles,
                 mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight);
@@ -94,6 +99,31 @@
         mBubbleController.setOverflowCallback(() -> {
             onDataChanged(mBubbleController.getOverflowBubbles());
         });
+        onThemeChanged();
+    }
+
+    /**
+     * Handle theme changes.
+     */
+    void onThemeChanged() {
+        final int mode =
+                getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+        switch (mode) {
+            case Configuration.UI_MODE_NIGHT_NO:
+                if (DEBUG_OVERFLOW) {
+                    Log.d(TAG, "Set overflow UI to light mode");
+                }
+                mEmptyStateImage.setImageDrawable(
+                        getResources().getDrawable(R.drawable.ic_empty_bubble_overflow_light));
+                break;
+            case Configuration.UI_MODE_NIGHT_YES:
+                if (DEBUG_OVERFLOW) {
+                    Log.d(TAG, "Set overflow UI to dark mode");
+                }
+                mEmptyStateImage.setImageDrawable(
+                        getResources().getDrawable(R.drawable.ic_empty_bubble_overflow_dark));
+                break;
+        }
     }
 
     void setBackgroundColor() {
@@ -134,6 +164,7 @@
     @Override
     public void onResume() {
         super.onResume();
+        onThemeChanged();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 6a7b0da..044feaa 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -514,7 +514,7 @@
         mDismissTargetContainer = new FrameLayout(context);
         mDismissTargetContainer.setLayoutParams(new FrameLayout.LayoutParams(
                 MATCH_PARENT,
-                getResources().getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height),
+                getResources().getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height),
                 Gravity.BOTTOM));
         mDismissTargetContainer.setClipChildren(false);
         mDismissTargetContainer.addView(targetView);
@@ -523,7 +523,7 @@
 
         // Start translated down so the target springs up.
         targetView.setTranslationY(
-                getResources().getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height));
+                getResources().getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height));
 
         // Save the MagneticTarget instance for the newly set up view - we'll add this to the
         // MagnetizedObjects.
@@ -713,7 +713,7 @@
         } else {
             mBubbleContainer.removeView(mBubbleOverflow.getBtn());
             mBubbleOverflow.updateIcon(mContext, this);
-            overflowBtnIndex = mBubbleContainer.getChildCount() - 1;
+            overflowBtnIndex = mBubbleContainer.getChildCount();
         }
         mBubbleContainer.addView(mBubbleOverflow.getBtn(), overflowBtnIndex,
                 new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index ea1abf9..a0b4938 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -323,6 +323,9 @@
 
     /** Plays a dismiss animation on the dragged out bubble. */
     public void dismissDraggedOutBubble(View bubble, Runnable after) {
+        if (bubble == null) {
+            return;
+        }
         animationForChild(bubble)
                 .withStiffness(SpringForce.STIFFNESS_HIGH)
                 .scaleX(1.1f)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 764fda0..1291dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -151,10 +151,10 @@
         subtitle.text = data.control.subtitle
         favorite.isChecked = data.favorite
         removed.text = if (data.removed) "Removed" else ""
-        favorite.setOnClickListener {
+        itemView.setOnClickListener {
+            favorite.isChecked = !favorite.isChecked
             favoriteCallback(data.control.controlId, favorite.isChecked)
         }
-        itemView.setOnClickListener { favorite.performClick() }
         applyRenderInfo(renderInfo)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index f2303e6..fe1e632 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -55,13 +55,19 @@
 
     companion object {
         private const val TAG = "ControlsFavoritingActivity"
+
+        // If provided and no structure is available, use as the title
         const val EXTRA_APP = "extra_app_label"
+
+        // If provided, show this structure page first
+        const val EXTRA_STRUCTURE = "extra_structure"
         private const val TOOLTIP_PREFS_KEY = Prefs.Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT
         private const val TOOLTIP_MAX_SHOWN = 2
     }
 
     private var component: ComponentName? = null
     private var appName: CharSequence? = null
+    private var structureExtra: CharSequence? = null
 
     private lateinit var structurePager: ViewPager2
     private lateinit var statusText: TextView
@@ -111,6 +117,7 @@
         val collator = Collator.getInstance(resources.configuration.locales[0])
         comparator = compareBy(collator) { it.structureName }
         appName = intent.getCharSequenceExtra(EXTRA_APP)
+        structureExtra = intent.getCharSequenceExtra(EXTRA_STRUCTURE) ?: ""
         component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
 
         bindViews()
@@ -137,9 +144,15 @@
                 listOfStructures = controlsByStructure.map {
                     StructureContainer(it.key, AllModel(it.value, favoriteKeys, emptyZoneString))
                 }.sortedWith(comparator)
+
+                val structureIndex = listOfStructures.indexOfFirst {
+                    sc -> sc.structureName == structureExtra
+                }.let { if (it == -1) 0 else it }
+
                 executor.execute {
                     doneButton.isEnabled = true
                     structurePager.adapter = StructureAdapter(listOfStructures)
+                    structurePager.setCurrentItem(structureIndex)
                     if (error) {
                         statusText.text = resources.getText(R.string.controls_favorite_load_error)
                     } else {
@@ -247,7 +260,10 @@
         requireViewById<Button>(R.id.other_apps).apply {
             visibility = View.VISIBLE
             setOnClickListener {
-                this@ControlsFavoritingActivity.onBackPressed()
+                val i = Intent()
+                i.setComponent(
+                    ComponentName(context, ControlsProviderSelectorActivity::class.java))
+                context.startActivity(i)
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index 7d3a860..b1cb04e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -51,7 +51,6 @@
 ) {
     val icon: ImageView = layout.requireViewById(R.id.icon)
     val status: TextView = layout.requireViewById(R.id.status)
-    val statusExtra: TextView = layout.requireViewById(R.id.status_extra)
     val title: TextView = layout.requireViewById(R.id.title)
     val subtitle: TextView = layout.requireViewById(R.id.subtitle)
     val context: Context = layout.getContext()
@@ -65,6 +64,8 @@
         val ld = layout.getBackground() as LayerDrawable
         ld.mutate()
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
+        // needed for marquee to start
+        status.setSelected(true)
     }
 
     fun bindData(cws: ControlWithState) {
@@ -103,8 +104,7 @@
 
         behavior?.bind(cws)
 
-        layout.setContentDescription(
-            "${title.text} ${subtitle.text} ${status.text} ${statusExtra.text}")
+        layout.setContentDescription("${title.text} ${subtitle.text} ${status.text}")
     }
 
     fun actionResponse(@ControlAction.ResponseResult response: Int) {
@@ -113,15 +113,12 @@
 
     fun setTransientStatus(tempStatus: String) {
         val previousText = status.getText()
-        val previousTextExtra = statusExtra.getText()
 
         cancelUpdate = uiExecutor.executeDelayed({
                 status.setText(previousText)
-                statusExtra.setText(previousTextExtra)
             }, UPDATE_DELAY_IN_MILLIS)
 
         status.setText(tempStatus)
-        statusExtra.setText("")
     }
 
     fun action(action: ControlAction) {
@@ -154,7 +151,6 @@
         }
 
         status.setTextColor(fg)
-        statusExtra.setTextColor(fg)
 
         icon.setImageDrawable(ri.icon)
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 05a0c45..208d911 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -21,10 +21,12 @@
 import android.content.Context
 import android.content.Intent
 import android.content.SharedPreferences
+import android.content.res.Configuration
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.LayerDrawable
 import android.service.controls.Control
 import android.service.controls.actions.ControlAction
+import android.util.TypedValue
 import android.util.Log
 import android.view.ContextThemeWrapper
 import android.view.LayoutInflater
@@ -43,6 +45,7 @@
 import com.android.systemui.controls.controller.ControlInfo
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.controller.StructureInfo
+import com.android.systemui.controls.management.ControlsFavoritingActivity
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.management.ControlsProviderSelectorActivity
 import com.android.systemui.dagger.qualifiers.Background
@@ -90,21 +93,8 @@
     private lateinit var lastItems: List<SelectionItem>
     private var popup: ListPopupWindow? = null
     private var activeDialog: Dialog? = null
-    private val addControlsItem: SelectionItem
     private var hidden = true
 
-    init {
-        val addDrawable = context.getDrawable(R.drawable.ic_add).apply {
-            setTint(context.resources.getColor(R.color.control_secondary_text, null))
-        }
-        addControlsItem = SelectionItem(
-            context.resources.getString(R.string.controls_providers_title),
-            "",
-            addDrawable,
-            EMPTY_COMPONENT
-        )
-    }
-
     override val available: Boolean
         get() = controlsController.get().available
 
@@ -182,7 +172,7 @@
         inflater.inflate(R.layout.controls_no_favorites, parent, true)
 
         val viewGroup = parent.requireViewById(R.id.controls_no_favorites_group) as ViewGroup
-        viewGroup.setOnClickListener(launchSelectorActivityListener(context))
+        viewGroup.setOnClickListener { v: View -> startProviderSelectorActivity(v.context) }
 
         val subtitle = parent.requireViewById<TextView>(R.id.controls_subtitle)
         subtitle.setText(context.resources.getString(R.string.quick_controls_subtitle))
@@ -196,16 +186,28 @@
         }
     }
 
-    private fun launchSelectorActivityListener(context: Context): (View) -> Unit {
-        return { _ ->
-            val closeDialog = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
-            context.sendBroadcast(closeDialog)
-
-            val i = Intent()
-            i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java))
-            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
-            context.startActivity(i)
+    private fun startFavoritingActivity(context: Context, si: StructureInfo) {
+        val i = Intent(context, ControlsFavoritingActivity::class.java).apply {
+            putExtra(ControlsFavoritingActivity.EXTRA_APP,
+                controlsListingController.get().getAppLabel(si.componentName))
+            putExtra(ControlsFavoritingActivity.EXTRA_STRUCTURE, si.structure)
+            putExtra(Intent.EXTRA_COMPONENT_NAME, si.componentName)
+            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
         }
+        startActivity(context, i)
+    }
+
+    private fun startProviderSelectorActivity(context: Context) {
+        val i = Intent(context, ControlsProviderSelectorActivity::class.java).apply {
+            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+        }
+        startActivity(context, i)
+    }
+
+    private fun startActivity(context: Context, intent: Intent) {
+        val closeDialog = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
+        context.sendBroadcast(closeDialog)
+        context.startActivity(intent)
     }
 
     private fun showControlsView(items: List<SelectionItem>) {
@@ -246,7 +248,7 @@
                         ) {
                             when (pos) {
                                 // 0: Add Control
-                                0 -> launchSelectorActivityListener(view.context)(parent)
+                                0 -> startFavoritingActivity(view.context, selectedStructure)
                                 else -> Log.w(ControlsUiController.TAG,
                                     "Unsupported index ($pos) on 'more' menu selection")
                             }
@@ -345,10 +347,12 @@
         val inflater = LayoutInflater.from(context)
         inflater.inflate(R.layout.controls_with_favorites, parent, true)
 
+        val maxColumns = findMaxColumns()
+
         val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup
         var lastRow: ViewGroup = createRow(inflater, listView)
         selectedStructure.controls.forEach {
-            if (lastRow.getChildCount() == 2) {
+            if (lastRow.getChildCount() == maxColumns) {
                 lastRow = createRow(inflater, listView)
             }
             val baseLayout = inflater.inflate(
@@ -365,12 +369,40 @@
             controlViewsById.put(key, cvh)
         }
 
-        // add spacer if necessary to keep control size consistent
-        if ((selectedStructure.controls.size % 2) == 1) {
+        // add spacers if necessary to keep control size consistent
+        var spacersToAdd = selectedStructure.controls.size % maxColumns
+        while (spacersToAdd > 0) {
             lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f))
+            spacersToAdd--
         }
     }
 
+    /**
+     * For low-dp width screens that also employ an increased font scale, adjust the
+     * number of columns. This helps prevent text truncation on these devices.
+     */
+    private fun findMaxColumns(): Int {
+        val res = context.resources
+        var maxColumns = res.getInteger(R.integer.controls_max_columns)
+        val maxColumnsAdjustWidth =
+            res.getInteger(R.integer.controls_max_columns_adjust_below_width_dp)
+
+        val outValue = TypedValue()
+        res.getValue(R.dimen.controls_max_columns_adjust_above_font_scale, outValue, true)
+        val maxColumnsAdjustFontScale = outValue.getFloat()
+
+        val config = res.configuration
+        val isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT
+        if (isPortrait &&
+            config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED &&
+            config.screenWidthDp <= maxColumnsAdjustWidth &&
+            config.fontScale >= maxColumnsAdjustFontScale) {
+            maxColumns--
+        }
+
+        return maxColumns
+    }
+
     private fun loadPreference(structures: List<StructureInfo>): StructureInfo {
         if (structures.isEmpty()) return EMPTY_STRUCTURE
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index f79c8b2..5a95665 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -47,9 +47,10 @@
     lateinit var control: Control
     lateinit var cvh: ControlViewHolder
     lateinit var rangeTemplate: RangeTemplate
-    lateinit var statusExtra: TextView
     lateinit var status: TextView
     lateinit var context: Context
+    var currentStatusText: CharSequence = ""
+    var currentRangeValue: String = ""
 
     companion object {
         private const val DEFAULT_FORMAT = "%.1f"
@@ -83,8 +84,8 @@
     override fun bind(cws: ControlWithState) {
         this.control = cws.control!!
 
-        statusExtra = cvh.statusExtra
-        status.setText(control.getStatusText())
+        currentStatusText = control.getStatusText()
+        status.setText(currentStatusText)
 
         val ld = cvh.layout.getBackground() as LayerDrawable
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
@@ -96,7 +97,7 @@
         val checked = template.isChecked()
         val currentRatio = rangeTemplate.getCurrentValue() /
                 (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue())
-        updateRange(currentRatio, checked)
+        updateRange(currentRatio, checked, /* isDragging */ false)
 
         cvh.applyRenderInfo(checked)
 
@@ -147,7 +148,7 @@
                                 AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE)
                             val ratioDiff = (value - rangeTemplate.getCurrentValue()) /
                                 (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue())
-                            updateRange(ratioDiff, template.isChecked())
+                            updateRange(ratioDiff, template.isChecked(), /* isDragging */ false)
                             endUpdateRange()
                             true
                         }
@@ -167,26 +168,27 @@
     }
 
     fun beginUpdateRange() {
-        status.setVisibility(View.GONE)
-        statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+        status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
                 .getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
     }
 
-    fun updateRange(ratioDiff: Float, checked: Boolean) {
+    fun updateRange(ratioDiff: Float, checked: Boolean, isDragging: Boolean) {
         val changeAmount = if (checked) (MAX_LEVEL * ratioDiff).toInt() else MIN_LEVEL
         val newLevel = Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, clipLayer.getLevel() + changeAmount))
         clipLayer.setLevel(newLevel)
 
         if (checked) {
             val newValue = levelToRangeValue(clipLayer.getLevel())
-            val formattedNewValue = format(rangeTemplate.getFormatString().toString(),
+            currentRangeValue = format(rangeTemplate.getFormatString().toString(),
                     DEFAULT_FORMAT, newValue)
-
-            statusExtra.setText(formattedNewValue)
-            statusExtra.setVisibility(View.VISIBLE)
+            val text = if (isDragging) {
+                currentRangeValue
+            } else {
+                "$currentStatusText $currentRangeValue"
+            }
+            status.setText(text)
         } else {
-            statusExtra.setText("")
-            statusExtra.setVisibility(View.GONE)
+            status.setText(currentStatusText)
         }
     }
 
@@ -210,9 +212,9 @@
     }
 
     fun endUpdateRange() {
-        statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+        status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
                 .getDimensionPixelSize(R.dimen.control_status_normal).toFloat())
-        status.setVisibility(View.VISIBLE)
+        status.setText("$currentStatusText $currentRangeValue")
         cvh.action(FloatAction(rangeTemplate.getTemplateId(),
             findNearestStep(levelToRangeValue(clipLayer.getLevel()))))
     }
@@ -260,7 +262,8 @@
                 isDragging = true
             }
 
-            this@ToggleRangeBehavior.updateRange(-xDiff / v.getWidth(), true)
+            this@ToggleRangeBehavior.updateRange(-xDiff / v.getWidth(),
+                /* checked */ true, /* isDragging */ true)
             return true
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 5911805..a7c4043 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -37,6 +37,8 @@
 import android.hardware.SensorPrivacyManager;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
+import android.net.NetworkScoreManager;
+import android.net.wifi.WifiManager;
 import android.os.BatteryStats;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -193,6 +195,12 @@
         return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL);
     }
 
+    @Provides
+    @Singleton
+    static NetworkScoreManager provideNetworkScoreManager(Context context) {
+        return context.getSystemService(NetworkScoreManager.class);
+    }
+
     @Singleton
     @Provides
     static NotificationManager provideNotificationManager(Context context) {
@@ -273,6 +281,12 @@
         return (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
     }
 
+    @Provides
+    @Singleton
+    static WifiManager provideWifiManager(Context context) {
+        return context.getSystemService(WifiManager.class);
+    }
+
     @Singleton
     @Provides
     static WindowManager provideWindowManager(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index c16dce1..3f88f25 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -40,7 +40,7 @@
 
     private int mDockState = DockManager.STATE_NONE;
 
-    public DozeDockHandler(AmbientDisplayConfiguration config, DozeMachine machine,
+    DozeDockHandler(AmbientDisplayConfiguration config, DozeMachine machine,
             DockManager dockManager) {
         mMachine = machine;
         mConfig = config;
@@ -74,8 +74,13 @@
         @Override
         public void onEvent(int dockState) {
             if (DEBUG) Log.d(TAG, "dock event = " + dockState);
-            final DozeMachine.State nextState;
+
             mDockState = dockState;
+            if (isPulsing()) {
+                return;
+            }
+
+            DozeMachine.State nextState;
             switch (mDockState) {
                 case DockManager.STATE_DOCKED:
                     nextState = State.DOZE_AOD_DOCKED;
@@ -90,10 +95,15 @@
                 default:
                     return;
             }
-
             mMachine.requestState(nextState);
         }
 
+        private boolean isPulsing() {
+            DozeMachine.State state = mMachine.getState();
+            return state == State.DOZE_REQUEST_PULSE || state == State.DOZE_PULSING
+                    || state == State.DOZE_PULSING_BRIGHT;
+        }
+
         void register() {
             if (mRegistered) {
                 return;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 3bed338..18bfd89 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.doze;
 
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
+
 import android.annotation.MainThread;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Trace;
@@ -336,8 +339,8 @@
             return State.DOZE;
         }
         if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD_PAUSING
-                || mState == State.DOZE_AOD || mState == State.DOZE)
-                && requestedState == State.DOZE_PULSE_DONE) {
+                || mState == State.DOZE_AOD || mState == State.DOZE
+                || mState == State.DOZE_AOD_DOCKED) && requestedState == State.DOZE_PULSE_DONE) {
             Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
             return mState;
         }
@@ -368,8 +371,8 @@
             case DOZE_PULSE_DONE:
                 final State nextState;
                 @Wakefulness int wakefulness = mWakefulnessLifecycle.getWakefulness();
-                if (wakefulness == WakefulnessLifecycle.WAKEFULNESS_AWAKE
-                        || wakefulness == WakefulnessLifecycle.WAKEFULNESS_WAKING) {
+                if (state != State.INITIALIZED && (wakefulness == WAKEFULNESS_AWAKE
+                        || wakefulness == WAKEFULNESS_WAKING)) {
                     nextState = State.FINISH;
                 } else if (mDockManager.isDocked()) {
                     nextState = mDockManager.isHidden() ? State.DOZE : State.DOZE_AOD_DOCKED;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 6d99ef1..4dd5e87 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -78,10 +78,13 @@
 import android.widget.TextView;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.colorextraction.drawable.ScrimDrawable;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.EmergencyAffordanceManager;
@@ -171,6 +174,7 @@
     private final IActivityManager mIActivityManager;
     private final TelecomManager mTelecomManager;
     private final MetricsLogger mMetricsLogger;
+    private final UiEventLogger mUiEventLogger;
     private final NotificationShadeDepthController mDepthController;
     private final BlurUtils mBlurUtils;
 
@@ -203,6 +207,23 @@
     private final ControlsListingController mControlsListingController;
     private boolean mAnyControlsProviders = false;
 
+    @VisibleForTesting
+    public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "The global actions / power menu surface became visible on the screen.")
+        GA_POWER_MENU_OPEN(337);
+
+        private final int mId;
+
+        GlobalActionsEvent(int id) {
+            mId = id;
+        }
+
+        @Override
+        public int getId() {
+            return mId;
+        }
+    }
+
     /**
      * @param context everything needs a context :(
      */
@@ -223,7 +244,7 @@
             ControlsUiController controlsUiController, IWindowManager iWindowManager,
             @Background Executor backgroundExecutor,
             ControlsListingController controlsListingController,
-            ControlsController controlsController) {
+            ControlsController controlsController, UiEventLogger uiEventLogger) {
         mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = audioManager;
@@ -240,6 +261,7 @@
         mIActivityManager = iActivityManager;
         mTelecomManager = telecomManager;
         mMetricsLogger = metricsLogger;
+        mUiEventLogger = uiEventLogger;
         mDepthController = depthController;
         mSysuiColorExtractor = colorExtractor;
         mStatusBarService = statusBarService;
@@ -467,6 +489,7 @@
 
         mAdapter = new MyAdapter();
 
+        mDepthController.setShowingHomeControls(shouldShowControls());
         ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, getWalletPanelViewController(),
                 mDepthController, mSysuiColorExtractor, mStatusBarService,
                 mNotificationShadeWindowController,
@@ -997,6 +1020,7 @@
      */
     public void onShow(DialogInterface dialog) {
         mMetricsLogger.visible(MetricsEvent.POWER_MENU);
+        mUiEventLogger.log(GlobalActionsEvent.GA_POWER_MENU_OPEN);
     }
 
     /**
@@ -1757,8 +1781,12 @@
             }
             if (mBackgroundDrawable == null) {
                 mBackgroundDrawable = new ScrimDrawable();
-                mScrimAlpha = mBlurUtils.supportsBlursOnWindows()
-                        ? ScrimController.BLUR_SCRIM_ALPHA : ScrimController.BUSY_SCRIM_ALPHA;
+                if (mControlsUiController != null) {
+                    mScrimAlpha = 1.0f;
+                } else {
+                    mScrimAlpha = mBlurUtils.supportsBlursOnWindows()
+                            ? ScrimController.BLUR_SCRIM_ALPHA : ScrimController.BUSY_SCRIM_ALPHA;
+                }
             }
             getWindow().setBackgroundDrawable(mBackgroundDrawable);
         }
@@ -1818,8 +1846,9 @@
             if (!(mBackgroundDrawable instanceof ScrimDrawable)) {
                 return;
             }
-            ((ScrimDrawable) mBackgroundDrawable).setColor(colors.supportsDarkText() ? Color.WHITE
-                    : Color.BLACK, animate);
+            boolean hasControls = mControlsUiController != null;
+            ((ScrimDrawable) mBackgroundDrawable).setColor(
+                    !hasControls && colors.supportsDarkText() ? Color.WHITE : Color.BLACK, animate);
             View decorView = getWindow().getDecorView();
             if (colors.supportsDarkText()) {
                 decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index ce29859..15cf1a0 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -98,8 +98,21 @@
     public void showShutdownUi(boolean isReboot, String reason) {
         ScrimDrawable background = new ScrimDrawable();
 
-        Dialog d = new Dialog(mContext,
+        final Dialog d = new Dialog(mContext,
                 com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
+
+        d.setOnShowListener(dialog -> {
+            if (mBlurUtils.supportsBlursOnWindows()) {
+                background.setAlpha((int) (ScrimController.BLUR_SCRIM_ALPHA * 255));
+                mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
+                        mBlurUtils.blurRadiusOfRatio(1));
+            } else {
+                float backgroundAlpha = mContext.getResources().getFloat(
+                        com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
+                background.setAlpha((int) (backgroundAlpha * 255));
+            }
+        });
+
         // Window initialization
         Window window = d.getWindow();
         window.requestFeature(Window.FEATURE_NO_TITLE);
@@ -146,16 +159,6 @@
             reasonView.setText(rebootReasonMessage);
         }
 
-        if (mBlurUtils.supportsBlursOnWindows()) {
-            background.setAlpha((int) (ScrimController.BLUR_SCRIM_ALPHA * 255));
-            mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
-                        mBlurUtils.blurRadiusOfRatio(1));
-        } else {
-            float backgroundAlpha = mContext.getResources().getFloat(
-                    com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
-            background.setAlpha((int) (backgroundAlpha * 255));
-        }
-
         d.show();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java b/packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java
new file mode 100644
index 0000000..71bc7c2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media;
+
+import android.content.Context;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+
+import javax.inject.Inject;
+
+/**
+ * Testable wrapper around {@link MediaController} constructor.
+ */
+public class MediaControllerFactory {
+
+    private final Context mContext;
+
+    @Inject
+    public MediaControllerFactory(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Creates a new MediaController from a session's token.
+     *
+     * @param token The token for the session. This value must never be null.
+     */
+    public MediaController create(MediaSession.Token token) {
+        return new MediaController(mContext, token);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
new file mode 100644
index 0000000..aa5ebaa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media
+
+import android.content.res.ColorStateList
+import android.text.format.DateUtils
+import android.view.View
+import android.widget.SeekBar
+import android.widget.TextView
+import androidx.annotation.UiThread
+import androidx.lifecycle.Observer
+
+import com.android.systemui.R
+
+/**
+ * Observer for changes from SeekBarViewModel.
+ *
+ * <p>Updates the seek bar views in response to changes to the model.
+ */
+class SeekBarObserver(view: View) : Observer<SeekBarViewModel.Progress> {
+
+    private val seekBarView: SeekBar
+    private val elapsedTimeView: TextView
+    private val totalTimeView: TextView
+
+    init {
+        seekBarView = view.findViewById(R.id.media_progress_bar)
+        elapsedTimeView = view.findViewById(R.id.media_elapsed_time)
+        totalTimeView = view.findViewById(R.id.media_total_time)
+    }
+
+    /** Updates seek bar views when the data model changes. */
+    @UiThread
+    override fun onChanged(data: SeekBarViewModel.Progress) {
+        if (data.enabled && seekBarView.visibility == View.GONE) {
+            seekBarView.visibility = View.VISIBLE
+            elapsedTimeView.visibility = View.VISIBLE
+            totalTimeView.visibility = View.VISIBLE
+        } else if (!data.enabled && seekBarView.visibility == View.VISIBLE) {
+            seekBarView.visibility = View.GONE
+            elapsedTimeView.visibility = View.GONE
+            totalTimeView.visibility = View.GONE
+            return
+        }
+
+        // TODO: update the style of the disabled progress bar
+        seekBarView.setEnabled(data.seekAvailable)
+
+        data.color?.let {
+            var tintList = ColorStateList.valueOf(it)
+            seekBarView.setThumbTintList(tintList)
+            tintList = tintList.withAlpha(192) // 75%
+            seekBarView.setProgressTintList(tintList)
+            tintList = tintList.withAlpha(128) // 50%
+            seekBarView.setProgressBackgroundTintList(tintList)
+            elapsedTimeView.setTextColor(it)
+            totalTimeView.setTextColor(it)
+        }
+
+        data.elapsedTime?.let {
+            seekBarView.setProgress(it)
+            elapsedTimeView.setText(DateUtils.formatElapsedTime(
+                    it / DateUtils.SECOND_IN_MILLIS))
+        }
+
+        data.duration?.let {
+            seekBarView.setMax(it)
+            totalTimeView.setText(DateUtils.formatElapsedTime(
+                    it / DateUtils.SECOND_IN_MILLIS))
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
new file mode 100644
index 0000000..cf8f268
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media
+
+import android.media.MediaMetadata
+import android.media.session.MediaController
+import android.media.session.PlaybackState
+import android.view.MotionEvent
+import android.view.View
+import android.widget.SeekBar
+import androidx.annotation.AnyThread
+import androidx.annotation.WorkerThread
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.LiveData
+
+import com.android.systemui.util.concurrency.DelayableExecutor
+
+private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L
+
+/** ViewModel for seek bar in QS media player. */
+class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
+
+    private val _progress = MutableLiveData<Progress>().apply {
+        postValue(Progress(false, false, null, null, null))
+    }
+    val progress: LiveData<Progress>
+        get() = _progress
+    private var controller: MediaController? = null
+    private var playbackState: PlaybackState? = null
+
+    /** Listening state (QS open or closed) is used to control polling of progress. */
+    var listening = true
+        set(value) {
+            if (value) {
+                checkPlaybackPosition()
+            }
+        }
+
+    /**
+     * Handle request to change the current position in the media track.
+     * @param position Place to seek to in the track.
+     */
+    @WorkerThread
+    fun onSeek(position: Long) {
+        controller?.transportControls?.seekTo(position)
+    }
+
+    /**
+     * Updates media information.
+     * @param mediaController controller for media session
+     * @param color foreground color for UI elements
+     */
+    @WorkerThread
+    fun updateController(mediaController: MediaController?, color: Int) {
+        controller = mediaController
+        playbackState = controller?.playbackState
+        val mediaMetadata = controller?.metadata
+        val seekAvailable = ((playbackState?.actions ?: 0L) and PlaybackState.ACTION_SEEK_TO) != 0L
+        val position = playbackState?.position?.toInt()
+        val duration = mediaMetadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.toInt()
+        val enabled = if (duration != null && duration <= 0) false else true
+        _progress.postValue(Progress(enabled, seekAvailable, position, duration, color))
+        if (shouldPollPlaybackPosition()) {
+            checkPlaybackPosition()
+        }
+    }
+
+    @AnyThread
+    private fun checkPlaybackPosition(): Runnable = bgExecutor.executeDelayed({
+        val currentPosition = controller?.playbackState?.position?.toInt()
+        if (currentPosition != null && _progress.value!!.elapsedTime != currentPosition) {
+            _progress.postValue(_progress.value!!.copy(elapsedTime = currentPosition))
+        }
+        if (shouldPollPlaybackPosition()) {
+            checkPlaybackPosition()
+        }
+    }, POSITION_UPDATE_INTERVAL_MILLIS)
+
+    @WorkerThread
+    private fun shouldPollPlaybackPosition(): Boolean {
+        val state = playbackState?.state
+        val moving = if (state == null) false else
+                state == PlaybackState.STATE_PLAYING ||
+                state == PlaybackState.STATE_BUFFERING ||
+                state == PlaybackState.STATE_FAST_FORWARDING ||
+                state == PlaybackState.STATE_REWINDING
+        return moving && listening
+    }
+
+    /** Gets a listener to attach to the seek bar to handle seeking. */
+    val seekBarListener: SeekBar.OnSeekBarChangeListener
+        get() {
+            return SeekBarChangeListener(this, bgExecutor)
+        }
+
+    /** Gets a listener to attach to the seek bar to disable touch intercepting. */
+    val seekBarTouchListener: View.OnTouchListener
+        get() {
+            return SeekBarTouchListener()
+        }
+
+    private class SeekBarChangeListener(
+        val viewModel: SeekBarViewModel,
+        val bgExecutor: DelayableExecutor
+    ) : SeekBar.OnSeekBarChangeListener {
+        override fun onProgressChanged(bar: SeekBar, progress: Int, fromUser: Boolean) {
+            if (fromUser) {
+                bgExecutor.execute {
+                    viewModel.onSeek(progress.toLong())
+                }
+            }
+        }
+        override fun onStartTrackingTouch(bar: SeekBar) {
+        }
+        override fun onStopTrackingTouch(bar: SeekBar) {
+            val pos = bar.progress.toLong()
+            bgExecutor.execute {
+                viewModel.onSeek(pos)
+            }
+        }
+    }
+
+    private class SeekBarTouchListener : View.OnTouchListener {
+        override fun onTouch(view: View, event: MotionEvent): Boolean {
+            view.parent.requestDisallowInterceptTouchEvent(true)
+            return view.onTouchEvent(event)
+        }
+    }
+
+    /** State seen by seek bar UI. */
+    data class Progress(
+        val enabled: Boolean,
+        val seekAvailable: Boolean,
+        val elapsedTime: Int?,
+        val duration: Int?,
+        val color: Int?
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 1868536..e24d29f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -231,7 +231,12 @@
     /**
      * @return {@link Rect} of the destination PiP window bounds.
      */
-    Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
+    Rect getDestinationBounds(ComponentName componentName, float aspectRatio, Rect bounds,
+            Size minimalSize) {
+        if (!componentName.equals(mLastPipComponentName)) {
+            onResetReentryBoundsUnchecked();
+            mLastPipComponentName = componentName;
+        }
         final Rect destinationBounds;
         if (bounds == null) {
             final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
@@ -246,11 +251,7 @@
             transformBoundsToAspectRatio(destinationBounds, aspectRatio,
                     false /* useCurrentMinEdgeSize */);
         }
-        if (destinationBounds.equals(bounds)) {
-            return bounds;
-        }
         mAspectRatio = aspectRatio;
-        onResetReentryBoundsUnchecked();
         mLastDestinationBounds.set(destinationBounds);
         return destinationBounds;
     }
@@ -483,6 +484,7 @@
         pw.println(prefix + TAG);
         pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
         pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
+        pw.println(innerPrefix + "mReentrySize=" + mReentrySize);
         pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
         pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
         pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 15c9dba..b10dd93 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -37,7 +37,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.RemoteException;
 import android.util.Log;
 import android.util.Size;
 import android.view.SurfaceControl;
@@ -248,7 +247,7 @@
     public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
         Objects.requireNonNull(info, "Requires RunningTaskInfo");
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                getAspectRatioOrDefault(info.pictureInPictureParams),
+                info.topActivity, getAspectRatioOrDefault(info.pictureInPictureParams),
                 null /* bounds */, getMinimalSize(info.topActivityInfo));
         Objects.requireNonNull(destinationBounds, "Missing destination bounds");
         mTaskInfo = info;
@@ -304,7 +303,7 @@
             return;
         }
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                getAspectRatioOrDefault(newParams),
+                info.topActivity, getAspectRatioOrDefault(newParams),
                 null /* bounds */, getMinimalSize(info.topActivityInfo));
         Objects.requireNonNull(destinationBounds, "Missing destination bounds");
         scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
@@ -320,23 +319,29 @@
      * TODO(b/152809058): consolidate the display info handling logic in SysUI
      */
     @SuppressWarnings("unchecked")
-    public void mayUpdateCurrentAnimationOnRotationChange() {
+    public void onMovementBoundsChanged(boolean fromImeAdjustment, boolean fromShelfAdjustment) {
         final PipAnimationController.PipTransitionAnimator animator =
                 mPipAnimationController.getCurrentAnimator();
-        if (animator != null && animator.isRunning()
-                && animator.getTransitionDirection() == TRANSITION_DIRECTION_TO_PIP) {
-            final Rect currentDestinationBounds = animator.getDestinationBounds();
-            if (mPipBoundsHandler.getDisplayBounds().contains(currentDestinationBounds)) {
-                return;
-            }
-            final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams),
-                    null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
-            if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
-                animator.updateEndValue(newDestinationBounds);
-            }
-            animator.setDestinationBounds(newDestinationBounds);
+        if (animator == null || !animator.isRunning()
+                || animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
+            return;
         }
+
+        final Rect currentDestinationBounds = animator.getDestinationBounds();
+        if (!fromImeAdjustment && !fromShelfAdjustment
+                && mPipBoundsHandler.getDisplayBounds().contains(currentDestinationBounds)) {
+            // no need to update the destination bounds, bail early
+            return;
+        }
+
+        final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
+                mTaskInfo.topActivity, getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams),
+                null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
+        if (newDestinationBounds.equals(currentDestinationBounds)) return;
+        if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
+            animator.updateEndValue(newDestinationBounds);
+        }
+        animator.setDestinationBounds(newDestinationBounds);
     }
 
     /**
@@ -541,7 +546,12 @@
             return null;
         }
         final ActivityInfo.WindowLayout windowLayout = activityInfo.windowLayout;
-        return new Size(windowLayout.minWidth, windowLayout.minHeight);
+        // -1 will be populated if an activity specifies defaultWidth/defaultHeight in <layout>
+        // without minWidth/minHeight
+        if (windowLayout.minWidth > 0 && windowLayout.minHeight > 0) {
+            return new Size(windowLayout.minWidth, windowLayout.minHeight);
+        }
+        return null;
     }
 
     private float getAspectRatioOrDefault(@Nullable PictureInPictureParams params) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
deleted file mode 100644
index b725811..0000000
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.pip.phone;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.widget.FrameLayout;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.shared.system.WindowManagerWrapper;
-
-/**
- * Displays the dismiss UI and target for floating objects.
- */
-public class PipDismissViewController {
-
-    // This delay controls how long to wait before we show the target when the user first moves
-    // the PIP, to prevent the target from animating if the user just wants to fling the PIP
-    public static final int SHOW_TARGET_DELAY = 100;
-    private static final int SHOW_TARGET_DURATION = 350;
-    private static final int HIDE_TARGET_DURATION = 225;
-
-    private Context mContext;
-    private WindowManager mWindowManager;
-    private View mDismissView;
-
-    // Used for dismissing a bubble -- bubble should be in the target to be considered a dismiss
-    private View mTargetView;
-    private int mTargetSlop;
-    private Point mWindowSize;
-    private int[] mLoc = new int[2];
-    private boolean mIntersecting;
-    private Vibrator mVibe;
-
-    public PipDismissViewController(Context context) {
-        mContext = context;
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        mVibe = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
-    }
-
-    /**
-     * Creates the dismiss target for showing via {@link #showDismissTarget()}.
-     */
-    public void createDismissTarget() {
-        if (mDismissView == null) {
-            // Determine sizes for the view
-            final Rect stableInsets = new Rect();
-            WindowManagerWrapper.getInstance().getStableInsets(stableInsets);
-            mWindowSize = new Point();
-            mWindowManager.getDefaultDisplay().getRealSize(mWindowSize);
-            final int gradientHeight = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.pip_dismiss_gradient_height);
-            final int bottomMargin = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.pip_dismiss_text_bottom_margin);
-            mTargetSlop = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.bubble_dismiss_slop);
-
-            // Create a new view for the dismiss target
-            LayoutInflater inflater = LayoutInflater.from(mContext);
-            mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null);
-            mDismissView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-            mDismissView.forceHasOverlappingRendering(false);
-
-            // Set the gradient background
-            Drawable gradient = mContext.getResources().getDrawable(R.drawable.pip_dismiss_scrim);
-            gradient.setAlpha((int) (255 * 0.85f));
-            mDismissView.setBackground(gradient);
-
-            // Adjust bottom margins of the text
-            mTargetView = mDismissView.findViewById(R.id.pip_dismiss_text);
-            FrameLayout.LayoutParams tlp = (FrameLayout.LayoutParams) mTargetView.getLayoutParams();
-            tlp.bottomMargin = stableInsets.bottom + bottomMargin;
-            mTargetView.setLayoutParams(tlp);
-
-            // Add the target to the window
-            LayoutParams lp =  new LayoutParams(
-                    LayoutParams.MATCH_PARENT, gradientHeight,
-                    0, mWindowSize.y - gradientHeight,
-                    LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                            | LayoutParams.FLAG_NOT_TOUCHABLE
-                            | LayoutParams.FLAG_NOT_FOCUSABLE,
-                    PixelFormat.TRANSLUCENT);
-            lp.setTitle("pip-dismiss-overlay");
-            lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
-            lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
-            lp.setFitInsetsTypes(0 /* types */);
-            mWindowManager.addView(mDismissView, lp);
-        }
-        mDismissView.animate().cancel();
-    }
-
-
-    /**
-     * Updates the dismiss target based on location of the view, only used for bubbles not for PIP.
-     *
-     * @return whether the view is within the dismiss target.
-     */
-    public boolean updateTarget(View view) {
-        if (mDismissView == null) {
-            return false;
-        }
-        if (mDismissView.getAlpha() > 0) {
-            view.getLocationOnScreen(mLoc);
-            Rect viewRect = new Rect(mLoc[0], mLoc[1], mLoc[0] + view.getWidth(),
-                    mLoc[1] + view.getHeight());
-            mTargetView.getLocationOnScreen(mLoc);
-            Rect targetRect = new Rect(mLoc[0], mLoc[1], mLoc[0] + mTargetView.getWidth(),
-                    mLoc[1] + mTargetView.getHeight());
-            expandRect(targetRect, mTargetSlop);
-            boolean intersecting = targetRect.intersect(viewRect);
-            if (intersecting != mIntersecting) {
-                // TODO: is this the right effect?
-                mVibe.vibrate(VibrationEffect.get(intersecting
-                        ? VibrationEffect.EFFECT_CLICK
-                        : VibrationEffect.EFFECT_TICK));
-            }
-            mIntersecting = intersecting;
-            return intersecting;
-        }
-        return false;
-    }
-
-    /**
-     * Shows the dismiss target.
-     */
-    public void showDismissTarget() {
-        mDismissView.animate()
-                .alpha(1f)
-                .setInterpolator(Interpolators.LINEAR)
-                .setStartDelay(SHOW_TARGET_DELAY)
-                .setDuration(SHOW_TARGET_DURATION)
-                .start();
-    }
-
-    /**
-     * Hides and destroys the dismiss target.
-     */
-    public void destroyDismissTarget() {
-        if (mDismissView != null) {
-            mDismissView.animate()
-                    .alpha(0f)
-                    .setInterpolator(Interpolators.LINEAR)
-                    .setStartDelay(0)
-                    .setDuration(HIDE_TARGET_DURATION)
-                    .withEndAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mWindowManager.removeViewImmediate(mDismissView);
-                            mDismissView = null;
-                        }
-                    })
-                    .start();
-        }
-    }
-
-    private void expandRect(Rect outRect, int expandAmount) {
-        outRect.left = Math.max(0, outRect.left - expandAmount);
-        outRect.top = Math.max(0, outRect.top - expandAmount);
-        outRect.right = Math.min(mWindowSize.x, outRect.right + expandAmount);
-        outRect.bottom = Math.min(mWindowSize.y, outRect.bottom + expandAmount);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 99d6df5..918c45b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -362,7 +362,7 @@
         mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
                 animatingBounds, fromImeAdjustment, fromShelfAdjustment,
                 mTmpDisplayInfo.rotation);
-        mPipTaskOrganizer.mayUpdateCurrentAnimationOnRotationChange();
+        mPipTaskOrganizer.onMovementBoundsChanged(fromImeAdjustment, fromShelfAdjustment);
     }
 
     public void dump(PrintWriter pw) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 7974281..a192afc 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -24,8 +24,6 @@
 import android.app.ActivityManager.StackInfo;
 import android.app.IActivityTaskManager;
 import android.content.Context;
-import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.Debug;
 import android.os.RemoteException;
@@ -40,6 +38,7 @@
 import com.android.systemui.util.FloatingContentCoordinator;
 import com.android.systemui.util.animation.FloatProperties;
 import com.android.systemui.util.animation.PhysicsAnimator;
+import com.android.systemui.util.magnetictarget.MagnetizedObject;
 
 import java.io.PrintWriter;
 import java.util.function.Consumer;
@@ -61,9 +60,6 @@
     /** Friction to use for PIP when it moves via physics fling animations. */
     private static final float DEFAULT_FRICTION = 2f;
 
-    // The fraction of the stack height that the user has to drag offscreen to dismiss the PiP
-    private static final float DISMISS_OFFSCREEN_FRACTION = 0.3f;
-
     private final Context mContext;
     private final IActivityTaskManager mActivityTaskManager;
     private final PipTaskOrganizer mPipTaskOrganizer;
@@ -103,7 +99,7 @@
     /**
      * Update listener that resizes the PIP to {@link #mAnimatedBounds}.
      */
-    private final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener =
+    final PhysicsAnimator.UpdateListener<Rect> mResizePipUpdateListener =
             (target, values) -> resizePipUnchecked(mAnimatedBounds);
 
     /** FlingConfig instances provided to PhysicsAnimator for fling gestures. */
@@ -122,6 +118,13 @@
 
     private final Consumer<Rect> mUpdateBoundsCallback = mBounds::set;
 
+    /**
+     * Whether we're springing to the touch event location (vs. moving it to that position
+     * instantly). We spring-to-touch after PIP is dragged out of the magnetic target, since it was
+     * 'stuck' in the target and needs to catch up to the touch location.
+     */
+    private boolean mSpringingToTouch = false;
+
     public PipMotionHelper(Context context, IActivityTaskManager activityTaskManager,
             PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController,
             PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils,
@@ -162,7 +165,7 @@
     }
 
     /**
-     * Synchronizes the current bounds with the pinned stack.
+     * Synchronizes the current bounds with the pinned stack, cancelling any ongoing animations.
      */
     void synchronizePinnedStackBounds() {
         cancelAnimations();
@@ -178,6 +181,21 @@
     }
 
     /**
+     * Synchronizes the current bounds with either the pinned stack, or the ongoing animation. This
+     * is done to prepare for a touch gesture.
+     */
+    void synchronizePinnedStackBoundsForTouchGesture() {
+        if (mAnimatingToBounds.isEmpty()) {
+            // If we're not animating anywhere, sync normally.
+            synchronizePinnedStackBounds();
+        } else {
+            // If we're animating, set the current bounds to the animated bounds. That way, the
+            // touch gesture will begin at the most recent animated location of the bounds.
+            mBounds.set(mAnimatedBounds);
+        }
+    }
+
+    /**
      * Tries to move the pinned stack to the given {@param bounds}.
      */
     void movePip(Rect toBounds) {
@@ -196,9 +214,35 @@
             mFloatingContentCoordinator.onContentMoved(this);
         }
 
-        cancelAnimations();
-        resizePipUnchecked(toBounds);
-        mBounds.set(toBounds);
+        if (!mSpringingToTouch) {
+            // If we are moving PIP directly to the touch event locations, cancel any animations and
+            // move PIP to the given bounds.
+            cancelAnimations();
+            resizePipUnchecked(toBounds);
+            mBounds.set(toBounds);
+        } else {
+            // If PIP is 'catching up' after being stuck in the dismiss target, update the animation
+            // to spring towards the new touch location.
+            mAnimatedBoundsPhysicsAnimator
+                    .spring(FloatProperties.RECT_X, toBounds.left, mSpringConfig)
+                    .spring(FloatProperties.RECT_Y, toBounds.top, mSpringConfig)
+                    .withEndActions(() -> mSpringingToTouch = false);
+
+            startBoundsAnimator(toBounds.left /* toX */, toBounds.top /* toY */);
+        }
+    }
+
+    /** Set whether we're springing-to-touch to catch up after being stuck in the dismiss target. */
+    void setSpringingToTouch(boolean springingToTouch) {
+        if (springingToTouch) {
+            mAnimatedBounds.set(mBounds);
+        }
+
+        mSpringingToTouch = springingToTouch;
+    }
+
+    void prepareForAnimation() {
+        mAnimatedBounds.set(mBounds);
     }
 
     /**
@@ -263,24 +307,11 @@
     }
 
     /**
-     * @return whether the PiP at the current bounds should be dismissed.
-     */
-    boolean shouldDismissPip() {
-        Point displaySize = new Point();
-        mContext.getDisplay().getRealSize(displaySize);
-        final int y = displaySize.y - mStableInsets.bottom;
-        if (mBounds.bottom > y) {
-            float offscreenFraction = (float) (mBounds.bottom - y) / mBounds.height();
-            return offscreenFraction >= DISMISS_OFFSCREEN_FRACTION;
-        }
-        return false;
-    }
-
-    /**
      * Flings the PiP to the closest snap target.
      */
     void flingToSnapTarget(
-            float velocityX, float velocityY, Runnable updateAction, @Nullable Runnable endAction) {
+            float velocityX, float velocityY,
+            @Nullable Runnable updateAction, @Nullable Runnable endAction) {
         mAnimatedBounds.set(mBounds);
         mAnimatedBoundsPhysicsAnimator
                 .flingThenSpring(
@@ -288,20 +319,18 @@
                         true /* flingMustReachMinOrMax */)
                 .flingThenSpring(
                         FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
-                .addUpdateListener((target, values) -> updateAction.run())
                 .withEndActions(endAction);
 
+        if (updateAction != null) {
+            mAnimatedBoundsPhysicsAnimator.addUpdateListener(
+                    (target, values) -> updateAction.run());
+        }
+
         final float xEndValue = velocityX < 0 ? mMovementBounds.left : mMovementBounds.right;
         final float estimatedFlingYEndValue =
                 PhysicsAnimator.estimateFlingEndValue(mBounds.top, velocityY, mFlingConfigY);
 
-        setAnimatingToBounds(new Rect(
-                (int) xEndValue,
-                (int) estimatedFlingYEndValue,
-                (int) xEndValue + mBounds.width(),
-                (int) estimatedFlingYEndValue + mBounds.height()));
-
-        startBoundsAnimation();
+        startBoundsAnimator(xEndValue /* toX */, estimatedFlingYEndValue /* toY */);
     }
 
     /**
@@ -322,25 +351,21 @@
         mAnimatedBoundsPhysicsAnimator
                 .spring(FloatProperties.RECT_X, bounds.left, springConfig)
                 .spring(FloatProperties.RECT_Y, bounds.top, springConfig);
-        startBoundsAnimation();
-
-        setAnimatingToBounds(bounds);
+        startBoundsAnimator(bounds.left /* toX */, bounds.top /* toY */);
     }
 
     /**
      * Animates the dismissal of the PiP off the edge of the screen.
      */
     void animateDismiss(float velocityX, float velocityY, @Nullable Runnable updateAction) {
-        final float velocity = PointF.length(velocityX, velocityY);
-        final boolean isFling = velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond();
-        final Point dismissEndPoint = getDismissEndPoint(mBounds, velocityX, velocityY, isFling);
-
         mAnimatedBounds.set(mBounds);
 
-        // Animate to the dismiss end point, and then dismiss PIP.
+        // Animate off the bottom of the screen, then dismiss PIP.
         mAnimatedBoundsPhysicsAnimator
-                .spring(FloatProperties.RECT_X, dismissEndPoint.x, velocityX, mSpringConfig)
-                .spring(FloatProperties.RECT_Y, dismissEndPoint.y, velocityY, mSpringConfig)
+                .spring(FloatProperties.RECT_Y,
+                        mBounds.bottom + mBounds.height(),
+                        velocityY,
+                        mSpringConfig)
                 .withEndActions(this::dismissPip);
 
         // If we were provided with an update action, run it whenever there's an update.
@@ -349,7 +374,7 @@
                     (target, values) -> updateAction.run());
         }
 
-        startBoundsAnimation();
+        startBoundsAnimator(mBounds.left /* toX */, mBounds.bottom + mBounds.height() /* toY */);
     }
 
     /**
@@ -401,6 +426,7 @@
     private void cancelAnimations() {
         mAnimatedBoundsPhysicsAnimator.cancel();
         mAnimatingToBounds.setEmpty();
+        mSpringingToTouch = false;
     }
 
     /** Set new fling configs whose min/max values respect the given movement bounds. */
@@ -418,11 +444,25 @@
      * This will also add end actions to the bounds animator that cancel the TimeAnimator and update
      * the 'real' bounds to equal the final animated bounds.
      */
-    private void startBoundsAnimation() {
-        cancelAnimations();
+    private void startBoundsAnimator(float toX, float toY) {
+        if (!mSpringingToTouch) {
+            cancelAnimations();
+        }
+
+        // Set animatingToBounds directly to avoid allocating a new Rect, but then call
+        // setAnimatingToBounds to run the normal logic for changing animatingToBounds.
+        mAnimatingToBounds.set(
+                (int) toX,
+                (int) toY,
+                (int) toX + mBounds.width(),
+                (int) toY + mBounds.height());
+        setAnimatingToBounds(mAnimatingToBounds);
 
         mAnimatedBoundsPhysicsAnimator
-                .withEndActions(() ->  mPipTaskOrganizer.scheduleFinishResizePip(mAnimatedBounds))
+                .withEndActions(() -> {
+                    mPipTaskOrganizer.scheduleFinishResizePip(mAnimatedBounds);
+                    mAnimatingToBounds.setEmpty();
+                })
                 .addUpdateListener(mResizePipUpdateListener)
                 .start();
     }
@@ -465,47 +505,29 @@
     }
 
     /**
-     * @return the coordinates the PIP should animate to based on the direction of velocity when
-     *         dismissing.
+     * Returns a MagnetizedObject wrapper for PIP's animated bounds. This is provided to the
+     * magnetic dismiss target so it can calculate PIP's size and position.
      */
-    private Point getDismissEndPoint(Rect pipBounds, float velX, float velY, boolean isFling) {
-        Point displaySize = new Point();
-        mContext.getDisplay().getRealSize(displaySize);
-        final float bottomBound = displaySize.y + pipBounds.height() * .1f;
-        if (isFling && velX != 0 && velY != 0) {
-            // Line is defined by: y = mx + b, m = slope, b = y-intercept
-            // Find the slope
-            final float slope = velY / velX;
-            // Sub in slope and PiP position to solve for y-intercept: b = y - mx
-            final float yIntercept = pipBounds.top - slope * pipBounds.left;
-            // Now find the point on this line when y = bottom bound: x = (y - b) / m
-            final float x = (bottomBound - yIntercept) / slope;
-            return new Point((int) x, (int) bottomBound);
-        } else {
-            // If it wasn't a fling the velocity on 'up' is not reliable for direction of movement,
-            // just animate downwards.
-            return new Point(pipBounds.left, (int) bottomBound);
-        }
-    }
+    MagnetizedObject<Rect> getMagnetizedPip() {
+        return new MagnetizedObject<Rect>(
+                mContext, mAnimatedBounds, FloatProperties.RECT_X, FloatProperties.RECT_Y) {
+            @Override
+            public float getWidth(@NonNull Rect animatedPipBounds) {
+                return animatedPipBounds.width();
+            }
 
-    /**
-     * @return whether the gesture it towards the dismiss area based on the velocity when
-     *         dismissing.
-     */
-    public boolean isGestureToDismissArea(Rect pipBounds, float velX, float velY,
-            boolean isFling) {
-        Point endpoint = getDismissEndPoint(pipBounds, velX, velY, isFling);
-        // Center the point
-        endpoint.x += pipBounds.width() / 2;
-        endpoint.y += pipBounds.height() / 2;
+            @Override
+            public float getHeight(@NonNull Rect animatedPipBounds) {
+                return animatedPipBounds.height();
+            }
 
-        // The dismiss area is the middle third of the screen, half the PIP's height from the bottom
-        Point size = new Point();
-        mContext.getDisplay().getRealSize(size);
-        final int left = size.x / 3;
-        Rect dismissArea = new Rect(left, size.y - (pipBounds.height() / 2), left * 2,
-                size.y + pipBounds.height());
-        return dismissArea.contains(endpoint.x, endpoint.y);
+            @Override
+            public void getLocationOnScreen(
+                    @NonNull Rect animatedPipBounds, @NonNull int[] loc) {
+                loc[0] = animatedPipBounds.left;
+                loc[1] = animatedPipBounds.top;
+            }
+        };
     }
 
     public void dump(PrintWriter pw, String prefix) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index dfd5d2f..bbb4939 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -20,11 +20,13 @@
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
 
+import android.annotation.SuppressLint;
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -33,14 +35,23 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Size;
+import android.view.Gravity;
 import android.view.IPinnedStackController;
 import android.view.InputEvent;
 import android.view.MotionEvent;
+import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.logging.MetricsLoggerWrapper;
@@ -51,7 +62,10 @@
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.DismissCircleView;
 import com.android.systemui.util.FloatingContentCoordinator;
+import com.android.systemui.util.animation.PhysicsAnimator;
+import com.android.systemui.util.magnetictarget.MagnetizedObject;
 
 import java.io.PrintWriter;
 
@@ -62,9 +76,6 @@
 public class PipTouchHandler {
     private static final String TAG = "PipTouchHandler";
 
-    // Allow the PIP to be flung from anywhere on the screen to the bottom to be dismissed.
-    private static final boolean ENABLE_FLING_DISMISS = false;
-
     private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
     private static final int BOTTOM_OFFSET_BUFFER_DP = 1;
 
@@ -73,17 +84,45 @@
     // Allow PIP to resize to a slightly bigger state upon touch
     private final boolean mEnableResize;
     private final Context mContext;
+    private final WindowManager mWindowManager;
     private final IActivityManager mActivityManager;
     private final PipBoundsHandler mPipBoundsHandler;
     private PipResizeGestureHandler mPipResizeGestureHandler;
     private IPinnedStackController mPinnedStackController;
 
     private final PipMenuActivityController mMenuController;
-    private final PipDismissViewController mDismissViewController;
     private final PipSnapAlgorithm mSnapAlgorithm;
     private final AccessibilityManager mAccessibilityManager;
     private boolean mShowPipMenuOnAnimationEnd = false;
 
+    /**
+     * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
+     * PIP.
+     */
+    private MagnetizedObject<Rect> mMagnetizedPip;
+
+    /**
+     * Container for the dismiss circle, so that it can be animated within the container via
+     * translation rather than within the WindowManager via slow layout animations.
+     */
+    private ViewGroup mTargetViewContainer;
+
+    /** Circle view used to render the dismiss target. */
+    private DismissCircleView mTargetView;
+
+    /**
+     * MagneticTarget instance wrapping the target view and allowing us to set its magnetic radius.
+     */
+    private MagnetizedObject.MagneticTarget mMagneticTarget;
+
+    /** PhysicsAnimator instance for animating the dismiss target in/out. */
+    private PhysicsAnimator<View> mMagneticTargetAnimator;
+
+    /** Default configuration to use for springing the dismiss target in/out. */
+    private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
+            new PhysicsAnimator.SpringConfig(
+                    SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_NO_BOUNCY);
+
     // The current movement bounds
     private Rect mMovementBounds = new Rect();
     // The current resized bounds, changed by user resize.
@@ -104,21 +143,20 @@
     private int mDeferResizeToNormalBoundsUntilRotation = -1;
     private int mDisplayRotation;
 
+    /**
+     * Runnable that can be posted delayed to show the target. This needs to be saved as a member
+     * variable so we can pass it to removeCallbacks.
+     */
+    private Runnable mShowTargetAction = this::showDismissTargetMaybe;
+
     private Handler mHandler = new Handler();
-    private Runnable mShowDismissAffordance = new Runnable() {
-        @Override
-        public void run() {
-            if (mEnableDismissDragToEdge) {
-                mDismissViewController.showDismissTarget();
-            }
-        }
-    };
 
     // Behaviour states
     private int mMenuState = MENU_STATE_NONE;
     private boolean mIsImeShowing;
     private int mImeHeight;
     private int mImeOffset;
+    private int mDismissAreaHeight;
     private boolean mIsShelfShowing;
     private int mShelfHeight;
     private int mMovementBoundsExtraOffsets;
@@ -168,6 +206,7 @@
         }
     }
 
+    @SuppressLint("InflateParams")
     public PipTouchHandler(Context context, IActivityManager activityManager,
             IActivityTaskManager activityTaskManager, PipMenuActivityController menuController,
             InputConsumerController inputConsumerController,
@@ -180,9 +219,9 @@
         mContext = context;
         mActivityManager = activityManager;
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mMenuController = menuController;
         mMenuController.addListener(new PipMenuListener());
-        mDismissViewController = new PipDismissViewController(context);
         mSnapAlgorithm = pipSnapAlgorithm;
         mFlingAnimationUtils = new FlingAnimationUtils(context.getResources().getDisplayMetrics(),
                 2.5f);
@@ -200,6 +239,7 @@
         mExpandedShortestEdgeSize = res.getDimensionPixelSize(
                 R.dimen.pip_expanded_shortest_edge_size);
         mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
+        mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
 
         mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
         mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu);
@@ -212,6 +252,56 @@
         mFloatingContentCoordinator = floatingContentCoordinator;
         mConnection = new PipAccessibilityInteractionConnection(mMotionHelper,
                 this::onAccessibilityShowMenu, mHandler);
+
+        final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
+        mTargetView = new DismissCircleView(context);
+        final FrameLayout.LayoutParams newParams =
+                new FrameLayout.LayoutParams(targetSize, targetSize);
+        newParams.gravity = Gravity.CENTER;
+        mTargetView.setLayoutParams(newParams);
+
+        mTargetViewContainer = new FrameLayout(context);
+        mTargetViewContainer.setClipChildren(false);
+        mTargetViewContainer.addView(mTargetView);
+
+        mMagnetizedPip = mMotionHelper.getMagnetizedPip();
+        mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
+        mMagnetizedPip.setPhysicsAnimatorUpdateListener(mMotionHelper.mResizePipUpdateListener);
+        mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
+            @Override
+            public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+                mMotionHelper.prepareForAnimation();
+
+                // Show the dismiss target, in case the initial touch event occurred within the
+                // magnetic field radius.
+                showDismissTargetMaybe();
+            }
+
+            @Override
+            public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
+                    float velX, float velY, boolean wasFlungOut) {
+                if (wasFlungOut) {
+                    mMotionHelper.flingToSnapTarget(velX, velY, null, null);
+                    hideDismissTarget();
+                } else {
+                    mMotionHelper.setSpringingToTouch(true);
+                }
+            }
+
+            @Override
+            public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+                mHandler.post(() -> {
+                    mMotionHelper.animateDismiss(0, 0, null);
+                    hideDismissTarget();
+                });
+
+
+                MetricsLoggerWrapper.logPictureInPictureDismissByDrag(mContext,
+                        PipUtils.getTopPipActivity(mContext, mActivityManager));
+            }
+        });
+
+        mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
     }
 
     public void setTouchGesture(PipTouchGesture gesture) {
@@ -231,7 +321,8 @@
     }
 
     public void onActivityPinned() {
-        cleanUpDismissTarget();
+        createDismissTargetMaybe();
+
         mShowPipMenuOnAnimationEnd = true;
         mPipResizeGestureHandler.onActivityPinned();
         mFloatingContentCoordinator.onContentAdded(mMotionHelper);
@@ -264,6 +355,10 @@
     public void onConfigurationChanged() {
         mMotionHelper.onConfigurationChanged();
         mMotionHelper.synchronizePinnedStackBounds();
+
+        // Recreate the dismiss target for the new orientation.
+        cleanUpDismissTarget();
+        createDismissTargetMaybe();
     }
 
     public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
@@ -351,6 +446,74 @@
         }
     }
 
+    /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
+    private void createDismissTargetMaybe() {
+        if (!mTargetViewContainer.isAttachedToWindow()) {
+            mHandler.removeCallbacks(mShowTargetAction);
+            mMagneticTargetAnimator.cancel();
+
+            final Point windowSize = new Point();
+            mWindowManager.getDefaultDisplay().getRealSize(windowSize);
+            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                    WindowManager.LayoutParams.MATCH_PARENT,
+                    mDismissAreaHeight,
+                    0, windowSize.y - mDismissAreaHeight,
+                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                    PixelFormat.TRANSLUCENT);
+            lp.setTitle("pip-dismiss-overlay");
+            lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+            lp.setFitInsetsTypes(0 /* types */);
+
+            mTargetViewContainer.setVisibility(View.INVISIBLE);
+            mWindowManager.addView(mTargetViewContainer, lp);
+        }
+    }
+
+    /** Makes the dismiss target visible and animates it in, if it isn't already visible. */
+    private void showDismissTargetMaybe() {
+        createDismissTargetMaybe();
+
+        if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
+
+            mTargetView.setTranslationY(mTargetViewContainer.getHeight());
+            mTargetViewContainer.setVisibility(View.VISIBLE);
+
+            // Set the magnetic field radius to half of PIP's width.
+            mMagneticTarget.setMagneticFieldRadiusPx(mMotionHelper.getBounds().width());
+
+            // Cancel in case we were in the middle of animating it out.
+            mMagneticTargetAnimator.cancel();
+            mMagneticTargetAnimator
+                    .spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
+                    .start();
+        }
+    }
+
+    /** Animates the magnetic dismiss target out and then sets it to GONE. */
+    private void hideDismissTarget() {
+        mHandler.removeCallbacks(mShowTargetAction);
+        mMagneticTargetAnimator
+                .spring(DynamicAnimation.TRANSLATION_Y,
+                        mTargetViewContainer.getHeight(),
+                        mTargetSpringConfig)
+                .withEndActions(() ->  mTargetViewContainer.setVisibility(View.GONE))
+                .start();
+    }
+
+    /**
+     * Removes the dismiss target and cancels any pending callbacks to show it.
+     */
+    private void cleanUpDismissTarget() {
+        mHandler.removeCallbacks(mShowTargetAction);
+
+        if (mTargetViewContainer.isAttachedToWindow()) {
+            mWindowManager.removeView(mTargetViewContainer);
+        }
+    }
+
     private void onRegistrationChanged(boolean isRegistered) {
         mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
                 ? mConnection : null);
@@ -375,8 +538,24 @@
         if (mPinnedStackController == null) {
             return true;
         }
+
         MotionEvent ev = (MotionEvent) inputEvent;
 
+        if (mMagnetizedPip.maybeConsumeMotionEvent(ev)) {
+            // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
+            // to the touch state. Touch state needs a DOWN event in order to later process MOVE
+            // events it'll receive if the object is dragged out of the magnetic field.
+            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                mTouchState.onTouchEvent(ev);
+            }
+
+            // Continue tracking velocity when the object is in the magnetic field, since we want to
+            // respect touch input velocity if the object is dragged out and then flung.
+            mTouchState.addMovementToVelocityTracker(ev);
+
+            return true;
+        }
+
         // Update the touch state
         mTouchState.onTouchEvent(ev);
 
@@ -384,7 +563,7 @@
 
         switch (ev.getAction()) {
             case MotionEvent.ACTION_DOWN: {
-                mMotionHelper.synchronizePinnedStackBounds();
+                mMotionHelper.synchronizePinnedStackBoundsForTouchGesture();
                 mGesture.onDown(mTouchState);
                 break;
             }
@@ -600,17 +779,13 @@
             mDelta.set(0f, 0f);
             mStartPosition.set(bounds.left, bounds.top);
             mMovementWithinDismiss = touchState.getDownTouchPosition().y >= mMovementBounds.bottom;
+            mMotionHelper.setSpringingToTouch(false);
 
             // If the menu is still visible then just poke the menu
             // so that it will timeout after the user stops touching it
             if (mMenuState != MENU_STATE_NONE) {
                 mMenuController.pokeMenu();
             }
-
-            if (mEnableDismissDragToEdge) {
-                mDismissViewController.createDismissTarget();
-                mHandler.postDelayed(mShowDismissAffordance, SHOW_DISMISS_AFFORDANCE_DELAY);
-            }
         }
 
         @Override
@@ -623,8 +798,10 @@
                 mSavedSnapFraction = -1f;
 
                 if (mEnableDismissDragToEdge) {
-                    mHandler.removeCallbacks(mShowDismissAffordance);
-                    mDismissViewController.showDismissTarget();
+                    if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
+                        mHandler.removeCallbacks(mShowTargetAction);
+                        showDismissTargetMaybe();
+                    }
                 }
             }
 
@@ -644,10 +821,6 @@
                 mTmpBounds.offsetTo((int) left, (int) top);
                 mMotionHelper.movePip(mTmpBounds, true /* isDragging */);
 
-                if (mEnableDismissDragToEdge) {
-                    updateDismissFraction();
-                }
-
                 final PointF curPos = touchState.getLastTouchPosition();
                 if (mMovementWithinDismiss) {
                     // Track if movement remains near the bottom edge to identify swipe to dismiss
@@ -661,9 +834,7 @@
         @Override
         public boolean onUp(PipTouchState touchState) {
             if (mEnableDismissDragToEdge) {
-                // Clean up the dismiss target regardless of the touch state in case the touch
-                // enabled state changes while the user is interacting
-                cleanUpDismissTarget();
+                hideDismissTarget();
             }
 
             if (!touchState.isUserInteracting()) {
@@ -671,26 +842,8 @@
             }
 
             final PointF vel = touchState.getVelocity();
-            final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
             final float velocity = PointF.length(vel.x, vel.y);
             final boolean isFling = velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond();
-            final boolean isUpWithinDimiss = ENABLE_FLING_DISMISS
-                    && touchState.getLastTouchPosition().y >= mMovementBounds.bottom
-                    && mMotionHelper.isGestureToDismissArea(mMotionHelper.getBounds(), vel.x,
-                            vel.y, isFling);
-            final boolean isFlingToBot = isFling && vel.y > 0 && !isHorizontal
-                    && (mMovementWithinDismiss || isUpWithinDimiss);
-            if (mEnableDismissDragToEdge) {
-                // Check if the user dragged or flung the PiP offscreen to dismiss it
-                if (mMotionHelper.shouldDismissPip() || isFlingToBot) {
-                    MetricsLoggerWrapper.logPictureInPictureDismissByDrag(mContext,
-                            PipUtils.getTopPipActivity(mContext, mActivityManager));
-                    mMotionHelper.animateDismiss(
-                            vel.x, vel.y,
-                            PipTouchHandler.this::updateDismissFraction /* updateAction */);
-                    return true;
-                }
-            }
 
             if (touchState.isDragging()) {
                 Runnable endAction = null;
@@ -749,14 +902,6 @@
     }
 
     /**
-     * Removes the dismiss target and cancels any pending callbacks to show it.
-     */
-    private void cleanUpDismissTarget() {
-        mHandler.removeCallbacks(mShowDismissAffordance);
-        mDismissViewController.destroyDismissTarget();
-    }
-
-    /**
      * @return whether the menu will resize as a part of showing the full menu.
      */
     private boolean willResizeMenu() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index e3f65ef..dc286c1 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -92,7 +92,7 @@
 
                 // Initialize the velocity tracker
                 initOrResetVelocityTracker();
-                addMovement(ev);
+                addMovementToVelocityTracker(ev);
 
                 mActivePointerId = ev.getPointerId(0);
                 if (DEBUG) {
@@ -120,7 +120,7 @@
                 }
 
                 // Update the velocity tracker
-                addMovement(ev);
+                addMovementToVelocityTracker(ev);
                 int pointerIndex = ev.findPointerIndex(mActivePointerId);
                 if (pointerIndex == -1) {
                     Log.e(TAG, "Invalid active pointer id on MOVE: " + mActivePointerId);
@@ -151,7 +151,7 @@
                 }
 
                 // Update the velocity tracker
-                addMovement(ev);
+                addMovementToVelocityTracker(ev);
 
                 int pointerIndex = ev.getActionIndex();
                 int pointerId = ev.getPointerId(pointerIndex);
@@ -174,7 +174,7 @@
                 }
 
                 // Update the velocity tracker
-                addMovement(ev);
+                addMovementToVelocityTracker(ev);
                 mVelocityTracker.computeCurrentVelocity(1000,
                         mViewConfig.getScaledMaximumFlingVelocity());
                 mVelocity.set(mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
@@ -318,6 +318,20 @@
         return -1;
     }
 
+    void addMovementToVelocityTracker(MotionEvent event) {
+        if (mVelocityTracker == null) {
+            return;
+        }
+
+        // Add movement to velocity tracker using raw screen X and Y coordinates instead
+        // of window coordinates because the window frame may be moving at the same time.
+        float deltaX = event.getRawX() - event.getX();
+        float deltaY = event.getRawY() - event.getY();
+        event.offsetLocation(deltaX, deltaY);
+        mVelocityTracker.addMovement(event);
+        event.offsetLocation(-deltaX, -deltaY);
+    }
+
     private void initOrResetVelocityTracker() {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
@@ -333,16 +347,6 @@
         }
     }
 
-    private void addMovement(MotionEvent event) {
-        // Add movement to velocity tracker using raw screen X and Y coordinates instead
-        // of window coordinates because the window frame may be moving at the same time.
-        float deltaX = event.getRawX() - event.getX();
-        float deltaY = event.getRawY() - event.getY();
-        event.offsetLocation(deltaX, deltaY);
-        mVelocityTracker.addMovement(event);
-        event.offsetLocation(-deltaX, -deltaY);
-    }
-
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index 9c175bc..8efeef1 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -30,6 +30,14 @@
  */
 public class PipControlsView extends LinearLayout {
 
+    public PipControlsView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PipControlsView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
     public PipControlsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
         LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
index f710f7f..448531a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
@@ -25,13 +25,18 @@
 
 class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTileLayout {
 
+    companion object {
+        private const val NUM_LINES = 2
+    }
+
     protected val mRecords = ArrayList<QSPanel.TileRecord>()
     private var _listening = false
     private var smallTileSize = 0
     private val twoLineHeight
-        get() = smallTileSize * 2 + cellMarginVertical
+        get() = smallTileSize * NUM_LINES + cellMarginVertical * (NUM_LINES - 1)
     private var cellMarginHorizontal = 0
     private var cellMarginVertical = 0
+    private var tilesToShow = 0
 
     init {
         isFocusableInTouchMode = true
@@ -68,7 +73,7 @@
     override fun updateResources(): Boolean {
         with(mContext.resources) {
             smallTileSize = getDimensionPixelSize(R.dimen.qs_quick_tile_size)
-            cellMarginHorizontal = getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal)
+            cellMarginHorizontal = getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal_two_line)
             cellMarginVertical = getDimensionPixelSize(R.dimen.new_qs_vertical_margin)
         }
         requestLayout()
@@ -83,11 +88,12 @@
         }
     }
 
-    override fun getNumVisibleTiles() = mRecords.size
+    override fun getNumVisibleTiles() = tilesToShow
 
     override fun onConfigurationChanged(newConfig: Configuration) {
         super.onConfigurationChanged(newConfig)
         updateResources()
+        postInvalidate()
     }
 
     override fun onFinishInflate() {
@@ -95,39 +101,58 @@
     }
 
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
-        var previousView: View = this
-        var tiles = 0
 
         mRecords.forEach {
-            val tileView = it.tileView
-            if (tileView.visibility != View.GONE) {
-                tileView.updateAccessibilityOrder(previousView)
-                previousView = tileView
-                tiles++
-                tileView.measure(exactly(smallTileSize), exactly(smallTileSize))
-            }
+            it.tileView.measure(exactly(smallTileSize), exactly(smallTileSize))
         }
 
         val height = twoLineHeight
-        val columns = tiles / 2
-        val width = paddingStart + paddingEnd +
-                columns * smallTileSize +
-                (columns - 1) * cellMarginHorizontal
-        setMeasuredDimension(width, height)
+        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height)
     }
 
-    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
-        val tiles = mRecords.filter { it.tileView.visibility != View.GONE }
-        tiles.forEachIndexed {
-            index, tile ->
-            val column = index % (tiles.size / 2)
-            val left = getLeftForColumn(column)
-            val top = if (index < tiles.size / 2) 0 else getTopBottomRow()
-            tile.tileView.layout(left, top, left + smallTileSize, top + smallTileSize)
+    private fun calculateMaxColumns(availableWidth: Int): Int {
+        if (smallTileSize + cellMarginHorizontal == 0) {
+            return 0
+        } else {
+            return (availableWidth - smallTileSize) / (smallTileSize + cellMarginHorizontal) + 1
         }
     }
 
-    private fun getLeftForColumn(column: Int) = column * (smallTileSize + cellMarginHorizontal)
+    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+        val availableWidth = r - l - paddingLeft - paddingRight
+        val maxColumns = calculateMaxColumns(availableWidth)
+        val actualColumns = Math.min(maxColumns, mRecords.size / NUM_LINES)
+        if (actualColumns == 0) {
+            // No tileSize or horizontal margin
+            return
+        }
+        tilesToShow = actualColumns * NUM_LINES
+
+        val interTileSpace = if (actualColumns <= 2) {
+            // Extra "column" of padding to be distributed on each end
+            (availableWidth - actualColumns * smallTileSize) / actualColumns
+        } else {
+            (availableWidth - actualColumns * smallTileSize) / (actualColumns - 1)
+        }
+
+        for (index in 0 until mRecords.size) {
+            val tileView = mRecords[index].tileView
+            if (index >= tilesToShow) {
+                tileView.visibility = View.GONE
+            } else {
+                tileView.visibility = View.VISIBLE
+                if (index > 0) tileView.updateAccessibilityOrder(mRecords[index - 1].tileView)
+                val column = index % actualColumns
+                val left = getLeftForColumn(column, interTileSpace, actualColumns <= 2)
+                val top = if (index < actualColumns) 0 else getTopBottomRow()
+                tileView.layout(left, top, left + smallTileSize, top + smallTileSize)
+            }
+        }
+    }
+
+    private fun getLeftForColumn(column: Int, interSpace: Int, sideMargin: Boolean): Int {
+        return (if (sideMargin) interSpace / 2 else 0) + column * (smallTileSize + interSpace)
+    }
 
     private fun getTopBottomRow() = smallTileSize + cellMarginVertical
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
index 8922e14..339a408 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
@@ -16,11 +16,14 @@
 
 package com.android.systemui.qs;
 
+import static com.android.systemui.util.SysuiLifecycle.viewAttachLifecycle;
+
 import android.app.Notification;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.media.session.MediaController;
 import android.media.session.MediaSession;
 import android.util.Log;
 import android.view.View;
@@ -28,12 +31,16 @@
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.SeekBar;
 import android.widget.TextView;
 
 import com.android.settingslib.media.MediaDevice;
 import com.android.systemui.R;
 import com.android.systemui.media.MediaControlPanel;
+import com.android.systemui.media.SeekBarObserver;
+import com.android.systemui.media.SeekBarViewModel;
 import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.concurrent.Executor;
 
@@ -54,6 +61,9 @@
     };
 
     private final QSPanel mParent;
+    private final DelayableExecutor mBackgroundExecutor;
+    private final SeekBarViewModel mSeekBarViewModel;
+    private final SeekBarObserver mSeekBarObserver;
 
     /**
      * Initialize quick shade version of player
@@ -64,10 +74,20 @@
      * @param backgroundExecutor
      */
     public QSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager,
-            Executor foregroundExecutor, Executor backgroundExecutor) {
+            Executor foregroundExecutor, DelayableExecutor backgroundExecutor) {
         super(context, parent, manager, R.layout.qs_media_panel, QS_ACTION_IDS, foregroundExecutor,
                 backgroundExecutor);
         mParent = (QSPanel) parent;
+        mBackgroundExecutor = backgroundExecutor;
+        mSeekBarViewModel = new SeekBarViewModel(backgroundExecutor);
+        mSeekBarObserver = new SeekBarObserver(getView());
+        // Can't use the viewAttachLifecycle of media player because remove/add is used to adjust
+        // priority of players. As soon as it is removed, the lifecycle will end and the seek bar
+        // will stop updating. So, use the lifecycle of the parent instead.
+        mSeekBarViewModel.getProgress().observe(viewAttachLifecycle(parent), mSeekBarObserver);
+        SeekBar bar = getView().findViewById(R.id.media_progress_bar);
+        bar.setOnSeekBarChangeListener(mSeekBarViewModel.getSeekBarListener());
+        bar.setOnTouchListener(mSeekBarViewModel.getSeekBarTouchListener());
     }
 
     /**
@@ -115,6 +135,11 @@
             thisBtn.setVisibility(View.GONE);
         }
 
+        // Seek Bar
+        final MediaController controller = new MediaController(getContext(), token);
+        mBackgroundExecutor.execute(
+                () -> mSeekBarViewModel.updateController(controller, iconColor));
+
         // Set up long press menu
         View guts = mMediaNotifView.findViewById(R.id.media_guts);
         View options = mMediaNotifView.findViewById(R.id.qs_media_controls_options);
@@ -155,4 +180,16 @@
             return true; // consumed click
         });
     }
+
+    /**
+     * Sets the listening state of the player.
+     *
+     * Should be set to true when the QS panel is open. Otherwise, false. This is a signal to avoid
+     * unnecessary work when the QS panel is closed.
+     *
+     * @param listening True when player should be active. Otherwise, false.
+     */
+    public void setListening(boolean listening) {
+        mSeekBarViewModel.setListening(listening);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 33cc086..c8412ff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -69,6 +69,7 @@
 import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -103,7 +104,7 @@
     private final NotificationMediaManager mNotificationMediaManager;
     private final LocalBluetoothManager mLocalBluetoothManager;
     private final Executor mForegroundExecutor;
-    private final Executor mBackgroundExecutor;
+    private final DelayableExecutor mBackgroundExecutor;
     private LocalMediaManager mLocalMediaManager;
     private MediaDevice mDevice;
     private boolean mUpdateCarousel = false;
@@ -166,7 +167,7 @@
             QSLogger qsLogger,
             NotificationMediaManager notificationMediaManager,
             @Main Executor foregroundExecutor,
-            @Background Executor backgroundExecutor,
+            @Background DelayableExecutor backgroundExecutor,
             @Nullable LocalBluetoothManager localBluetoothManager
     ) {
         super(context, attrs);
@@ -278,7 +279,7 @@
             Log.d(TAG, "creating new player");
             player = new QSMediaPlayer(mContext, this, mNotificationMediaManager,
                     mForegroundExecutor, mBackgroundExecutor);
-
+            player.setListening(mListening);
             if (player.isPlaying()) {
                 mMediaCarousel.addView(player.getView(), 0, lp); // add in front
             } else {
@@ -584,6 +585,9 @@
         if (mListening) {
             refreshAllTiles();
         }
+        for (QSMediaPlayer player : mMediaPlayers) {
+            player.setListening(mListening);
+        }
     }
 
     private String getTilesSpecs() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index be01d75..e6876bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -43,6 +43,7 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.Utils;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -65,7 +66,10 @@
     private int mMaxTiles;
     protected QSPanel mFullPanel;
     private QuickQSMediaPlayer mMediaPlayer;
+    /** Whether or not the QS media player feature is enabled. */
     private boolean mUsingMediaPlayer;
+    /** Whether or not the QuickQSPanel currently contains a media player. */
+    private boolean mHasMediaPlayer;
     private LinearLayout mHorizontalLinearLayout;
 
     // Only used with media
@@ -81,7 +85,7 @@
             QSLogger qsLogger,
             NotificationMediaManager notificationMediaManager,
             @Main Executor foregroundExecutor,
-            @Background Executor backgroundExecutor,
+            @Background DelayableExecutor backgroundExecutor,
             @Nullable LocalBluetoothManager localBluetoothManager
     ) {
         super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, notificationMediaManager,
@@ -184,8 +188,8 @@
 
     boolean switchTileLayout() {
         if (!mUsingMediaPlayer) return false;
-        if (mMediaPlayer.hasMediaSession()
-                && mHorizontalLinearLayout.getVisibility() == View.GONE) {
+        mHasMediaPlayer = mMediaPlayer.hasMediaSession();
+        if (mHasMediaPlayer && mHorizontalLinearLayout.getVisibility() == View.GONE) {
             mHorizontalLinearLayout.setVisibility(View.VISIBLE);
             ((View) mRegularTileLayout).setVisibility(View.GONE);
             mTileLayout.setListening(false);
@@ -197,8 +201,7 @@
             if (mHost != null) setTiles(mHost.getTiles());
             mTileLayout.setListening(mListening);
             return true;
-        } else if (!mMediaPlayer.hasMediaSession()
-                && mHorizontalLinearLayout.getVisibility() == View.VISIBLE) {
+        } else if (!mHasMediaPlayer && mHorizontalLinearLayout.getVisibility() == View.VISIBLE) {
             mHorizontalLinearLayout.setVisibility(View.GONE);
             ((View) mRegularTileLayout).setVisibility(View.VISIBLE);
             mTileLayout.setListening(false);
@@ -214,8 +217,9 @@
         return false;
     }
 
-    public boolean hasMediaPlayerSession() {
-        return mMediaPlayer.hasMediaSession();
+    /** Returns true if this panel currently contains a media player. */
+    public boolean hasMediaPlayer() {
+        return mHasMediaPlayer;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 11b625f..e1ffad4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -344,7 +344,7 @@
         if (mQsDisabled) {
             lp.height = resources.getDimensionPixelSize(
                     com.android.internal.R.dimen.quick_qs_offset_height);
-        } else if (useQsMediaPlayer(mContext) && mHeaderQsPanel.hasMediaPlayerSession()) {
+        } else if (useQsMediaPlayer(mContext) && mHeaderQsPanel.hasMediaPlayer()) {
             lp.height = Math.max(getMinimumHeight(),
                     resources.getDimensionPixelSize(
                             com.android.internal.R.dimen.quick_qs_total_height_with_media));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
index f9b1473..ebdcc00 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
@@ -25,6 +25,7 @@
 import android.os.Message;
 import android.provider.Settings;
 import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
@@ -260,7 +261,9 @@
                 mCarrierGroups[i].setVisibility(View.GONE);
             }
             mNoSimTextView.setText(info.carrierText);
-            mNoSimTextView.setVisibility(View.VISIBLE);
+            if (!TextUtils.isEmpty(info.carrierText)) {
+                mNoSimTextView.setVisibility(View.VISIBLE);
+            }
         }
         handleUpdateState(); // handleUpdateCarrierInfo is always called from main thread.
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index 4f90527..447f48b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -29,6 +31,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.PseudoGridView;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+
 /**
  * Quick settings detail view for user switching.
  */
@@ -101,6 +104,19 @@
             return v;
         }
 
+        private static Drawable getDrawable(Context context,
+                UserSwitcherController.UserRecord item) {
+            Drawable icon = getIconDrawable(context, item);
+            int iconColorRes = item.isCurrent ? R.color.qs_user_switcher_selected_avatar_icon_color
+                    : R.color.qs_user_switcher_avatar_icon_color;
+            icon.setTint(context.getResources().getColor(iconColorRes, context.getTheme()));
+
+            int bgRes = item.isCurrent ? R.drawable.bg_avatar_selected : R.drawable.qs_bg_avatar;
+            Drawable bg = context.getDrawable(bgRes);
+            LayerDrawable drawable = new LayerDrawable(new Drawable[]{bg, icon});
+            return drawable;
+        }
+
         @Override
         public void onClick(View view) {
             UserSwitcherController.UserRecord tag =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index df85ed5..66bc177 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -55,6 +55,7 @@
 import android.util.Log;
 import android.view.InputMonitor;
 import android.view.MotionEvent;
+import android.view.Surface;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.policy.ScreenDecorationsUtils;
@@ -416,6 +417,19 @@
             }
         }
 
+        @Override
+        public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
+            if (!verifyCaller("onQuickSwitchToNewTask")) {
+                return;
+            }
+            long token = Binder.clearCallingIdentity();
+            try {
+                mHandler.post(() -> notifyQuickSwitchToNewTask(rotation));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         private boolean verifyCaller(String reason) {
             final int callerId = Binder.getCallingUserHandle().getIdentifier();
             if (callerId != mCurrentBoundedUserId) {
@@ -785,6 +799,12 @@
         }
     }
 
+    private void notifyQuickSwitchToNewTask(@Surface.Rotation int rotation) {
+        for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+            mConnectionCallbacks.get(i).onQuickSwitchToNewTask(rotation);
+        }
+    }
+
     public void notifyQuickScrubStarted() {
         for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
             mConnectionCallbacks.get(i).onQuickScrubStarted();
@@ -850,6 +870,7 @@
     public interface OverviewProxyListener {
         default void onConnectionChanged(boolean isConnected) {}
         default void onQuickStepStarted() {}
+        default void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {}
         default void onOverviewShown(boolean fromHome) {}
         default void onQuickScrubStarted() {}
         /** Notify changes in the nav bar button alpha */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index e21861a..366ef93 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -21,6 +21,7 @@
 import static android.view.WindowManager.DOCKED_RIGHT;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 
+import android.animation.AnimationHandler;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -32,10 +33,8 @@
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Message;
 import android.util.AttributeSet;
 import android.util.Slog;
-import android.view.Choreographer;
 import android.view.Display;
 import android.view.InsetsState;
 import android.view.MotionEvent;
@@ -57,12 +56,12 @@
 import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
 
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
-import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -111,8 +110,6 @@
     private static final Interpolator IME_ADJUST_INTERPOLATOR =
             new PathInterpolator(0.2f, 0f, 0.1f, 1f);
 
-    private static final int MSG_RESIZE_STACK = 0;
-
     private DividerHandleView mHandle;
     private View mBackground;
     private MinimizedDockShadow mMinimizedShadow;
@@ -149,6 +146,7 @@
     private SplitDisplayLayout mSplitLayout;
     private DividerCallbacks mCallback;
     private final Rect mStableInsets = new Rect();
+    private final AnimationHandler mAnimationHandler = new AnimationHandler();
 
     private boolean mGrowRecents;
     private ValueAnimator mCurrentAnimator;
@@ -159,7 +157,6 @@
     private boolean mHomeStackResizable;
     private boolean mAdjustedForIme;
     private DividerState mState;
-    private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
 
     private SplitScreenTaskOrganizer mTiles;
     boolean mFirstLayout = true;
@@ -173,18 +170,7 @@
     // used interact with keyguard.
     private boolean mSurfaceHidden = false;
 
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_RESIZE_STACK:
-                    resizeStackSurfaces(msg.arg1, msg.arg2, (SnapTarget) msg.obj);
-                    break;
-                default:
-                    super.handleMessage(msg);
-            }
-        }
-    };
+    private final Handler mHandler = new Handler();
 
     private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
         @Override
@@ -277,11 +263,10 @@
     public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, context.getDisplay(),
-                Choreographer.getInstance());
         final DisplayManager displayManager =
                 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
         mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
     }
 
     @Override
@@ -326,7 +311,6 @@
     void onDividerRemoved() {
         mRemoved = true;
         mCallback = null;
-        mHandler.removeMessages(MSG_RESIZE_STACK);
     }
 
     @Override
@@ -548,7 +532,7 @@
                 if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
                     SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget(
                             mStartPosition, 0 /* velocity */, false /* hardDismiss */);
-                    resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget);
+                    resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget);
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -633,7 +617,7 @@
         if (DEBUG) Slog.d(TAG, "Getting fling " + position + "->" + snapTarget.position);
         final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE;
         ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
-        anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(),
+        anim.addUpdateListener(animation -> resizeStackSurfaces((int) animation.getAnimatedValue(),
                 taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
                         ? TASK_POSITION_SAME
                         : snapTarget.taskPosition,
@@ -682,7 +666,6 @@
 
             @Override
             public void onAnimationCancel(Animator animation) {
-                mHandler.removeMessages(MSG_RESIZE_STACK);
                 mCancelled = true;
             }
 
@@ -693,8 +676,6 @@
                     delay = endDelay;
                 } else if (mCancelled) {
                     delay = 0;
-                } else if (mSfChoreographer.getSurfaceFlingerOffsetMs() > 0) {
-                    delay = mSfChoreographer.getSurfaceFlingerOffsetMs();
                 }
                 if (delay == 0) {
                     endAction.accept(mCancelled);
@@ -705,6 +686,7 @@
                 }
             }
         });
+        anim.setAnimationHandler(mAnimationHandler);
         mCurrentAnimator = anim;
         return anim;
     }
@@ -1047,13 +1029,6 @@
                 mDividerSize);
     }
 
-    public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) {
-        Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
-                taskSnapTarget);
-        message.setAsynchronous(true);
-        mSfChoreographer.scheduleAtSfVsync(mHandler, message);
-    }
-
     private void resizeStackSurfaces(SnapTarget taskSnapTarget) {
         resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget);
     }
@@ -1085,14 +1060,6 @@
         crop.offsetTo(-(otherTaskRect.left - otherRect.left),
                 -(otherTaskRect.top - otherRect.top));
         t.setWindowCrop(mTiles.mSecondarySurface, crop);
-        // Reposition home and recents surfaces or they would be positioned relatively to its
-        // parent (split-screen secondary task) position.
-        for (int i = mTiles.mHomeAndRecentsSurfaces.size() - 1; i >= 0; --i) {
-            t.setPosition(mTiles.mHomeAndRecentsSurfaces.get(i),
-                    mTiles.mHomeBounds.left - otherTaskRect.left,
-                    mTiles.mHomeBounds.top - otherTaskRect.top);
-            t.setWindowCrop(mTiles.mHomeAndRecentsSurfaces.get(i), null);
-        }
         final SurfaceControl dividerCtrl = getWindowSurfaceControl();
         if (dividerCtrl != null) {
             if (isHorizontalDivision()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 94afde78..2419515 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -322,10 +322,10 @@
         default void suppressAmbientDisplay(boolean suppress) { }
 
         /**
-         * @see IStatusBar#showToast(String, IBinder, CharSequence, IBinder, int,
+         * @see IStatusBar#showToast(int, String, IBinder, CharSequence, IBinder, int,
          * ITransientNotificationCallback)
          */
-        default void showToast(String packageName, IBinder token, CharSequence text,
+        default void showToast(int uid, String packageName, IBinder token, CharSequence text,
                 IBinder windowToken, int duration,
                 @Nullable ITransientNotificationCallback callback) { }
 
@@ -798,7 +798,7 @@
     }
 
     @Override
-    public void showToast(String packageName, IBinder token, CharSequence text,
+    public void showToast(int uid, String packageName, IBinder token, CharSequence text,
             IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
@@ -807,7 +807,8 @@
             args.arg3 = text;
             args.arg4 = windowToken;
             args.arg5 = callback;
-            args.argi1 = duration;
+            args.argi1 = uid;
+            args.argi2 = duration;
             mHandler.obtainMessage(MSG_SHOW_TOAST, args).sendToTarget();
         }
     }
@@ -1276,9 +1277,10 @@
                     IBinder windowToken = (IBinder) args.arg4;
                     ITransientNotificationCallback callback =
                             (ITransientNotificationCallback) args.arg5;
-                    int duration = args.argi1;
+                    int uid = args.argi1;
+                    int duration = args.argi2;
                     for (Callbacks callbacks : mCallbacks) {
-                        callbacks.showToast(packageName, token, text, windowToken, duration,
+                        callbacks.showToast(uid, packageName, token, text, windowToken, duration,
                                 callback);
                     }
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index a978cad..729f934 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -21,6 +21,7 @@
 import android.animation.ValueAnimator
 import android.app.WallpaperManager
 import android.util.Log
+import android.util.MathUtils
 import android.view.Choreographer
 import android.view.View
 import androidx.annotation.VisibleForTesting
@@ -32,14 +33,15 @@
 import com.android.systemui.Interpolators
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
 import com.android.systemui.statusbar.phone.PanelExpansionListener
+import com.android.systemui.statusbar.phone.ScrimController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import java.io.FileDescriptor
 import java.io.PrintWriter
-import java.lang.IllegalArgumentException
 import javax.inject.Inject
 import javax.inject.Singleton
 import kotlin.math.max
@@ -69,10 +71,51 @@
     private var notificationAnimator: Animator? = null
     private var updateScheduled: Boolean = false
     private var shadeExpansion = 0f
+    private var ignoreShadeBlurUntilHidden: Boolean = false
     @VisibleForTesting
     var shadeSpring = DepthAnimation()
     @VisibleForTesting
     var globalActionsSpring = DepthAnimation()
+    var showingHomeControls: Boolean = false
+
+    @VisibleForTesting
+    var brightnessMirrorSpring = DepthAnimation()
+    var brightnessMirrorVisible: Boolean = false
+        set(value) {
+            field = value
+            brightnessMirrorSpring.animateTo(if (value) blurUtils.blurRadiusOfRatio(1f)
+                else 0)
+        }
+
+    /**
+     * When launching an app from the shade, the animations progress should affect how blurry the
+     * shade is, overriding the expansion amount.
+     */
+    var notificationLaunchAnimationParams: ActivityLaunchAnimator.ExpandAnimationParameters? = null
+        set(value) {
+            field = value
+            if (value != null) {
+                scheduleUpdate()
+                return
+            }
+
+            if (shadeSpring.radius == 0) {
+                return
+            }
+            ignoreShadeBlurUntilHidden = true
+            shadeSpring.animateTo(0)
+            shadeSpring.finishIfRunning()
+        }
+
+    /**
+     * Force stop blur effect when necessary.
+     */
+    private var scrimsVisible: Boolean = false
+        set(value) {
+            if (field == value) return
+            field = value
+            scheduleUpdate()
+        }
 
     /**
      * Blur radius of the wake-up animation on this frame.
@@ -91,7 +134,32 @@
     val updateBlurCallback = Choreographer.FrameCallback {
         updateScheduled = false
 
-        val blur = max(max(shadeSpring.radius, wakeAndUnlockBlurRadius), globalActionsSpring.radius)
+        var shadeRadius = max(shadeSpring.radius, wakeAndUnlockBlurRadius).toFloat()
+        shadeRadius *= 1f - brightnessMirrorSpring.ratio
+        val launchProgress = notificationLaunchAnimationParams?.linearProgress ?: 0f
+        shadeRadius *= (1f - launchProgress) * (1f - launchProgress)
+
+        if (ignoreShadeBlurUntilHidden) {
+            if (shadeRadius == 0f) {
+                ignoreShadeBlurUntilHidden = false
+            } else {
+                shadeRadius = 0f
+            }
+        }
+
+        // Home controls have black background, this means that we should not have blur when they
+        // are fully visible, otherwise we'll enter Client Composition unnecessarily.
+        var globalActionsRadius = globalActionsSpring.radius
+        if (showingHomeControls) {
+            globalActionsRadius = 0
+        }
+        var blur = max(shadeRadius.toInt(), globalActionsRadius)
+
+        // Make blur be 0 if it is necessary to stop blur effect.
+        if (scrimsVisible) {
+            blur = 0
+        }
+
         blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur)
         try {
             wallpaperManager.setWallpaperZoomOut(root.windowToken,
@@ -148,8 +216,13 @@
             if (isDozing) {
                 shadeSpring.finishIfRunning()
                 globalActionsSpring.finishIfRunning()
+                brightnessMirrorSpring.finishIfRunning()
             }
         }
+
+        override fun onDozeAmountChanged(linear: Float, eased: Float) {
+            wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased)
+        }
     }
 
     init {
@@ -158,6 +231,10 @@
             keyguardStateController.addCallback(keyguardStateCallback)
         }
         statusBarStateController.addCallback(statusBarStateCallback)
+        notificationShadeWindowController.setScrimsVisibilityListener {
+            // Stop blur effect when scrims is opaque to avoid unnecessary GPU composition.
+            visibility -> scrimsVisible = visibility == ScrimController.OPAQUE
+        }
     }
 
     /**
@@ -173,10 +250,13 @@
 
     private fun updateShadeBlur() {
         var newBlur = 0
-        if (statusBarStateController.state == StatusBarState.SHADE) {
-            newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion)
+        val state = statusBarStateController.state
+        if (state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) {
+            val animatedBlur =
+                    Interpolators.SHADE_ANIMATION.getInterpolation(
+                            MathUtils.constrain(shadeExpansion / 0.15f, 0f, 1f))
+            newBlur = blurUtils.blurRadiusOfRatio(0.35f * animatedBlur + 0.65f * shadeExpansion)
         }
-
         shadeSpring.animateTo(newBlur)
     }
 
@@ -199,7 +279,11 @@
             it.increaseIndent()
             it.println("shadeRadius: ${shadeSpring.radius}")
             it.println("globalActionsRadius: ${globalActionsSpring.radius}")
+            it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
             it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
+            it.println("notificationLaunchAnimationProgress: " +
+                    "${notificationLaunchAnimationParams?.linearProgress}")
+            it.println("ignoreShadeBlurUntilHidden: $ignoreShadeBlurUntilHidden")
         }
     }
 
@@ -212,7 +296,12 @@
          * Blur radius visible on the UI, in pixels.
          */
         var radius = 0
-            private set
+
+        /**
+         * Depth ratio of the current blur radius.
+         */
+        val ratio
+            get() = blurUtils.ratioOfBlurRadius(radius)
 
         /**
          * Radius that we're animating to.
@@ -239,7 +328,7 @@
         init {
             springAnimation.spring = SpringForce(0.0f)
             springAnimation.spring.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
-            springAnimation.spring.stiffness = SpringForce.STIFFNESS_MEDIUM
+            springAnimation.spring.stiffness = SpringForce.STIFFNESS_HIGH
             springAnimation.addEndListener { _, _, _, _ -> pendingRadius = -1 }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index fe2f1f3..1297f99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -177,12 +177,32 @@
                     currentUserId);
             ent.setSensitive(sensitive, deviceSensitive);
             ent.getRow().setNeedsRedaction(needsRedaction);
-            if (mGroupManager.isChildInGroupWithSummary(ent.getSbn())) {
-                NotificationEntry summary = mGroupManager.getGroupSummary(ent.getSbn());
-                List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(summary);
+            boolean isChildInGroup = mGroupManager.isChildInGroupWithSummary(ent.getSbn());
+
+            boolean groupChangesAllowed = mVisualStabilityManager.areGroupChangesAllowed()
+                    || !ent.hasFinishedInitialization();
+            NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn());
+            if (!groupChangesAllowed) {
+                // We don't to change groups while the user is looking at them
+                boolean wasChildInGroup = ent.isChildInGroup();
+                if (isChildInGroup && !wasChildInGroup) {
+                    isChildInGroup = wasChildInGroup;
+                    mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager);
+                } else if (!isChildInGroup && wasChildInGroup) {
+                    // We allow grouping changes if the group was collapsed
+                    if (mGroupManager.isLogicalGroupExpanded(ent.getSbn())) {
+                        isChildInGroup = wasChildInGroup;
+                        parent = ent.getRow().getNotificationParent().getEntry();
+                        mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager);
+                    }
+                }
+            }
+
+            if (isChildInGroup) {
+                List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent);
                 if (orderedChildren == null) {
                     orderedChildren = new ArrayList<>();
-                    mTmpChildOrderMap.put(summary, orderedChildren);
+                    mTmpChildOrderMap.put(parent, orderedChildren);
                 }
                 orderedChildren.add(ent);
             } else {
@@ -205,7 +225,7 @@
         }
 
         for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
-            if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getEntry().getSbn())) {
+            if (mEntryManager.getPendingOrActiveNotif(viewToRemove.getEntry().getKey()) != null) {
                 // we are only transferring this notification to its parent, don't generate an
                 // animation
                 mListContainer.setChildTransferInProgress(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 7c06157..6aef6b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
@@ -57,6 +58,7 @@
     private final NotificationListContainer mNotificationContainer;
     private final float mWindowCornerRadius;
     private final NotificationShadeWindowViewController mNotificationShadeWindowViewController;
+    private final NotificationShadeDepthController mDepthController;
     private Callback mCallback;
     private final Runnable mTimeoutRunnable = () -> {
         setAnimationPending(false);
@@ -70,9 +72,11 @@
             NotificationShadeWindowViewController notificationShadeWindowViewController,
             Callback callback,
             NotificationPanelViewController notificationPanel,
+            NotificationShadeDepthController depthController,
             NotificationListContainer container) {
         mNotificationPanel = notificationPanel;
         mNotificationContainer = container;
+        mDepthController = depthController;
         mNotificationShadeWindowViewController = notificationShadeWindowViewController;
         mCallback = callback;
         mWindowCornerRadius = ScreenDecorationsUtils
@@ -212,7 +216,7 @@
                                 mWindowCornerRadius, progress);
                         applyParamsToWindow(primary);
                         applyParamsToNotification(mParams);
-                        applyParamsToNotificationList(mParams);
+                        applyParamsToNotificationShade(mParams);
                     }
                 });
                 anim.addListener(new AnimatorListenerAdapter() {
@@ -256,14 +260,15 @@
             if (!running) {
                 mCallback.onExpandAnimationFinished(mIsFullScreenLaunch);
                 applyParamsToNotification(null);
-                applyParamsToNotificationList(null);
+                applyParamsToNotificationShade(null);
             }
 
         }
 
-        private void applyParamsToNotificationList(ExpandAnimationParameters params) {
+        private void applyParamsToNotificationShade(ExpandAnimationParameters params) {
             mNotificationContainer.applyExpandAnimationParams(params);
             mNotificationPanel.applyExpandAnimationParams(params);
+            mDepthController.setNotificationLaunchAnimationParams(params);
         }
 
         private void applyParamsToNotification(ExpandAnimationParameters params) {
@@ -295,7 +300,7 @@
     };
 
     public static class ExpandAnimationParameters {
-        float linearProgress;
+        public float linearProgress;
         int[] startPosition;
         float startTranslationZ;
         int left;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index 7ef1d0e..53ec570 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.row.NotificationContentView
+import com.android.systemui.statusbar.phone.NotificationGroupManager
 import java.util.concurrent.ConcurrentHashMap
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -60,6 +61,7 @@
 @Singleton
 class ConversationNotificationManager @Inject constructor(
     private val notificationEntryManager: NotificationEntryManager,
+    private val notificationGroupManager: NotificationGroupManager,
     private val context: Context
 ) {
     // Need this state to be thread safe, since it's accessed from the ui thread
@@ -81,10 +83,19 @@
                             if (rankingMap.getRanking(entry.sbn.key, ranking) &&
                                     ranking.isConversation) {
                                 val important = ranking.channel.isImportantConversation
+                                var changed = false
                                 entry.row?.layouts?.asSequence()
                                         ?.flatMap(::getLayouts)
                                         ?.mapNotNull { it as? ConversationLayout }
-                                        ?.forEach { it.setIsImportantConversation(important) }
+                                        ?.forEach {
+                                            if (important != it.isImportantConversation) {
+                                                it.setIsImportantConversation(important)
+                                                changed = true
+                                            }
+                                        }
+                                if (changed) {
+                                    notificationGroupManager.updateIsolation(entry)
+                                }
                             }
                         }
             }
@@ -92,12 +103,20 @@
             override fun onEntryInflated(entry: NotificationEntry) {
                 if (!entry.ranking.isConversation) return
                 fun updateCount(isExpanded: Boolean) {
-                    if (isExpanded && !notifPanelCollapsed) {
+                    if (isExpanded && (!notifPanelCollapsed || entry.isPinnedAndExpanded())) {
                         resetCount(entry.key)
                         entry.row?.let(::resetBadgeUi)
                     }
                 }
-                entry.row?.setOnExpansionChangedListener(::updateCount)
+                entry.row?.setOnExpansionChangedListener { isExpanded ->
+                    if (entry.row?.isShown == true && isExpanded) {
+                        entry.row.performOnIntrinsicHeightReached {
+                            updateCount(isExpanded)
+                        }
+                    } else {
+                        updateCount(isExpanded)
+                    }
+                }
                 updateCount(entry.row?.isExpanded == true)
             }
 
@@ -158,7 +177,8 @@
 
     private fun resetBadgeUi(row: ExpandableNotificationRow): Unit =
             (row.layouts?.asSequence() ?: emptySequence())
-                    .mapNotNull { layout -> layout.contractedChild as? ConversationLayout }
+                    .flatMap { layout -> layout.allViews.asSequence()}
+                    .mapNotNull { view -> view as? ConversationLayout }
                     .forEach { convoLayout -> convoLayout.setUnreadCount(0) }
 
     private data class ConversationState(val unreadCount: Int, val notification: Notification)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicChildBindController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicChildBindController.java
index 059d6ff..148cdea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicChildBindController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicChildBindController.java
@@ -95,8 +95,8 @@
 
     private void freeChildContent(NotificationEntry entry) {
         RowContentBindParams params = mStage.getStageParams(entry);
-        params.freeContentViews(FLAG_CONTENT_VIEW_CONTRACTED);
-        params.freeContentViews(FLAG_CONTENT_VIEW_EXPANDED);
+        params.markContentViewsFreeable(FLAG_CONTENT_VIEW_CONTRACTED);
+        params.markContentViewsFreeable(FLAG_CONTENT_VIEW_EXPANDED);
         mStage.requestRebind(entry, null);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index d2f781d..295adae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -252,7 +252,7 @@
     }
 
     @Override
-    public void onReorderingAllowed() {
+    public void onChangeAllowed() {
         updateNotifications("reordering is now allowed");
     }
 
@@ -539,7 +539,8 @@
         }
     }
 
-    private void addNotificationInternal(StatusBarNotification notification,
+    private void addNotificationInternal(
+            StatusBarNotification notification,
             RankingMap rankingMap) throws InflationException {
         String key = notification.getKey();
         if (DEBUG) {
@@ -579,6 +580,9 @@
         for (NotifCollectionListener listener : mNotifCollectionListeners) {
             listener.onEntryAdded(entry);
         }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onRankingApplied();
+        }
     }
 
     public void addNotification(StatusBarNotification notification, RankingMap ranking) {
@@ -635,6 +639,9 @@
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPostEntryUpdated(entry);
         }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onRankingApplied();
+        }
     }
 
     public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
@@ -693,6 +700,9 @@
         for (NotifCollectionListener listener : mNotifCollectionListeners) {
             listener.onRankingUpdate(rankingMap);
         }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onRankingApplied();
+        }
     }
 
     private void updateRankingOfPendingNotifications(@Nullable RankingMap rankingMap) {
@@ -799,6 +809,9 @@
      */
     public void updateRanking(RankingMap rankingMap, String reason) {
         updateRankingAndSort(rankingMap, reason);
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onRankingApplied();
+        }
     }
 
     /** Resorts / filters the current notification set with the current RankingMap */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index b357ada..7ac5995 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -42,12 +42,14 @@
 
     private static final long TEMPORARY_REORDERING_ALLOWED_DURATION = 1000;
 
-    private final ArrayList<Callback> mCallbacks =  new ArrayList<>();
+    private final ArrayList<Callback> mReorderingAllowedCallbacks = new ArrayList<>();
+    private final ArrayList<Callback> mGroupChangesAllowedCallbacks = new ArrayList<>();
     private final Handler mHandler;
 
     private boolean mPanelExpanded;
     private boolean mScreenOn;
     private boolean mReorderingAllowed;
+    private boolean mGroupChangedAllowed;
     private boolean mIsTemporaryReorderingAllowed;
     private long mTemporaryReorderingStart;
     private VisibilityLocationProvider mVisibilityLocationProvider;
@@ -83,13 +85,22 @@
 
     /**
      * Add a callback to invoke when reordering is allowed again.
-     * @param callback
      */
     public void addReorderingAllowedCallback(Callback callback) {
-        if (mCallbacks.contains(callback)) {
+        if (mReorderingAllowedCallbacks.contains(callback)) {
             return;
         }
-        mCallbacks.add(callback);
+        mReorderingAllowedCallbacks.add(callback);
+    }
+
+    /**
+     * Add a callback to invoke when group changes are allowed again.
+     */
+    public void addGroupChangesAllowedCallback(Callback callback) {
+        if (mGroupChangesAllowedCallbacks.contains(callback)) {
+            return;
+        }
+        mGroupChangesAllowedCallbacks.add(callback);
     }
 
     /**
@@ -97,7 +108,7 @@
      */
     public void setPanelExpanded(boolean expanded) {
         mPanelExpanded = expanded;
-        updateReorderingAllowed();
+        updateAllowedStates();
     }
 
     /**
@@ -105,7 +116,7 @@
      */
     public void setScreenOn(boolean screenOn) {
         mScreenOn = screenOn;
-        updateReorderingAllowed();
+        updateAllowedStates();
     }
 
     /**
@@ -116,25 +127,30 @@
             return;
         }
         mPulsing = pulsing;
-        updateReorderingAllowed();
+        updateAllowedStates();
     }
 
-    private void updateReorderingAllowed() {
+    private void updateAllowedStates() {
         boolean reorderingAllowed =
                 (!mScreenOn || !mPanelExpanded || mIsTemporaryReorderingAllowed) && !mPulsing;
         boolean changedToTrue = reorderingAllowed && !mReorderingAllowed;
         mReorderingAllowed = reorderingAllowed;
         if (changedToTrue) {
-            notifyCallbacks();
+            notifyChangeAllowed(mReorderingAllowedCallbacks);
+        }
+        boolean groupChangesAllowed = (!mScreenOn || !mPanelExpanded) && !mPulsing;
+        changedToTrue = groupChangesAllowed && !mGroupChangedAllowed;
+        mGroupChangedAllowed = groupChangesAllowed;
+        if (changedToTrue) {
+            notifyChangeAllowed(mGroupChangesAllowedCallbacks);
         }
     }
 
-    private void notifyCallbacks() {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            Callback callback = mCallbacks.get(i);
-            callback.onReorderingAllowed();
+    private void notifyChangeAllowed(ArrayList<Callback> callbacks) {
+        for (int i = 0; i < callbacks.size(); i++) {
+            callbacks.get(i).onChangeAllowed();
         }
-        mCallbacks.clear();
+        callbacks.clear();
     }
 
     /**
@@ -145,6 +161,13 @@
     }
 
     /**
+     * @return whether changes in the grouping should be allowed right now.
+     */
+    public boolean areGroupChangesAllowed() {
+        return mGroupChangedAllowed;
+    }
+
+    /**
      * @return whether a specific notification is allowed to reorder. Certain notifications are
      * allowed to reorder even if {@link #isReorderingAllowed()} returns false, like newly added
      * notifications or heads-up notifications that are out of view.
@@ -197,12 +220,12 @@
             mTemporaryReorderingStart = SystemClock.elapsedRealtime();
         }
         mIsTemporaryReorderingAllowed = true;
-        updateReorderingAllowed();
+        updateAllowedStates();
     }
 
     private final Runnable mOnTemporaryReorderingExpired = () -> {
         mIsTemporaryReorderingAllowed = false;
-        updateReorderingAllowed();
+        updateAllowedStates();
     };
 
     /**
@@ -229,9 +252,9 @@
 
     public interface Callback {
         /**
-         * Called when reordering is allowed again.
+         * Called when changing is allowed again.
          */
-        void onReorderingAllowed();
+        void onChangeAllowed();
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
new file mode 100644
index 0000000..57f8a6a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection
+
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection
+
+/**
+ * Stores the state that [ShadeListBuilder] assigns to this [ListEntry]
+ */
+data class ListAttachState private constructor(
+    /**
+     * Null if not attached to the current shade list. If top-level, then the shade list root. If
+     * part of a group, then that group's GroupEntry.
+     */
+    var parent: GroupEntry?,
+
+    /**
+     * The section that this ListEntry was sorted into. If the child of the group, this will be the
+     * parent's section. Null if not attached to the list.
+     */
+    var section: NotifSection?,
+    var sectionIndex: Int,
+
+    /**
+     * If a [NotifFilter] is excluding this entry from the list, then that filter. Always null for
+     * [GroupEntry]s.
+     */
+    var excludingFilter: NotifFilter?,
+
+    /**
+     * The [NotifPromoter] promoting this entry to top-level, if any. Always null for [GroupEntry]s.
+     */
+    var promoter: NotifPromoter?
+) {
+
+    /** Copies the state of another instance. */
+    fun clone(other: ListAttachState) {
+        parent = other.parent
+        section = other.section
+        sectionIndex = other.sectionIndex
+        excludingFilter = other.excludingFilter
+        promoter = other.promoter
+    }
+
+    /** Resets back to a "clean" state (the same as created by the factory method) */
+    fun reset() {
+        parent = null
+        section = null
+        sectionIndex = -1
+        excludingFilter = null
+        promoter = null
+    }
+
+    companion object {
+        @JvmStatic
+        fun create(): ListAttachState {
+            return ListAttachState(
+                    null,
+                    null,
+                    -1,
+                    null,
+                    null)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index b5c81b2..0caf0dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -102,11 +102,11 @@
                     .append(")");
         }
 
-        if (entry.mNotifSection != null) {
+        if (entry.getNotifSection() != null) {
             sb.append(" sectionIndex=")
                     .append(entry.getSection())
                     .append(" sectionName=")
-                    .append(entry.mNotifSection.getName());
+                    .append(entry.getNotifSection().getName());
         }
 
         if (includeRecordKeeping) {
@@ -133,15 +133,15 @@
                         .append(" ");
             }
 
-            if (notifEntry.mExcludingFilter != null) {
+            if (notifEntry.getExcludingFilter() != null) {
                 rksb.append("filter=")
-                        .append(notifEntry.mExcludingFilter)
+                        .append(notifEntry.getExcludingFilter().getName())
                         .append(" ");
             }
 
-            if (notifEntry.mNotifPromoter != null) {
+            if (notifEntry.getNotifPromoter() != null) {
                 rksb.append("promoter=")
-                        .append(notifEntry.mNotifPromoter)
+                        .append(notifEntry.getNotifPromoter().getName())
                         .append(" ");
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index b048d03..837374f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -16,7 +16,8 @@
 
 package com.android.systemui.statusbar.notification.collection;
 
-import android.annotation.Nullable;
+
+import androidx.annotation.Nullable;
 
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 
@@ -27,13 +28,11 @@
 public abstract class ListEntry {
     private final String mKey;
 
-    @Nullable private GroupEntry mParent;
-    @Nullable private GroupEntry mPreviousParent;
-    @Nullable NotifSection mNotifSection;
-
-    private int mSection = -1;
     int mFirstAddedIteration = -1;
 
+    private final ListAttachState mPreviousAttachState = ListAttachState.create();
+    private final ListAttachState mAttachState = ListAttachState.create();
+
     ListEntry(String key) {
         mKey = key;
     }
@@ -51,27 +50,40 @@
     public abstract @Nullable NotificationEntry getRepresentativeEntry();
 
     @Nullable public GroupEntry getParent() {
-        return mParent;
+        return mAttachState.getParent();
     }
 
     void setParent(@Nullable GroupEntry parent) {
-        mParent = parent;
+        mAttachState.setParent(parent);
     }
 
     @Nullable public GroupEntry getPreviousParent() {
-        return mPreviousParent;
-    }
-
-    void setPreviousParent(@Nullable GroupEntry previousParent) {
-        mPreviousParent = previousParent;
+        return mPreviousAttachState.getParent();
     }
 
     /** The section this notification was assigned to (0 to N-1, where N is number of sections). */
     public int getSection() {
-        return mSection;
+        return mAttachState.getSectionIndex();
     }
 
-    void setSection(int section) {
-        mSection = section;
+    @Nullable public NotifSection getNotifSection() {
+        return mAttachState.getSection();
+    }
+
+    ListAttachState getAttachState() {
+        return mAttachState;
+    }
+
+    ListAttachState getPreviousAttachState() {
+        return mPreviousAttachState;
+    }
+
+    /**
+     * Stores the current attach state into {@link #getPreviousAttachState()}} and then starts a
+     * fresh attach state (all entries will be null/default-initialized).
+     */
+    void beginNewAttachState() {
+        mPreviousAttachState.clone(mAttachState);
+        mAttachState.reset();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index c9cc670..9c2cac71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -504,6 +504,11 @@
                             extender));
         }
 
+        mLogger.logLifetimeExtensionEnded(
+                entry.getKey(),
+                extender,
+                entry.mLifetimeExtenders.size());
+
         if (!isLifetimeExtended(entry)) {
             if (tryRemoveNotification(entry)) {
                 dispatchEventsAndRebuildList();
@@ -529,6 +534,7 @@
         mAmDispatchingToOtherCode = true;
         for (NotifLifetimeExtender extender : mLifetimeExtenders) {
             if (extender.shouldExtendLifetime(entry, entry.mCancellationReason)) {
+                mLogger.logLifetimeExtended(entry.getKey(), extender);
                 entry.mLifetimeExtenders.add(extender);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 808e1b3..c1ba26d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -67,7 +67,6 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
 import com.android.systemui.statusbar.notification.row.NotificationGuts;
-import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
 
 import java.util.ArrayList;
@@ -105,18 +104,6 @@
     /** List of dismiss interceptors that are intercepting the dismissal of this notification. */
     final List<NotifDismissInterceptor> mDismissInterceptors = new ArrayList<>();
 
-    /** If this notification was filtered out, then the filter that did the filtering. */
-    @Nullable NotifFilter mExcludingFilter;
-
-    /**
-     * The NotifFilter, if any, that was active on this notification during the previous run of
-     * the list builder.
-     */
-    @Nullable NotifFilter mPreviousExcludingFilter;
-
-    /** If this was a group child that was promoted to the top level, then who did the promoting. */
-    @Nullable NotifPromoter mNotifPromoter;
-
     /**
      * If this notification was cancelled by system server, then the reason that was supplied.
      * Uncancelled notifications always have REASON_NOT_CANCELED. Note that lifetime-extended
@@ -149,7 +136,6 @@
      */
     public EditedSuggestionInfo editedSuggestionInfo;
 
-    private NotificationEntry parent; // our parent (if we're in a group)
     private ExpandableNotificationRow row; // the outer expanded view
     private ExpandableNotificationRowController mRowController;
 
@@ -283,6 +269,14 @@
         mDismissState = requireNonNull(dismissState);
     }
 
+    @Nullable public NotifFilter getExcludingFilter() {
+        return getAttachState().getExcludingFilter();
+    }
+
+    @Nullable public NotifPromoter getNotifPromoter() {
+        return getAttachState().getPromoter();
+    }
+
     /*
      * Convenience getters for SBN and Ranking members
      */
@@ -583,10 +577,6 @@
         if (row != null) row.resetUserExpansion();
     }
 
-    public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) {
-        if (row != null) row.freeContentViewWhenSafe(inflationFlag);
-    }
-
     public boolean rowExists() {
         return row != null;
     }
@@ -611,6 +601,13 @@
         return row != null && row.isPinned();
     }
 
+    /**
+     * Is this entry pinned and was expanded while doing so
+     */
+    public boolean isPinnedAndExpanded() {
+        return row != null && row.isPinnedAndExpanded();
+    }
+
     public void setRowPinned(boolean pinned) {
         if (row != null) row.setPinned(pinned);
     }
@@ -719,7 +716,7 @@
     }
 
     public boolean isChildInGroup() {
-        return parent == null;
+        return row != null && row.isChildInGroup();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 19f7cef..0a3b02c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -58,6 +58,7 @@
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -273,8 +274,6 @@
      * if we detect that behavior, we should crash instantly.
      */
     private void buildList() {
-        mLogger.logStartBuildList(mIterationCount);
-
         mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
         mPipelineState.setState(STATE_BUILD_STARTED);
 
@@ -316,21 +315,23 @@
 
         // Step 7: Lock in our group structure and log anything that's changed since the last run
         mPipelineState.incrementTo(STATE_FINALIZING);
-        logFilterChanges();
-        logParentingChanges();
+        logChanges();
         freeEmptyGroups();
 
         // Step 8: Dispatch the new list, first to any listeners and then to the view layer
-        if (mIterationCount % 10 == 0) {
-            mLogger.logFinalList(mNotifList);
-        }
         dispatchOnBeforeRenderList(mReadOnlyNotifList);
         if (mOnRenderListListener != null) {
             mOnRenderListListener.onRenderList(mReadOnlyNotifList);
         }
 
         // Step 9: We're done!
-        mLogger.logEndBuildList(mIterationCount);
+        mLogger.logEndBuildList(
+                mIterationCount,
+                mReadOnlyNotifList.size(),
+                countChildren(mReadOnlyNotifList));
+        if (mIterationCount % 10 == 0) {
+            mLogger.logFinalList(mNotifList);
+        }
         mPipelineState.setState(STATE_IDLE);
         mIterationCount++;
     }
@@ -354,18 +355,13 @@
 
     private void resetNotifs() {
         for (GroupEntry group : mGroups.values()) {
-            group.setPreviousParent(group.getParent());
-            group.setParent(null);
+            group.beginNewAttachState();
             group.clearChildren();
             group.setSummary(null);
         }
 
         for (NotificationEntry entry : mAllEntries) {
-            entry.setPreviousParent(entry.getParent());
-            entry.setParent(null);
-
-            entry.mPreviousExcludingFilter = entry.mExcludingFilter;
-            entry.mExcludingFilter = null;
+            entry.beginNewAttachState();
 
             if (entry.mFirstAddedIteration == -1) {
                 entry.mFirstAddedIteration = mIterationCount;
@@ -439,6 +435,7 @@
                         group.setSummary(entry);
                     } else {
                         mLogger.logDuplicateSummary(
+                                mIterationCount,
                                 group.getKey(),
                                 existingSummary.getKey(),
                                 entry.getKey());
@@ -460,7 +457,7 @@
 
                 final String topLevelKey = entry.getKey();
                 if (mGroups.containsKey(topLevelKey)) {
-                    mLogger.logDuplicateTopLevelKey(topLevelKey);
+                    mLogger.logDuplicateTopLevelKey(mIterationCount, topLevelKey);
                 } else {
                     entry.setParent(ROOT_ENTRY);
                     out.add(entry);
@@ -591,10 +588,10 @@
      * filtered out during any of the filtering steps.
      */
     private void annulAddition(ListEntry entry) {
-        // TODO: We should null out the entry's section and promoter here. However, if we do that,
-        //  future runs will think that the section changed. We need a mPreviousNotifSection,
-        //  similar to what we do for parents.
         entry.setParent(null);
+        entry.getAttachState().setSectionIndex(-1);
+        entry.getAttachState().setSection(null);
+        entry.getAttachState().setPromoter(null);
         if (entry.mFirstAddedIteration == mIterationCount) {
             entry.mFirstAddedIteration = -1;
         }
@@ -607,8 +604,8 @@
             if (entry instanceof GroupEntry) {
                 GroupEntry parent = (GroupEntry) entry;
                 for (NotificationEntry child : parent.getChildren()) {
-                    child.mNotifSection = sectionWithIndex.first;
-                    child.setSection(sectionWithIndex.second);
+                    child.getAttachState().setSection(sectionWithIndex.first);
+                    child.getAttachState().setSectionIndex(sectionWithIndex.second);
                 }
                 parent.sortChildren(sChildComparator);
             }
@@ -622,36 +619,52 @@
         mGroups.values().removeIf(ge -> ge.getSummary() == null && ge.getChildren().isEmpty());
     }
 
-    private void logFilterChanges() {
+    private void logChanges() {
         for (NotificationEntry entry : mAllEntries) {
-            if (entry.mExcludingFilter != entry.mPreviousExcludingFilter) {
-                mLogger.logFilterChanged(
-                        entry.getKey(),
-                        entry.mPreviousExcludingFilter,
-                        entry.mExcludingFilter);
-            }
+            logAttachStateChanges(entry);
+        }
+        for (GroupEntry group : mGroups.values()) {
+            logAttachStateChanges(group);
         }
     }
 
-    private void logParentingChanges() {
-        for (NotificationEntry entry : mAllEntries) {
-            if (entry.getParent() != entry.getPreviousParent()) {
-                mLogger.logParentChanged(
-                        entry.getKey(),
-                        entry.getPreviousParent() == null
-                                ? null : entry.getPreviousParent().getKey(),
-                        entry.getParent() == null
-                                ? null : entry.getParent().getKey());
+    private void logAttachStateChanges(ListEntry entry) {
+
+        final ListAttachState curr = entry.getAttachState();
+        final ListAttachState prev = entry.getPreviousAttachState();
+
+        if (!Objects.equals(curr, prev)) {
+            mLogger.logEntryAttachStateChanged(
+                    mIterationCount,
+                    entry.getKey(),
+                    prev.getParent(),
+                    curr.getParent());
+
+            if (curr.getParent() != prev.getParent()) {
+                mLogger.logParentChanged(mIterationCount, prev.getParent(), curr.getParent());
             }
-        }
-        for (GroupEntry group : mGroups.values()) {
-            if (group.getParent() != group.getPreviousParent()) {
-                mLogger.logParentChanged(
-                        group.getKey(),
-                        group.getPreviousParent() == null
-                                ? null : group.getPreviousParent().getKey(),
-                        group.getParent() == null
-                                ? null : group.getParent().getKey());
+
+            if (curr.getExcludingFilter() != prev.getExcludingFilter()) {
+                mLogger.logFilterChanged(
+                        mIterationCount, prev.getExcludingFilter(), curr.getExcludingFilter());
+            }
+
+            // When something gets detached, its promoter and section are always set to null, so
+            // don't bother logging those changes.
+            final boolean wasDetached = curr.getParent() == null && prev.getParent() != null;
+
+            if (!wasDetached && curr.getPromoter() != prev.getPromoter()) {
+                mLogger.logPromoterChanged(
+                        mIterationCount, prev.getPromoter(), curr.getPromoter());
+            }
+
+            if (!wasDetached && curr.getSection() != prev.getSection()) {
+                mLogger.logSectionChanged(
+                        mIterationCount,
+                        prev.getSection(),
+                        prev.getSectionIndex(),
+                        curr.getSection(),
+                        curr.getSectionIndex());
             }
         }
     }
@@ -698,8 +711,9 @@
     };
 
     private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) {
-        entry.mExcludingFilter = findRejectingFilter(entry, now, filters);
-        return entry.mExcludingFilter != null;
+        final NotifFilter filter = findRejectingFilter(entry, now, filters);
+        entry.getAttachState().setExcludingFilter(filter);
+        return filter != null;
     }
 
     @Nullable private static NotifFilter findRejectingFilter(NotificationEntry entry, long now,
@@ -717,15 +731,7 @@
 
     private boolean applyTopLevelPromoters(NotificationEntry entry) {
         NotifPromoter promoter = findPromoter(entry);
-
-        if (promoter != entry.mNotifPromoter) {
-            mLogger.logPromoterChanged(
-                    entry.getKey(),
-                    entry.mNotifPromoter != null ? entry.mNotifPromoter.getName() : null,
-                    promoter != null ? promoter.getName() : null);
-            entry.mNotifPromoter = promoter;
-        }
-
+        entry.getAttachState().setPromoter(promoter);
         return promoter != null;
     }
 
@@ -744,17 +750,8 @@
         final NotifSection section = sectionWithIndex.first;
         final Integer sectionIndex = sectionWithIndex.second;
 
-        if (section != entry.mNotifSection) {
-            mLogger.logSectionChanged(
-                    entry.getKey(),
-                    entry.mNotifSection != null ? entry.mNotifSection.getName() : null,
-                    entry.getSection(),
-                    section.getName(),
-                    sectionIndex);
-
-            entry.mNotifSection = section;
-            entry.setSection(sectionIndex);
-        }
+        entry.getAttachState().setSection(section);
+        entry.getAttachState().setSectionIndex(sectionIndex);
 
         return sectionWithIndex;
     }
@@ -776,6 +773,17 @@
         }
     }
 
+    private static int countChildren(List<ListEntry> entries) {
+        int count = 0;
+        for (int i = 0; i < entries.size(); i++) {
+            final ListEntry entry = entries.get(i);
+            if (entry instanceof GroupEntry) {
+                count += ((GroupEntry) entry).getChildren().size();
+            }
+        }
+        return count;
+    }
+
     private void dispatchOnBeforeTransformGroups(List<ListEntry> entries) {
         for (int i = 0; i < mOnBeforeTransformGroupsListeners.size(); i++) {
             mOnBeforeTransformGroupsListeners.get(i).onBeforeTransformGroups(entries);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
new file mode 100644
index 0000000..1bac938
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A coordinator that elevates important conversation notifications
+ */
+@Singleton
+class ConversationCoordinator @Inject constructor() : Coordinator {
+
+    private val notificationPromoter = object : NotifPromoter(TAG) {
+        override fun shouldPromoteToTopLevel(entry: NotificationEntry): Boolean {
+            return entry.channel?.isImportantConversation == true
+        }
+    }
+
+    override fun attach(pipeline: NotifPipeline) {
+        pipeline.addPromoter(notificationPromoter)
+    }
+
+    companion object {
+        private const val TAG = "ConversationCoordinator"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
index 573c129..2a3b2b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
+import static com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager.alertAgain;
 
 import android.annotation.Nullable;
 
@@ -28,6 +29,8 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpViewBinder;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
@@ -55,6 +58,8 @@
     private static final String TAG = "HeadsUpCoordinator";
 
     private final HeadsUpManager mHeadsUpManager;
+    private final HeadsUpViewBinder mHeadsUpViewBinder;
+    private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
     private final NotificationRemoteInputManager mRemoteInputManager;
 
     // tracks the current HeadUpNotification reported by HeadsUpManager
@@ -66,8 +71,12 @@
     @Inject
     public HeadsUpCoordinator(
             HeadsUpManager headsUpManager,
+            HeadsUpViewBinder headsUpViewBinder,
+            NotificationInterruptStateProvider notificationInterruptStateProvider,
             NotificationRemoteInputManager remoteInputManager) {
         mHeadsUpManager = headsUpManager;
+        mHeadsUpViewBinder = headsUpViewBinder;
+        mNotificationInterruptStateProvider = notificationInterruptStateProvider;
         mRemoteInputManager = remoteInputManager;
     }
 
@@ -84,8 +93,51 @@
         return mNotifSection;
     }
 
+    private void onHeadsUpViewBound(NotificationEntry entry) {
+        mHeadsUpManager.showNotification(entry);
+    }
+
     private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
         /**
+         * Notification was just added and if it should heads up, bind the view and then show it.
+         */
+        @Override
+        public void onEntryAdded(NotificationEntry entry) {
+            if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
+                mHeadsUpViewBinder.bindHeadsUpView(
+                        entry,
+                        HeadsUpCoordinator.this::onHeadsUpViewBound);
+            }
+        }
+
+        /**
+         * Notification could've updated to be heads up or not heads up. Even if it did update to
+         * heads up, if the notification specified that it only wants to alert once, don't heads
+         * up again.
+         */
+        @Override
+        public void onEntryUpdated(NotificationEntry entry) {
+            boolean hunAgain = alertAgain(entry, entry.getSbn().getNotification());
+            // includes check for whether this notification should be filtered:
+            boolean shouldHeadsUp = mNotificationInterruptStateProvider.shouldHeadsUp(entry);
+            final boolean wasHeadsUp = mHeadsUpManager.isAlerting(entry.getKey());
+            if (wasHeadsUp) {
+                if (shouldHeadsUp) {
+                    mHeadsUpManager.updateNotification(entry.getKey(), hunAgain);
+                } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.getKey())) {
+                    // We don't want this to be interrupting anymore, let's remove it
+                    mHeadsUpManager.removeNotification(
+                            entry.getKey(), false /* removeImmediately */);
+                }
+            } else if (shouldHeadsUp && hunAgain) {
+                // This notification was updated to be heads up, show it!
+                mHeadsUpViewBinder.bindHeadsUpView(
+                        entry,
+                        HeadsUpCoordinator.this::onHeadsUpViewBound);
+            }
+        }
+
+        /**
          * Stop alerting HUNs that are removed from the notification collection
          */
         @Override
@@ -98,6 +150,11 @@
                 mHeadsUpManager.removeNotification(entry.getKey(), removeImmediatelyForRemoteInput);
             }
         }
+
+        @Override
+        public void onEntryCleanUp(NotificationEntry entry) {
+            mHeadsUpViewBinder.abortBindCallback(entry);
+        }
     };
 
     private final NotifLifetimeExtender mLifetimeExtender = new NotifLifetimeExtender() {
@@ -153,6 +210,9 @@
                 mNotifPromoter.invalidateList();
                 mNotifSection.invalidateList();
             }
+            if (!isHeadsUp) {
+                mHeadsUpViewBinder.unbindHeadsUpView(entry);
+            }
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
index 03c0ae6..2b279bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -56,6 +56,7 @@
             DeviceProvisionedCoordinator deviceProvisionedCoordinator,
             BubbleCoordinator bubbleCoordinator,
             HeadsUpCoordinator headsUpCoordinator,
+            ConversationCoordinator conversationCoordinator,
             PreparationCoordinator preparationCoordinator) {
         dumpManager.registerDumpable(TAG, this);
         mCoordinators.add(new HideLocallyDismissedNotifsCoordinator());
@@ -66,6 +67,7 @@
         mCoordinators.add(deviceProvisionedCoordinator);
         mCoordinators.add(bubbleCoordinator);
         if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
+            mCoordinators.add(conversationCoordinator);
             mCoordinators.add(headsUpCoordinator);
             mCoordinators.add(preparationCoordinator);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 742615c..9973ef9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -33,9 +33,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
 import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -63,8 +61,6 @@
     private final NotifViewBarn mViewBarn;
     private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>();
     private final IStatusBarService mStatusBarService;
-    private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
-    private final HeadsUpManager mHeadsUpManager;
 
     @Inject
     public PreparationCoordinator(
@@ -72,9 +68,7 @@
             NotifInflaterImpl notifInflater,
             NotifInflationErrorManager errorManager,
             NotifViewBarn viewBarn,
-            IStatusBarService service,
-            NotificationInterruptStateProvider notificationInterruptStateProvider,
-            HeadsUpManager headsUpManager
+            IStatusBarService service
     ) {
         mLogger = logger;
         mNotifInflater = notifInflater;
@@ -83,8 +77,6 @@
         mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
         mViewBarn = viewBarn;
         mStatusBarService = service;
-        mNotificationInterruptStateProvider = notificationInterruptStateProvider;
-        mHeadsUpManager = headsUpManager;
     }
 
     @Override
@@ -158,11 +150,6 @@
             mLogger.logNotifInflated(entry.getKey());
             mViewBarn.registerViewForEntry(entry, entry.getRow());
             mInflationStates.put(entry, STATE_INFLATED);
-
-            // TODO: should eventually be moved to HeadsUpCoordinator
-            if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
-                mHeadsUpManager.showNotification(entry);
-            }
             mNotifInflatingFilter.invalidateList();
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 7237284..32f1822 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.notification.collection.inflation;
 
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
-
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -227,24 +225,17 @@
 
         final boolean useIncreasedCollapsedHeight =
                 mMessagingUtil.isImportantMessaging(sbn, entry.getImportance());
-        final boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight
-                && !mPresenter.isPresenterFullyCollapsed();
         final boolean isLowPriority = entry.isAmbient();
 
         RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
         params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
-        params.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
         params.setUseLowPriority(entry.isAmbient());
 
-        if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
-            params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
-        }
         //TODO: Replace this API with RowContentBindParams directly
         row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry));
         params.rebindAllContentViews();
         mRowContentBindStage.requestRebind(entry, en -> {
             row.setUsesIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
-            row.setUsesIncreasedHeadsUpHeight(useIncreasedHeadsUp);
             row.setIsLowPriority(isLowPriority);
             mInflationCallback.onAsyncInflationFinished(en);
         });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index e946cf1..aa10782 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -24,6 +24,8 @@
 import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.ListEntry
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection
 import javax.inject.Inject
 
 class ShadeListBuilderLogger @Inject constructor(
@@ -36,19 +38,13 @@
         })
     }
 
-    fun logStartBuildList(iterationCount: Int) {
+    fun logEndBuildList(iterationCount: Int, topLevelEntries: Int, numChildren: Int) {
         buffer.log(TAG, INFO, {
-            int1 = iterationCount
+            long1 = iterationCount.toLong()
+            int1 = topLevelEntries
+            int2 = numChildren
         }, {
-            "Starting to build shade list (run #$int1)"
-        })
-    }
-
-    fun logEndBuildList(iterationCount: Int) {
-        buffer.log(TAG, INFO, {
-            int1 = iterationCount
-        }, {
-            "Finished building shade list (run #$int1)"
+            "(Build $long1) Build complete ($int1 top-level entries, $int2 children)"
         })
     }
 
@@ -97,90 +93,115 @@
         })
     }
 
-    fun logDuplicateSummary(groupKey: String, existingKey: String, newKey: String) {
+    fun logDuplicateSummary(buildId: Int, groupKey: String, existingKey: String, newKey: String) {
         buffer.log(TAG, WARNING, {
+            int1 = buildId
             str1 = groupKey
             str2 = existingKey
             str3 = newKey
         }, {
-            """Duplicate summary for group "$str1": "$str2" vs. "$str3""""
+            """(Build $int1) Duplicate summary for group "$str1": "$str2" vs. "$str3""""
         })
     }
 
-    fun logDuplicateTopLevelKey(topLevelKey: String) {
+    fun logDuplicateTopLevelKey(buildId: Int, topLevelKey: String) {
         buffer.log(TAG, WARNING, {
+            int1 = buildId
             str1 = topLevelKey
         }, {
-            "Duplicate top-level key: $str1"
+            "(Build $int1) Duplicate top-level key: $str1"
         })
     }
 
-    fun logParentChanged(key: String, prevParent: String?, newParent: String?) {
+    fun logEntryAttachStateChanged(
+        buildId: Int,
+        key: String,
+        prevParent: GroupEntry?,
+        newParent: GroupEntry?
+    ) {
         buffer.log(TAG, INFO, {
+            int1 = buildId
             str1 = key
-            str2 = prevParent
-            str3 = newParent
+            str2 = prevParent?.key
+            str3 = newParent?.key
         }, {
-            "Parent change for $str1: $str2 -> $str3"
+            if (str2 == null && str3 != null) {
+                "(Build $int1) ATTACHED {$str1}"
+            } else if (str2 != null && str3 == null) {
+                "(Build $int1) DETACHED {$str1}"
+            } else {
+                "(Build $int1) MODIFIED {$str1}"
+            }
+        })
+    }
+
+    fun logParentChanged(buildId: Int, prevParent: GroupEntry?, newParent: GroupEntry?) {
+        buffer.log(TAG, INFO, {
+            int1 = buildId
+            str1 = prevParent?.key
+            str2 = newParent?.key
+        }, {
+            if (str1 == null && str2 != null) {
+                "(Build $int1)     Parent is {$str2}"
+            } else if (str1 != null && str2 == null) {
+                "(Build $int1)     Parent was {$str1}"
+            } else {
+                "(Build $int1)     Reparent: {$str2} -> {$str3}"
+            }
         })
     }
 
     fun logFilterChanged(
-        key: String,
+        buildId: Int,
         prevFilter: NotifFilter?,
         newFilter: NotifFilter?
     ) {
         buffer.log(TAG, INFO, {
-            str1 = key
-            str2 = prevFilter?.name
-            str3 = newFilter?.name
+            int1 = buildId
+            str1 = prevFilter?.name
+            str2 = newFilter?.name
         }, {
-            "Filter changed for $str1: $str2 -> $str3"
+            "(Build $int1)     Filter changed: $str1 -> $str2"
         })
     }
 
     fun logPromoterChanged(
-        key: String,
-        prevPromoter: String?,
-        newPromoter: String?
+        buildId: Int,
+        prevPromoter: NotifPromoter?,
+        newPromoter: NotifPromoter?
     ) {
         buffer.log(TAG, INFO, {
-            str1 = key
-            str2 = prevPromoter
-            str3 = newPromoter
+            int1 = buildId
+            str1 = prevPromoter?.name
+            str2 = newPromoter?.name
         }, {
-            "Promoter changed for $str1: $str2 -> $str3"
+            "(Build $int1)     Promoter changed: $str1 -> $str2"
         })
     }
 
     fun logSectionChanged(
-        key: String,
-        prevSection: String?,
+        buildId: Int,
+        prevSection: NotifSection?,
         prevIndex: Int,
-        section: String,
-        index: Int
+        newSection: NotifSection?,
+        newIndex: Int
     ) {
         buffer.log(TAG, INFO, {
-            str1 = key
-            str2 = section
-            int1 = index
-            str3 = prevSection
-            int2 = prevIndex
+            long1 = buildId.toLong()
+            str1 = prevSection?.name
+            int1 = prevIndex
+            str2 = newSection?.name
+            int2 = newIndex
         }, {
-            if (str3 == null) {
-                "Section assigned for $str1: '$str2' (#$int1)"
+            if (str1 == null) {
+                "(Build $long1)     Section assigned: '$str2' (#$int2)"
             } else {
-                "Section changed for $str1: '$str3' (#$int2) -> '$str2' (#$int1)"
+                "(Build $long1)     Section changed: '$str1' (#$int1) -> '$str2' (#$int2)"
             }
         })
     }
 
     fun logFinalList(entries: List<ListEntry>) {
-        buffer.log(TAG, DEBUG, {
-            int1 = entries.size
-        }, {
-            "List is finalized ($int1 top-level entries):"
-        })
         if (entries.isEmpty()) {
             buffer.log(TAG, DEBUG, {}, { "(empty list)" })
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index 0c0cded..41ca52d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -74,7 +74,9 @@
      * non-lifetime-extended notification entries will have their ranking object updated.
      *
      * Ranking updates occur whenever a notification is added, updated, or removed, or when a
-     * standalone ranking is sent from the server.
+     * standalone ranking is sent from the server. If a non-standalone ranking is applied, the event
+     * that accompanied the ranking is emitted first (e.g. {@link #onEntryAdded}), followed by the
+     * ranking event.
      */
     default void onRankingApplied() {
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index ef302f6..c69882d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -111,6 +111,29 @@
             "RemoteException while attempting to clear all notifications:\n$str1"
         })
     }
+
+    fun logLifetimeExtended(key: String, extender: NotifLifetimeExtender) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = extender.name
+        }, {
+            "LIFETIME EXTENDED: $str1 by $str2"
+        })
+    }
+
+    fun logLifetimeExtensionEnded(
+        key: String,
+        extender: NotifLifetimeExtender,
+        totalExtenders: Int
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = extender.name
+            int1 = totalExtenders
+        }, {
+            "LIFETIME EXTENSION ENDED for $str1 by '$str2'; $int1 remaining extensions"
+        })
+    }
 }
 
 private const val TAG = "NotifCollection"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpBindController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpBindController.java
new file mode 100644
index 0000000..a7b1f37
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpBindController.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.headsup;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Controller class for old pipeline heads up view binding. It listens to
+ * {@link NotificationEntryManager} entry events and appropriately binds or unbinds the heads up
+ * view.
+ *
+ * This has a subtle contract with {@link NotificationAlertingManager} where this controller handles
+ * the heads up binding, but {@link NotificationAlertingManager} listens for general inflation
+ * events to actually mark it heads up/update. In the new pipeline, we combine the classes.
+ * See {@link HeadsUpCoordinator}.
+ */
+@Singleton
+public class HeadsUpBindController {
+    private final HeadsUpViewBinder mHeadsUpViewBinder;
+    private final NotificationInterruptStateProvider mInterruptStateProvider;
+
+    @Inject
+    HeadsUpBindController(
+            HeadsUpViewBinder headsUpViewBinder,
+            NotificationInterruptStateProvider notificationInterruptStateProvider) {
+        mInterruptStateProvider = notificationInterruptStateProvider;
+        mHeadsUpViewBinder = headsUpViewBinder;
+    }
+
+    /**
+     * Attach this controller and add its listeners.
+     */
+    public void attach(
+            NotificationEntryManager entryManager,
+            HeadsUpManager headsUpManager) {
+        entryManager.addCollectionListener(mCollectionListener);
+        headsUpManager.addListener(mOnHeadsUpChangedListener);
+    }
+
+    private NotifCollectionListener mCollectionListener = new NotifCollectionListener() {
+        @Override
+        public void onEntryAdded(NotificationEntry entry) {
+            if (mInterruptStateProvider.shouldHeadsUp(entry)) {
+                mHeadsUpViewBinder.bindHeadsUpView(entry, null);
+            }
+        }
+
+        @Override
+        public void onEntryUpdated(NotificationEntry entry) {
+            if (mInterruptStateProvider.shouldHeadsUp(entry)) {
+                mHeadsUpViewBinder.bindHeadsUpView(entry, null);
+            }
+        }
+
+        @Override
+        public void onEntryCleanUp(NotificationEntry entry) {
+            mHeadsUpViewBinder.abortBindCallback(entry);
+        }
+    };
+
+    private OnHeadsUpChangedListener mOnHeadsUpChangedListener  = new OnHeadsUpChangedListener() {
+        @Override
+        public void onHeadsUpStateChanged(@NonNull NotificationEntry entry, boolean isHeadsUp) {
+            if (!isHeadsUp) {
+                mHeadsUpViewBinder.unbindHeadsUpView(entry);
+            }
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpViewBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpViewBinder.java
new file mode 100644
index 0000000..37acfa8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpViewBinder.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.headsup;
+
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
+
+import android.util.ArrayMap;
+
+import androidx.annotation.Nullable;
+import androidx.core.os.CancellationSignal;
+
+import com.android.internal.util.NotificationMessagingUtil;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator;
+import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
+import com.android.systemui.statusbar.notification.row.RowContentBindParams;
+import com.android.systemui.statusbar.notification.row.RowContentBindStage;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Wrapper around heads up view binding logic. {@link HeadsUpViewBinder} is responsible for
+ * figuring out the right heads up inflation parameters and inflating/freeing the heads up
+ * content view.
+ *
+ * TODO: This should be moved into {@link HeadsUpCoordinator} when the old pipeline is deprecated
+ * (i.e. when {@link HeadsUpBindController} is removed).
+ */
+@Singleton
+public class HeadsUpViewBinder {
+    private final RowContentBindStage mStage;
+    private final NotificationMessagingUtil mNotificationMessagingUtil;
+    private final Map<NotificationEntry, CancellationSignal> mOngoingBindCallbacks =
+            new ArrayMap<>();
+
+    private NotificationPresenter mNotificationPresenter;
+
+    @Inject
+    HeadsUpViewBinder(
+            NotificationMessagingUtil notificationMessagingUtil,
+            RowContentBindStage bindStage) {
+        mNotificationMessagingUtil = notificationMessagingUtil;
+        mStage = bindStage;
+    }
+
+    /**
+     * Set notification presenter to determine parameters for heads up view inflation.
+     */
+    public void setPresenter(NotificationPresenter presenter) {
+        mNotificationPresenter = presenter;
+    }
+
+    /**
+     * Bind heads up view to the notification row.
+     * @param callback callback after heads up view is bound
+     */
+    public void bindHeadsUpView(NotificationEntry entry, @Nullable BindCallback callback) {
+        RowContentBindParams params = mStage.getStageParams(entry);
+        final boolean isImportantMessage = mNotificationMessagingUtil.isImportantMessaging(
+                entry.getSbn(), entry.getImportance());
+        final boolean useIncreasedHeadsUp = isImportantMessage
+                && !mNotificationPresenter.isPresenterFullyCollapsed();
+        params.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
+        params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
+        CancellationSignal signal = mStage.requestRebind(entry, en -> {
+            en.getRow().setUsesIncreasedHeadsUpHeight(params.useIncreasedHeadsUpHeight());
+            if (callback != null) {
+                callback.onBindFinished(en);
+            }
+        });
+        abortBindCallback(entry);
+        mOngoingBindCallbacks.put(entry, signal);
+    }
+
+    /**
+     * Abort any callbacks waiting for heads up view binding to finish for a given notification.
+     * @param entry notification with bind in progress
+     */
+    public void abortBindCallback(NotificationEntry entry) {
+        CancellationSignal ongoingBindCallback = mOngoingBindCallbacks.remove(entry);
+        if (ongoingBindCallback != null) {
+            ongoingBindCallback.cancel();
+        }
+    }
+
+    /**
+     * Unbind the heads up view from the notification row.
+     */
+    public void unbindHeadsUpView(NotificationEntry entry) {
+        abortBindCallback(entry);
+        mStage.getStageParams(entry).markContentViewsFreeable(FLAG_CONTENT_VIEW_HEADS_UP);
+        mStage.requestRebind(entry, null);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 7a7178c..d1cceae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.statusbar.notification.NotificationListController
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
 import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
+import com.android.systemui.statusbar.notification.headsup.HeadsUpBindController
 import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper
@@ -35,6 +36,7 @@
 import com.android.systemui.statusbar.phone.StatusBar
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.statusbar.notification.headsup.HeadsUpViewBinder
 import com.android.systemui.statusbar.policy.RemoteInputUriController
 import dagger.Lazy
 import java.io.FileDescriptor
@@ -63,7 +65,9 @@
     private val bubbleController: BubbleController,
     private val groupManager: NotificationGroupManager,
     private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper,
-    private val headsUpManager: HeadsUpManager
+    private val headsUpManager: HeadsUpManager,
+    private val headsUpBindController: HeadsUpBindController,
+    private val headsUpViewBinder: HeadsUpViewBinder
 ) : NotificationsController {
 
     override fun initialize(
@@ -91,6 +95,7 @@
                 presenter,
                 listContainer,
                 bindRowCallback)
+        headsUpViewBinder.setPresenter(presenter)
         notifBindPipelineInitializer.initialize()
 
         if (featureFlags.isNewNotifPipelineEnabled) {
@@ -109,6 +114,7 @@
             groupAlertTransferHelper.bind(entryManager, groupManager)
             headsUpManager.addListener(groupManager)
             headsUpManager.addListener(groupAlertTransferHelper)
+            headsUpBindController.attach(entryManager, headsUpManager)
             groupManager.setHeadsUpManager(headsUpManager)
             groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java
index b572502..5d07098 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification.interruption;
 
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
 
 import android.app.Notification;
 import android.service.notification.StatusBarNotification;
@@ -95,16 +94,10 @@
         // TODO: Instead of this back and forth, we should listen to changes in heads up and
         // cancel on-going heads up view inflation using the bind pipeline.
         if (entry.getRow().getPrivateLayout().getHeadsUpChild() != null) {
-            // Possible for shouldHeadsUp to change between the inflation starting and ending.
-            // If it does and we no longer need to heads up, we should free the view.
-            if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
-                mHeadsUpManager.showNotification(entry);
-                if (!mStatusBarStateController.isDozing()) {
-                    // Mark as seen immediately
-                    setNotificationShown(entry.getSbn());
-                }
-            } else {
-                entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
+            mHeadsUpManager.showNotification(entry);
+            if (!mStatusBarStateController.isDozing()) {
+                // Mark as seen immediately
+                setNotificationShown(entry.getSbn());
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index be3873a..5879c15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -83,9 +83,9 @@
 
     private val Ranking.personTypeInfo
         get() = when {
+            !isConversation -> TYPE_NON_PERSON
             channel?.isImportantConversation == true -> TYPE_IMPORTANT_PERSON
-            isConversation -> TYPE_PERSON
-            else -> TYPE_NON_PERSON
+            else -> TYPE_PERSON
         }
 
     private fun extractPersonTypeInfo(sbn: StatusBarNotification) =
@@ -96,7 +96,7 @@
             return TYPE_NON_PERSON
         }
 
-        val childTypes = groupManager.getLogicalChildren(statusBarNotification)
+        val childTypes = groupManager.getChildren(statusBarNotification)
                 ?.asSequence()
                 ?.map { getPeopleNotificationType(it.sbn, it.ranking) }
                 ?: return TYPE_NON_PERSON
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 19b5f5c..5c578df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -17,12 +17,7 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_EXPANDED;
 import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
 
 import android.animation.Animator;
@@ -89,6 +84,7 @@
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.logging.NotificationCounters;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
@@ -148,6 +144,7 @@
     private KeyguardBypassController mBypassController;
     private LayoutListener mLayoutListener;
     private RowContentBindStage mRowContentBindStage;
+    private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
     private int mIconTransformContentShift;
     private int mMaxHeadsUpHeightBeforeN;
     private int mMaxHeadsUpHeightBeforeP;
@@ -287,6 +284,12 @@
                 if (isPinned()) {
                     nowExpanded = !mExpandedWhenPinned;
                     mExpandedWhenPinned = nowExpanded;
+                    // Also notify any expansion changed listeners. This is necessary since the
+                    // expansion doesn't actually change (it's already system expanded) but it
+                    // changes visually
+                    if (mExpansionChangedListener != null) {
+                        mExpansionChangedListener.onExpansionChanged(nowExpanded);
+                    }
                 } else {
                     nowExpanded = !isExpanded();
                     setUserExpanded(nowExpanded);
@@ -329,6 +332,7 @@
     private NotificationInlineImageResolver mImageResolver;
     private NotificationMediaManager mMediaManager;
     @Nullable private OnExpansionChangedListener mExpansionChangedListener;
+    @Nullable private Runnable mOnIntrinsicHeightReachedRunnable;
 
     private SystemNotificationAsyncTask mSystemNotificationAsyncTask =
             new SystemNotificationAsyncTask();
@@ -361,6 +365,16 @@
         return Arrays.copyOf(mLayouts, mLayouts.length);
     }
 
+    /**
+     * Is this entry pinned and was expanded while doing so
+     */
+    public boolean isPinnedAndExpanded() {
+        if (!isPinned()) {
+            return false;
+        }
+        return mExpandedWhenPinned;
+    }
+
     @Override
     public boolean isGroupExpansionChanging() {
         if (isChildInGroup()) {
@@ -461,41 +475,16 @@
      * Marks a content view as freeable, setting it so that future inflations do not reinflate
      * and ensuring that the view is freed when it is safe to remove.
      *
-     * TODO: This should be moved to the respective coordinator and call
-     * {@link RowContentBindParams#freeContentViews} directly after disappear animation
-     * finishes instead of depending on binding API to know when it's "safe".
-     *
      * @param inflationFlag flag corresponding to the content view to be freed
+     * @deprecated By default, {@link NotificationContentInflater#unbindContent} will tell the
+     * view hierarchy to only free when the view is safe to remove so this method is no longer
+     * needed. Will remove when all uses are gone.
      */
+    @Deprecated
     public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) {
-        // View should not be reinflated in the future
-        Runnable freeViewRunnable = () -> {
-            // Possible for notification to be removed after free request.
-            if (!isRemoved()) {
-                RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry);
-                params.freeContentViews(inflationFlag);
-                mRowContentBindStage.requestRebind(mEntry, null /* callback */);
-            }
-        };
-        switch (inflationFlag) {
-            case FLAG_CONTENT_VIEW_CONTRACTED:
-                getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_CONTRACTED,
-                        freeViewRunnable);
-                break;
-            case FLAG_CONTENT_VIEW_EXPANDED:
-                getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_EXPANDED,
-                        freeViewRunnable);
-                break;
-            case FLAG_CONTENT_VIEW_HEADS_UP:
-                getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_HEADSUP,
-                        freeViewRunnable);
-                break;
-            case FLAG_CONTENT_VIEW_PUBLIC:
-                getPublicLayout().performWhenContentInactive(VISIBLE_TYPE_CONTRACTED,
-                        freeViewRunnable);
-            default:
-                break;
-        }
+        RowContentBindParams params = mRowContentBindStage.getStageParams(mEntry);
+        params.markContentViewsFreeable(inflationFlag);
+        mRowContentBindStage.requestRebind(mEntry, null /* callback */);
     }
 
     /**
@@ -1145,7 +1134,7 @@
     @Override
     public void onPluginDisconnected(NotificationMenuRowPlugin plugin) {
         boolean existed = mMenuRow.getMenuView() != null;
-        mMenuRow = new NotificationMenuRow(mContext);
+        mMenuRow = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         if (existed) {
             createMenu();
         }
@@ -1569,7 +1558,7 @@
                 if (needsRedaction) {
                     params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
                 } else {
-                    params.freeContentViews(FLAG_CONTENT_VIEW_PUBLIC);
+                    params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
                 }
                 mRowContentBindStage.requestRebind(mEntry, null /* callback */);
             }
@@ -1582,7 +1571,6 @@
 
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mMenuRow = new NotificationMenuRow(mContext);
         mImageResolver = new NotificationInlineImageResolver(context,
                 new NotificationInlineImageCache());
         initDimens();
@@ -1603,9 +1591,13 @@
             NotificationMediaManager notificationMediaManager,
             OnAppOpsClickListener onAppOpsClickListener,
             FalsingManager falsingManager,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            PeopleNotificationIdentifier peopleNotificationIdentifier) {
         mAppName = appName;
-        if (mMenuRow != null && mMenuRow.getMenuView() != null) {
+        if (mMenuRow == null) {
+            mMenuRow = new NotificationMenuRow(mContext, peopleNotificationIdentifier);
+        }
+        if (mMenuRow.getMenuView() != null) {
             mMenuRow.setAppName(mAppName);
         }
         mLogger = logger;
@@ -1620,6 +1612,7 @@
         setAppOpsOnClickListener(onAppOpsClickListener);
         mFalsingManager = falsingManager;
         mStatusbarStateController = statusBarStateController;
+        mPeopleNotificationIdentifier = peopleNotificationIdentifier;
     }
 
     private void initDimens() {
@@ -2714,6 +2707,7 @@
         if (mMenuRow != null && mMenuRow.getMenuView() != null) {
             mMenuRow.onParentHeightUpdate();
         }
+        handleIntrinsicHeightReached();
     }
 
     @Override
@@ -2931,6 +2925,24 @@
         mExpansionChangedListener = listener;
     }
 
+    /**
+     * Perform an action when the notification height has reached its intrinsic height.
+     *
+     * @param runnable the runnable to run
+     */
+    public void performOnIntrinsicHeightReached(@Nullable Runnable runnable) {
+        mOnIntrinsicHeightReachedRunnable = runnable;
+        handleIntrinsicHeightReached();
+    }
+
+    private void handleIntrinsicHeightReached() {
+        if (mOnIntrinsicHeightReachedRunnable != null
+                && getActualHeight() == getIntrinsicHeight()) {
+            mOnIntrinsicHeightReachedRunnable.run();
+            mOnIntrinsicHeightReachedRunnable = null;
+        }
+    }
+
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 39fab43..8b3d06b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -28,6 +28,7 @@
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.dagger.AppName;
 import com.android.systemui.statusbar.notification.row.dagger.DismissRunnable;
 import com.android.systemui.statusbar.notification.row.dagger.NotificationKey;
@@ -68,6 +69,7 @@
     private Runnable mOnDismissRunnable;
     private final FalsingManager mFalsingManager;
     private final boolean mAllowLongPress;
+    private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     @Inject
     public ExpandableNotificationRowController(ExpandableNotificationRow view,
@@ -83,7 +85,8 @@
             NotificationRowContentBinder.InflationCallback inflationCallback,
             NotificationGutsManager notificationGutsManager,
             @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
-            @DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager) {
+            @DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager,
+            PeopleNotificationIdentifier peopleNotificationIdentifier) {
         mView = view;
         mActivatableNotificationViewController = activatableNotificationViewController;
         mMediaManager = mediaManager;
@@ -104,6 +107,7 @@
         mOnAppOpsClickListener = mNotificationGutsManager::openGuts;
         mAllowLongPress = allowLongPress;
         mFalsingManager = falsingManager;
+        mPeopleNotificationIdentifier = peopleNotificationIdentifier;
     }
 
     /**
@@ -123,7 +127,8 @@
                 mMediaManager,
                 mOnAppOpsClickListener,
                 mFalsingManager,
-                mStatusBarStateController
+                mStatusBarStateController,
+                mPeopleNotificationIdentifier
         );
         mView.setOnDismissRunnable(mOnDismissRunnable);
         mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java
index d744fc3..e4e3ebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.widget.FrameLayout;
@@ -25,12 +28,15 @@
 import androidx.annotation.Nullable;
 import androidx.core.os.CancellationSignal;
 
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -75,14 +81,18 @@
 public final class NotifBindPipeline {
     private final Map<NotificationEntry, BindEntry> mBindEntries = new ArrayMap<>();
     private final NotifBindPipelineLogger mLogger;
+    private final List<BindCallback> mScratchCallbacksList = new ArrayList<>();
+    private final Handler mMainHandler;
     private BindStage mStage;
 
     @Inject
     NotifBindPipeline(
             CommonNotifCollection collection,
-            NotifBindPipelineLogger logger) {
+            NotifBindPipelineLogger logger,
+            @Main Looper mainLooper) {
         collection.addCollectionListener(mCollectionListener);
         mLogger = logger;
+        mMainHandler = new NotifBindPipelineHandler(mainLooper);
     }
 
     /**
@@ -107,7 +117,7 @@
         final BindEntry bindEntry = getBindEntry(entry);
         bindEntry.row = row;
         if (bindEntry.invalidated) {
-            startPipeline(entry);
+            requestPipelineRun(entry);
         }
     }
 
@@ -130,7 +140,31 @@
             signal.setOnCancelListener(() -> callbacks.remove(callback));
         }
 
-        startPipeline(entry);
+        requestPipelineRun(entry);
+    }
+
+    /**
+     * Request pipeline to start.
+     *
+     * We avoid starting the pipeline immediately as multiple clients may request rebinds
+     * back-to-back due to a single change (e.g. notification update), and it's better to start
+     * the real work once rather than repeatedly start and cancel it.
+     */
+    private void requestPipelineRun(NotificationEntry entry) {
+        final BindEntry bindEntry = getBindEntry(entry);
+        if (bindEntry.row == null) {
+            // Row is not managed yet but may be soon. Stop for now.
+            return;
+        }
+        mLogger.logRequestPipelineRun(entry.getKey());
+
+        // Abort any existing pipeline run
+        mStage.abortStage(entry, bindEntry.row);
+
+        if (!mMainHandler.hasMessages(START_PIPELINE_MSG, entry)) {
+            Message msg = Message.obtain(mMainHandler, START_PIPELINE_MSG, entry);
+            mMainHandler.sendMessage(msg);
+        }
     }
 
     /**
@@ -146,12 +180,7 @@
 
         final BindEntry bindEntry = mBindEntries.get(entry);
         final ExpandableNotificationRow row = bindEntry.row;
-        if (row == null) {
-            // Row is not managed yet but may be soon. Stop for now.
-            return;
-        }
 
-        mStage.abortStage(entry, row);
         mStage.executeStage(entry, row, (en) -> onPipelineComplete(en));
     }
 
@@ -162,10 +191,15 @@
         mLogger.logFinishedPipeline(entry.getKey(), callbacks.size());
 
         bindEntry.invalidated = false;
-        for (BindCallback cb : callbacks) {
-            cb.onBindFinished(entry);
-        }
+        // Move all callbacks to separate list as callbacks may themselves add/remove callbacks.
+        // TODO: Throw an exception for this re-entrant behavior once we deprecate
+        // NotificationGroupAlertTransferHelper
+        mScratchCallbacksList.addAll(callbacks);
         callbacks.clear();
+        for (int i = 0; i < mScratchCallbacksList.size(); i++) {
+            mScratchCallbacksList.get(i).onBindFinished(entry);
+        }
+        mScratchCallbacksList.clear();
     }
 
     private final NotifCollectionListener mCollectionListener = new NotifCollectionListener() {
@@ -183,6 +217,7 @@
                 mStage.abortStage(entry, row);
             }
             mStage.deleteStageParams(entry);
+            mMainHandler.removeMessages(START_PIPELINE_MSG, entry);
         }
     };
 
@@ -211,4 +246,25 @@
         public final Set<BindCallback> callbacks = new ArraySet<>();
         public boolean invalidated;
     }
+
+    private static final int START_PIPELINE_MSG = 1;
+
+    private class NotifBindPipelineHandler extends Handler {
+
+        NotifBindPipelineHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case START_PIPELINE_MSG:
+                    NotificationEntry entry = (NotificationEntry) msg.obj;
+                    startPipeline(entry);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown message type: " + msg.what);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
index 2717d7a..1997304 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
@@ -40,6 +40,14 @@
         })
     }
 
+    fun logRequestPipelineRun(notifKey: String) {
+        buffer.log(TAG, INFO, {
+            str1 = notifKey
+        }, {
+            "Request pipeline run for notif: $str1"
+        })
+    }
+
     fun logStartPipeline(notifKey: String) {
         buffer.log(TAG, INFO, {
             str1 = notifKey
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 719f74f..9d54437 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -118,6 +118,9 @@
             mRemoteViewCache.clearCache(entry);
         }
 
+        // Cancel any pending frees on any view we're trying to bind since we should be bound after.
+        cancelContentViewFrees(row, contentToBind);
+
         AsyncInflationTask task = new AsyncInflationTask(
                 mBgExecutor,
                 mInflateSynchronously,
@@ -198,44 +201,69 @@
     }
 
     /**
-     * Frees the content view associated with the inflation flag.  Will only succeed if the
-     * view is safe to remove.
+     * Frees the content view associated with the inflation flag as soon as the view is not showing.
      *
      * @param inflateFlag the flag corresponding to the content view which should be freed
      */
-    private void freeNotificationView(NotificationEntry entry, ExpandableNotificationRow row,
+    private void freeNotificationView(
+            NotificationEntry entry,
+            ExpandableNotificationRow row,
             @InflationFlag int inflateFlag) {
         switch (inflateFlag) {
             case FLAG_CONTENT_VIEW_CONTRACTED:
-                if (row.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) {
+                row.getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_CONTRACTED, () -> {
                     row.getPrivateLayout().setContractedChild(null);
                     mRemoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_CONTRACTED);
-                }
+                });
                 break;
             case FLAG_CONTENT_VIEW_EXPANDED:
-                if (row.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_EXPANDED)) {
+                row.getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_EXPANDED, () -> {
                     row.getPrivateLayout().setExpandedChild(null);
                     mRemoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_EXPANDED);
-                }
+                });
                 break;
             case FLAG_CONTENT_VIEW_HEADS_UP:
-                if (row.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) {
+                row.getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_HEADSUP, () -> {
                     row.getPrivateLayout().setHeadsUpChild(null);
                     mRemoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_HEADS_UP);
                     row.getPrivateLayout().setHeadsUpInflatedSmartReplies(null);
-                }
+                });
                 break;
             case FLAG_CONTENT_VIEW_PUBLIC:
-                if (row.getPublicLayout().isContentViewInactive(VISIBLE_TYPE_CONTRACTED)) {
+                row.getPublicLayout().performWhenContentInactive(VISIBLE_TYPE_CONTRACTED, () -> {
                     row.getPublicLayout().setContractedChild(null);
                     mRemoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_PUBLIC);
-                }
+                });
                 break;
             default:
                 break;
         }
     }
 
+    /**
+     * Cancel any pending content view frees from {@link #freeNotificationView} for the provided
+     * content views.
+     *
+     * @param row top level notification row containing the content views
+     * @param contentViews content views to cancel pending frees on
+     */
+    private void cancelContentViewFrees(
+            ExpandableNotificationRow row,
+            @InflationFlag int contentViews) {
+        if ((contentViews & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
+            row.getPrivateLayout().removeContentInactiveRunnable(VISIBLE_TYPE_CONTRACTED);
+        }
+        if ((contentViews & FLAG_CONTENT_VIEW_EXPANDED) != 0) {
+            row.getPrivateLayout().removeContentInactiveRunnable(VISIBLE_TYPE_EXPANDED);
+        }
+        if ((contentViews & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
+            row.getPrivateLayout().removeContentInactiveRunnable(VISIBLE_TYPE_HEADSUP);
+        }
+        if ((contentViews & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
+            row.getPublicLayout().removeContentInactiveRunnable(VISIBLE_TYPE_CONTRACTED);
+        }
+    }
+
     private static InflationProgress inflateSmartReplyViews(InflationProgress result,
             @InflationFlag int reInflateFlags, NotificationEntry entry, Context context,
             Context packageContext, HeadsUpManager headsUpManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 8efdc1b..3c3f1b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.PendingIntent;
@@ -385,6 +386,7 @@
      */
     public void setContractedChild(@Nullable View child) {
         if (mContractedChild != null) {
+            mOnContentViewInactiveListeners.remove(mContractedChild);
             mContractedChild.animate().cancel();
             removeView(mContractedChild);
         }
@@ -432,6 +434,7 @@
                     ((ViewGroup)mExpandedRemoteInput.getParent()).removeView(mExpandedRemoteInput);
                 }
             }
+            mOnContentViewInactiveListeners.remove(mExpandedChild);
             mExpandedChild.animate().cancel();
             removeView(mExpandedChild);
             mExpandedRemoteInput = null;
@@ -470,6 +473,7 @@
                     ((ViewGroup)mHeadsUpRemoteInput.getParent()).removeView(mHeadsUpRemoteInput);
                 }
             }
+            mOnContentViewInactiveListeners.remove(mHeadsUpChild);
             mHeadsUpChild.animate().cancel();
             removeView(mHeadsUpChild);
             mHeadsUpRemoteInput = null;
@@ -985,6 +989,14 @@
         }
     }
 
+    public @NonNull View[] getAllViews() {
+        return new View[] {
+                mContractedChild,
+                mHeadsUpChild,
+                mExpandedChild,
+                mSingleLineView };
+    }
+
     public NotificationViewWrapper getVisibleWrapper(int visibleType) {
         switch (visibleType) {
             case VISIBLE_TYPE_EXPANDED:
@@ -1108,7 +1120,6 @@
 
     public void onNotificationUpdated(NotificationEntry entry) {
         mStatusBarNotification = entry.getSbn();
-        mOnContentViewInactiveListeners.clear();
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateAllSingleLineViews();
         ExpandableNotificationRow row = entry.getRow();
@@ -1623,7 +1634,7 @@
      * @param visibleType visible type corresponding to the content view to listen
      * @param listener runnable to run once when the content view becomes inactive
      */
-    public void performWhenContentInactive(int visibleType, Runnable listener) {
+    void performWhenContentInactive(int visibleType, Runnable listener) {
         View view = getViewForVisibleType(visibleType);
         // View is already inactive
         if (view == null || isContentViewInactive(visibleType)) {
@@ -1634,6 +1645,22 @@
     }
 
     /**
+     * Remove content inactive listeners for a given content view . See
+     * {@link #performWhenContentInactive}.
+     *
+     * @param visibleType visible type corresponding to the content type
+     */
+    void removeContentInactiveRunnable(int visibleType) {
+        View view = getViewForVisibleType(visibleType);
+        // View is already inactive
+        if (view == null) {
+            return;
+        }
+
+        mOnContentViewInactiveListeners.remove(view);
+    }
+
+    /**
      * Whether or not the content view is inactive.  This means it should not be visible
      * or the showing content as removing it would cause visual jank.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 8e2bfb8..6fc1264 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -20,7 +20,6 @@
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
 
 import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
 
@@ -44,7 +43,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.transition.ChangeBounds;
@@ -56,15 +54,12 @@
 import android.util.Slog;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
-import android.widget.Button;
-import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.notification.ConversationIconFactory;
-import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
@@ -517,7 +512,6 @@
         bgHandler.post(
                 new UpdateChannelRunnable(mINotificationManager, mPackageName,
                         mAppUid, mSelectedAction, mNotificationChannel));
-        mVisualStabilityManager.temporarilyAllowReordering();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 212cba6..83a6eb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -45,8 +45,9 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.AlphaOptimizedImageView;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
@@ -114,12 +115,16 @@
 
     private boolean mIsUserTouching;
 
-    public NotificationMenuRow(Context context) {
+    private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
+
+    public NotificationMenuRow(Context context,
+            PeopleNotificationIdentifier peopleNotificationIdentifier) {
         mContext = context;
         mShouldShowMenu = context.getResources().getBoolean(R.bool.config_showNotificationGear);
         mHandler = new Handler(Looper.getMainLooper());
         mLeftMenuItems = new ArrayList<>();
         mRightMenuItems = new ArrayList<>();
+        mPeopleNotificationIdentifier = peopleNotificationIdentifier;
     }
 
     @Override
@@ -260,7 +265,10 @@
             mSnoozeItem = createSnoozeItem(mContext);
         }
         mAppOpsItem = createAppOpsItem(mContext);
-        if (mParent.getEntry().getBucket() == NotificationSectionsManager.BUCKET_PEOPLE) {
+        NotificationEntry entry = mParent.getEntry();
+        int personNotifType = mPeopleNotificationIdentifier
+                .getPeopleNotificationType(entry.getSbn(), entry.getRanking());
+        if (personNotifType != PeopleNotificationIdentifier.TYPE_NON_PERSON) {
             mInfoItem = createConversationItem(mContext);
         } else {
             mInfoItem = createInfoItem(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java
index 88ed0bb..d3fec69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java
@@ -109,11 +109,14 @@
     }
 
     /**
-     * Free the content view so that it will no longer be bound after the rebind request.
+     * Mark the content view to be freed. The view may not be immediately freeable since it may
+     * be visible and animating out but this lets the binder know to free the view when safe.
+     * Note that the callback passed into {@link RowContentBindStage#requestRebind}
+     * may return before the view is actually freed since the view is considered up-to-date.
      *
      * @see InflationFlag
      */
-    public void freeContentViews(@InflationFlag int contentViews) {
+    public void markContentViewsFreeable(@InflationFlag int contentViews) {
         mContentViews &= ~contentViews;
         mDirtyContentViews &= ~contentViews;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 0c311b40..5205bab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -130,10 +130,18 @@
         if (mNotificationHeader != null) {
             mNotificationHeader.setAppOpsOnClickListener(listener);
         }
-        mAppOps.setOnClickListener(listener);
-        mCameraIcon.setOnClickListener(listener);
-        mMicIcon.setOnClickListener(listener);
-        mOverlayIcon.setOnClickListener(listener);
+        if (mAppOps != null) {
+            mAppOps.setOnClickListener(listener);
+        }
+        if (mCameraIcon != null) {
+            mCameraIcon.setOnClickListener(listener);
+        }
+        if (mMicIcon != null) {
+            mMicIcon.setOnClickListener(listener);
+        }
+        if (mOverlayIcon != null) {
+            mOverlayIcon.setOnClickListener(listener);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index d38bc9f..d02037c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -20,6 +20,7 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.annotation.ColorInt;
 import android.annotation.IntDef;
 import android.annotation.LayoutRes;
 import android.annotation.NonNull;
@@ -555,6 +556,12 @@
         updateSectionBoundaries();
     }
 
+    void setHeaderForegroundColor(@ColorInt int color) {
+        mPeopleHubView.setTextColor(color);
+        mGentleHeader.setForegroundColor(color);
+        mAlertingHeader.setForegroundColor(color);
+    }
+
     /**
      * For now, declare the available notification buckets (sections) here so that other
      * presentation code can decide what to do based on an entry's buckets
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 823b186..6054b50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -33,6 +33,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeAnimator;
 import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -3865,9 +3866,16 @@
         initVelocityTrackerIfNotExists();
         mVelocityTracker.addMovement(ev);
 
-        final int action = ev.getAction();
+        final int action = ev.getActionMasked();
+        if (ev.findPointerIndex(mActivePointerId) == -1 && action != MotionEvent.ACTION_DOWN) {
+            // Incomplete gesture, possibly due to window swap mid-gesture. Ignore until a new
+            // one starts.
+            Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent "
+                    + MotionEvent.actionToString(ev.getActionMasked()));
+            return true;
+        }
 
-        switch (action & MotionEvent.ACTION_MASK) {
+        switch (action) {
             case MotionEvent.ACTION_DOWN: {
                 if (getChildCount() == 0 || !isInContentBounds(ev)) {
                     return false;
@@ -4806,7 +4814,9 @@
         mUsingLightTheme = lightTheme;
         Context context = new ContextThemeWrapper(mContext,
                 lightTheme ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI);
-        final int textColor = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor);
+        final @ColorInt int textColor =
+                Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor);
+        mSectionsManager.setHeaderForegroundColor(textColor);
         mFooterView.setTextColor(textColor);
         mEmptyShadeView.setTextColor(textColor);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
index bc25c71..a1d898f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -16,11 +16,13 @@
 
 package com.android.systemui.statusbar.notification.stack
 
+import android.annotation.ColorInt
 import android.content.Context
 import android.util.AttributeSet
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ImageView
+import android.widget.TextView
 import com.android.systemui.R
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin
 import com.android.systemui.statusbar.notification.people.DataListener
@@ -31,12 +33,14 @@
         StackScrollerDecorView(context, attrs), SwipeableView {
 
     private lateinit var contents: ViewGroup
+    private lateinit var label: TextView
 
     lateinit var personViewAdapters: Sequence<DataListener<PersonViewModel?>>
         private set
 
     override fun onFinishInflate() {
         contents = requireViewById(R.id.people_list)
+        label = requireViewById(R.id.header_label)
         personViewAdapters = (0 until contents.childCount)
                 .asSequence() // so we can map
                 .mapNotNull { idx ->
@@ -49,6 +53,8 @@
         setVisible(true /* nowVisible */, false /* animate */)
     }
 
+    fun setTextColor(@ColorInt color: Int) = label.setTextColor(color)
+
     override fun findContentView(): View = contents
     override fun findSecondaryView(): View? = null
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index a3d8eec..5777ba1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import android.annotation.ColorInt;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -124,4 +126,9 @@
         mLabelTextId = resId;
         mLabelView.setText(resId);
     }
+
+    void setForegroundColor(@ColorInt int color) {
+        mLabelView.setTextColor(color);
+        mClearAllButton.setImageTintList(ColorStateList.valueOf(color));
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 8efda21..f103bd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -19,6 +19,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -26,10 +27,14 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
 import android.hardware.input.InputManager;
+import android.net.Uri;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.ISystemGestureExclusionListener;
 import android.view.InputChannel;
@@ -40,6 +45,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.Surface;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
@@ -53,8 +59,10 @@
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.tracing.ProtoTraceable;
 import com.android.systemui.tracing.ProtoTracer;
 import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto;
@@ -72,6 +80,8 @@
     private static final String TAG = "EdgeBackGestureHandler";
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
             "gestures.back_timeout", 250);
+    private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
+
 
     private ISystemGestureExclusionListener mGestureExclusionListener =
             new ISystemGestureExclusionListener.Stub() {
@@ -88,6 +98,33 @@
                 }
             };
 
+    private OverviewProxyService.OverviewProxyListener mQuickSwitchListener =
+            new OverviewProxyService.OverviewProxyListener() {
+                @Override
+                public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
+                    mStartingQuickstepRotation = rotation;
+                    updateDisabledForQuickstep();
+                }
+            };
+
+    private TaskStackChangeListener mTaskStackChangeListener = new TaskStackChangeListener() {
+        @Override
+        public void onRecentTaskListFrozenChanged(boolean frozen) {
+            if (!frozen) {
+                mStartingQuickstepRotation = -1;
+                mDisabledForQuickstep = false;
+            }
+        }
+    };
+
+    private final ContentObserver mFixedRotationObserver = new ContentObserver(
+            new Handler(Looper.getMainLooper())) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            updatedFixedRotation();
+        }
+    };
+
     private final Context mContext;
     private final OverviewProxyService mOverviewProxyService;
     private PluginManager mPluginManager;
@@ -110,6 +147,11 @@
     private final float mTouchSlop;
     // Duration after which we consider the event as longpress.
     private final int mLongPressTimeout;
+    private int mStartingQuickstepRotation = -1;
+    // We temporarily disable back gesture when user is quickswitching
+    // between apps of different orientations
+    private boolean mDisabledForQuickstep;
+    private boolean mFixedRotationFlagEnabled;
 
     private final PointF mDownPoint = new PointF();
     private final PointF mEndPoint = new PointF();
@@ -193,6 +235,13 @@
      */
     public void onNavBarAttached() {
         mIsAttached = true;
+        updatedFixedRotation();
+        if (mFixedRotationFlagEnabled) {
+            setRotationCallbacks(true);
+        }
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(FIXED_ROTATION_TRANSFORM_SETTING_NAME),
+                false /* notifyForDescendants */, mFixedRotationObserver, UserHandle.USER_ALL);
         updateIsEnabled();
     }
 
@@ -201,9 +250,25 @@
      */
     public void onNavBarDetached() {
         mIsAttached = false;
+        if (mFixedRotationFlagEnabled) {
+            setRotationCallbacks(false);
+        }
+        mContext.getContentResolver().unregisterContentObserver(mFixedRotationObserver);
         updateIsEnabled();
     }
 
+    private void setRotationCallbacks(boolean enable) {
+        if (enable) {
+            ActivityManagerWrapper.getInstance().registerTaskStackListener(
+                    mTaskStackChangeListener);
+            mOverviewProxyService.addCallback(mQuickSwitchListener);
+        } else {
+            ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
+                    mTaskStackChangeListener);
+            mOverviewProxyService.removeCallback(mQuickSwitchListener);
+        }
+    }
+
     public void onNavigationModeChanged(int mode, Context currentUserContext) {
         mIsGesturalModeEnabled = QuickStepContract.isGesturalMode(mode);
         updateIsEnabled();
@@ -405,7 +470,8 @@
             mLogGesture = false;
             mInRejectedExclusion = false;
             mAllowGesture = !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
-                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
+                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY())
+                    && !mDisabledForQuickstep;
             if (mAllowGesture) {
                 mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
                 mEdgeBackPlugin.onMotionEvent(ev);
@@ -466,6 +532,11 @@
         Dependency.get(ProtoTracer.class).update();
     }
 
+    private void updateDisabledForQuickstep() {
+        int rotation = mContext.getResources().getConfiguration().windowConfiguration.getRotation();
+        mDisabledForQuickstep = mStartingQuickstepRotation != rotation;
+    }
+
     @Override
     public void onDisplayAdded(int displayId) { }
 
@@ -474,6 +545,10 @@
 
     @Override
     public void onDisplayChanged(int displayId) {
+        if (mStartingQuickstepRotation > -1) {
+            updateDisabledForQuickstep();
+        }
+
         if (displayId == mDisplayId) {
             updateDisplaySize();
         }
@@ -502,6 +577,17 @@
         InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
     }
 
+    private void updatedFixedRotation() {
+        boolean oldFlag = mFixedRotationFlagEnabled;
+        mFixedRotationFlagEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                FIXED_ROTATION_TRANSFORM_SETTING_NAME, 0) != 0;
+        if (oldFlag == mFixedRotationFlagEnabled) {
+            return;
+        }
+
+        setRotationCallbacks(mFixedRotationFlagEnabled);
+    }
+
     public void setInsets(int leftInset, int rightInset) {
         mLeftInset = leftInset;
         mRightInset = rightInset;
@@ -514,6 +600,7 @@
         pw.println("EdgeBackGestureHandler:");
         pw.println("  mIsEnabled=" + mIsEnabled);
         pw.println("  mAllowGesture=" + mAllowGesture);
+        pw.println("  mDisabledForQuickstep=" + mDisabledForQuickstep);
         pw.println("  mInRejectedExclusion" + mInRejectedExclusion);
         pw.println("  mExcludeRegion=" + mExcludeRegion);
         pw.println("  mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 63fe700..6b0df95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -337,7 +337,7 @@
     //  VisualStabilityManager.Callback overrides:
 
     @Override
-    public void onReorderingAllowed() {
+    public void onChangeAllowed() {
         mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
         for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
             if (isAlerting(entry.getKey())) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index f06cfec..82e02b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -203,7 +203,9 @@
             Log.wtf(TAG, "onFullyShown when view was null");
         } else {
             mKeyguardView.onResume();
-            mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode());
+            if (mRoot != null) {
+                mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode());
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index b46ca40..8636cb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -104,6 +104,8 @@
 
     private DisplayCutout mDisplayCutout;
     private int mRoundedCornerPadding = 0;
+    // right and left padding applied to this view to account for cutouts and rounded corners
+    private Pair<Integer, Integer> mPadding = new Pair(0, 0);
 
     public KeyguardStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -158,10 +160,13 @@
                 getResources().getDimensionPixelSize(
                         com.android.internal.R.dimen.text_size_small_material));
         lp = (MarginLayoutParams) mCarrierLabel.getLayoutParams();
-        lp.setMarginStart(
-                getResources().getDimensionPixelSize(R.dimen.keyguard_carrier_text_margin));
-        mCarrierLabel.setLayoutParams(lp);
 
+        int marginStart = calculateMargin(
+                getResources().getDimensionPixelSize(R.dimen.keyguard_carrier_text_margin),
+                mPadding.first);
+        lp.setMarginStart(marginStart);
+
+        mCarrierLabel.setLayoutParams(lp);
         updateKeyguardStatusBarHeight();
     }
 
@@ -220,6 +225,7 @@
                 : 0;
         int marginEnd = mKeyguardUserSwitcherShowing ? mSystemIconsSwitcherHiddenExpandedMargin :
                 baseMarginEnd;
+        marginEnd = calculateMargin(marginEnd, mPadding.second);
         if (marginEnd != lp.getMarginEnd()) {
             lp.setMarginEnd(marginEnd);
             mSystemIconsContainer.setLayoutParams(lp);
@@ -252,10 +258,10 @@
     private void updatePadding(Pair<Integer, Integer> cornerCutoutMargins) {
         final int waterfallTop =
                 mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
-        Pair<Integer, Integer> padding =
+        mPadding =
                 StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
                         mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
-        setPadding(padding.first, waterfallTop, padding.second, 0);
+        setPadding(mPadding.first, waterfallTop, mPadding.second, 0);
     }
 
     private boolean updateLayoutParamsNoCutout() {
@@ -502,6 +508,17 @@
         }
     }
 
+    /**
+     * Calculates the margin that isn't already accounted for in the view's padding.
+     */
+    private int calculateMargin(int margin, int padding) {
+        if (padding >= margin) {
+            return 0;
+        } else {
+            return margin - padding;
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardStatusBarView:");
         pw.println("  mBatteryCharging: " + mBatteryCharging);
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 d70484e..a19d35a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -50,19 +50,22 @@
     static final int STATE_BIOMETRICS_ERROR = 3;
     private float mDozeAmount;
     private int mIconColor;
-    private StateProvider mStateProvider;
     private int mOldState;
+    private int mState;
     private boolean mPulsing;
     private boolean mDozing;
     private boolean mKeyguardJustShown;
+    private boolean mPredrawRegistered;
     private final SparseArray<Drawable> mDrawableCache = new SparseArray<>();
 
     private final OnPreDrawListener mOnPreDrawListener = new OnPreDrawListener() {
         @Override
         public boolean onPreDraw() {
             getViewTreeObserver().removeOnPreDrawListener(this);
+            mPredrawRegistered = false;
 
-            int newState = mStateProvider.getState();
+            int newState = mState;
+            mOldState = mState;
             Drawable icon = getIcon(newState);
             setImageDrawable(icon, false);
 
@@ -80,7 +83,7 @@
                             @Override
                             public void onAnimationEnd(Drawable drawable) {
                                 if (getDrawable() == animation
-                                        && newState == mStateProvider.getState()
+                                        && newState == mState
                                         && newState == STATE_SCANNING_FACE) {
                                     animation.start();
                                 } else {
@@ -100,10 +103,6 @@
         super(context, attrs);
     }
 
-    void setStateProvider(StateProvider stateProvider) {
-        mStateProvider = stateProvider;
-    }
-
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
@@ -135,13 +134,16 @@
         return false;
     }
 
-    void update(int oldState, boolean pulsing, boolean dozing, boolean keyguardJustShown) {
-        mOldState = oldState;
+    void update(int newState, boolean pulsing, boolean dozing, boolean keyguardJustShown) {
+        mState = newState;
         mPulsing = pulsing;
         mDozing = dozing;
         mKeyguardJustShown = keyguardJustShown;
 
-        getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);
+        if (!mPredrawRegistered) {
+            mPredrawRegistered = true;
+            getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);
+        }
     }
 
     void setDozeAmount(float dozeAmount) {
@@ -175,7 +177,7 @@
         return mDrawableCache.get(iconRes);
     }
 
-    static int getIconForState(int state) {
+    private static int getIconForState(int state) {
         int iconRes;
         switch (state) {
             case STATE_LOCKED:
@@ -196,7 +198,7 @@
         return iconRes;
     }
 
-    static int getAnimationIndexForTransition(int oldState, int newState, boolean pulsing,
+    private static int getAnimationIndexForTransition(int oldState, int newState, boolean pulsing,
             boolean dozing, boolean keyguardJustShown) {
 
         // Never animate when screen is off
@@ -260,9 +262,4 @@
         }
         return LOCK_ANIM_RES_IDS[0][lockAnimIndex];
     }
-
-    interface StateProvider {
-        int getState();
-    }
-
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index f7c861b..a633e19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -352,7 +352,6 @@
         mLockIcon.setOnClickListener(this::handleClick);
         mLockIcon.setOnLongClickListener(this::handleLongClick);
         mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
-        mLockIcon.setStateProvider(this::getState);
 
         if (mLockIcon.isAttachedToWindow()) {
             mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon);
@@ -462,7 +461,7 @@
             shouldUpdate = false;
         }
         if (shouldUpdate && mLockIcon != null) {
-            mLockIcon.update(mLastState, mPulsing, mDozing, mKeyguardJustShown);
+            mLockIcon.update(state, mPulsing, mDozing, mKeyguardJustShown);
         }
         mLastState = state;
         mKeyguardJustShown = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 6fd3bb2..3105155 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -26,6 +26,7 @@
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_FORCE_OPAQUE;
 import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -56,6 +57,8 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
 import android.os.Binder;
@@ -71,6 +74,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
+import android.view.Gravity;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -104,6 +108,7 @@
 import com.android.systemui.recents.Recents;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.AutoHideUiElement;
 import com.android.systemui.statusbar.CommandQueue;
@@ -133,7 +138,7 @@
  * on clicks and view states of the nav bar.
  */
 public class NavigationBarFragment extends LifecycleFragment implements Callbacks,
-        NavigationModeController.ModeChangedListener {
+        NavigationModeController.ModeChangedListener, DisplayManager.DisplayListener {
 
     public static final String TAG = "NavigationBar";
     private static final boolean DEBUG = false;
@@ -141,6 +146,8 @@
     private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
     private static final String EXTRA_APPEARANCE = "appearance";
     private static final String EXTRA_TRANSIENT_STATE = "transient_state";
+    private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
+
 
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -199,6 +206,23 @@
     private boolean mIsOnDefaultDisplay;
     public boolean mHomeBlockedThisTouch;
 
+    /**
+     * When user is QuickSwitching between apps of different orientations, we'll draw a fake
+     * home handle on the orientation they originally touched down to start their swipe
+     * gesture to indicate to them that they can continue in that orientation without having to
+     * rotate the phone
+     * The secondary handle will show when we get
+     * {@link OverviewProxyListener#onQuickSwitchToNewTask(int)} callback with the
+     * original handle hidden and we'll flip the visibilities once the
+     * {@link #mTasksFrozenListener} fires
+     */
+    private NavigationHandle mOrientationHandle;
+    private WindowManager.LayoutParams mOrientationParams;
+    private boolean mFrozenTasks;
+    private int mStartingQuickSwitchRotation;
+    private int mCurrentRotation;
+    private boolean mFixedRotationEnabled;
+
     /** Only for default display */
     @Nullable
     private AssistHandleViewController mAssistHandlerViewController;
@@ -249,6 +273,12 @@
         }
 
         @Override
+        public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
+            mStartingQuickSwitchRotation = rotation;
+            orientSecondaryHomeHandle();
+        }
+
+        @Override
         public void startAssistant(Bundle bundle) {
             mAssistManager.startAssist(bundle);
         }
@@ -271,6 +301,22 @@
         }
     };
 
+    private TaskStackChangeListener mTasksFrozenListener = new TaskStackChangeListener() {
+        @Override
+        public void onRecentTaskListFrozenChanged(boolean frozen) {
+            mFrozenTasks = frozen;
+            orientSecondaryHomeHandle();
+        }
+    };
+
+    private NavigationBarTransitions.DarkIntensityListener mOrientationHandleIntensityListener =
+            new NavigationBarTransitions.DarkIntensityListener() {
+                @Override
+                public void onDarkIntensity(float darkIntensity) {
+                    mOrientationHandle.setDarkIntensity(darkIntensity);
+                }
+            };
+
     private final ContextButtonListener mRotationButtonListener = (button, visible) -> {
         if (visible) {
             // If the button will actually become visible and the navbar is about to hide,
@@ -294,6 +340,14 @@
         }
     };
 
+    private final ContentObserver mFixedRotationObserver = new ContentObserver(
+            new Handler(Looper.getMainLooper())) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            updatedFixedRotation();
+        }
+    };
+
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
         @Override
@@ -351,6 +405,10 @@
                 Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
                 false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
 
+        mContentResolver.registerContentObserver(
+                Settings.Global.getUriFor(FIXED_ROTATION_TRANSFORM_SETTING_NAME),
+                false /* notifyForDescendants */, mFixedRotationObserver, UserHandle.USER_ALL);
+
         if (savedInstanceState != null) {
             mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
             mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
@@ -376,6 +434,7 @@
         mNavigationModeController.removeListener(this);
         mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
         mContentResolver.unregisterContentObserver(mAssistContentObserver);
+        mContentResolver.unregisterContentObserver(mFixedRotationObserver);
 
         DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
     }
@@ -406,6 +465,7 @@
         }
         mNavigationBarView.setNavigationIconHints(mNavigationIconHints);
         mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
+        updatedFixedRotation();
 
         prepareNavigationBarView();
         checkNavBarModes();
@@ -442,6 +502,9 @@
                 new AssistHandleViewController(mHandler, mNavigationBarView);
             getBarTransitions().addDarkIntensityListener(mAssistHandlerViewController);
         }
+
+        initSecondaryHomeHandleForRotation();
+        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTasksFrozenListener);
     }
 
     @Override
@@ -458,6 +521,13 @@
         }
         mOverviewProxyService.removeCallback(mOverviewProxyListener);
         mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
+        ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTasksFrozenListener);
+        if (mOrientationHandle != null) {
+            resetSecondaryHandle();
+            getContext().getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+            getBarTransitions().removeDarkIntensityListener(mOrientationHandleIntensityListener);
+            mWindowManager.removeView(mOrientationHandle);
+        }
     }
 
     @Override
@@ -490,6 +560,90 @@
         repositionNavigationBar();
     }
 
+    private void initSecondaryHomeHandleForRotation() {
+        if (!canShowSecondaryHandle()) {
+            return;
+        }
+
+        getContext().getSystemService(DisplayManager.class)
+                .registerDisplayListener(this, new Handler(Looper.getMainLooper()));
+
+        mOrientationHandle = new VerticalNavigationHandle(getContext());
+
+        getBarTransitions().addDarkIntensityListener(mOrientationHandleIntensityListener);
+        mOrientationParams = new WindowManager.LayoutParams(0, 0,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_SLIPPERY,
+                PixelFormat.TRANSLUCENT);
+        mWindowManager.addView(mOrientationHandle, mOrientationParams);
+        mOrientationHandle.setVisibility(View.GONE);
+    }
+
+    private void orientSecondaryHomeHandle() {
+        if (!canShowSecondaryHandle()) {
+            return;
+        }
+
+        if (!mFrozenTasks) {
+            resetSecondaryHandle();
+        } else {
+            int deltaRotation = deltaRotation(mCurrentRotation, mStartingQuickSwitchRotation);
+            int height = 0;
+            int width = 0;
+            Rect dispSize = mWindowManager.getCurrentWindowMetrics().getBounds();
+            switch (deltaRotation) {
+                case Surface.ROTATION_90:
+                case Surface.ROTATION_270:
+                    height = dispSize.height();
+                    width = getResources()
+                            .getDimensionPixelSize(R.dimen.navigation_bar_height);
+                    break;
+                case Surface.ROTATION_180:
+                case Surface.ROTATION_0:
+                    // TODO(b/152683657): Need to determine best UX for this
+                    resetSecondaryHandle();
+                    return;
+            }
+
+            mOrientationParams.gravity =
+                    deltaRotation == Surface.ROTATION_90 ? Gravity.LEFT : Gravity.RIGHT;
+            mOrientationParams.height = height;
+            mOrientationParams.width = width;
+            mWindowManager.updateViewLayout(mOrientationHandle, mOrientationParams);
+            mNavigationBarView.setVisibility(View.GONE);
+            mOrientationHandle.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private void resetSecondaryHandle() {
+        if (mOrientationHandle != null) {
+            // Case where nav mode is changed w/o ever invoking a quickstep
+            // mOrientedHandle is initialized lazily
+            mOrientationHandle.setVisibility(View.GONE);
+        }
+        if (mNavigationBarView != null) {
+            mNavigationBarView.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private int deltaRotation(int oldRotation, int newRotation) {
+        int delta = newRotation - oldRotation;
+        if (delta < 0) delta += 4;
+        return delta;
+    }
+
+    private void updatedFixedRotation() {
+        mFixedRotationEnabled = Settings.Global.getInt(mContentResolver,
+                FIXED_ROTATION_TRANSFORM_SETTING_NAME, 0) != 0;
+        if (!canShowSecondaryHandle()) {
+            resetSecondaryHandle();
+        }
+    }
+
     @Override
     public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mNavigationBarView != null) {
@@ -1112,6 +1266,10 @@
         mNavBarMode = mode;
         updateScreenPinningGestures();
 
+        if (!canShowSecondaryHandle()) {
+            resetSecondaryHandle();
+        }
+
         // Workaround for b/132825155, for secondary users, we currently don't receive configuration
         // changes on overlay package change since SystemUI runs for the system user. In this case,
         // trigger a new configuration change to ensure that the nav bar is updated in the same way.
@@ -1156,6 +1314,34 @@
     private final AccessibilityServicesStateChangeListener mAccessibilityListener =
             this::updateAccessibilityServicesState;
 
+    @Override
+    public void onDisplayAdded(int displayId) {
+
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+
+    }
+
+    @Override
+    public void onDisplayChanged(int displayId) {
+        if (!canShowSecondaryHandle()) {
+            return;
+        }
+
+        int rotation = getContext().getResources().getConfiguration()
+                .windowConfiguration.getRotation();
+        if (rotation != mCurrentRotation) {
+            mCurrentRotation = rotation;
+            orientSecondaryHomeHandle();
+        }
+    }
+
+    private boolean canShowSecondaryHandle() {
+        return mFixedRotationEnabled && mNavBarMode == NAV_BAR_MODE_GESTURAL;
+    }
+
     private final Consumer<Integer> mRotationWatcher = rotation -> {
         if (mNavigationBarView != null
                 && mNavigationBarView.needsReorient(rotation)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
index abceb11..b874795 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
@@ -32,11 +32,11 @@
 
 public class NavigationHandle extends View implements ButtonInterface {
 
-    private final Paint mPaint = new Paint();
+    protected final Paint mPaint = new Paint();
     private @ColorInt final int mLightColor;
     private @ColorInt final int mDarkColor;
-    private final int mRadius;
-    private final int mBottom;
+    protected final int mRadius;
+    protected final int mBottom;
     private boolean mRequiresInvalidate;
 
     public NavigationHandle(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 8c31a37..dd9c820 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -391,7 +391,9 @@
                         alertNotificationWhenPossible(entry, mHeadsUpManager);
                     } else {
                         // The transfer is no longer valid. Free the content.
-                        entry.getRow().freeContentViewWhenSafe(mHeadsUpManager.getContentFlag());
+                        mRowContentBindStage.getStageParams(entry).markContentViewsFreeable(
+                                contentFlag);
+                        mRowContentBindStage.requestRebind(entry, null);
                     }
                 }
             });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index ccf6707..84dd48b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.annotation.Nullable;
+import android.app.NotificationChannel;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 import android.util.Log;
@@ -85,6 +86,17 @@
         return group.expanded;
     }
 
+    /**
+     * @return if the group that this notification is associated with logically is expanded
+     */
+    public boolean isLogicalGroupExpanded(StatusBarNotification sbn) {
+        NotificationGroup group = mGroupMap.get(sbn.getGroupKey());
+        if (group == null) {
+            return false;
+        }
+        return group.expanded;
+    }
+
     public void setGroupExpanded(StatusBarNotification sbn, boolean expanded) {
         NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
         if (group == null) {
@@ -147,7 +159,15 @@
         }
     }
 
+    /**
+     * Notify the group manager that a new entry was added
+     */
     public void onEntryAdded(final NotificationEntry added) {
+        updateIsolation(added);
+        onEntryAddedInternal(added);
+    }
+
+    private void onEntryAddedInternal(final NotificationEntry added) {
         if (added.isRowRemoved()) {
             added.setDebugThrowable(new Throwable());
         }
@@ -193,9 +213,7 @@
     }
 
     private void onEntryBecomingChild(NotificationEntry entry) {
-        if (shouldIsolate(entry)) {
-            isolateNotification(entry);
-        }
+        updateIsolation(entry);
     }
 
     private void updateSuppression(NotificationGroup group) {
@@ -242,15 +260,6 @@
         return count;
     }
 
-    private NotificationEntry getIsolatedChild(String groupKey) {
-        for (StatusBarNotification sbn : mIsolatedEntries.values()) {
-            if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn.getKey())) {
-                return mGroupMap.get(sbn.getKey()).summary;
-            }
-        }
-        return null;
-    }
-
     /**
      * Update an entry's group information
      * @param entry notification entry to update
@@ -278,7 +287,7 @@
         if (mGroupMap.get(getGroupKey(entry.getKey(), oldGroupKey)) != null) {
             onEntryRemovedInternal(entry, oldGroupKey, oldIsGroup, oldIsGroupSummary);
         }
-        onEntryAdded(entry);
+        onEntryAddedInternal(entry);
         mIsUpdatingUnchangedGroup = false;
         if (isIsolated(entry.getSbn().getKey())) {
             mIsolatedEntries.put(entry.getKey(), entry.getSbn());
@@ -413,14 +422,29 @@
             return null;
         }
         ArrayList<NotificationEntry> children = new ArrayList<>(group.children.values());
-        NotificationEntry isolatedChild = getIsolatedChild(summary.getGroupKey());
-        if (isolatedChild != null) {
-            children.add(isolatedChild);
+        for (StatusBarNotification sbn : mIsolatedEntries.values()) {
+            if (sbn.getGroupKey().equals(summary.getGroupKey())) {
+                children.add(mGroupMap.get(sbn.getKey()).summary);
+            }
         }
         return children;
     }
 
     /**
+     * Get the children that are in the summary's group, not including those isolated.
+     *
+     * @param summary summary of a group
+     * @return list of the children
+     */
+    public @Nullable ArrayList<NotificationEntry> getChildren(StatusBarNotification summary) {
+        NotificationGroup group = mGroupMap.get(summary.getGroupKey());
+        if (group == null) {
+            return null;
+        }
+        return new ArrayList<>(group.children.values());
+    }
+
+    /**
      * If there is a {@link NotificationGroup} associated with the provided entry, this method
      * will update the suppression of that group.
      */
@@ -495,17 +519,7 @@
 
     @Override
     public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
-        onAlertStateChanged(entry, isHeadsUp);
-    }
-
-    private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting) {
-        if (isAlerting) {
-            if (shouldIsolate(entry)) {
-                isolateNotification(entry);
-            }
-        } else {
-            stopIsolatingNotification(entry);
-        }
+        updateIsolation(entry);
     }
 
     /**
@@ -519,13 +533,17 @@
 
     private boolean shouldIsolate(NotificationEntry entry) {
         StatusBarNotification sbn = entry.getSbn();
-        NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
         if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
             return false;
         }
+        NotificationChannel channel = entry.getChannel();
+        if (channel != null && channel.isImportantConversation()) {
+            return true;
+        }
         if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
             return false;
         }
+        NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
         return (sbn.getNotification().fullScreenIntent != null
                     || notificationGroup == null
                     || !notificationGroup.expanded
@@ -545,7 +563,7 @@
 
         mIsolatedEntries.put(sbn.getKey(), sbn);
 
-        onEntryAdded(entry);
+        onEntryAddedInternal(entry);
         // We also need to update the suppression of the old group, because this call comes
         // even before the groupManager knows about the notification at all.
         // When the notification gets added afterwards it is already isolated and therefore
@@ -557,17 +575,31 @@
     }
 
     /**
+     * Update the isolation of an entry, splitting it from the group.
+     */
+    public void updateIsolation(NotificationEntry entry) {
+        boolean isIsolated = isIsolated(entry.getSbn().getKey());
+        if (shouldIsolate(entry)) {
+            if (!isIsolated) {
+                isolateNotification(entry);
+            }
+        } else if (isIsolated) {
+            stopIsolatingNotification(entry);
+        }
+    }
+
+    /**
      * Stop isolating a notification and re-group it with its original logical group.
      *
      * @param entry the notification to un-isolate
      */
     private void stopIsolatingNotification(NotificationEntry entry) {
         StatusBarNotification sbn = entry.getSbn();
-        if (mIsolatedEntries.containsKey(sbn.getKey())) {
+        if (isIsolated(sbn.getKey())) {
             // not isolated anymore, we need to update the groups
             onEntryRemovedInternal(entry, entry.getSbn());
             mIsolatedEntries.remove(sbn.getKey());
-            onEntryAdded(entry);
+            onEntryAddedInternal(entry);
             for (OnGroupChangeListener listener : mListeners) {
                 listener.onGroupsChanged();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index e1e679f..462b42a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -61,6 +61,7 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.function.Consumer;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -92,6 +93,7 @@
     private final State mCurrentState = new State();
     private OtherwisedCollapsedListener mListener;
     private ForcePluginOpenListener mForcePluginOpenListener;
+    private Consumer<Integer> mScrimsVisibilityListener;
     private final ArrayList<WeakReference<StatusBarWindowCallback>>
             mCallbacks = Lists.newArrayList();
 
@@ -150,6 +152,16 @@
         mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback));
     }
 
+    /**
+     * Register a listener to monitor scrims visibility
+     * @param listener A listener to monitor scrims visibility
+     */
+    public void setScrimsVisibilityListener(Consumer<Integer> listener) {
+        if (listener != null && mScrimsVisibilityListener != listener) {
+            mScrimsVisibilityListener = listener;
+        }
+    }
+
     private boolean shouldEnableKeyguardScreenRotation() {
         Resources res = mContext.getResources();
         return SystemProperties.getBoolean("lockscreen.rot_override", false)
@@ -477,6 +489,7 @@
     public void setScrimsVisibility(int scrimsVisibility) {
         mCurrentState.mScrimsVisibility = scrimsVisibility;
         apply(mCurrentState);
+        mScrimsVisibilityListener.accept(scrimsVisibility);
     }
 
     /**
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 119662c..fa55b74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -176,6 +176,7 @@
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
@@ -589,6 +590,7 @@
     private ActivityLaunchAnimator mActivityLaunchAnimator;
     protected StatusBarNotificationPresenter mPresenter;
     private NotificationActivityStarter mNotificationActivityStarter;
+    private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
     private final BubbleController mBubbleController;
     private final BubbleController.BubbleExpandListener mBubbleExpandListener;
 
@@ -679,6 +681,7 @@
             PhoneStatusBarPolicy phoneStatusBarPolicy,
             KeyguardIndicationController keyguardIndicationController,
             DismissCallbackRegistry dismissCallbackRegistry,
+            Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
         super(context);
         mNotificationsController = notificationsController;
@@ -735,6 +738,7 @@
         mScreenPinningRequest = screenPinningRequest;
         mDozeScrimController = dozeScrimController;
         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+        mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
         mVolumeComponent = volumeComponent;
         mCommandQueue = commandQueue;
         mRecentsOptional = recentsOptional;
@@ -1135,6 +1139,7 @@
             mBrightnessMirrorController = new BrightnessMirrorController(
                     mNotificationShadeWindowView,
                     mNotificationPanelViewController,
+                    mNotificationShadeDepthControllerLazy.get(),
                     (visible) -> {
                         mBrightnessMirrorVisible = visible;
                         updateScrimController();
@@ -1230,6 +1235,7 @@
         // Set up the initial notification state.
         mActivityLaunchAnimator = new ActivityLaunchAnimator(
                 mNotificationShadeWindowViewController, this, mNotificationPanelViewController,
+                mNotificationShadeDepthControllerLazy.get(),
                 (NotificationListContainer) mStackScroller);
 
         // TODO: inject this.
@@ -3333,12 +3339,12 @@
         Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
         Trace.beginSection("StatusBar#updateDozingState");
 
-        boolean sleepingFromKeyguard =
-                mStatusBarKeyguardViewManager.isGoingToSleepVisibleNotOccluded();
+        boolean visibleNotOccluded = mStatusBarKeyguardViewManager.isShowing()
+                && !mStatusBarKeyguardViewManager.isOccluded();
         boolean wakeAndUnlock = mBiometricUnlockController.getMode()
                 == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
         boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock)
-                || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard);
+                || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && visibleNotOccluded);
 
         mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation);
         updateQsExpansionEnabled();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 31db8eb..45719c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -168,7 +168,6 @@
     private boolean mLastIsDocked;
     private boolean mLastPulsing;
     private int mLastBiometricMode;
-    private boolean mGoingToSleepVisibleNotOccluded;
     private boolean mLastLockVisible;
 
     private OnDismissAction mAfterKeyguardGoneAction;
@@ -450,37 +449,12 @@
         }
     }
 
-    public boolean isGoingToSleepVisibleNotOccluded() {
-        return mGoingToSleepVisibleNotOccluded;
-    }
-
-    @Override
-    public void onStartedGoingToSleep() {
-        mGoingToSleepVisibleNotOccluded = isShowing() && !isOccluded();
-    }
-
     @Override
     public void onFinishedGoingToSleep() {
-        mGoingToSleepVisibleNotOccluded = false;
         mBouncer.onScreenTurnedOff();
     }
 
     @Override
-    public void onStartedWakingUp() {
-        // TODO: remove
-    }
-
-    @Override
-    public void onScreenTurningOn() {
-        // TODO: remove
-    }
-
-    @Override
-    public void onScreenTurnedOn() {
-        // TODO: remove
-    }
-
-    @Override
     public void onRemoteInputActive(boolean active) {
         mRemoteInputActive = active;
         updateStates();
@@ -999,7 +973,6 @@
         pw.println("  mOccluded: " + mOccluded);
         pw.println("  mRemoteInputActive: " + mRemoteInputActive);
         pw.println("  mDozing: " + mDozing);
-        pw.println("  mGoingToSleepVisibleNotOccluded: " + mGoingToSleepVisibleNotOccluded);
         pw.println("  mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction);
         pw.println("  mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables);
         pw.println("  mPendingWakeupAction: " + mPendingWakeupAction);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java
new file mode 100644
index 0000000..a15ca95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.content.Context;
+import android.graphics.Canvas;
+
+import com.android.systemui.R;
+
+/** Temporarily shown view when using QuickSwitch to switch between apps of different rotations */
+public class VerticalNavigationHandle extends NavigationHandle {
+    private final int mWidth;
+
+    public VerticalNavigationHandle(Context context) {
+        super(context);
+        mWidth = context.getResources().getDimensionPixelSize(R.dimen.navigation_home_handle_width);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        int left;
+        int top;
+        int bottom;
+        int right;
+
+        int radiusOffset = mRadius * 2;
+        right = getWidth() - mBottom;
+        top = getHeight() / 2 - (mWidth / 2); /* (height of screen / 2) - (height of bar / 2) */
+        left = getWidth() - mBottom - radiusOffset;
+        bottom = getHeight() / 2 + (mWidth / 2);
+        canvas.drawRoundRect(left, top, right, bottom, mRadius, mRadius, mPaint);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index bbc7e7a..b81a519 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -51,6 +51,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
@@ -197,6 +198,7 @@
             UserInfoControllerImpl userInfoControllerImpl,
             PhoneStatusBarPolicy phoneStatusBarPolicy,
             KeyguardIndicationController keyguardIndicationController,
+            Lazy<NotificationShadeDepthController> notificationShadeDepthController,
             DismissCallbackRegistry dismissCallbackRegistry,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
         return new StatusBar(
@@ -276,6 +278,7 @@
                 phoneStatusBarPolicy,
                 keyguardIndicationController,
                 dismissCallbackRegistry,
+                notificationShadeDepthController,
                 statusBarTouchableRegionManager);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index bf5900f..95b41a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -71,7 +71,7 @@
     protected boolean mPluggedIn;
     protected boolean mCharging;
     private boolean mCharged;
-    private boolean mPowerSave;
+    protected boolean mPowerSave;
     private boolean mAodPowerSave;
     private boolean mTestmode = false;
     private boolean mHasReceivedBattery = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index d62da10..78111fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -24,6 +24,7 @@
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 
@@ -39,16 +40,19 @@
     private final NotificationShadeWindowView mStatusBarWindow;
     private final Consumer<Boolean> mVisibilityCallback;
     private final NotificationPanelViewController mNotificationPanel;
+    private final NotificationShadeDepthController mDepthController;
     private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
     private final int[] mInt2Cache = new int[2];
     private View mBrightnessMirror;
 
     public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
             NotificationPanelViewController notificationPanelViewController,
+            NotificationShadeDepthController notificationShadeDepthController,
             @NonNull Consumer<Boolean> visibilityCallback) {
         mStatusBarWindow = statusBarWindow;
         mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
         mNotificationPanel = notificationPanelViewController;
+        mDepthController = notificationShadeDepthController;
         mNotificationPanel.setPanelAlphaEndAction(() -> {
             mBrightnessMirror.setVisibility(View.INVISIBLE);
         });
@@ -59,11 +63,13 @@
         mBrightnessMirror.setVisibility(View.VISIBLE);
         mVisibilityCallback.accept(true);
         mNotificationPanel.setPanelAlpha(0, true /* animate */);
+        mDepthController.setBrightnessMirrorVisible(true);
     }
 
     public void hideMirror() {
         mVisibilityCallback.accept(false);
         mNotificationPanel.setPanelAlpha(255, true /* animate */);
+        mDepthController.setBrightnessMirrorVisible(false);
     }
 
     public void setLocation(View original) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 66a1d3f..0d5a149 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -161,7 +161,6 @@
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpStateChanged(entry, false);
         }
-        entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
     }
 
     protected void updatePinnedMode() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 7d54981..45e47f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -21,6 +21,8 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.database.DataSetObserver;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -294,6 +296,21 @@
             return convertView;
         }
 
+        private static Drawable getDrawable(Context context,
+                UserSwitcherController.UserRecord item) {
+            Drawable drawable = getIconDrawable(context, item);
+            int iconColorRes = item.isCurrent ? R.color.kg_user_switcher_selected_avatar_icon_color
+                    : R.color.kg_user_switcher_avatar_icon_color;
+            drawable.setTint(context.getResources().getColor(iconColorRes, context.getTheme()));
+
+            if (item.isCurrent) {
+                Drawable bg = context.getDrawable(R.drawable.bg_avatar_selected);
+                drawable = new LayerDrawable(new Drawable[]{bg, drawable});
+            }
+
+            return drawable;
+        }
+
         @Override
         public void onClick(View v) {
             UserSwitcherController.UserRecord user = (UserSwitcherController.UserRecord) v.getTag();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 99709402..6e5f8a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -33,6 +33,7 @@
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -173,10 +174,13 @@
     @Inject
     public NetworkControllerImpl(Context context, @Background Looper bgLooper,
             DeviceProvisionedController deviceProvisionedController,
-            BroadcastDispatcher broadcastDispatcher) {
-        this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
-                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
-                (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
+            BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager,
+            TelephonyManager telephonyManager, WifiManager wifiManager,
+            NetworkScoreManager networkScoreManager) {
+        this(context, connectivityManager,
+                telephonyManager,
+                wifiManager,
+                networkScoreManager,
                 SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
                 new CallbackHandler(),
                 new AccessPointControllerImpl(context),
@@ -190,6 +194,7 @@
     @VisibleForTesting
     NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
             TelephonyManager telephonyManager, WifiManager wifiManager,
+            NetworkScoreManager networkScoreManager,
             SubscriptionManager subManager, Config config, Looper bgLooper,
             CallbackHandler callbackHandler,
             AccessPointControllerImpl accessPointController,
@@ -229,7 +234,7 @@
             }
         });
         mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
-                mCallbackHandler, this, mWifiManager);
+                mCallbackHandler, this, mWifiManager, mConnectivityManager, networkScoreManager);
 
         mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
index 94aa391..86998ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT 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 com.android.systemui.statusbar.policy;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 69eaaa4..bb0b5e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -31,7 +31,6 @@
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
-import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -52,7 +51,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.Utils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.GuestResumeSessionReceiver;
 import com.android.systemui.Prefs;
@@ -684,18 +682,17 @@
             }
         }
 
-        public Drawable getDrawable(Context context, UserRecord item) {
+        protected static Drawable getIconDrawable(Context context, UserRecord item) {
+            int iconRes;
             if (item.isAddUser) {
-                return context.getDrawable(R.drawable.ic_add_circle_qs);
+                iconRes = R.drawable.ic_add_circle;
+            } else if (item.isGuest) {
+                iconRes = R.drawable.ic_avatar_guest_user;
+            } else {
+                iconRes = R.drawable.ic_avatar_user;
             }
-            Drawable icon = UserIcons.getDefaultUserIcon(
-                    context.getResources(), item.resolveId(), /* light= */ false);
-            if (item.isGuest) {
-                icon.setColorFilter(Utils.getColorAttrDefaultColor(context,
-                        android.R.attr.colorForeground),
-                        Mode.SRC_IN);
-            }
-            return icon;
+
+            return context.getDrawable(iconRes);
         }
 
         public void refresh() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index c2fc18f..b258fd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -42,13 +42,10 @@
 
     public WifiSignalController(Context context, boolean hasMobileDataFeature,
             CallbackHandler callbackHandler, NetworkControllerImpl networkController,
-            WifiManager wifiManager) {
+            WifiManager wifiManager, ConnectivityManager connectivityManager,
+            NetworkScoreManager networkScoreManager) {
         super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
                 callbackHandler, networkController);
-        NetworkScoreManager networkScoreManager =
-                context.getSystemService(NetworkScoreManager.class);
-        ConnectivityManager connectivityManager =
-                context.getSystemService(ConnectivityManager.class);
         mWifiTracker = new WifiStatusTracker(mContext, wifiManager, networkScoreManager,
                 connectivityManager, this::handleStatusUpdated);
         mWifiTracker.setListening(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 07985ab..02ae1f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -27,6 +27,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -66,7 +67,8 @@
             // If the system process isn't there we're doomed anyway.
         }
 
-        new AudioRecordingDisclosureBar(mContext).start();
+        // Creating AudioRecordingDisclosureBar and just letting it run
+        new AudioRecordingDisclosureBar(mContext);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
new file mode 100644
index 0000000..87b3956
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tv.micdisclosure;
+
+import android.content.Context;
+
+import java.util.Set;
+
+/**
+ * A base class for implementing observers for different kinds of activities related to audio
+ * recording. These observers are to be initialized by {@link AudioRecordingDisclosureBar} and to
+ * report back to it.
+ */
+abstract class AudioActivityObserver {
+
+    interface OnAudioActivityStateChangeListener {
+        void onAudioActivityStateChange(boolean active, String packageName);
+    }
+
+    final Context mContext;
+
+    final OnAudioActivityStateChangeListener mListener;
+
+    AudioActivityObserver(Context context, OnAudioActivityStateChangeListener listener) {
+        mContext = context;
+        mListener = listener;
+    }
+
+    abstract Set<String> getActivePackages();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
similarity index 81%
rename from packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index e70e30a..9148683 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open 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,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.tv;
+package com.android.systemui.statusbar.tv.micdisclosure;
 
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
@@ -25,7 +25,6 @@
 import android.animation.PropertyValuesHolder;
 import android.annotation.IntDef;
 import android.annotation.UiThread;
-import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -40,6 +39,7 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.tv.TvStatusBar;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -54,9 +54,10 @@
  *
  * @see TvStatusBar
  */
-class AudioRecordingDisclosureBar {
-    private static final String TAG = "AudioRecordingDisclosureBar";
-    private static final boolean DEBUG = false;
+public class AudioRecordingDisclosureBar implements
+        AudioActivityObserver.OnAudioActivityStateChangeListener {
+    private static final String TAG = "AudioRecordingDisclosure";
+    static final boolean DEBUG = false;
 
     // This title is used to test the microphone disclosure indicator in
     // CtsSystemUiHostTestCases:TvMicrophoneCaptureIndicatorTest
@@ -98,10 +99,12 @@
     private TextView mTextView;
 
     @State private int mState = STATE_NOT_SHOWN;
+
     /**
-     * Set of the applications that currently are conducting audio recording.
+     * Array of the observers that monitor different aspects of the system, such as AppOps and
+     * microphone foreground services
      */
-    private final Set<String> mActiveAudioRecordingPackages = new ArraySet<>();
+    private final AudioActivityObserver[] mAudioActivityObservers;
     /**
      * Set of applications that we've notified the user about since the indicator came up. Meaning
      * that if an application is in this list then at some point since the indicator came up, it
@@ -119,29 +122,52 @@
      * one of the two aforementioned states.
      */
     private final Queue<String> mPendingNotificationPackages = new LinkedList<>();
+    /**
+     * Set of applications for which we make an exception and do not show the indicator. This gets
+     * populated once - in {@link #AudioRecordingDisclosureBar(Context)}.
+     */
+    private final Set<String> mExemptPackages;
 
-    AudioRecordingDisclosureBar(Context context) {
+    public AudioRecordingDisclosureBar(Context context) {
         mContext = context;
-    }
 
-    void start() {
-        // Register AppOpsManager callback
-        final AppOpsManager appOpsManager = (AppOpsManager) mContext.getSystemService(
-                Context.APP_OPS_SERVICE);
-        appOpsManager.startWatchingActive(
-                new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
-                mContext.getMainExecutor(),
-                new OnActiveRecordingListener());
+        mExemptPackages = new ArraySet<>(
+                Arrays.asList(mContext.getResources().getStringArray(
+                        R.array.audio_recording_disclosure_exempt_apps)));
+
+        mAudioActivityObservers = new AudioActivityObserver[]{
+                new RecordAudioAppOpObserver(mContext, this),
+                new MicrophoneForegroundServicesObserver(mContext, this),
+        };
     }
 
     @UiThread
-    private void onStartedRecording(String packageName) {
-        if (!mActiveAudioRecordingPackages.add(packageName)) {
-            // This app is already known to perform recording
+    @Override
+    public void onAudioActivityStateChange(boolean active, String packageName) {
+        if (DEBUG) {
+            Log.d(TAG,
+                    "onAudioActivityStateChange, packageName=" + packageName + ", active="
+                            + active);
+        }
+
+        if (mExemptPackages.contains(packageName)) {
+            if (DEBUG) Log.d(TAG, "   - exempt package: ignoring");
             return;
         }
+
+        if (active) {
+            showIndicatorForPackageIfNeeded(packageName);
+        } else {
+            hideIndicatorIfNeeded();
+        }
+    }
+
+    @UiThread
+    private void showIndicatorForPackageIfNeeded(String packageName) {
+        if (DEBUG) Log.d(TAG, "showIndicatorForPackageIfNeeded, packageName=" + packageName);
         if (!mSessionNotifiedPackages.add(packageName)) {
             // We've already notified user about this app, no need to do it again.
+            if (DEBUG) Log.d(TAG, "   - already notified");
             return;
         }
 
@@ -167,23 +193,33 @@
     }
 
     @UiThread
-    private void onDoneRecording(String packageName) {
-        if (!mActiveAudioRecordingPackages.remove(packageName)) {
-            // Was not marked as an active recorder, do nothing
-            return;
+    private void hideIndicatorIfNeeded() {
+        if (DEBUG) Log.d(TAG, "hideIndicatorIfNeeded");
+        // If not MINIMIZED, will check whether the indicator should be hidden when the indicator
+        // comes to the STATE_MINIMIZED eventually.
+        if (mState != STATE_MINIMIZED) return;
+
+        // If is in the STATE_MINIMIZED, but there are other active recorders - simply ignore.
+        for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) {
+            for (String activePackage : mAudioActivityObservers[index].getActivePackages()) {
+                if (mExemptPackages.contains(activePackage)) continue;
+                if (DEBUG) Log.d(TAG, "   - there are still ongoing activities");
+                return;
+            }
         }
 
-        // If not MINIMIZED, will check whether the indicator should be hidden when the indicator
-        // comes to the STATE_MINIMIZED eventually. If is in the STATE_MINIMIZED, but there are
-        // other active recorders - simply ignore.
-        if (mState == STATE_MINIMIZED && mActiveAudioRecordingPackages.isEmpty()) {
-            mSessionNotifiedPackages.clear();
-            hide();
-        }
+        // Clear the state and hide the indicator.
+        mSessionNotifiedPackages.clear();
+        hide();
     }
 
     @UiThread
     private void show(String packageName) {
+        final String label = getApplicationLabel(packageName);
+        if (DEBUG) {
+            Log.d(TAG, "Showing indicator for " + packageName + " (" + label + ")...");
+        }
+
         // Inflate the indicator view
         mIndicatorView = LayoutInflater.from(mContext).inflate(
                 R.layout.tv_audio_recording_indicator,
@@ -196,7 +232,6 @@
         mBgRight = mIndicatorView.findViewById(R.id.bg_right);
 
         // Set up the notification text
-        final String label = getApplicationLabel(packageName);
         mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
 
         // Initially change the visibility to INVISIBLE, wait until and receives the size and
@@ -260,6 +295,9 @@
     @UiThread
     private void expand(String packageName) {
         final String label = getApplicationLabel(packageName);
+        if (DEBUG) {
+            Log.d(TAG, "Expanding for " + packageName + " (" + label + ")...");
+        }
         mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
 
         final AnimatorSet set = new AnimatorSet();
@@ -283,6 +321,7 @@
 
     @UiThread
     private void minimize() {
+        if (DEBUG) Log.d(TAG, "Minimizing...");
         final int targetOffset = mTextsContainers.getWidth();
         final AnimatorSet set = new AnimatorSet();
         set.playTogether(
@@ -305,6 +344,7 @@
 
     @UiThread
     private void hide() {
+        if (DEBUG) Log.d(TAG, "Hiding...");
         final int targetOffset =
                 mIndicatorView.getWidth() - (int) mIconTextsContainer.getTranslationX();
         final AnimatorSet set = new AnimatorSet();
@@ -326,6 +366,7 @@
 
     @UiThread
     private void onExpanded() {
+        if (DEBUG) Log.d(TAG, "Expanded");
         mState = STATE_SHOWN;
 
         mIndicatorView.postDelayed(this::minimize, MAXIMIZED_DURATION);
@@ -333,20 +374,21 @@
 
     @UiThread
     private void onMinimized() {
+        if (DEBUG) Log.d(TAG, "Minimized");
         mState = STATE_MINIMIZED;
 
         if (!mPendingNotificationPackages.isEmpty()) {
             // There is a new application that started recording, tell the user about it.
             expand(mPendingNotificationPackages.poll());
-        } else if (mActiveAudioRecordingPackages.isEmpty()) {
-            // Nobody is recording anymore, clear state and remove the indicator.
-            mSessionNotifiedPackages.clear();
-            hide();
+        } else {
+            hideIndicatorIfNeeded();
         }
     }
 
     @UiThread
     private void onHidden() {
+        if (DEBUG) Log.d(TAG, "Hidden");
+
         final WindowManager windowManager = (WindowManager) mContext.getSystemService(
                 Context.WINDOW_SERVICE);
         windowManager.removeView(mIndicatorView);
@@ -392,35 +434,4 @@
         }
         return pm.getApplicationLabel(appInfo).toString();
     }
-
-    private class OnActiveRecordingListener implements AppOpsManager.OnOpActiveChangedListener {
-        private final Set<String> mExemptApps;
-
-        private OnActiveRecordingListener() {
-            mExemptApps = new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(
-                    R.array.audio_recording_disclosure_exempt_apps)));
-        }
-
-        @Override
-        public void onOpActiveChanged(String op, int uid, String packageName, boolean active) {
-            if (DEBUG) {
-                Log.d(TAG,
-                        "OP_RECORD_AUDIO active change, active=" + active + ", app="
-                                + packageName);
-            }
-
-            if (mExemptApps.contains(packageName)) {
-                if (DEBUG) {
-                    Log.d(TAG, "\t- exempt app");
-                }
-                return;
-            }
-
-            if (active) {
-                onStartedRecording(packageName);
-            } else {
-                onDoneRecording(packageName);
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
new file mode 100644
index 0000000..1ede88a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tv.micdisclosure;
+
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
+
+import static com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar.DEBUG;
+
+import android.annotation.UiThread;
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.app.IProcessObserver;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The purpose of these class is to detect packages that are running foreground services of type
+ * 'microphone' and to report back to {@link AudioRecordingDisclosureBar}.
+ */
+class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
+    private static final String TAG = "MicrophoneForegroundServicesObserver";
+    private static final boolean ENABLED = true;
+
+    private final IActivityManager mActivityManager;
+    /**
+     * A dictionary that maps PIDs to the package names. We only keep track of the PIDs that are
+     * "active" (those that are running FGS with FOREGROUND_SERVICE_TYPE_MICROPHONE flag).
+     */
+    private final SparseArray<String[]> mPidToPackages = new SparseArray<>();
+    /**
+     * A dictionary that maps "active" packages to the number of the "active" processes associated
+     * with those packages. We really only need this in case when one application is running in
+     * multiple processes, so that we don't lose track of the package when one of its "active"
+     * processes ceases, while others remain "active".
+     */
+    private final Map<String, Integer> mPackageToProcessCount = new ArrayMap<>();
+
+    MicrophoneForegroundServicesObserver(Context context,
+            OnAudioActivityStateChangeListener listener) {
+        super(context, listener);
+
+        mActivityManager = ActivityManager.getService();
+        try {
+            mActivityManager.registerProcessObserver(mProcessObserver);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Couldn't register process observer", e);
+        }
+    }
+
+    @Override
+    Set<String> getActivePackages() {
+        return ENABLED ? mPackageToProcessCount.keySet() : Collections.emptySet();
+    }
+
+    @UiThread
+    private void onProcessForegroundServicesChanged(int pid, boolean hasMicFgs) {
+        final String[] changedPackages;
+        if (hasMicFgs) {
+            if (mPidToPackages.contains(pid)) {
+                // We are already tracking this pid - ignore.
+                changedPackages = null;
+            } else {
+                changedPackages = getPackageNames(pid);
+                mPidToPackages.append(pid, changedPackages);
+            }
+        } else {
+            changedPackages = mPidToPackages.removeReturnOld(pid);
+        }
+
+        if (changedPackages == null) {
+            return;
+        }
+
+        for (int index = changedPackages.length - 1; index >= 0; index--) {
+            final String packageName = changedPackages[index];
+            int processCount = mPackageToProcessCount.getOrDefault(packageName, 0);
+            final boolean shouldNotify;
+            if (hasMicFgs) {
+                processCount++;
+                shouldNotify = processCount == 1;
+            } else {
+                processCount--;
+                shouldNotify = processCount == 0;
+            }
+            if (processCount > 0) {
+                mPackageToProcessCount.put(packageName, processCount);
+            } else {
+                mPackageToProcessCount.remove(packageName);
+            }
+            if (shouldNotify) notifyPackageStateChanged(packageName, hasMicFgs);
+        }
+    }
+
+    @UiThread
+    private void onProcessDied(int pid) {
+        final String[] packages = mPidToPackages.removeReturnOld(pid);
+        if (packages == null) {
+            // This PID was not active - ignore.
+            return;
+        }
+
+        for (int index = packages.length - 1; index >= 0; index--) {
+            final String packageName = packages[index];
+            int processCount = mPackageToProcessCount.getOrDefault(packageName, 0);
+            if (processCount <= 0) {
+                Log.e(TAG, "Bookkeeping error, process count for " + packageName + " is "
+                        + processCount);
+                continue;
+            }
+            processCount--;
+            if (processCount > 0) {
+                mPackageToProcessCount.put(packageName, processCount);
+            } else {
+                mPackageToProcessCount.remove(packageName);
+                notifyPackageStateChanged(packageName, false);
+            }
+        }
+    }
+
+    @UiThread
+    private void notifyPackageStateChanged(String packageName, boolean active) {
+        if (active) {
+            if (DEBUG) Log.d(TAG, "New microphone fgs detected, package=" + packageName);
+        } else {
+            if (DEBUG) Log.d(TAG, "Microphone fgs is gone, package=" + packageName);
+        }
+
+        if (ENABLED) mListener.onAudioActivityStateChange(active, packageName);
+    }
+
+    @UiThread
+    private String[] getPackageNames(int pid) {
+        final List<ActivityManager.RunningAppProcessInfo> runningApps;
+        try {
+            runningApps = mActivityManager.getRunningAppProcesses();
+        } catch (RemoteException e) {
+            Log.d(TAG, "Couldn't get package name for pid=" + pid);
+            return null;
+        }
+        if (runningApps == null) {
+            Log.wtf(TAG, "No running apps reported");
+        }
+        for (ActivityManager.RunningAppProcessInfo app : runningApps) {
+            if (app.pid == pid) {
+                return app.pkgList;
+            }
+        }
+        return null;
+    }
+
+    private final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
+        @Override
+        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {}
+
+        @Override
+        public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
+            mContext.getMainExecutor().execute(() -> onProcessForegroundServicesChanged(pid,
+                    (serviceTypes & FOREGROUND_SERVICE_TYPE_MICROPHONE) != 0));
+        }
+
+        @Override
+        public void onProcessDied(int pid, int uid) {
+            mContext.getMainExecutor().execute(
+                    () -> MicrophoneForegroundServicesObserver.this.onProcessDied(pid));
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
new file mode 100644
index 0000000..b5b1c2b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tv.micdisclosure;
+
+import static com.android.systemui.statusbar.tv.micdisclosure.AudioRecordingDisclosureBar.DEBUG;
+
+import android.annotation.UiThread;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.Set;
+
+/**
+ * The purpose of these class is to detect packages that are conducting audio recording (according
+ * to {@link AppOpsManager}) and report this to {@link AudioRecordingDisclosureBar}.
+ */
+class RecordAudioAppOpObserver extends AudioActivityObserver implements
+        AppOpsManager.OnOpActiveChangedListener {
+    private static final String TAG = "RecordAudioAppOpObserver";
+
+    /**
+     * Set of the applications that currently are conducting audio recording according to {@link
+     * AppOpsManager}.
+     */
+    private final Set<String> mActiveAudioRecordingPackages = new ArraySet<>();
+
+    RecordAudioAppOpObserver(Context context, OnAudioActivityStateChangeListener listener) {
+        super(context, listener);
+
+        // Register AppOpsManager callback
+        final AppOpsManager appOpsManager = (AppOpsManager) mContext.getSystemService(
+                Context.APP_OPS_SERVICE);
+        appOpsManager.startWatchingActive(
+                new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
+                mContext.getMainExecutor(),
+                this);
+    }
+
+    @UiThread
+    @Override
+    Set<String> getActivePackages() {
+        return mActiveAudioRecordingPackages;
+    }
+
+    @UiThread
+    @Override
+    public void onOpActiveChanged(String op, int uid, String packageName, boolean active) {
+        if (DEBUG) {
+            Log.d(TAG,
+                    "OP_RECORD_AUDIO active change, active=" + active + ", package="
+                            + packageName);
+        }
+
+        if (active) {
+            if (mActiveAudioRecordingPackages.add(packageName)) {
+                mListener.onAudioActivityStateChange(true, packageName);
+            }
+        } else {
+            if (mActiveAudioRecordingPackages.remove(packageName)) {
+                mListener.onAudioActivityStateChange(false, packageName);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
index 0242e834..9b465ae 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
+++ b/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java
@@ -21,15 +21,13 @@
 import android.app.INotificationManager;
 import android.app.ITransientNotificationCallback;
 import android.content.Context;
+import android.content.res.Resources;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.Toast;
+import android.view.accessibility.IAccessibilityManager;
 import android.widget.ToastPresenter;
 
 import com.android.internal.R;
@@ -49,37 +47,33 @@
 public class ToastUI extends SystemUI implements CommandQueue.Callbacks {
     private static final String TAG = "ToastUI";
 
-    /**
-     * Values taken from {@link Toast}.
-     */
-    private static final long DURATION_SHORT = 4000;
-    private static final long DURATION_LONG = 7000;
-
     private final CommandQueue mCommandQueue;
-    private final WindowManager mWindowManager;
     private final INotificationManager mNotificationManager;
-    private final AccessibilityManager mAccessibilityManager;
-    private final ToastPresenter mPresenter;
-    private ToastEntry mCurrentToast;
+    private final IAccessibilityManager mAccessibilityManager;
+    private final int mGravity;
+    private final int mY;
+    @Nullable private ToastPresenter mPresenter;
+    @Nullable private ITransientNotificationCallback mCallback;
 
     @Inject
     public ToastUI(Context context, CommandQueue commandQueue) {
         this(context, commandQueue,
-                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE),
                 INotificationManager.Stub.asInterface(
                         ServiceManager.getService(Context.NOTIFICATION_SERVICE)),
-                AccessibilityManager.getInstance(context));
+                IAccessibilityManager.Stub.asInterface(
+                        ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)));
     }
 
     @VisibleForTesting
-    ToastUI(Context context, CommandQueue commandQueue, WindowManager windowManager,
-            INotificationManager notificationManager, AccessibilityManager accessibilityManager) {
+    ToastUI(Context context, CommandQueue commandQueue, INotificationManager notificationManager,
+            @Nullable IAccessibilityManager accessibilityManager) {
         super(context);
         mCommandQueue = commandQueue;
-        mWindowManager = windowManager;
         mNotificationManager = notificationManager;
         mAccessibilityManager = accessibilityManager;
-        mPresenter = new ToastPresenter(context, accessibilityManager);
+        Resources resources = mContext.getResources();
+        mGravity = resources.getInteger(R.integer.config_toastDefaultGravity);
+        mY = resources.getDimensionPixelSize(R.dimen.toast_y_offset);
     }
 
     @Override
@@ -89,35 +83,24 @@
 
     @Override
     @MainThread
-    public void showToast(String packageName, IBinder token, CharSequence text,
+    public void showToast(int uid, String packageName, IBinder token, CharSequence text,
             IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) {
-        if (mCurrentToast != null) {
+        if (mPresenter != null) {
             hideCurrentToast();
         }
-        View view = mPresenter.getTextToastView(text);
-        LayoutParams params = getLayoutParams(packageName, windowToken, duration);
-        mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback);
-        try {
-            mWindowManager.addView(view, params);
-        } catch (WindowManager.BadTokenException e) {
-            Log.w(TAG, "Error while attempting to show toast from " + packageName, e);
-            return;
-        }
-        mPresenter.trySendAccessibilityEvent(view, packageName);
-        if (callback != null) {
-            try {
-                callback.onToastShown();
-            } catch (RemoteException e) {
-                Log.w(TAG, "Error calling back " + packageName + " to notify onToastShow()", e);
-            }
-        }
+        Context context = mContext.createContextAsUser(UserHandle.getUserHandleForUid(uid), 0);
+        View view = ToastPresenter.getTextToastView(context, text);
+        mCallback = callback;
+        mPresenter = new ToastPresenter(context, mAccessibilityManager, mNotificationManager,
+                packageName);
+        mPresenter.show(view, token, windowToken, duration, mGravity, 0, mY, 0, 0, mCallback);
     }
 
     @Override
     @MainThread
     public void hideToast(String packageName, IBinder token) {
-        if (mCurrentToast == null || !Objects.equals(mCurrentToast.packageName, packageName)
-                || !Objects.equals(mCurrentToast.token, token)) {
+        if (mPresenter == null || !Objects.equals(mPresenter.getPackageName(), packageName)
+                || !Objects.equals(mPresenter.getToken(), token)) {
             Log.w(TAG, "Attempt to hide non-current toast from package " + packageName);
             return;
         }
@@ -126,51 +109,7 @@
 
     @MainThread
     private void hideCurrentToast() {
-        if (mCurrentToast.view.getParent() != null) {
-            mWindowManager.removeViewImmediate(mCurrentToast.view);
-        }
-        String packageName = mCurrentToast.packageName;
-        try {
-            mNotificationManager.finishToken(packageName, mCurrentToast.windowToken);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error finishing toast window token from package " + packageName, e);
-        }
-        if (mCurrentToast.callback != null) {
-            try {
-                mCurrentToast.callback.onToastHidden();
-            } catch (RemoteException e) {
-                Log.w(TAG, "Error calling back " + packageName + " to notify onToastHide()", e);
-            }
-        }
-        mCurrentToast = null;
-    }
-
-    private LayoutParams getLayoutParams(String packageName, IBinder windowToken, int duration) {
-        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
-        mPresenter.startLayoutParams(params, packageName);
-        int gravity = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_toastDefaultGravity);
-        int yOffset = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);
-        mPresenter.adjustLayoutParams(params, windowToken, duration, gravity, 0, yOffset, 0, 0);
-        return params;
-    }
-
-    private static class ToastEntry {
-        public final String packageName;
-        public final IBinder token;
-        public final View view;
-        public final IBinder windowToken;
-
-        @Nullable
-        public final ITransientNotificationCallback callback;
-
-        private ToastEntry(String packageName, IBinder token, View view, IBinder windowToken,
-                @Nullable ITransientNotificationCallback callback) {
-            this.packageName = packageName;
-            this.token = token;
-            this.view = view;
-            this.windowToken = windowToken;
-            this.callback = callback;
-        }
+        mPresenter.hide(mCallback);
+        mPresenter = null;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java b/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java
index 711a0df..d731753 100644
--- a/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/util/SysuiLifecycle.java
@@ -48,6 +48,9 @@
 
         ViewLifecycle(View v) {
             v.addOnAttachStateChangeListener(this);
+            if (v.isAttachedToWindow()) {
+                mLifecycle.markState(RESUMED);
+            }
         }
 
         @NonNull
diff --git a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
index 812a1e4..f27bdbf 100644
--- a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
@@ -160,6 +160,18 @@
     lateinit var magnetListener: MagnetizedObject.MagnetListener
 
     /**
+     * Optional update listener to provide to the PhysicsAnimator that is used to spring the object
+     * into the target.
+     */
+    var physicsAnimatorUpdateListener: PhysicsAnimator.UpdateListener<T>? = null
+
+    /**
+     * Optional end listener to provide to the PhysicsAnimator that is used to spring the object
+     * into the target.
+     */
+    var physicsAnimatorEndListener: PhysicsAnimator.EndListener<T>? = null
+
+    /**
      * Sets whether forcefully flinging the object vertically towards a target causes it to be
      * attracted to the target and then released immediately, despite never being dragged within the
      * magnetic field.
@@ -479,6 +491,14 @@
                 .spring(yProperty, yProperty.getValue(underlyingObject) + yDiff, velY,
                         springConfig)
 
+        if (physicsAnimatorUpdateListener != null) {
+            animator.addUpdateListener(physicsAnimatorUpdateListener!!)
+        }
+
+        if (physicsAnimatorEndListener != null) {
+            animator.addEndListener(physicsAnimatorEndListener!!)
+        }
+
         if (after != null) {
             animator.withEndActions(after)
         }
@@ -560,13 +580,15 @@
         private val tempLoc = IntArray(2)
 
         fun updateLocationOnScreen() {
-            targetView.getLocationOnScreen(tempLoc)
+            targetView.post {
+                targetView.getLocationOnScreen(tempLoc)
 
-            // Add half of the target size to get the center, and subtract translation since the
-            // target could be animating in while we're doing this calculation.
-            centerOnScreen.set(
-                    tempLoc[0] + targetView.width / 2f - targetView.translationX,
-                    tempLoc[1] + targetView.height / 2f - targetView.translationY)
+                // Add half of the target size to get the center, and subtract translation since the
+                // target could be animating in while we're doing this calculation.
+                centerOnScreen.set(
+                        tempLoc[0] + targetView.width / 2f - targetView.translationX,
+                        tempLoc[1] + targetView.height / 2f - targetView.translationY)
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
index bae5bb4..c22b718f 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
@@ -272,13 +272,18 @@
                     }
                     mAnimation.cancel();
                 }
-                mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE;
                 final float defaultY = mImeSourceControl.getSurfacePosition().y;
                 final float x = mImeSourceControl.getSurfacePosition().x;
                 final float hiddenY = defaultY + imeSource.getFrame().height();
                 final float shownY = defaultY;
                 final float startY = show ? hiddenY : shownY;
                 final float endY = show ? shownY : hiddenY;
+                if (mAnimationDirection == DIRECTION_NONE && mImeShowing && show) {
+                    // IME is already showing, so set seek to end
+                    seekValue = shownY;
+                    seek = true;
+                }
+                mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE;
                 mImeShowing = show;
                 mAnimation = ValueAnimator.ofFloat(startY, endY);
                 mAnimation.setDuration(
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 381ccdb..e5da603 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -194,7 +194,9 @@
                 return;
             }
             final Display display = mDisplayController.getDisplay(mDisplayId);
-            SurfaceControlViewHost viewRoot = new SurfaceControlViewHost(mContext, display, wwm);
+            SurfaceControlViewHost viewRoot =
+                    new SurfaceControlViewHost(mContext, display, wwm,
+                            true /* useSfChoreographer */);
             attrs.flags |= FLAG_HARDWARE_ACCELERATED;
             viewRoot.setView(view, attrs);
             mViewRoots.put(view, viewRoot);
@@ -256,12 +258,13 @@
                 Rect outVisibleInsets, Rect outStableInsets,
                 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
                 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-                Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
+                InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
+                SurfaceControl outBLASTSurfaceControl) {
             int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight,
                     viewVisibility, flags, frameNumber, outFrame, outOverscanInsets,
                     outContentInsets, outVisibleInsets, outStableInsets,
                     cutout, mergedConfiguration, outSurfaceControl, outInsetsState,
-                    outSurfaceSize, outBLASTSurfaceControl);
+                    outActiveControls, outSurfaceSize, outBLASTSurfaceControl);
             if (res != 0) {
                 return res;
             }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
index 072bc44..4bcf917 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
@@ -16,8 +16,12 @@
 
 package com.android.keyguard
 
+import android.app.Notification
 import android.graphics.drawable.Icon
 import android.media.MediaMetadata
+import android.media.session.MediaController
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
@@ -28,7 +32,9 @@
 
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.media.MediaControllerFactory
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -38,6 +44,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.any
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
@@ -48,9 +55,12 @@
 public class KeyguardMediaPlayerTest : SysuiTestCase() {
 
     private lateinit var keyguardMediaPlayer: KeyguardMediaPlayer
+    @Mock private lateinit var mockMediaFactory: MediaControllerFactory
+    @Mock private lateinit var mockMediaController: MediaController
+    private lateinit var playbackState: PlaybackState
     private lateinit var fakeExecutor: FakeExecutor
     private lateinit var mediaMetadata: MediaMetadata.Builder
-    private lateinit var entry: NotificationEntryBuilder
+    private lateinit var entry: NotificationEntry
     @Mock private lateinit var mockView: View
     private lateinit var songView: TextView
     private lateinit var artistView: TextView
@@ -70,8 +80,16 @@
 
     @Before
     public fun setup() {
+        playbackState = PlaybackState.Builder().run {
+            build()
+        }
+        mockMediaController = mock(MediaController::class.java)
+        whenever(mockMediaController.getPlaybackState()).thenReturn(playbackState)
+        mockMediaFactory = mock(MediaControllerFactory::class.java)
+        whenever(mockMediaFactory.create(any())).thenReturn(mockMediaController)
+
         fakeExecutor = FakeExecutor(FakeSystemClock())
-        keyguardMediaPlayer = KeyguardMediaPlayer(context, fakeExecutor)
+        keyguardMediaPlayer = KeyguardMediaPlayer(context, mockMediaFactory, fakeExecutor)
         mockIcon = mock(Icon::class.java)
 
         mockView = mock(View::class.java)
@@ -81,7 +99,9 @@
         whenever<TextView>(mockView.findViewById(R.id.header_artist)).thenReturn(artistView)
 
         mediaMetadata = MediaMetadata.Builder()
-        entry = NotificationEntryBuilder()
+        entry = NotificationEntryBuilder().build()
+        entry.getSbn().getNotification().extras.putParcelable(Notification.EXTRA_MEDIA_SESSION,
+                MediaSession.Token(1, null))
 
         ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
 
@@ -109,7 +129,7 @@
 
     @Test
     public fun testUpdateControls() {
-        keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
+        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
         FakeExecutor.exhaustExecutors(fakeExecutor)
         verify(mockView).setVisibility(View.VISIBLE)
     }
@@ -122,11 +142,22 @@
     }
 
     @Test
+    public fun testUpdateControlsNullPlaybackState() {
+        // GIVEN that the playback state is null (ie. the media session was destroyed)
+        whenever(mockMediaController.getPlaybackState()).thenReturn(null)
+        // WHEN updated
+        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
+        FakeExecutor.exhaustExecutors(fakeExecutor)
+        // THEN the controls are cleared (ie. visibility is set to GONE)
+        verify(mockView).setVisibility(View.GONE)
+    }
+
+    @Test
     public fun testSongName() {
         val song: String = "Song"
         mediaMetadata.putText(MediaMetadata.METADATA_KEY_TITLE, song)
 
-        keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
+        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
 
         assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
         assertThat(songView.getText()).isEqualTo(song)
@@ -137,7 +168,7 @@
         val artist: String = "Artist"
         mediaMetadata.putText(MediaMetadata.METADATA_KEY_ARTIST, artist)
 
-        keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
+        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
 
         assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
         assertThat(artistView.getText()).isEqualTo(artist)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index eecde72..73f9d8a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -590,7 +590,8 @@
         when(mPackageManager.resolveService(any(Intent.class), eq(0))).thenReturn(resolveInfo);
         when(mDevicePolicyManager.isSecondaryLockscreenEnabled(eq(UserHandle.of(user))))
                 .thenReturn(true, false);
-        when(mDevicePolicyManager.getProfileOwnerAsUser(user))
+        when(mDevicePolicyManager.getProfileOwnerOrDeviceOwnerSupervisionComponent(
+                UserHandle.of(user)))
                 .thenReturn(new ComponentName(packageName, cls));
 
         // Initially null.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
index 471149c..6decb88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -23,6 +23,7 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.annotation.UiThreadTest;
@@ -52,7 +53,11 @@
         mDependency.injectMockDependency(NotificationMediaManager.class);
         allowTestableLooperAsMainThread();
         Context context = getContext();
-        mRow = new NotificationTestHelper(context, mDependency).createRow();
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        mRow = helper.createRow();
         mCallback = mock(ExpandHelper.Callback.class);
         mExpandHelper = new ExpandHelper(context, mCallback, 10, 100);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
index 475023e..5227aaf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -160,7 +160,7 @@
                 LOW_BMP_HEIGHT /* bmpHeight */,
                 LOW_BMP_WIDTH /* surfaceWidth */,
                 LOW_BMP_HEIGHT /* surfaceHeight */,
-                true /* assertion */);
+                false /* assertion */);
     }
 
     @Test
@@ -172,7 +172,7 @@
                 INVALID_BMP_HEIGHT /* bmpHeight */,
                 ImageWallpaper.GLEngine.MIN_SURFACE_WIDTH /* surfaceWidth */,
                 ImageWallpaper.GLEngine.MIN_SURFACE_HEIGHT /* surfaceHeight */,
-                true /* assertion */);
+                false /* assertion */);
     }
 
     private void verifySurfaceSizeAndAssertTransition(int bmpWidth, int bmpHeight,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
index 7821ae2..847e442 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -91,7 +91,7 @@
         fakeExecutor = FakeExecutor(FakeSystemClock())
 
         userBroadcastDispatcher = UserBroadcastDispatcher(
-                mockContext, USER_ID, handler, testableLooper.looper)
+                mockContext, USER_ID, testableLooper.looper)
         userBroadcastDispatcher.pendingResult = mPendingResult
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 6f3fbb9..037f04ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -223,7 +223,10 @@
         mNotificationShadeWindowController.attach();
 
         // Need notifications for bubbles
-        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
         mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
         mNonBubbleNotifRow = mNotificationTestHelper.createRow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index c86b5f7..d2f9127 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -109,7 +109,10 @@
 
     @Before
     public void setUp() throws Exception {
-        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         MockitoAnnotations.initMocks(this);
 
         mEntryA1 = createBubbleEntry(1, "a1", "package.a");
@@ -599,13 +602,13 @@
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryA2, 2000);
         sendUpdatedEntryAtTime(mEntryB1, 3000); // [B1, A2, A1]
-        changeExpandedStateAtTime(true, 4000L);
+        changeExpandedStateAtTime(true, 4000L); // B1 marked updated at 4000L
         mBubbleData.setListener(mListener);
 
         // Test
         sendUpdatedEntryAtTime(mEntryC1, 4000);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleC1, mBubbleB1, mBubbleA2, mBubbleA1);
+        assertOrderChangedTo(mBubbleB1, mBubbleC1, mBubbleA2, mBubbleA1);
     }
 
     /**
@@ -789,8 +792,7 @@
      * When the stack transitions to the collapsed state, the selected bubble is brought to the top.
      * Bubbles within the same group should move up with it.
      * <p>
-     * When the stack transitions back to the expanded state, the previous ordering is restored, as
-     * long as no changes have been made (adds, removes or updates) while in the collapsed state.
+     * When the stack transitions back to the expanded state, this new order is kept as is.
      */
     @Test
     public void test_expansionChanges() {
@@ -813,20 +815,12 @@
         // stack is expanded. When next collapsed, sorting will be applied and saved, just prior
         // to moving the selected bubble to the top (first).
         //
-        // In this case, the expected re-expand state will be: [B1, B2, A2*, A1]
-        //
-        // That state is restored as long as no changes occur (add/remove/update) while in
-        // the collapsed state.
+        // In this case, the expected re-expand state will be: [A2, A1, B1, B2]
         //
         // collapse -> selected bubble (A2) moves first.
         changeExpandedStateAtTime(false, 8000L);
         verifyUpdateReceived();
         assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2);
-
-        // expand -> "original" order/grouping restored
-        changeExpandedStateAtTime(true, 10000L);
-        verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleB1, mBubbleB2, mBubbleA2, mBubbleA1);
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index a31e3f8d..545de21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -210,7 +210,10 @@
         mNotificationShadeWindowController.attach();
 
         // Need notifications for bubbles
-        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
         mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
         mNonBubbleNotifRow = mNotificationTestHelper.createRow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index c9bb401..9985d21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -20,8 +20,10 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.testing.AndroidTestingRunner;
@@ -56,6 +58,7 @@
         mDockManagerFake = spy(new DockManagerFake());
         mDockHandler = new DozeDockHandler(mConfig, mMachine, mDockManagerFake);
 
+        when(mMachine.getState()).thenReturn(State.DOZE_AOD);
         doReturn(true).when(mConfig).alwaysOnEnabled(anyInt());
         mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
     }
@@ -101,4 +104,31 @@
 
         verify(mMachine).requestState(eq(State.DOZE));
     }
+
+    @Test
+    public void onEvent_dockedWhilePulsing_wontRequestStateChange() {
+        when(mMachine.getState()).thenReturn(State.DOZE_PULSING);
+
+        mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED);
+
+        verify(mMachine, never()).requestState(any(State.class));
+    }
+
+    @Test
+    public void onEvent_noneWhilePulsing_wontRequestStateChange() {
+        when(mMachine.getState()).thenReturn(State.DOZE_PULSING);
+
+        mDockManagerFake.setDockEvent(DockManager.STATE_NONE);
+
+        verify(mMachine, never()).requestState(any(State.class));
+    }
+
+    @Test
+    public void onEvent_hideWhilePulsing_wontRequestStateChange() {
+        when(mMachine.getState()).thenReturn(State.DOZE_PULSING);
+
+        mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED_HIDE);
+
+        verify(mMachine, never()).requestState(any(State.class));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index c483314..1f07f46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -254,6 +254,17 @@
     }
 
     @Test
+    public void testPulseDone_whileDockedAoD_staysDockedAod() {
+        when(mDockManager.isDocked()).thenReturn(true);
+        mMachine.requestState(INITIALIZED);
+        mMachine.requestState(DOZE_AOD_DOCKED);
+
+        mMachine.requestState(DOZE_PULSE_DONE);
+
+        verify(mPartMock, never()).transitionTo(DOZE_AOD_DOCKED, DOZE_PULSE_DONE);
+    }
+
+    @Test
     public void testPulseDone_dozeSuppressed_afterDocked_goesToDoze() {
         when(mHost.isDozeSuppressed()).thenReturn(true);
         when(mDockManager.isDocked()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
new file mode 100644
index 0000000..137a126
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.globalactions;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.service.dreams.IDreamManager;
+import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.IWindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.controls.controller.ControlsController;
+import com.android.systemui.controls.management.ControlsListingController;
+import com.android.systemui.controls.ui.ControlsUiController;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.GlobalActions;
+import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class GlobalActionsDialogTest extends SysuiTestCase {
+    private GlobalActionsDialog mGlobalActionsDialog;
+
+    @Mock private GlobalActions.GlobalActionsManager mWindowManagerFuncs;
+    @Mock private AudioManager mAudioManager;
+    @Mock private IDreamManager mDreamManager;
+    @Mock private DevicePolicyManager mDevicePolicyManager;
+    @Mock private LockPatternUtils mLockPatternUtils;
+    @Mock private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock private ConnectivityManager mConnectivityManager;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private ContentResolver mContentResolver;
+    @Mock private Resources mResources;
+    @Mock private ConfigurationController mConfigurationController;
+    @Mock private ActivityStarter mActivityStarter;
+    @Mock private KeyguardStateController mKeyguardStateController;
+    @Mock private UserManager mUserManager;
+    @Mock private TrustManager mTrustManager;
+    @Mock private IActivityManager mActivityManager;
+    @Mock private MetricsLogger mMetricsLogger;
+    @Mock private NotificationShadeDepthController mDepthController;
+    @Mock private SysuiColorExtractor mColorExtractor;
+    @Mock private IStatusBarService mStatusBarService;
+    @Mock private BlurUtils mBlurUtils;
+    @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
+    @Mock private ControlsUiController mControlsUiController;
+    @Mock private IWindowManager mWindowManager;
+    @Mock private Executor mBackgroundExecutor;
+    @Mock private ControlsListingController mControlsListingController;
+    @Mock private ControlsController mControlsController;
+    @Mock private UiEventLogger mUiEventLogger;
+
+    private TestableLooper mTestableLooper;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mTestableLooper = TestableLooper.get(this);
+        allowTestableLooperAsMainThread();
+        mGlobalActionsDialog = new GlobalActionsDialog(mContext,
+                mWindowManagerFuncs,
+                mAudioManager,
+                mDreamManager,
+                mDevicePolicyManager,
+                mLockPatternUtils,
+                mBroadcastDispatcher,
+                mConnectivityManager,
+                mTelephonyManager,
+                mContentResolver,
+                null,
+                mResources,
+                mConfigurationController,
+                mActivityStarter,
+                mKeyguardStateController,
+                mUserManager,
+                mTrustManager,
+                mActivityManager,
+                null,
+                mMetricsLogger,
+                mDepthController,
+                mColorExtractor,
+                mStatusBarService,
+                mBlurUtils,
+                mNotificationShadeWindowController,
+                mControlsUiController,
+                mWindowManager,
+                mBackgroundExecutor,
+                mControlsListingController,
+                mControlsController,
+                mUiEventLogger
+        );
+    }
+    @Test
+    public void testShouldLogVisibility() {
+        mGlobalActionsDialog.onShow(null);
+        verify(mUiEventLogger, times(1))
+                .log(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_OPEN);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
new file mode 100644
index 0000000..260f520
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media
+
+import android.graphics.Color
+import android.content.res.ColorStateList
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.widget.SeekBar
+import android.widget.TextView
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+public class SeekBarObserverTest : SysuiTestCase() {
+
+    private lateinit var observer: SeekBarObserver
+    @Mock private lateinit var mockView: View
+    private lateinit var seekBarView: SeekBar
+    private lateinit var elapsedTimeView: TextView
+    private lateinit var totalTimeView: TextView
+
+    @Before
+    fun setUp() {
+        mockView = mock(View::class.java)
+        seekBarView = SeekBar(context)
+        elapsedTimeView = TextView(context)
+        totalTimeView = TextView(context)
+        whenever<SeekBar>(
+                mockView.findViewById(R.id.media_progress_bar)).thenReturn(seekBarView)
+        whenever<TextView>(
+                mockView.findViewById(R.id.media_elapsed_time)).thenReturn(elapsedTimeView)
+        whenever<TextView>(mockView.findViewById(R.id.media_total_time)).thenReturn(totalTimeView)
+        observer = SeekBarObserver(mockView)
+    }
+
+    @Test
+    fun seekBarGone() {
+        // WHEN seek bar is disabled
+        val isEnabled = false
+        val data = SeekBarViewModel.Progress(isEnabled, false, null, null, null)
+        observer.onChanged(data)
+        // THEN seek bar visibility is set to GONE
+        assertThat(seekBarView.getVisibility()).isEqualTo(View.GONE)
+        assertThat(elapsedTimeView.getVisibility()).isEqualTo(View.GONE)
+        assertThat(totalTimeView.getVisibility()).isEqualTo(View.GONE)
+    }
+
+    @Test
+    fun seekBarVisible() {
+        // WHEN seek bar is enabled
+        val isEnabled = true
+        val data = SeekBarViewModel.Progress(isEnabled, true, 3000, 12000, -1)
+        observer.onChanged(data)
+        // THEN seek bar is visible
+        assertThat(seekBarView.getVisibility()).isEqualTo(View.VISIBLE)
+        assertThat(elapsedTimeView.getVisibility()).isEqualTo(View.VISIBLE)
+        assertThat(totalTimeView.getVisibility()).isEqualTo(View.VISIBLE)
+    }
+
+    @Test
+    fun seekBarProgress() {
+        // WHEN seek bar progress is about half
+        val data = SeekBarViewModel.Progress(true, true, 3000, 120000, -1)
+        observer.onChanged(data)
+        // THEN seek bar is visible
+        assertThat(seekBarView.progress).isEqualTo(100)
+        assertThat(seekBarView.max).isEqualTo(120000)
+        assertThat(elapsedTimeView.getText()).isEqualTo("00:03")
+        assertThat(totalTimeView.getText()).isEqualTo("02:00")
+    }
+
+    @Test
+    fun seekBarDisabledWhenSeekNotAvailable() {
+        // WHEN seek is not available
+        val isSeekAvailable = false
+        val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000, -1)
+        observer.onChanged(data)
+        // THEN seek bar is not enabled
+        assertThat(seekBarView.isEnabled()).isFalse()
+    }
+
+    @Test
+    fun seekBarEnabledWhenSeekNotAvailable() {
+        // WHEN seek is available
+        val isSeekAvailable = true
+        val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000, -1)
+        observer.onChanged(data)
+        // THEN seek bar is not enabled
+        assertThat(seekBarView.isEnabled()).isTrue()
+    }
+
+    @Test
+    fun seekBarColor() {
+        // WHEN data included color
+        val data = SeekBarViewModel.Progress(true, true, 3000, 120000, Color.RED)
+        observer.onChanged(data)
+        // THEN seek bar is colored
+        val red = ColorStateList.valueOf(Color.RED)
+        assertThat(elapsedTimeView.getTextColors()).isEqualTo(red)
+        assertThat(totalTimeView.getTextColors()).isEqualTo(red)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
new file mode 100644
index 0000000..f316d04
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media
+
+import android.graphics.Color
+import android.media.MediaMetadata
+import android.media.session.MediaController
+import android.media.session.PlaybackState
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.widget.SeekBar
+import androidx.arch.core.executor.ArchTaskExecutor
+import androidx.arch.core.executor.TaskExecutor
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+public class SeekBarViewModelTest : SysuiTestCase() {
+
+    private lateinit var viewModel: SeekBarViewModel
+    private lateinit var fakeExecutor: FakeExecutor
+    private val taskExecutor: TaskExecutor = object : TaskExecutor() {
+        override fun executeOnDiskIO(runnable: Runnable) {
+            runnable.run()
+        }
+        override fun postToMainThread(runnable: Runnable) {
+            runnable.run()
+        }
+        override fun isMainThread(): Boolean {
+            return true
+        }
+    }
+    @Mock private lateinit var mockController: MediaController
+    @Mock private lateinit var mockTransport: MediaController.TransportControls
+
+    @Before
+    fun setUp() {
+        fakeExecutor = FakeExecutor(FakeSystemClock())
+        viewModel = SeekBarViewModel(fakeExecutor)
+        mockController = mock(MediaController::class.java)
+        mockTransport = mock(MediaController.TransportControls::class.java)
+
+        // LiveData to run synchronously
+        ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
+    }
+
+    @After
+    fun tearDown() {
+        ArchTaskExecutor.getInstance().setDelegate(null)
+    }
+
+    @Test
+    fun updateColor() {
+        viewModel.updateController(mockController, Color.RED)
+        assertThat(viewModel.progress.value!!.color).isEqualTo(Color.RED)
+    }
+
+    @Test
+    fun updateDuration() {
+        // GIVEN that the duration is contained within the metadata
+        val duration = 12000L
+        val metadata = MediaMetadata.Builder().run {
+            putLong(MediaMetadata.METADATA_KEY_DURATION, duration)
+            build()
+        }
+        whenever(mockController.getMetadata()).thenReturn(metadata)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN the duration is extracted
+        assertThat(viewModel.progress.value!!.duration).isEqualTo(duration)
+        assertThat(viewModel.progress.value!!.enabled).isTrue()
+    }
+
+    @Test
+    fun updateDurationNegative() {
+        // GIVEN that the duration is negative
+        val duration = -1L
+        val metadata = MediaMetadata.Builder().run {
+            putLong(MediaMetadata.METADATA_KEY_DURATION, duration)
+            build()
+        }
+        whenever(mockController.getMetadata()).thenReturn(metadata)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN the seek bar is disabled
+        assertThat(viewModel.progress.value!!.enabled).isFalse()
+    }
+
+    @Test
+    fun updateDurationZero() {
+        // GIVEN that the duration is zero
+        val duration = 0L
+        val metadata = MediaMetadata.Builder().run {
+            putLong(MediaMetadata.METADATA_KEY_DURATION, duration)
+            build()
+        }
+        whenever(mockController.getMetadata()).thenReturn(metadata)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN the seek bar is disabled
+        assertThat(viewModel.progress.value!!.enabled).isFalse()
+    }
+
+    @Test
+    fun updateElapsedTime() {
+        // GIVEN that the PlaybackState contins the current position
+        val position = 200L
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, position, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN elapsed time is captured
+        assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(200.toInt())
+    }
+
+    @Test
+    fun updateSeekAvailable() {
+        // GIVEN that seek is included in actions
+        val state = PlaybackState.Builder().run {
+            setActions(PlaybackState.ACTION_SEEK_TO)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN seek is available
+        assertThat(viewModel.progress.value!!.seekAvailable).isTrue()
+    }
+
+    @Test
+    fun updateSeekNotAvailable() {
+        // GIVEN that seek is not included in actions
+        val state = PlaybackState.Builder().run {
+            setActions(PlaybackState.ACTION_PLAY)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN seek is not available
+        assertThat(viewModel.progress.value!!.seekAvailable).isFalse()
+    }
+
+    @Test
+    fun handleSeek() {
+        whenever(mockController.getTransportControls()).thenReturn(mockTransport)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN user input is dispatched
+        val pos = 42L
+        viewModel.onSeek(pos)
+        fakeExecutor.runAllReady()
+        // THEN transport controls should be used
+        verify(mockTransport).seekTo(pos)
+    }
+
+    @Test
+    fun handleProgressChangedUser() {
+        whenever(mockController.getTransportControls()).thenReturn(mockTransport)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN user starts dragging the seek bar
+        val pos = 42
+        viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, true)
+        fakeExecutor.runAllReady()
+        // THEN transport controls should be used
+        verify(mockTransport).seekTo(pos.toLong())
+    }
+
+    @Test
+    fun handleProgressChangedOther() {
+        whenever(mockController.getTransportControls()).thenReturn(mockTransport)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN user starts dragging the seek bar
+        val pos = 42
+        viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, false)
+        fakeExecutor.runAllReady()
+        // THEN transport controls should be used
+        verify(mockTransport, never()).seekTo(pos.toLong())
+    }
+
+    @Test
+    fun handleStartTrackingTouch() {
+        whenever(mockController.getTransportControls()).thenReturn(mockTransport)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN user starts dragging the seek bar
+        val pos = 42
+        val bar = SeekBar(context).apply {
+            progress = pos
+        }
+        viewModel.seekBarListener.onStartTrackingTouch(bar)
+        fakeExecutor.runAllReady()
+        // THEN transport controls should be used
+        verify(mockTransport, never()).seekTo(pos.toLong())
+    }
+
+    @Test
+    fun handleStopTrackingTouch() {
+        whenever(mockController.getTransportControls()).thenReturn(mockTransport)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN user ends drag
+        val pos = 42
+        val bar = SeekBar(context).apply {
+            progress = pos
+        }
+        viewModel.seekBarListener.onStopTrackingTouch(bar)
+        fakeExecutor.runAllReady()
+        // THEN transport controls should be used
+        verify(mockTransport).seekTo(pos.toLong())
+    }
+
+    @Test
+    fun queuePollTaskWhenPlaying() {
+        // GIVEN that the track is playing
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, 100L, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN the controller is updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN a task is queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun noQueuePollTaskWhenStopped() {
+        // GIVEN that the playback state is stopped
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_STOPPED, 200L, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN an update task is not queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(0)
+    }
+
+    @Test
+    fun queuePollTaskWhenListening() {
+        // GIVEN listening
+        viewModel.listening = true
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // AND the playback state is playing
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, 200L, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN an update task is queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun noQueuePollTaskWhenNotListening() {
+        // GIVEN not listening
+        viewModel.listening = false
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // AND the playback state is playing
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_STOPPED, 200L, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        // WHEN updated
+        viewModel.updateController(mockController, Color.RED)
+        // THEN an update task is not queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(0)
+    }
+
+    @Test
+    fun pollTaskQueuesAnotherPollTaskWhenPlaying() {
+        // GIVEN that the track is playing
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, 100L, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN the next task runs
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // THEN another task is queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun taskUpdatesProgress() {
+        // GIVEN that the PlaybackState contins the current position
+        val position = 200L
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, position, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        viewModel.updateController(mockController, Color.RED)
+        // AND the playback state advances
+        val nextPosition = 300L
+        val nextState = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, nextPosition, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(nextState)
+        // WHEN the task runs
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // THEN elapsed time is captured
+        assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(nextPosition.toInt())
+    }
+
+    @Test
+    fun startListeningQueuesPollTask() {
+        // GIVEN not listening
+        viewModel.listening = false
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // AND the playback state is playing
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_STOPPED, 200L, 1f)
+            build()
+        }
+        whenever(mockController.getPlaybackState()).thenReturn(state)
+        viewModel.updateController(mockController, Color.RED)
+        // WHEN start listening
+        viewModel.listening = true
+        // THEN an update task is queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(1)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
index 0bf0f04..425bf88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.pip;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.content.ComponentName;
@@ -56,11 +57,15 @@
 
     private PipBoundsHandler mPipBoundsHandler;
     private DisplayInfo mDefaultDisplayInfo;
+    private ComponentName mTestComponentName1;
+    private ComponentName mTestComponentName2;
 
     @Before
     public void setUp() throws Exception {
         initializeMockResources();
         mPipBoundsHandler = new PipBoundsHandler(mContext, new PipSnapAlgorithm(mContext));
+        mTestComponentName1 = new ComponentName(mContext, "component1");
+        mTestComponentName2 = new ComponentName(mContext, "component2");
 
         mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
     }
@@ -121,7 +126,7 @@
         };
         for (float aspectRatio : aspectRatios) {
             final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
             final float actualAspectRatio =
                     destinationBounds.width() / (destinationBounds.height() * 1f);
             assertEquals("Destination bounds matches the given aspect ratio",
@@ -137,7 +142,7 @@
         };
         for (float aspectRatio : invalidAspectRatios) {
             final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
             final float actualAspectRatio =
                     destinationBounds.width() / (destinationBounds.height() * 1f);
             assertEquals("Destination bounds fallbacks to default aspect ratio",
@@ -153,7 +158,7 @@
         currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
 
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                aspectRatio, currentBounds, EMPTY_MINIMAL_SIZE);
+                mTestComponentName1, aspectRatio, currentBounds, EMPTY_MINIMAL_SIZE);
 
         final float actualAspectRatio =
                 destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -177,7 +182,7 @@
             final float aspectRatio = aspectRatios[i];
             final Size minimalSize = minimalSizes[i];
             final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
+                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
             assertTrue("Destination bounds is no smaller than minimal requirement",
                     (destinationBounds.width() == minimalSize.getWidth()
                             && destinationBounds.height() >= minimalSize.getHeight())
@@ -198,7 +203,7 @@
         final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);
 
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                aspectRatio, currentBounds, minSize);
+                mTestComponentName1, aspectRatio, currentBounds, minSize);
 
         assertTrue("Destination bounds ignores minimal size",
                 destinationBounds.width() > minSize.getWidth()
@@ -206,81 +211,92 @@
     }
 
     @Test
+    public void getDestinationBounds_withDifferentComponentName_ignoreLastPosition() {
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
+                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+
+        oldPosition.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);
+
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName2,
+                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+
+        assertNonBoundsInclusionWithMargin("ignore saved bounds", oldPosition, newPosition);
+    }
+
+    @Test
     public void setShelfHeight_offsetBounds() {
         final int shelfHeight = 100;
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsHandler.setShelfHeight(true, shelfHeight);
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -shelfHeight);
-        assertBoundsWithMargin("offsetBounds by shelf", oldPosition, newPosition);
+        assertBoundsInclusionWithMargin("offsetBounds by shelf", oldPosition, newPosition);
     }
 
     @Test
     public void onImeVisibilityChanged_offsetBounds() {
         final int imeHeight = 100;
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -imeHeight);
-        assertBoundsWithMargin("offsetBounds by IME", oldPosition, newPosition);
+        assertBoundsInclusionWithMargin("offsetBounds by IME", oldPosition, newPosition);
     }
 
     @Test
     public void onSaveReentryBounds_restoreLastPosition() {
-        final ComponentName componentName = new ComponentName(mContext, "component1");
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(componentName, oldPosition);
+        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);
 
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
-        assertBoundsWithMargin("restoreLastPosition", oldPosition, newPosition);
+        assertBoundsInclusionWithMargin("restoreLastPosition", oldPosition, newPosition);
     }
 
     @Test
     public void onResetReentryBounds_useDefaultBounds() {
-        final ComponentName componentName = new ComponentName(mContext, "component1");
-        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
+        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
         final Rect newBounds = new Rect(defaultBounds);
         newBounds.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
+        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);
 
-        mPipBoundsHandler.onResetReentryBounds(componentName);
-        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(
+        mPipBoundsHandler.onResetReentryBounds(mTestComponentName1);
+        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
-        assertBoundsWithMargin("useDefaultBounds", defaultBounds, actualBounds);
+        assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
     }
 
     @Test
     public void onResetReentryBounds_componentMismatch_restoreLastPosition() {
-        final ComponentName componentName = new ComponentName(mContext, "component1");
-        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
+        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
         final Rect newBounds = new Rect(defaultBounds);
         newBounds.offset(0, -100);
-        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
+        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);
 
-        mPipBoundsHandler.onResetReentryBounds(new ComponentName(mContext, "component2"));
-        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(
+        mPipBoundsHandler.onResetReentryBounds(mTestComponentName2);
+        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                 DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
-        assertBoundsWithMargin("restoreLastPosition", newBounds, actualBounds);
+        assertBoundsInclusionWithMargin("restoreLastPosition", newBounds, actualBounds);
     }
 
-    private void assertBoundsWithMargin(String from, Rect expected, Rect actual) {
+    private void assertBoundsInclusionWithMargin(String from, Rect expected, Rect actual) {
         final Rect expectedWithMargin = new Rect(expected);
         expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
         assertTrue(from + ": expect " + expected
@@ -288,4 +304,13 @@
                 + " with error margin " + ROUNDING_ERROR_MARGIN,
                 expectedWithMargin.contains(actual));
     }
+
+    private void assertNonBoundsInclusionWithMargin(String from, Rect expected, Rect actual) {
+        final Rect expectedWithMargin = new Rect(expected);
+        expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
+        assertFalse(from + ": expect " + expected
+                        + " not contains " + actual
+                        + " with error margin " + ROUNDING_ERROR_MARGIN,
+                expectedWithMargin.contains(actual));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index dbbbaac..862ebe13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -44,6 +44,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -87,7 +88,7 @@
     @Mock
     private Executor mForegroundExecutor;
     @Mock
-    private Executor mBackgroundExecutor;
+    private DelayableExecutor mBackgroundExecutor;
     @Mock
     private LocalBluetoothManager mLocalBluetoothManager;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
index fa02231..8a412bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.carrier;
 
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -219,4 +220,18 @@
                 mock(NetworkController.IconState.class),
                 0, 0, true, true, "", "", "", true, 0, true);
     }
+
+    @Test
+    public void testNoEmptyVisibleView_airplaneMode() {
+        CarrierTextController.CarrierTextCallbackInfo
+                info = new CarrierTextController.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{""},
+                true,
+                new int[]{0},
+                true /* airplaneMode */);
+        mCallback.updateCarrierInfo(info);
+        mTestableLooper.processAllMessages();
+        assertEquals(View.GONE, mQSCarrierGroup.getNoSimTextView().getVisibility());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 956bfd0..c874915 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -43,9 +44,9 @@
 import org.mockito.Mockito.anyString
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.doThrow
+import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
-import java.lang.IllegalArgumentException
 
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper
@@ -64,6 +65,7 @@
     @Mock private lateinit var viewRootImpl: ViewRootImpl
     @Mock private lateinit var shadeSpring: NotificationShadeDepthController.DepthAnimation
     @Mock private lateinit var globalActionsSpring: NotificationShadeDepthController.DepthAnimation
+    @Mock private lateinit var brightnessSpring: NotificationShadeDepthController.DepthAnimation
     @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
 
     private lateinit var statusBarStateListener: StatusBarStateController.StateListener
@@ -83,6 +85,7 @@
                 keyguardStateController, choreographer, wallpaperManager,
                 notificationShadeWindowController, dumpManager)
         notificationShadeDepthController.shadeSpring = shadeSpring
+        notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring
         notificationShadeDepthController.globalActionsSpring = globalActionsSpring
         notificationShadeDepthController.root = root
 
@@ -114,12 +117,27 @@
     }
 
     @Test
-    fun updateGlobalDialogVisibility_appliesBlur() {
+    fun updateGlobalDialogVisibility_animatesBlur() {
         notificationShadeDepthController.updateGlobalDialogVisibility(0.5f, root)
         verify(globalActionsSpring).animateTo(eq(maxBlur / 2), safeEq(root))
     }
 
     @Test
+    fun updateGlobalDialogVisibility_appliesBlur_withoutHomeControls() {
+        `when`(globalActionsSpring.radius).thenReturn(maxBlur)
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(maxBlur))
+    }
+
+    @Test
+    fun updateGlobalDialogVisibility_appliesBlur_unlessHomeControls() {
+        notificationShadeDepthController.showingHomeControls = true
+        `when`(globalActionsSpring.radius).thenReturn(maxBlur)
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(0))
+    }
+
+    @Test
     fun updateBlurCallback_setsBlurAndZoom() {
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
         verify(wallpaperManager).setWallpaperZoomOut(any(), anyFloat())
@@ -127,6 +145,23 @@
     }
 
     @Test
+    fun updateBlurCallback_setsBlur_whenExpanded() {
+        `when`(shadeSpring.radius).thenReturn(maxBlur)
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(maxBlur))
+    }
+
+    @Test
+    fun updateBlurCallback_appLaunchAnimation_overridesZoom() {
+        `when`(shadeSpring.radius).thenReturn(maxBlur)
+        val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters()
+        animProgress.linearProgress = 1f
+        notificationShadeDepthController.notificationLaunchAnimationParams = animProgress
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(0))
+    }
+
+    @Test
     fun updateBlurCallback_invalidWindow() {
         doThrow(IllegalArgumentException("test exception")).`when`(wallpaperManager)
                 .setWallpaperZoomOut(any(), anyFloat())
@@ -134,6 +169,48 @@
         verify(wallpaperManager).setWallpaperZoomOut(any(), anyFloat())
     }
 
+    @Test
+    fun brightnessMirrorVisible_whenVisible() {
+        notificationShadeDepthController.brightnessMirrorVisible = true
+        verify(brightnessSpring).animateTo(eq(maxBlur), any())
+    }
+
+    @Test
+    fun brightnessMirrorVisible_whenHidden() {
+        notificationShadeDepthController.brightnessMirrorVisible = false
+        verify(brightnessSpring).animateTo(eq(0), any())
+    }
+
+    @Test
+    fun brightnessMirror_hidesShadeBlur() {
+        // Brightness mirror is fully visible
+        `when`(brightnessSpring.ratio).thenReturn(1f)
+        // And shade is blurred
+        `when`(shadeSpring.radius).thenReturn(maxBlur)
+
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(notificationShadeWindowController).setBackgroundBlurRadius(0)
+        verify(blurUtils).applyBlur(safeEq(viewRootImpl), eq(0))
+    }
+
+    @Test
+    fun setNotificationLaunchAnimationParams_schedulesFrame() {
+        val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters()
+        animProgress.linearProgress = 0.5f
+        notificationShadeDepthController.notificationLaunchAnimationParams = animProgress
+        verify(choreographer).postFrameCallback(
+                eq(notificationShadeDepthController.updateBlurCallback))
+    }
+
+    @Test
+    fun setNotificationLaunchAnimationParams_whennNull_ignoresIfShadeHasNoBlur() {
+        val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters()
+        animProgress.linearProgress = 0.5f
+        `when`(shadeSpring.radius).thenReturn(0)
+        notificationShadeDepthController.notificationLaunchAnimationParams = animProgress
+        verify(shadeSpring, never()).animateTo(anyInt(), any())
+    }
+
     private fun <T : Any> safeEq(value: T): T {
         return eq(value) ?: value
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 83877f2..e55ea41 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -98,8 +98,10 @@
                 mLockscreenUserManager);
         mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
         mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
+        when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
+        when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
 
-        mHelper = new NotificationTestHelper(mContext, mDependency);
+        mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
 
         mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
                 mHandler, mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
index 0a38f16..2b94561 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
@@ -21,6 +21,7 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.widget.FrameLayout;
 
@@ -46,7 +47,10 @@
     @Before
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
-        mNotificationTestHelper = new NotificationTestHelper(getContext(), mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mHostLayout = new FrameLayout(getContext());
         mObserver = new AboveShelfObserver(mHostLayout);
         ExpandableNotificationRow row = mNotificationTestHelper.createRow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
index a07cfc3..cdef49d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -19,7 +19,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -31,6 +30,7 @@
 import android.view.View;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -39,8 +39,12 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -48,14 +52,22 @@
 public class ActivityLaunchAnimatorTest extends SysuiTestCase {
 
     private ActivityLaunchAnimator mLaunchAnimator;
-    private ActivityLaunchAnimator.Callback mCallback = mock(ActivityLaunchAnimator.Callback.class);
-    private NotificationShadeWindowViewController mNotificationShadeWindowViewController = mock(
-            NotificationShadeWindowViewController.class);
-    private NotificationShadeWindowView mNotificationShadeWindowView = mock(
-            NotificationShadeWindowView.class);
-    private NotificationListContainer mNotificationContainer
-            = mock(NotificationListContainer.class);
-    private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class);
+    @Mock
+    private ActivityLaunchAnimator.Callback mCallback;
+    @Mock
+    private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
+    @Mock
+    private NotificationShadeWindowView mNotificationShadeWindowView;
+    @Mock
+    private NotificationListContainer mNotificationContainer;
+    @Mock
+    private ExpandableNotificationRow mRow;
+    @Mock
+    private NotificationShadeDepthController mNotificationShadeDepthController;
+    @Mock
+    private NotificationPanelViewController mNotificationPanelViewController;
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
 
     @Before
     public void setUp() throws Exception {
@@ -66,7 +78,8 @@
         mLaunchAnimator = new ActivityLaunchAnimator(
                 mNotificationShadeWindowViewController,
                 mCallback,
-                mock(NotificationPanelViewController.class),
+                mNotificationPanelViewController,
+                mNotificationShadeDepthController,
                 mNotificationContainer);
 
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
index bf2d598..2904014 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
@@ -83,8 +83,8 @@
         mDynamicChildBindController.updateChildContentViews(mGroupNotifs);
 
         // THEN we free content views
-        verify(bindParams).freeContentViews(FLAG_CONTENT_VIEW_CONTRACTED);
-        verify(bindParams).freeContentViews(FLAG_CONTENT_VIEW_EXPANDED);
+        verify(bindParams).markContentViewsFreeable(FLAG_CONTENT_VIEW_CONTRACTED);
+        verify(bindParams).markContentViewsFreeable(FLAG_CONTENT_VIEW_EXPANDED);
         verify(mBindStage).requestRebind(eq(lastChild), any());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 97e0a31..277ac24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -32,6 +32,7 @@
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.annotation.UiThreadTest;
@@ -98,7 +99,11 @@
         mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
         when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
-        mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
+        NotificationTestHelper testHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        mRow = testHelper.createRow();
         mNotificationFilter = new NotificationFilter(mock(StatusBarStateController.class));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index 9079223..3d06c57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -110,7 +110,7 @@
         mVisualStabilityManager.setScreenOn(true);
         mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
         mVisualStabilityManager.setScreenOn(false);
-        verify(mCallback).onReorderingAllowed();
+        verify(mCallback).onChangeAllowed();
     }
 
     @Test
@@ -119,7 +119,7 @@
         mVisualStabilityManager.setScreenOn(true);
         mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
         mVisualStabilityManager.setPanelExpanded(false);
-        verify(mCallback).onReorderingAllowed();
+        verify(mCallback).onChangeAllowed();
     }
 
     @Test
@@ -130,7 +130,7 @@
         mVisualStabilityManager.setScreenOn(false);
         mVisualStabilityManager.setScreenOn(true);
         mVisualStabilityManager.setScreenOn(false);
-        verify(mCallback).onReorderingAllowed();
+        verify(mCallback).onChangeAllowed();
     }
 
     @Test
@@ -190,7 +190,7 @@
         mVisualStabilityManager.setPulsing(true);
         mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
         mVisualStabilityManager.setPulsing(false);
-        verify(mCallback).onReorderingAllowed();
+        verify(mCallback).onChangeAllowed();
     }
 
     @Test
@@ -204,7 +204,7 @@
         mVisualStabilityManager.temporarilyAllowReordering();
 
         // THEN callbacks are notified that reordering is allowed
-        verify(mCallback).onReorderingAllowed();
+        verify(mCallback).onChangeAllowed();
         assertTrue(mVisualStabilityManager.isReorderingAllowed());
     }
 
@@ -218,7 +218,7 @@
         mVisualStabilityManager.temporarilyAllowReordering();
 
         // THEN reordering is still not allowed
-        verify(mCallback, never()).onReorderingAllowed();
+        verify(mCallback, never()).onChangeAllowed();
         assertFalse(mVisualStabilityManager.isReorderingAllowed());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index f4fbd7b..43cf83f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -57,7 +57,7 @@
 
         /* ListEntry properties */
         entry.setParent(mParent);
-        entry.setSection(mSection);
+        entry.getAttachState().setSectionIndex(mSection);
         return entry;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index d7c7279..3adc3d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -417,8 +417,8 @@
         );
 
         // THEN each filtered notif records the NotifFilter that did it
-        assertEquals(preGroupFilter, mEntrySet.get(1).mExcludingFilter);
-        assertEquals(preGroupFilter, mEntrySet.get(3).mExcludingFilter);
+        assertEquals(preGroupFilter, mEntrySet.get(1).getExcludingFilter());
+        assertEquals(preGroupFilter, mEntrySet.get(3).getExcludingFilter());
     }
 
     @Test
@@ -447,8 +447,8 @@
         );
 
         // THEN each filtered notif records the filter that did it
-        assertEquals(filter1, mEntrySet.get(1).mExcludingFilter);
-        assertEquals(filter1, mEntrySet.get(3).mExcludingFilter);
+        assertEquals(filter1, mEntrySet.get(1).getExcludingFilter());
+        assertEquals(filter1, mEntrySet.get(3).getExcludingFilter());
     }
 
     @Test
@@ -471,7 +471,7 @@
         );
 
         // THEN each filtered notif records the filter that did it
-        assertEquals(filter1, mEntrySet.get(0).mExcludingFilter);
+        assertEquals(filter1, mEntrySet.get(0).getExcludingFilter());
     }
 
     @Test
@@ -502,8 +502,8 @@
         );
 
         // THEN each filtered notif records the filter that did it
-        assertEquals(filter1, mEntrySet.get(1).mExcludingFilter);
-        assertEquals(filter2, mEntrySet.get(2).mExcludingFilter);
+        assertEquals(filter1, mEntrySet.get(1).getExcludingFilter());
+        assertEquals(filter2, mEntrySet.get(2).getExcludingFilter());
     }
 
     @Test
@@ -541,8 +541,8 @@
         );
 
         // THEN each promoted notif records the promoter that did it
-        assertEquals(promoter, mEntrySet.get(2).mNotifPromoter);
-        assertEquals(promoter, mEntrySet.get(3).mNotifPromoter);
+        assertEquals(promoter, mEntrySet.get(2).getNotifPromoter());
+        assertEquals(promoter, mEntrySet.get(3).getNotifPromoter());
     }
 
     @Test
@@ -572,8 +572,8 @@
         verify(promoter2).shouldPromoteToTopLevel(mEntrySet.get(3));
 
         // THEN each promoter is recorded on each notif it promoted
-        assertEquals(promoter1, mEntrySet.get(2).mNotifPromoter);
-        assertEquals(promoter2, mEntrySet.get(3).mNotifPromoter);
+        assertEquals(promoter1, mEntrySet.get(2).getNotifPromoter());
+        assertEquals(promoter2, mEntrySet.get(3).getNotifPromoter());
     }
 
     @Test
@@ -650,34 +650,34 @@
         verify(pkg5Section).isInSection(mEntrySet.get(9));
 
         // THEN the correct section is assigned for entries in pkg1Section
-        assertEquals(pkg1Section, mEntrySet.get(2).mNotifSection);
+        assertEquals(pkg1Section, mEntrySet.get(2).getNotifSection());
         assertEquals(0, mEntrySet.get(2).getSection());
-        assertEquals(pkg1Section, mEntrySet.get(7).mNotifSection);
+        assertEquals(pkg1Section, mEntrySet.get(7).getNotifSection());
         assertEquals(0, mEntrySet.get(7).getSection());
 
         // THEN the correct section is assigned for entries in pkg2Section
-        assertEquals(pkg2Section, mEntrySet.get(1).mNotifSection);
+        assertEquals(pkg2Section, mEntrySet.get(1).getNotifSection());
         assertEquals(1, mEntrySet.get(1).getSection());
-        assertEquals(pkg2Section, mEntrySet.get(8).mNotifSection);
+        assertEquals(pkg2Section, mEntrySet.get(8).getNotifSection());
         assertEquals(1, mEntrySet.get(8).getSection());
-        assertEquals(pkg2Section, mBuiltList.get(3).mNotifSection);
+        assertEquals(pkg2Section, mBuiltList.get(3).getNotifSection());
         assertEquals(1, mBuiltList.get(3).getSection());
 
         // THEN no section was assigned to entries in pkg4Section (since they were filtered)
-        assertEquals(null, mEntrySet.get(0).mNotifSection);
+        assertEquals(null, mEntrySet.get(0).getNotifSection());
         assertEquals(-1, mEntrySet.get(0).getSection());
-        assertEquals(null, mEntrySet.get(10).mNotifSection);
+        assertEquals(null, mEntrySet.get(10).getNotifSection());
         assertEquals(-1, mEntrySet.get(10).getSection());
 
 
         // THEN the correct section is assigned for entries in pkg5Section
-        assertEquals(pkg5Section, mEntrySet.get(9).mNotifSection);
+        assertEquals(pkg5Section, mEntrySet.get(9).getNotifSection());
         assertEquals(3, mEntrySet.get(9).getSection());
 
         // THEN the children entries are assigned the same section as its parent
-        assertEquals(mBuiltList.get(3).mNotifSection, child(5).entry.mNotifSection);
+        assertEquals(mBuiltList.get(3).getNotifSection(), child(5).entry.getNotifSection());
         assertEquals(mBuiltList.get(3).getSection(), child(5).entry.getSection());
-        assertEquals(mBuiltList.get(3).mNotifSection, child(6).entry.mNotifSection);
+        assertEquals(mBuiltList.get(3).getNotifSection(), child(6).entry.getNotifSection());
         assertEquals(mBuiltList.get(3).getSection(), child(6).entry.getSection());
     }
 
@@ -700,7 +700,7 @@
 
         // THEN the entry that didn't have an explicit section gets assigned the DefaultSection
         assertEquals(1, notif(0).entry.getSection());
-        assertNotNull(notif(0).entry.mNotifSection);
+        assertNotNull(notif(0).entry.getNotifSection());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
new file mode 100644
index 0000000..dfc627e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.app.NotificationChannel
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class ConversationCoordinatorTest : SysuiTestCase() {
+
+    private var coordinator: ConversationCoordinator = ConversationCoordinator()
+
+    // captured listeners and pluggables:
+    private var promoter: NotifPromoter? = null
+
+    @Mock
+    private val pipeline: NotifPipeline? = null
+    @Mock
+    private val channel: NotificationChannel? = null
+    private var entry: NotificationEntry? = null
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(channel!!.isImportantConversation).thenReturn(true)
+
+        coordinator.attach(pipeline!!)
+
+        // capture arguments:
+        val notifPromoterCaptor = ArgumentCaptor.forClass(NotifPromoter::class.java)
+        verify(pipeline).addPromoter(notifPromoterCaptor.capture())
+        promoter = notifPromoterCaptor.value
+
+        entry = NotificationEntryBuilder().setChannel(channel).build()
+    }
+
+    @Test
+    fun testPromotesCurrentHUN() {
+
+        // only promote important conversations
+        assertTrue(promoter!!.shouldPromoteToTopLevel(entry))
+        assertFalse(promoter!!.shouldPromoteToTopLevel(NotificationEntryBuilder().build()))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
index 0c109c4..f3038ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -37,6 +39,9 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpViewBinder;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
@@ -63,6 +68,8 @@
 
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private HeadsUpManager mHeadsUpManager;
+    @Mock private HeadsUpViewBinder mHeadsUpViewBinder;
+    @Mock private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
     @Mock private RemoteInputController mRemoteInputController;
     @Mock private NotifLifetimeExtender.OnEndLifetimeExtensionCallback mEndLifetimeExtension;
@@ -76,6 +83,8 @@
 
         mCoordinator = new HeadsUpCoordinator(
                 mHeadsUpManager,
+                mHeadsUpViewBinder,
+                mNotificationInterruptStateProvider,
                 mRemoteInputManager
         );
 
@@ -168,6 +177,36 @@
     }
 
     @Test
+    public void testShowHUNOnInflationFinished() {
+        // WHEN a notification should HUN and its inflation is finished
+        when(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(true);
+
+        ArgumentCaptor<BindCallback> bindCallbackCaptor =
+                ArgumentCaptor.forClass(BindCallback.class);
+        mCollectionListener.onEntryAdded(mEntry);
+        verify(mHeadsUpViewBinder).bindHeadsUpView(eq(mEntry), bindCallbackCaptor.capture());
+
+        bindCallbackCaptor.getValue().onBindFinished(mEntry);
+
+        // THEN we tell the HeadsUpManager to show the notification
+        verify(mHeadsUpManager).showNotification(mEntry);
+    }
+
+    @Test
+    public void testNoHUNOnInflationFinished() {
+        // WHEN a notification shouldn't HUN and its inflation is finished
+        when(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(false);
+        ArgumentCaptor<BindCallback> bindCallbackCaptor =
+                ArgumentCaptor.forClass(BindCallback.class);
+        mCollectionListener.onEntryAdded(mEntry);
+
+        // THEN we never bind the heads up view or tell HeadsUpManager to show the notification
+        verify(mHeadsUpViewBinder, never()).bindHeadsUpView(
+                eq(mEntry), bindCallbackCaptor.capture());
+        verify(mHeadsUpManager, never()).showNotification(mEntry);
+    }
+
+    @Test
     public void testOnEntryRemovedRemovesHeadsUpNotification() {
         // GIVEN the current HUN is mEntry
         setCurrentHUN(mEntry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index 8143cf5..6b9e43b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -20,10 +20,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.os.RemoteException;
 import android.testing.AndroidTestingRunner;
@@ -41,9 +39,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
 import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -78,8 +74,6 @@
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private IStatusBarService mService;
     @Mock private NotifInflaterImpl mNotifInflater;
-    @Mock private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
-    @Mock private HeadsUpManager mHeadsUpManager;
 
     @Before
     public void setUp() {
@@ -94,9 +88,7 @@
                 mNotifInflater,
                 mErrorManager,
                 mock(NotifViewBarn.class),
-                mService,
-                mNotificationInterruptStateProvider,
-                mHeadsUpManager);
+                mService);
 
         ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
         mCoordinator.attach(mNotifPipeline);
@@ -180,24 +172,4 @@
         // THEN it isn't filtered from shade list
         assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0));
     }
-
-    @Test
-    public void testShowHUNOnInflationFinished() {
-        // WHEN a notification should HUN and its inflation is finished
-        when(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(true);
-        mCallback.onInflationFinished(mEntry);
-
-        // THEN we tell the HeadsUpManager to show the notification
-        verify(mHeadsUpManager).showNotification(mEntry);
-    }
-
-    @Test
-    public void testNoHUNOnInflationFinished() {
-        // WHEN a notification shouldn't HUN and its inflation is finished
-        when(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(false);
-        mCallback.onInflationFinished(mEntry);
-
-        // THEN we never tell the HeadsUpManager to show the notification
-        verify(mHeadsUpManager, never()).showNotification(mEntry);
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index cb37920..43dcbe3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -20,7 +20,6 @@
 
 import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL;
-import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -39,6 +38,7 @@
 import android.app.AppOpsManager;
 import android.app.NotificationChannel;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.ArraySet;
 import android.view.NotificationHeaderView;
@@ -79,7 +79,10 @@
     @Before
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
-        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mGroupRow = mNotificationTestHelper.createGroup();
         mGroupRow.setHeadsUpAnimatingAwayListener(
                 animatingAway -> mHeadsUpAnimatingAway = animatingAway);
@@ -135,22 +138,13 @@
     }
 
     @Test
-    public void testFreeContentViewWhenSafe() throws Exception {
-        ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_CONTENT_VIEW_ALL);
-
-        row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
-
-        assertNull(row.getPrivateLayout().getHeadsUpChild());
-    }
-
-    @Test
     public void setNeedsRedactionFreesViewWhenFalse() throws Exception {
         ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_CONTENT_VIEW_ALL);
         row.setNeedsRedaction(true);
         row.getPublicLayout().setVisibility(View.GONE);
 
         row.setNeedsRedaction(false);
-
+        TestableLooper.get(this).processAllMessages();
         assertNull(row.getPublicLayout().getContractedChild());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java
index 6408f7a..bdd82fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineTest.java
@@ -59,7 +59,10 @@
         MockitoAnnotations.initMocks(this);
         CommonNotifCollection collection = mock(CommonNotifCollection.class);
 
-        mBindPipeline = new NotifBindPipeline(collection, mock(NotifBindPipelineLogger.class));
+        mBindPipeline = new NotifBindPipeline(
+                collection,
+                mock(NotifBindPipelineLogger.class),
+                TestableLooper.get(this).getLooper());
         mBindPipeline.setStage(mStage);
 
         ArgumentCaptor<NotifCollectionListener> collectionListenerCaptor =
@@ -78,6 +81,7 @@
         // WHEN content is invalidated
         BindCallback callback = mock(BindCallback.class);
         mStage.requestRebind(mEntry, callback);
+        TestableLooper.get(this).processAllMessages();
 
         // WHEN stage finishes its work
         mStage.doWorkSynchronously();
@@ -94,6 +98,7 @@
         // GIVEN an in-progress pipeline run
         BindCallback callback = mock(BindCallback.class);
         CancellationSignal signal = mStage.requestRebind(mEntry, callback);
+        TestableLooper.get(this).processAllMessages();
 
         // WHEN the callback is cancelled.
         signal.cancel();
@@ -113,10 +118,12 @@
         // WHEN the pipeline is invalidated.
         BindCallback callback = mock(BindCallback.class);
         mStage.requestRebind(mEntry, callback);
+        TestableLooper.get(this).processAllMessages();
 
         // WHEN the pipeline is invalidated again before the work completes.
         BindCallback callback2 = mock(BindCallback.class);
         mStage.requestRebind(mEntry, callback2);
+        TestableLooper.get(this).processAllMessages();
 
         // WHEN the stage finishes all work.
         mStage.doWorkSynchronously();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
index 481bac2..7c8328d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
@@ -86,7 +86,7 @@
         when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
         mDependency.injectMockDependency(BubbleController.class);
 
-        mHelper = new NotificationTestHelper(mContext, mDependency);
+        mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
 
         mBlockingHelperManager = new NotificationBlockingHelperManager(
                 mContext, mGutsManager, mEntryManager, mock(MetricsLogger.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 6a65269..25da741 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -40,6 +40,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.view.ViewGroup;
@@ -94,8 +95,11 @@
                 .setContentTitle("Title")
                 .setContentText("Text")
                 .setStyle(new Notification.BigTextStyle().bigText("big text"));
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency).createRow(
-                mBuilder.build());
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        ExpandableNotificationRow row = helper.createRow(mBuilder.build());
         mRow = spy(row);
 
         final SmartReplyConstants smartReplyConstants = mock(SmartReplyConstants.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index 0f26898..b018b59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -76,13 +76,13 @@
     @Test
     @UiThreadTest
     public void testShowAppOpsIcons() {
-        View mockContracted = mock(View.class);
+        View mockContracted = mock(NotificationHeaderView.class);
         when(mockContracted.findViewById(com.android.internal.R.id.mic))
                 .thenReturn(mockContracted);
-        View mockExpanded = mock(View.class);
+        View mockExpanded = mock(NotificationHeaderView.class);
         when(mockExpanded.findViewById(com.android.internal.R.id.mic))
                 .thenReturn(mockExpanded);
-        View mockHeadsUp = mock(View.class);
+        View mockHeadsUp = mock(NotificationHeaderView.class);
         when(mockHeadsUp.findViewById(com.android.internal.R.id.mic))
                 .thenReturn(mockHeadsUp);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 6998edd..b6bd5e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -816,29 +816,4 @@
         verify(mMockINotificationManager, never()).createConversationNotificationChannelForPackage(
                 anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
     }
-
-    @Test
-    public void testAdjustImportanceTemporarilyAllowsReordering() {
-        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
-        mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
-        mNotificationInfo.bindNotification(
-                mShortcutManager,
-                mMockPackageManager,
-                mMockINotificationManager,
-                mVisualStabilityManager,
-                TEST_PACKAGE_NAME,
-                mNotificationChannel,
-                mEntry,
-                null,
-                null,
-                mIconFactory,
-                true);
-
-        mNotificationInfo.findViewById(R.id.silence).performClick();
-        mNotificationInfo.findViewById(R.id.done).performClick();
-
-        mTestableLooper.processAllMessages();
-
-        verify(mVisualStabilityManager).temporarilyAllowReordering();
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index bdd7a2e..be026f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -131,6 +131,7 @@
 
     @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
     @Mock private NotificationRowComponent.Builder mNotificationRowComponentBuilder;
+    @Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     private StatusBarNotification mSbn;
     private NotificationListenerService.RankingMap mRankingMap;
@@ -181,7 +182,8 @@
         NotifRemoteViewCache cache = new NotifRemoteViewCacheImpl(mEntryManager);
         NotifBindPipeline pipeline = new NotifBindPipeline(
                 mEntryManager,
-                mock(NotifBindPipelineLogger.class));
+                mock(NotifBindPipelineLogger.class),
+                TestableLooper.get(this).getLooper());
         mBgExecutor = new FakeExecutor(new FakeSystemClock());
         NotificationContentInflater binder = new NotificationContentInflater(
                 cache,
@@ -239,7 +241,8 @@
                                 mGutsManager,
                                 true,
                                 null,
-                                mFalsingManager
+                                mFalsingManager,
+                                mPeopleNotificationIdentifier
                         ));
 
         when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 5ad88c9..ed46423 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -72,6 +72,7 @@
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -118,6 +119,7 @@
     @Mock private INotificationManager mINotificationManager;
     @Mock private LauncherApps mLauncherApps;
     @Mock private ShortcutManager mShortcutManager;
+    @Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     @Before
     public void setUp() {
@@ -129,7 +131,7 @@
         mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
         mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
         mHandler = Handler.createAsync(mTestableLooper.getLooper());
-        mHelper = new NotificationTestHelper(mContext, mDependency);
+        mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
         when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
 
         mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
@@ -465,7 +467,8 @@
     }
 
     private NotificationMenuRowPlugin.MenuItem createTestMenuItem(ExpandableNotificationRow row) {
-        NotificationMenuRowPlugin menuRow = new NotificationMenuRow(mContext);
+        NotificationMenuRowPlugin menuRow =
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         menuRow.createMenu(row, row.getEntry().getSbn());
 
         NotificationMenuRowPlugin.MenuItem menuItem = menuRow.getLongpressMenuItem(mContext);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index b33d26f..99e8c7e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -40,6 +40,7 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 
 import org.junit.After;
@@ -54,11 +55,13 @@
 public class NotificationMenuRowTest extends LeakCheckedTest {
 
     private ExpandableNotificationRow mRow;
+    private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     @Before
     public void setup() {
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
         mRow = mock(ExpandableNotificationRow.class);
+        mPeopleNotificationIdentifier = mock(PeopleNotificationIdentifier.class);
         NotificationEntry entry = new NotificationEntryBuilder().build();
         when(mRow.getEntry()).thenReturn(entry);
     }
@@ -71,7 +74,8 @@
 
     @Test
     public void testAttachDetach() {
-        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        NotificationMenuRowPlugin row =
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         row.createMenu(mRow, null);
         ViewUtils.attachView(row.getMenuView());
         TestableLooper.get(this).processAllMessages();
@@ -81,7 +85,8 @@
 
     @Test
     public void testRecreateMenu() {
-        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        NotificationMenuRowPlugin row =
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         row.createMenu(mRow, null);
         assertTrue(row.getMenuView() != null);
         row.createMenu(mRow, null);
@@ -90,7 +95,8 @@
 
     @Test
     public void testResetUncreatedMenu() {
-        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        NotificationMenuRowPlugin row =
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         row.resetMenu();
     }
 
@@ -99,7 +105,7 @@
     public void testNoAppOpsInSlowSwipe() {
         Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 0);
 
-        NotificationMenuRow row = new NotificationMenuRow(mContext);
+        NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         row.createMenu(mRow, null);
 
         ViewGroup container = (ViewGroup) row.getMenuView();
@@ -111,7 +117,7 @@
     public void testNoSnoozeInSlowSwipe() {
         Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 0);
 
-        NotificationMenuRow row = new NotificationMenuRow(mContext);
+        NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         row.createMenu(mRow, null);
 
         ViewGroup container = (ViewGroup) row.getMenuView();
@@ -123,7 +129,7 @@
     public void testSnoozeInSlowSwipe() {
         Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 1);
 
-        NotificationMenuRow row = new NotificationMenuRow(mContext);
+        NotificationMenuRow row = new NotificationMenuRow(mContext, mPeopleNotificationIdentifier);
         row.createMenu(mRow, null);
 
         ViewGroup container = (ViewGroup) row.getMenuView();
@@ -133,7 +139,8 @@
 
     @Test
     public void testIsSnappedAndOnSameSide() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
 
         when(row.isMenuVisible()).thenReturn(true);
         when(row.isMenuSnapped()).thenReturn(true);
@@ -165,7 +172,8 @@
 
     @Test
     public void testGetMenuSnapTarget() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         when(row.isMenuOnLeft()).thenReturn(true);
         doReturn(30).when(row).getSpaceForMenu();
 
@@ -179,7 +187,8 @@
 
     @Test
     public void testIsSwipedEnoughToShowMenu() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         when(row.isMenuVisible()).thenReturn(true);
         when(row.isMenuOnLeft()).thenReturn(true);
         doReturn(40f).when(row).getMinimumSwipeDistance();
@@ -205,7 +214,8 @@
 
     @Test
     public void testIsWithinSnapMenuThreshold() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         doReturn(30f).when(row).getSnapBackThreshold();
         doReturn(50f).when(row).getDismissThreshold();
 
@@ -238,7 +248,8 @@
 
     @Test
     public void testShouldSnapBack() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         doReturn(40f).when(row).getSnapBackThreshold();
         when(row.isMenuVisible()).thenReturn(false);
         when(row.isMenuOnLeft()).thenReturn(true);
@@ -259,7 +270,8 @@
 
     @Test
     public void testCanBeDismissed() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         ExpandableNotificationRow parent = mock(ExpandableNotificationRow.class);
 
         when(row.getParent()).thenReturn(parent);
@@ -274,7 +286,8 @@
 
     @Test
     public void testIsTowardsMenu() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         when(row.isMenuVisible()).thenReturn(true);
         when(row.isMenuOnLeft()).thenReturn(true);
 
@@ -294,7 +307,8 @@
 
     @Test
     public void onSnapBack() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         NotificationMenuRowPlugin.OnMenuEventListener listener = mock(NotificationMenuRowPlugin
                 .OnMenuEventListener.class);
         row.setMenuClickListener(listener);
@@ -315,7 +329,8 @@
 
     @Test
     public void testOnSnap() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         when(row.isMenuOnLeft()).thenReturn(true);
         NotificationMenuRowPlugin.OnMenuEventListener listener = mock(NotificationMenuRowPlugin
                 .OnMenuEventListener.class);
@@ -335,7 +350,8 @@
 
     @Test
     public void testOnDismiss() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         doNothing().when(row).cancelDrag();
         row.onSnapOpen();
 
@@ -351,7 +367,8 @@
 
     @Test
     public void testOnDown() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         doNothing().when(row).beginDrag();
 
         row.onTouchStart();
@@ -361,7 +378,8 @@
 
     @Test
     public void testOnUp() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         row.onTouchStart();
 
         assertTrue("before onTouchEnd, isUserTouching is true", row.isUserTouching());
@@ -373,7 +391,8 @@
 
     @Test
     public void testIsMenuVisible() {
-        NotificationMenuRow row = Mockito.spy(new NotificationMenuRow((mContext)));
+        NotificationMenuRow row = Mockito.spy(
+                new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
         row.setMenuAlpha(0);
 
         assertFalse("when alpha is 0, menu is not visible", row.isMenuVisible());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 2134a3d..07f2085 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -38,6 +38,7 @@
 import android.graphics.drawable.Icon;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
+import android.testing.TestableLooper;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.widget.RemoteViews;
@@ -57,6 +58,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.icon.IconBuilder;
 import com.android.systemui.statusbar.notification.icon.IconManager;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpansionLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -91,6 +93,7 @@
     private static final String APP_NAME = "appName";
 
     private final Context mContext;
+    private final TestableLooper mTestLooper;
     private int mId;
     private final NotificationGroupManager mGroupManager;
     private ExpandableNotificationRow mRow;
@@ -100,9 +103,14 @@
     private final RowContentBindStage mBindStage;
     private final IconManager mIconManager;
     private StatusBarStateController mStatusBarStateController;
+    private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
-    public NotificationTestHelper(Context context, TestableDependency dependency) {
+    public NotificationTestHelper(
+            Context context,
+            TestableDependency dependency,
+            TestableLooper testLooper) {
         mContext = context;
+        mTestLooper = testLooper;
         dependency.injectMockDependency(NotificationMediaManager.class);
         dependency.injectMockDependency(BubbleController.class);
         dependency.injectMockDependency(NotificationShadeWindowController.class);
@@ -131,13 +139,17 @@
 
         CommonNotifCollection collection = mock(CommonNotifCollection.class);
 
-        mBindPipeline = new NotifBindPipeline(collection, mock(NotifBindPipelineLogger.class));
+        mBindPipeline = new NotifBindPipeline(
+                collection,
+                mock(NotifBindPipelineLogger.class),
+                mTestLooper.getLooper());
         mBindPipeline.setStage(mBindStage);
 
         ArgumentCaptor<NotifCollectionListener> collectionListenerCaptor =
                 ArgumentCaptor.forClass(NotifCollectionListener.class);
         verify(collection).addCollectionListener(collectionListenerCaptor.capture());
         mBindPipelineEntryListener = collectionListenerCaptor.getValue();
+        mPeopleNotificationIdentifier = mock(PeopleNotificationIdentifier.class);
     }
 
     /**
@@ -407,10 +419,11 @@
                 mock(NotificationMediaManager.class),
                 mock(ExpandableNotificationRow.OnAppOpsClickListener.class),
                 mock(FalsingManager.class),
-                mStatusBarStateController);
+                mStatusBarStateController,
+                mPeopleNotificationIdentifier);
         row.setAboveShelfChangedListener(aboveShelf -> { });
         mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
-        inflateAndWait(entry, mBindStage);
+        inflateAndWait(entry);
 
         // This would be done as part of onAsyncInflationFinished, but we skip large amounts of
         // the callback chain, so we need to make up for not adding it to the group manager
@@ -419,10 +432,10 @@
         return row;
     }
 
-    private static void inflateAndWait(NotificationEntry entry, RowContentBindStage stage)
-            throws Exception {
+    private void inflateAndWait(NotificationEntry entry) throws Exception {
         CountDownLatch countDownLatch = new CountDownLatch(1);
-        stage.requestRebind(entry, en -> countDownLatch.countDown());
+        mBindStage.requestRebind(entry, en -> countDownLatch.countDown());
+        mTestLooper.processAllMessages();
         assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java
index 0f2482c..96a58e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/RowContentBindStageTest.java
@@ -93,7 +93,7 @@
 
         // WHEN inflation flags are cleared and stage executed.
         final int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED;
-        params.freeContentViews(flags);
+        params.markContentViewsFreeable(flags);
         mRowContentBindStage.executeStage(mEntry, mRow, (en) -> { });
 
         // THEN binder unbinds flags.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
index b661b28..45f7c5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row.wrapper;
 
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.RemoteViews;
@@ -43,7 +44,11 @@
     @Before
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
-        mRow = new NotificationTestHelper(mContext, mDependency).createRow();
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        mRow = helper.createRow();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
index 18ea774..fbe4d73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
@@ -27,6 +27,7 @@
 import android.media.session.PlaybackState;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.RemoteViews;
@@ -97,7 +98,11 @@
         mNotif = builder.build();
         assertTrue(mNotif.hasMediaSession());
 
-        mRow = new NotificationTestHelper(mContext, mDependency).createRow(mNotif);
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        mRow = helper.createRow(mNotif);
 
         RemoteViews views = new RemoteViews(mContext.getPackageName(),
                 com.android.internal.R.layout.notification_template_material_big_media);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index 830e8d9..085bd90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -20,6 +20,7 @@
 
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -48,7 +49,11 @@
     public void setup() throws Exception {
         allowTestableLooperAsMainThread();
         mView = mock(View.class);
-        mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        mRow = helper.createRow();
         mNotificationViewWrapper = new TestableNotificationViewWrapper(mContext, mView, mRow);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index a2029c7..7037891 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.stack;
 
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -44,7 +45,10 @@
     @Before
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
-        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mGroup = mNotificationTestHelper.createGroup();
         mChildrenContainer = mGroup.getChildrenContainer();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
index ba2b946..d795cba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.filters.SmallTest;
@@ -66,7 +67,10 @@
                 mBypassController,
                 new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext));
         allowTestableLooperAsMainThread();
-        NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
+        NotificationTestHelper testHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mFirst = testHelper.createRow();
         mFirst.setHeadsUpAnimatingAwayListener(animatingAway
                 -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mFirst, animatingAway));
@@ -146,7 +150,10 @@
                 createSection(mFirst, mSecond),
                 createSection(null, null)
         });
-        NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
+        NotificationTestHelper testHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         ExpandableNotificationRow row = testHelper.createRow();
         NotificationEntry entry = mock(NotificationEntry.class);
         when(entry.getRow()).thenReturn(row);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index a74657e..e546dff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.TextView;
@@ -69,7 +70,10 @@
     @Before
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
-        NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
+        NotificationTestHelper testHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
         mFirst = testHelper.createRow();
         mDependency.injectTestDependency(DarkIconDispatcher.class, mDarkIconDispatcher);
         mHeadsUpStatusBarView = new HeadsUpStatusBarView(mContext, mock(View.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index f6a099d..67f94130 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -26,7 +26,6 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -236,8 +235,7 @@
         verify(mBindStage).requestRebind(eq(childEntry), callbackCaptor.capture());
         callbackCaptor.getValue().onBindFinished(childEntry);
 
-        verify(childEntry.getRow(), times(1)).freeContentViewWhenSafe(mHeadsUpManager
-            .getContentFlag());
+        assertTrue((params.getContentViews() & FLAG_CONTENT_VIEW_HEADS_UP) == 0);
         assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index b9c5b7c..dd28687 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -152,7 +152,10 @@
         when(mContentIntent.getCreatorUserHandle()).thenReturn(UserHandle.of(1));
         when(mContentIntent.getIntent()).thenReturn(mContentIntentInner);
 
-        mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
+        mNotificationTestHelper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
 
         // Create standard notification with contentIntent
         mNotificationRow = mNotificationTestHelper.createRow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 679ac22..b905bdd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -102,6 +102,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
 import com.android.systemui.statusbar.RemoteInputController;
@@ -249,6 +250,7 @@
     @Mock private ExtensionController mExtensionController;
     @Mock private UserInfoControllerImpl mUserInfoControllerImpl;
     @Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
+    @Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
     private ShadeController mShadeController;
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
     private InitController mInitController = new InitController();
@@ -404,6 +406,7 @@
                 mPhoneStatusBarPolicy,
                 mKeyguardIndicationController,
                 mDismissCallbackRegistry,
+                mNotificationShadeDepthControllerLazy,
                 mStatusBarTouchableRegionManager);
 
         when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index b5f57b6..962d773 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -39,6 +39,7 @@
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.provider.Settings;
@@ -101,6 +102,7 @@
     protected NetworkRegistrationInfo mFakeRegInfo;
     protected ConnectivityManager mMockCm;
     protected WifiManager mMockWm;
+    protected NetworkScoreManager mMockNsm;
     protected SubscriptionManager mMockSm;
     protected TelephonyManager mMockTm;
     protected BroadcastDispatcher mMockBd;
@@ -148,6 +150,7 @@
         mMockSm = mock(SubscriptionManager.class);
         mMockCm = mock(ConnectivityManager.class);
         mMockBd = mock(BroadcastDispatcher.class);
+        mMockNsm = mock(NetworkScoreManager.class);
         mMockSubDefaults = mock(SubscriptionDefaults.class);
         mNetCapabilities = new NetworkCapabilities();
         when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
@@ -196,8 +199,8 @@
             return null;
         }).when(mMockProvisionController).addCallback(any());
 
-        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
-                mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
+        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+                mMockNsm, mMockSm, mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mMockProvisionController, mMockBd);
         setupNetworkController();
@@ -244,18 +247,17 @@
     }
 
     protected NetworkControllerImpl setUpNoMobileData() {
-      when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
-      NetworkControllerImpl networkControllerNoMobile
-              = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
+        when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
+        NetworkControllerImpl networkControllerNoMobile =
+                new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockNsm, mMockSm,
                         mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
                         mock(AccessPointControllerImpl.class),
                         mock(DataUsageController.class), mMockSubDefaults,
                         mock(DeviceProvisionedController.class), mMockBd);
 
-      setupNetworkController();
+        setupNetworkController();
 
-      return networkControllerNoMobile;
-
+        return networkControllerNoMobile;
     }
 
     // 2 Bars 3G GSM.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 75f2619..6fffcff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -102,8 +102,8 @@
     public void test4gDataIcon() {
         // Switch to showing 4g icon and re-initialize the NetworkController.
         mConfig.show4gForLte = true;
-        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
-                mConfig, Looper.getMainLooper(), mCallbackHandler,
+        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+                mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
                 mock(AccessPointControllerImpl.class),
                 mock(DataUsageController.class), mMockSubDefaults,
                 mock(DeviceProvisionedController.class), mMockBd);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index b922f06..399b5c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -58,8 +58,8 @@
         // Turn off mobile network support.
         when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
         // Create a new NetworkController as this is currently handled in constructor.
-        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
-                mConfig, Looper.getMainLooper(), mCallbackHandler,
+        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+                mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
         setupNetworkController();
@@ -120,8 +120,8 @@
         // Turn off mobile network support.
         when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
         // Create a new NetworkController as this is currently handled in constructor.
-        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
-                mConfig, Looper.getMainLooper(), mCallbackHandler,
+        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+                mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
         setupNetworkController();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index 86add98..e88b514 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -105,8 +105,11 @@
 
     @Test
     public void testSendRemoteInput_intentContainsResultsAndSource() throws Exception {
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency)
-                .createRow();
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        ExpandableNotificationRow row = helper.createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
 
         setTestPendingIntent(view);
@@ -127,7 +130,11 @@
 
     private UserHandle getTargetInputMethodUser(UserHandle fromUser, UserHandle toUser)
             throws Exception {
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency).createRow(
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        ExpandableNotificationRow row = helper.createRow(
                 DUMMY_MESSAGE_APP_PKG,
                 UserHandle.getUid(fromUser.getIdentifier(), DUMMY_MESSAGE_APP_ID),
                 toUser);
@@ -169,8 +176,11 @@
 
     @Test
     public void testNoCrashWithoutVisibilityListener() throws Exception {
-        ExpandableNotificationRow row = new NotificationTestHelper(mContext, mDependency)
-                .createRow();
+        NotificationTestHelper helper = new NotificationTestHelper(
+                mContext,
+                mDependency,
+                TestableLooper.get(this));
+        ExpandableNotificationRow row = helper.createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
 
         view.setOnVisibilityChangedListener(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
index bc3a5b1..0a10ab2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/toast/ToastUITest.java
@@ -16,29 +16,43 @@
 
 package com.android.systemui.toast;
 
+import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
+import static android.widget.ToastPresenter.TEXT_TOAST_LAYOUT;
+
 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.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.INotificationManager;
 import android.app.ITransientNotificationCallback;
+import android.content.Context;
 import android.os.Binder;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.testing.AndroidTestingRunner;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 import android.widget.Toast;
+import android.widget.ToastPresenter;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
+import com.android.internal.util.IntPair;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.CommandQueue;
 
@@ -49,32 +63,53 @@
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class ToastUITest extends SysuiTestCase {
+    private static final int ANDROID_UID = 1000;
+    private static final int SYSTEMUI_UID = 10140;
+
+    private static final int UID_1 = 10255;
     private static final String PACKAGE_NAME_1 = "com.example1.test";
     private static final Binder TOKEN_1 = new Binder();
     private static final Binder WINDOW_TOKEN_1 = new Binder();
+
+    private static final int UID_2 = 10256;
     private static final String PACKAGE_NAME_2 = "com.example2.test";
     private static final Binder TOKEN_2 = new Binder();
     private static final Binder WINDOW_TOKEN_2 = new Binder();
+
     private static final String TEXT = "Hello World";
     private static final int MESSAGE_RES_ID = R.id.message;
 
+    private Context mContextSpy;
+    private ToastUI mToastUI;
+    @Mock private LayoutInflater mLayoutInflater;
     @Mock private CommandQueue mCommandQueue;
     @Mock private WindowManager mWindowManager;
     @Mock private INotificationManager mNotificationManager;
-    @Mock private AccessibilityManager mAccessibilityManager;
+    @Mock private IAccessibilityManager mAccessibilityManager;
     @Mock private ITransientNotificationCallback mCallback;
     @Captor private ArgumentCaptor<View> mViewCaptor;
     @Captor private ArgumentCaptor<ViewGroup.LayoutParams> mParamsCaptor;
-    private ToastUI mToastUI;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mToastUI = new ToastUI(mContext, mCommandQueue, mWindowManager, mNotificationManager,
+
+        // This is because inflate will result in WindowManager (WM) calls, which will fail since we
+        // are mocking it, so we mock LayoutInflater with the view obtained before mocking WM.
+        View view = ToastPresenter.getTextToastView(mContext, TEXT);
+        when(mLayoutInflater.inflate(eq(TEXT_TOAST_LAYOUT), any())).thenReturn(view);
+        mContext.addMockSystemService(LayoutInflater.class, mLayoutInflater);
+
+        mContext.addMockSystemService(WindowManager.class, mWindowManager);
+        mContextSpy = spy(mContext);
+        doReturn(mContextSpy).when(mContextSpy).createContextAsUser(any(), anyInt());
+
+        mToastUI = new ToastUI(mContextSpy, mCommandQueue, mNotificationManager,
                 mAccessibilityManager);
     }
 
@@ -87,7 +122,8 @@
 
     @Test
     public void testShowToast_addsCorrectViewToWindowManager() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+                null);
 
         verify(mWindowManager).addView(mViewCaptor.capture(), any());
         View view = mViewCaptor.getValue();
@@ -96,13 +132,14 @@
 
     @Test
     public void testShowToast_addsViewWithCorrectLayoutParamsToWindowManager() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+                null);
 
         verify(mWindowManager).addView(any(), mParamsCaptor.capture());
         ViewGroup.LayoutParams params = mParamsCaptor.getValue();
         assertThat(params).isInstanceOf(WindowManager.LayoutParams.class);
         WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
-        assertThat(windowParams.packageName).isEqualTo(mContext.getPackageName());
+        assertThat(windowParams.packageName).isEqualTo(mContextSpy.getPackageName());
         assertThat(windowParams.getTitle()).isEqualTo("Toast");
         assertThat(windowParams.token).isEqualTo(WINDOW_TOKEN_1);
         assertThat(windowParams.privateFlags
@@ -111,19 +148,7 @@
 
     @Test
     public void testShowToast_forAndroidPackage_addsAllUserFlag() throws Exception {
-        mToastUI.showToast("android", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
-
-        verify(mWindowManager).addView(any(), mParamsCaptor.capture());
-        ViewGroup.LayoutParams params = mParamsCaptor.getValue();
-        assertThat(params).isInstanceOf(WindowManager.LayoutParams.class);
-        WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
-        assertThat(windowParams.privateFlags
-                & WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isNotEqualTo(0);
-    }
-
-    @Test
-    public void testShowToast_forSystemUiPackage_addsAllUserFlag() throws Exception {
-        mToastUI.showToast("com.android.systemui", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(ANDROID_UID, "android", TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 null);
 
         verify(mWindowManager).addView(any(), mParamsCaptor.capture());
@@ -135,8 +160,21 @@
     }
 
     @Test
+    public void testShowToast_forSystemUiPackage_addsAllUserFlag() throws Exception {
+        mToastUI.showToast(SYSTEMUI_UID, "com.android.systemui", TOKEN_1, TEXT, WINDOW_TOKEN_1,
+                Toast.LENGTH_LONG, null);
+
+        verify(mWindowManager).addView(any(), mParamsCaptor.capture());
+        ViewGroup.LayoutParams params = mParamsCaptor.getValue();
+        assertThat(params).isInstanceOf(WindowManager.LayoutParams.class);
+        WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
+        assertThat(windowParams.privateFlags
+                & WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS).isNotEqualTo(0);
+    }
+
+    @Test
     public void testShowToast_callsCallback() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
 
         verify(mCallback).onToastShown();
@@ -144,14 +182,24 @@
 
     @Test
     public void testShowToast_sendsAccessibilityEvent() throws Exception {
-        when(mAccessibilityManager.isEnabled()).thenReturn(true);
+        // Enable accessibility
+        when(mAccessibilityManager.addClient(any(), anyInt())).thenReturn(
+                IntPair.of(STATE_FLAG_ACCESSIBILITY_ENABLED, AccessibilityEvent.TYPES_ALL_MASK));
+        // AccessibilityManager recycles the event that goes over the wire after making the binder
+        // call to the service. Since we are mocking the service, that call is local, so if we use
+        // ArgumentCaptor or ArgumentMatcher it will retain a reference to the recycled event, which
+        // will already have its state reset by the time we verify its contents. So, instead, we
+        // serialize it at call-time and later on deserialize it to verity its contents.
+        Parcel eventParcel = Parcel.obtain();
+        doAnswer(writeArgumentToParcel(0, eventParcel)).when(
+                mAccessibilityManager).sendAccessibilityEvent(any(), anyInt());
 
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG, null);
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+                null);
 
-        ArgumentCaptor<AccessibilityEvent> eventCaptor = ArgumentCaptor.forClass(
-                AccessibilityEvent.class);
-        verify(mAccessibilityManager).sendAccessibilityEvent(eventCaptor.capture());
-        AccessibilityEvent event = eventCaptor.getValue();
+        eventParcel.setDataPosition(0);
+        assertThat(eventParcel.dataSize()).isGreaterThan(0);
+        AccessibilityEvent event = AccessibilityEvent.CREATOR.createFromParcel(eventParcel);
         assertThat(event.getEventType()).isEqualTo(
                 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
         assertThat(event.getClassName()).isEqualTo(Toast.class.getName());
@@ -160,7 +208,7 @@
 
     @Test
     public void testHideToast_removesView() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
         View view = verifyWmAddViewAndAttachToParent();
 
@@ -171,17 +219,17 @@
 
     @Test
     public void testHideToast_finishesToken() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
 
         mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1);
 
-        verify(mNotificationManager).finishToken(PACKAGE_NAME_1, WINDOW_TOKEN_1);
+        verify(mNotificationManager).finishToken(PACKAGE_NAME_1, TOKEN_1);
     }
 
     @Test
     public void testHideToast_callsCallback() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
 
         mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_1);
@@ -191,7 +239,7 @@
 
     @Test
     public void testHideToast_whenNotCurrentToastToken_doesNotHideToast() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
 
         mToastUI.hideToast(PACKAGE_NAME_1, TOKEN_2);
@@ -201,7 +249,7 @@
 
     @Test
     public void testHideToast_whenNotCurrentToastPackage_doesNotHideToast() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
 
         mToastUI.hideToast(PACKAGE_NAME_2, TOKEN_1);
@@ -211,14 +259,15 @@
 
     @Test
     public void testShowToast_afterShowToast_hidesCurrentToast() throws Exception {
-        mToastUI.showToast(PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
+        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                 mCallback);
         View view = verifyWmAddViewAndAttachToParent();
 
-        mToastUI.showToast(PACKAGE_NAME_2, TOKEN_2, TEXT, WINDOW_TOKEN_2, Toast.LENGTH_LONG, null);
+        mToastUI.showToast(UID_2, PACKAGE_NAME_2, TOKEN_2, TEXT, WINDOW_TOKEN_2, Toast.LENGTH_LONG,
+                null);
 
         verify(mWindowManager).removeViewImmediate(view);
-        verify(mNotificationManager).finishToken(PACKAGE_NAME_1, WINDOW_TOKEN_1);
+        verify(mNotificationManager).finishToken(PACKAGE_NAME_1, TOKEN_1);
         verify(mCallback).onToastHidden();
     }
 
@@ -227,8 +276,15 @@
         verify(mWindowManager).addView(viewCaptor.capture(), any());
         View view = viewCaptor.getValue();
         // Simulate attaching to view hierarchy
-        ViewGroup parent = new FrameLayout(mContext);
+        ViewGroup parent = new FrameLayout(mContextSpy);
         parent.addView(view);
         return view;
     }
+
+    private Answer<Void> writeArgumentToParcel(int i, Parcel dest) {
+        return inv -> {
+            inv.<Parcelable>getArgument(i).writeToParcel(dest, 0);
+            return null;
+        };
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java
index ce8085a..486939d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/SysuiLifecycleTest.java
@@ -25,6 +25,8 @@
 
 import static com.android.systemui.util.SysuiLifecycle.viewAttachLifecycle;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -35,12 +37,15 @@
 import android.testing.ViewUtils;
 import android.view.View;
 
+import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleEventObserver;
 import androidx.lifecycle.LifecycleOwner;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -49,39 +54,122 @@
 @SmallTest
 public class SysuiLifecycleTest extends SysuiTestCase {
 
+    private View mView;
+
+    @Before
+    public void setUp() {
+        mView = new View(mContext);
+    }
+
+    @After
+    public void tearDown() {
+        if (mView.isAttachedToWindow()) {
+            ViewUtils.detachView(mView);
+            TestableLooper.get(this).processAllMessages();
+        }
+    }
+
     @Test
     public void testAttach() {
-        View v = new View(mContext);
         LifecycleEventObserver observer = mock(LifecycleEventObserver.class);
-        LifecycleOwner lifecycle = viewAttachLifecycle(v);
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
         lifecycle.getLifecycle().addObserver(observer);
 
-        ViewUtils.attachView(v);
+        ViewUtils.attachView(mView);
         TestableLooper.get(this).processAllMessages();
 
         verify(observer).onStateChanged(eq(lifecycle), eq(ON_CREATE));
         verify(observer).onStateChanged(eq(lifecycle), eq(ON_START));
         verify(observer).onStateChanged(eq(lifecycle), eq(ON_RESUME));
-
-        ViewUtils.detachView(v);
-        TestableLooper.get(this).processAllMessages();
     }
 
     @Test
     public void testDetach() {
-        View v = new View(mContext);
         LifecycleEventObserver observer = mock(LifecycleEventObserver.class);
-        LifecycleOwner lifecycle = viewAttachLifecycle(v);
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
         lifecycle.getLifecycle().addObserver(observer);
 
-        ViewUtils.attachView(v);
+        ViewUtils.attachView(mView);
         TestableLooper.get(this).processAllMessages();
 
-        ViewUtils.detachView(v);
+        ViewUtils.detachView(mView);
         TestableLooper.get(this).processAllMessages();
 
         verify(observer).onStateChanged(eq(lifecycle), eq(ON_PAUSE));
         verify(observer).onStateChanged(eq(lifecycle), eq(ON_STOP));
         verify(observer).onStateChanged(eq(lifecycle), eq(ON_DESTROY));
     }
+
+    @Test
+    public void testStateBeforeAttach() {
+        // WHEN a lifecycle is obtained from a view
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
+        // THEN the lifecycle state should be INITIAZED
+        assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(
+                Lifecycle.State.INITIALIZED);
+    }
+
+    @Test
+    public void testStateAfterAttach() {
+        // WHEN a lifecycle is obtained from a view
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
+        // AND the view is attached
+        ViewUtils.attachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        // THEN the lifecycle state should be RESUMED
+        assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.RESUMED);
+    }
+
+    @Test
+    public void testStateAfterDetach() {
+        // WHEN a lifecycle is obtained from a view
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
+        // AND the view is detached
+        ViewUtils.attachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        ViewUtils.detachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        // THEN the lifecycle state should be DESTROYED
+        assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.DESTROYED);
+    }
+
+    @Test
+    public void testStateAfterReattach() {
+        // WHEN a lifecycle is obtained from a view
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
+        // AND the view is re-attached
+        ViewUtils.attachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        ViewUtils.detachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        ViewUtils.attachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        // THEN the lifecycle state should still be DESTROYED, err RESUMED?
+        assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.RESUMED);
+    }
+
+    @Test
+    public void testStateWhenViewAlreadyAttached() {
+        // GIVEN that a view is already attached
+        ViewUtils.attachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        // WHEN a lifecycle is obtained from a view
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
+        // THEN the lifecycle state should be RESUMED
+        assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.RESUMED);
+    }
+
+    @Test
+    public void testStateWhenViewAlreadyDetached() {
+        // GIVEN that a view is already detached
+        ViewUtils.attachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        ViewUtils.detachView(mView);
+        TestableLooper.get(this).processAllMessages();
+        // WHEN a lifecycle is obtained from a view
+        LifecycleOwner lifecycle = viewAttachLifecycle(mView);
+        // THEN the lifecycle state should be INITIALIZED
+        assertThat(lifecycle.getLifecycle().getCurrentState()).isEqualTo(
+                Lifecycle.State.INITIALIZED);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt
index f1672b1..f6b7b74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt
@@ -106,6 +106,10 @@
                 location[1] = targetCenterY - targetSize / 2 // y = 800
             }
         }.`when`(targetView).getLocationOnScreen(ArgumentMatchers.any())
+        doAnswer { invocation ->
+            (invocation.arguments[0] as Runnable).run()
+            true
+        }.`when`(targetView).post(ArgumentMatchers.any())
         `when`(targetView.context).thenReturn(context)
 
         magneticTarget = MagnetizedObject.MagneticTarget(targetView, magneticFieldRadius)
@@ -408,6 +412,10 @@
         `when`(secondTargetView.width).thenReturn(targetSize)  // width = 200
         `when`(secondTargetView.height).thenReturn(targetSize) // height = 200
         doAnswer { invocation ->
+            (invocation.arguments[0] as Runnable).run()
+            true
+        }.`when`(secondTargetView).post(ArgumentMatchers.any())
+        doAnswer { invocation ->
             (invocation.arguments[0] as IntArray).also { location ->
                 // Return the top left of the target.
                 location[0] = secondTargetCenterX - targetSize / 2 // x = 0
diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp
index 96a4d20..24df5f6 100644
--- a/packages/Tethering/apex/Android.bp
+++ b/packages/Tethering/apex/Android.bp
@@ -17,6 +17,7 @@
 apex {
     name: "com.android.tethering",
     updatable: true,
+    min_sdk_version: "R",
     java_libs: ["framework-tethering"],
     apps: ["Tethering"],
     manifest: "manifest.json",
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index c5478d2..5b6fe91 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -33,6 +33,7 @@
 import android.net.LinkProperties;
 import android.net.MacAddress;
 import android.net.RouteInfo;
+import android.net.TetherOffloadRuleParcel;
 import android.net.TetheredClient;
 import android.net.TetheringManager;
 import android.net.TetheringRequestParcel;
@@ -40,7 +41,7 @@
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.DhcpServingParamsParcelExt;
-import android.net.dhcp.IDhcpLeaseCallbacks;
+import android.net.dhcp.IDhcpEventCallbacks;
 import android.net.dhcp.IDhcpServer;
 import android.net.ip.IpNeighborMonitor.NeighborEvent;
 import android.net.ip.RouterAdvertisementDaemon.RaParams;
@@ -279,6 +280,19 @@
             return new Ipv6ForwardingRule(newUpstreamIfindex, downstreamIfindex, address, srcMac,
                     dstMac);
         }
+
+        // Don't manipulate TetherOffloadRuleParcel directly because implementing onNewUpstream()
+        // would be error-prone due to generated stable AIDL classes not having a copy constructor.
+        public TetherOffloadRuleParcel toTetherOffloadRuleParcel() {
+            final TetherOffloadRuleParcel parcel = new TetherOffloadRuleParcel();
+            parcel.inputInterfaceIndex = upstreamIfindex;
+            parcel.outputInterfaceIndex = downstreamIfindex;
+            parcel.destination = address.getAddress();
+            parcel.prefixLength = 128;
+            parcel.srcL2Address = srcMac.toByteArray();
+            parcel.dstL2Address = dstMac.toByteArray();
+            return parcel;
+        }
     }
     private final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> mIpv6ForwardingRules =
             new LinkedHashMap<>();
@@ -448,7 +462,7 @@
         }
     }
 
-    private class DhcpLeaseCallback extends IDhcpLeaseCallbacks.Stub {
+    private class DhcpLeaseCallback extends IDhcpEventCallbacks.Stub {
         @Override
         public void onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables) {
             final ArrayList<TetheredClient> leases = new ArrayList<>();
@@ -482,6 +496,11 @@
         }
 
         @Override
+        public void onNewPrefixRequest(IpPrefix currentPrefix) {
+            //TODO: add specific implementation.
+        }
+
+        @Override
         public int getInterfaceVersion() {
             return this.VERSION;
         }
@@ -815,9 +834,7 @@
 
     private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
         try {
-            mNetd.tetherRuleAddDownstreamIpv6(mInterfaceParams.index, rule.upstreamIfindex,
-                    rule.address.getAddress(),  mInterfaceParams.macAddr.toByteArray(),
-                    rule.dstMac.toByteArray());
+            mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
             mIpv6ForwardingRules.put(rule.address, rule);
         } catch (RemoteException | ServiceSpecificException e) {
             mLog.e("Could not add IPv6 downstream rule: ", e);
@@ -826,7 +843,7 @@
 
     private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule, boolean removeFromMap) {
         try {
-            mNetd.tetherRuleRemoveDownstreamIpv6(rule.upstreamIfindex, rule.address.getAddress());
+            mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
             if (removeFromMap) {
                 mIpv6ForwardingRules.remove(rule.address);
             }
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index bd60594f..639cf65 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -20,6 +20,7 @@
 import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
 import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
 import static android.net.TetheringManager.TETHERING_INVALID;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
@@ -537,6 +538,7 @@
     private static boolean isValidDownstreamType(int type) {
         switch (type) {
             case TETHERING_BLUETOOTH:
+            case TETHERING_ETHERNET:
             case TETHERING_USB:
             case TETHERING_WIFI:
                 return true;
@@ -650,6 +652,11 @@
 
     private void handleRequestLatestTetheringEntitlementValue(int downstream,
             ResultReceiver receiver, boolean showEntitlementUi) {
+        if (!isValidDownstreamType(downstream)) {
+            receiver.send(TETHER_ERROR_ENTITLEMENT_UNKNOWN, null);
+            return;
+        }
+
         final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
         if (!isTetherProvisioningRequired(config)) {
             receiver.send(TETHER_ERROR_NO_ERROR, null);
diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp
index 1a1c30d..620261b 100644
--- a/packages/Tethering/tests/integration/Android.bp
+++ b/packages/Tethering/tests/integration/Android.bp
@@ -39,4 +39,9 @@
         "android.test.base",
         "android.test.mock",
     ],
+    jni_libs: [
+        // For mockito extended
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
 }
diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 843a4f1..b02bb23 100644
--- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
 import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -57,14 +58,17 @@
 
 import java.io.FileDescriptor;
 import java.net.Inet4Address;
+import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 @RunWith(AndroidJUnit4.class)
 @MediumTest
@@ -109,7 +113,7 @@
     }
 
     private void cleanUp() throws Exception {
-        mTm.stopTethering(TetheringManager.TETHERING_ETHERNET);
+        mTm.stopTethering(TETHERING_ETHERNET);
         if (mTetheringEventCallback != null) {
             mTetheringEventCallback.awaitInterfaceUntethered();
             mTetheringEventCallback.unregister();
@@ -150,10 +154,7 @@
         Log.d(TAG, "Including test interfaces");
         mEm.setIncludeTestInterfaces(true);
 
-        Log.d(TAG, "Requesting tethered interface");
-        mTetheredInterfaceRequester.requestInterface();
-
-        final String iface = mTetheredInterfaceRequester.awaitRequestedInterface();
+        final String iface = mTetheredInterfaceRequester.getInterface();
         assertEquals("TetheredInterfaceCallback for unexpected interface",
                 mTestIface.getInterfaceName(), iface);
 
@@ -165,14 +166,13 @@
         // This test requires manipulating packets. Skip if there is a physical Ethernet connected.
         assumeFalse(mEm.isAvailable());
 
-        Log.d(TAG, "Requesting tethered interface");
-        mTetheredInterfaceRequester.requestInterface();
+        CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface();
 
         mEm.setIncludeTestInterfaces(true);
 
         mTestIface = createTestInterface();
 
-        final String iface = mTetheredInterfaceRequester.awaitRequestedInterface();
+        final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals("TetheredInterfaceCallback for unexpected interface",
                 mTestIface.getInterfaceName(), iface);
 
@@ -180,12 +180,54 @@
     }
 
     @Test
+    public void testStaticIpv4() throws Exception {
+        assumeFalse(mEm.isAvailable());
+
+        mEm.setIncludeTestInterfaces(true);
+
+        mTestIface = createTestInterface();
+
+        final String iface = mTetheredInterfaceRequester.getInterface();
+        assertEquals("TetheredInterfaceCallback for unexpected interface",
+                mTestIface.getInterfaceName(), iface);
+
+        assertInvalidStaticIpv4Request(iface, null, null);
+        assertInvalidStaticIpv4Request(iface, "2001:db8::1/64", "2001:db8:2::/64");
+        assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", "2001:db8:2::/28");
+        assertInvalidStaticIpv4Request(iface, "2001:db8:2::/28", "192.0.2.2/28");
+        assertInvalidStaticIpv4Request(iface, "192.0.2.2/28", null);
+        assertInvalidStaticIpv4Request(iface, null, "192.0.2.2/28");
+        assertInvalidStaticIpv4Request(iface, "192.0.2.3/27", "192.0.2.2/28");
+
+        final String localAddr = "192.0.2.3/28";
+        final String clientAddr = "192.0.2.2/28";
+        mTetheringEventCallback = enableEthernetTethering(iface,
+                requestWithStaticIpv4(localAddr, clientAddr));
+
+        mTetheringEventCallback.awaitInterfaceTethered();
+        assertInterfaceHasIpAddress(iface, localAddr);
+
+        byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray();
+        byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray();
+
+        FileDescriptor fd = mTestIface.getFileDescriptor().getFileDescriptor();
+        mTapPacketReader = makePacketReader(fd, getMTU(mTestIface));
+        DhcpResults dhcpResults = runDhcp(fd, client1);
+        assertEquals(new LinkAddress(clientAddr), dhcpResults.ipAddress);
+
+        try {
+            runDhcp(fd, client2);
+            fail("Only one client should get an IP address");
+        } catch (TimeoutException expected) { }
+
+    }
+
+    @Test
     public void testPhysicalEthernet() throws Exception {
         assumeTrue(mEm.isAvailable());
 
         // Get an interface to use.
-        mTetheredInterfaceRequester.requestInterface();
-        String iface = mTetheredInterfaceRequester.awaitRequestedInterface();
+        final String iface = mTetheredInterfaceRequester.getInterface();
 
         // Enable Ethernet tethering and check that it starts.
         mTetheringEventCallback = enableEthernetTethering(iface);
@@ -275,7 +317,8 @@
         }
     }
 
-    private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception {
+    private MyTetheringEventCallback enableEthernetTethering(String iface,
+            TetheringRequest request) throws Exception {
         MyTetheringEventCallback callback = new MyTetheringEventCallback(mTm, iface);
         mTm.registerTetheringEventCallback(mHandler::post, callback);
 
@@ -286,34 +329,37 @@
             }
         };
         Log.d(TAG, "Starting Ethernet tethering");
-        mTm.startTethering(
-                new TetheringRequest.Builder(TetheringManager.TETHERING_ETHERNET).build(),
-                mHandler::post /* executor */,  startTetheringCallback);
+        mTm.startTethering(request, mHandler::post /* executor */,  startTetheringCallback);
         callback.awaitInterfaceTethered();
         return callback;
     }
 
+    private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception {
+        return enableEthernetTethering(iface,
+                new TetheringRequest.Builder(TETHERING_ETHERNET).build());
+    }
+
     private int getMTU(TestNetworkInterface iface) throws SocketException {
         NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName());
         assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif);
         return nif.getMTU();
     }
 
+    private TapPacketReader makePacketReader(FileDescriptor fd, int mtu) {
+        final TapPacketReader reader = new TapPacketReader(mHandler, fd, mtu);
+        mHandler.post(() -> reader.start());
+        HandlerUtilsKt.waitForIdle(mHandler, TIMEOUT_MS);
+        return reader;
+    }
+
     private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception {
         FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor();
-        mTapPacketReader = new TapPacketReader(mHandler, fd, mtu);
-        mHandler.post(() -> mTapPacketReader.start());
-        HandlerUtilsKt.waitForIdle(mHandler, TIMEOUT_MS);
-
+        mTapPacketReader = makePacketReader(fd, mtu);
         mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName());
         checkTetheredClientCallbacks(fd);
     }
 
-    private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception {
-        // Create a fake client.
-        byte[] clientMacAddr = new byte[6];
-        new Random().nextBytes(clientMacAddr);
-
+    private DhcpResults runDhcp(FileDescriptor fd, byte[] clientMacAddr) throws Exception {
         // We have to retransmit DHCP requests because IpServer declares itself to be ready before
         // its DhcpServer is actually started. TODO: fix this race and remove this loop.
         DhcpPacket offerPacket = null;
@@ -323,13 +369,25 @@
             offerPacket = getNextDhcpPacket();
             if (offerPacket instanceof DhcpOfferPacket) break;
         }
-        assertTrue("No DHCPOFFER received on interface within timeout",
-                offerPacket instanceof DhcpOfferPacket);
+        if (!(offerPacket instanceof DhcpOfferPacket)) {
+            throw new TimeoutException("No DHCPOFFER received on interface within timeout");
+        }
 
         sendDhcpRequest(fd, offerPacket, clientMacAddr);
         DhcpPacket ackPacket = getNextDhcpPacket();
-        assertTrue("No DHCPACK received on interface within timeout",
-                ackPacket instanceof DhcpAckPacket);
+        if (!(ackPacket instanceof DhcpAckPacket)) {
+            throw new TimeoutException("No DHCPACK received on interface within timeout");
+        }
+
+        return ackPacket.toDhcpResults();
+    }
+
+    private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception {
+        // Create a fake client.
+        byte[] clientMacAddr = new byte[6];
+        new Random().nextBytes(clientMacAddr);
+
+        DhcpResults dhcpResults = runDhcp(fd, clientMacAddr);
 
         final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected();
         assertEquals(1, clients.size());
@@ -337,7 +395,7 @@
 
         // Check the MAC address.
         assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress());
-        assertEquals(TetheringManager.TETHERING_ETHERNET, client.getTetheringType());
+        assertEquals(TETHERING_ETHERNET, client.getTetheringType());
 
         // Check the hostname.
         assertEquals(1, client.getAddresses().size());
@@ -345,7 +403,6 @@
         assertEquals(DHCP_HOSTNAME, info.getHostname());
 
         // Check the address is the one that was handed out in the DHCP ACK.
-        DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress());
 
         // Check that the lifetime is correct +/- 10s.
@@ -373,8 +430,8 @@
         private final Handler mHandler;
         private final EthernetManager mEm;
 
-        private volatile TetheredInterfaceRequest mRequest;
-        private volatile String mIface;
+        private TetheredInterfaceRequest mRequest;
+        private final CompletableFuture<String> mFuture = new CompletableFuture<>();
 
         TetheredInterfaceRequester(Handler handler, EthernetManager em) {
             mHandler = handler;
@@ -384,25 +441,28 @@
         @Override
         public void onAvailable(String iface) {
             Log.d(TAG, "Ethernet interface available: " + iface);
-            mIface = iface;
-            mInterfaceAvailableLatch.countDown();
+            mFuture.complete(iface);
         }
+
         @Override
-        public void onUnavailable() {}
-
-        public void requestInterface() {
-            assertNull("BUG: more than one tethered interface request", mRequest);
-            mRequest = mEm.requestTetheredInterface(mHandler::post, this);
+        public void onUnavailable() {
+            mFuture.completeExceptionally(new IllegalStateException("onUnavailable received"));
         }
 
-        public String awaitRequestedInterface() throws InterruptedException {
-            assertTrue("No tethered interface available after " + TIMEOUT_MS + "ms",
-                    mInterfaceAvailableLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            return mIface;
+        public CompletableFuture<String> requestInterface() {
+            assertNull("BUG: more than one tethered interface request", mRequest);
+            Log.d(TAG, "Requesting tethered interface");
+            mRequest = mEm.requestTetheredInterface(mHandler::post, this);
+            return mFuture;
+        }
+
+        public String getInterface() throws Exception {
+            return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         }
 
         public void release() {
             if (mRequest != null) {
+                mFuture.obtrudeException(new IllegalStateException("Request already released"));
                 mRequest.release();
                 mRequest = null;
             }
@@ -442,6 +502,34 @@
         assertEquals("LinkAddress scope does not match", l1.getScope(), l2.getScope());
     }
 
+    private TetheringRequest requestWithStaticIpv4(String local, String client) {
+        LinkAddress localAddr = local == null ? null : new LinkAddress(local);
+        LinkAddress clientAddr = client == null ? null : new LinkAddress(client);
+        return new TetheringRequest.Builder(TETHERING_ETHERNET)
+                .setStaticIpv4Addresses(localAddr, clientAddr).build();
+    }
+
+    private void assertInvalidStaticIpv4Request(String iface, String local, String client)
+            throws Exception {
+        try {
+            enableEthernetTethering(iface, requestWithStaticIpv4(local, client));
+            fail("Unexpectedly accepted invalid IPv4 configuration: " + local + ", " + client);
+        } catch (IllegalArgumentException | NullPointerException expected) { }
+    }
+
+    private void assertInterfaceHasIpAddress(String iface, String expected) throws Exception {
+        LinkAddress expectedAddr = new LinkAddress(expected);
+        NetworkInterface nif = NetworkInterface.getByName(iface);
+        for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
+            final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
+            if (expectedAddr.equals(addr)) {
+                return;
+            }
+        }
+        fail("Expected " + iface + " to have IP address " + expected + ", found "
+                + nif.getInterfaceAddresses());
+    }
+
     private TestNetworkInterface createTestInterface() throws Exception {
         TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class);
         TestNetworkInterface iface = tnm.createTapInterface();
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
index 530bc07..4ff1d37 100644
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -20,7 +20,16 @@
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
+        <service
+            android:name="com.android.server.connectivity.tethering.MockTetheringService"
+            android:permission="android.permission.TETHER_PRIVILEGED"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="com.android.server.connectivity.tethering.TetheringService"/>
+            </intent-filter>
+        </service>
     </application>
+
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.networkstack.tethering.tests.unit"
         android:label="Tethering service tests">
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 3106e0e..fdfdae8 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -43,7 +43,6 @@
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -66,6 +65,7 @@
 import android.net.LinkProperties;
 import android.net.MacAddress;
 import android.net.RouteInfo;
+import android.net.TetherOffloadRuleParcel;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServer;
 import android.net.dhcp.IDhcpServerCallbacks;
@@ -85,6 +85,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
 import org.mockito.Captor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
@@ -92,6 +93,7 @@
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.util.Arrays;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -514,6 +516,65 @@
         mLooper.dispatchAll();
     }
 
+    /**
+     * Custom ArgumentMatcher for TetherOffloadRuleParcel. This is needed because generated stable
+     * AIDL classes don't have equals(), so we cannot just use eq(). A custom assert, such as:
+     *
+     * private void checkFooCalled(StableParcelable p, ...) {
+     *     ArgumentCaptor<FooParam> captor = ArgumentCaptor.forClass(FooParam.class);
+     *     verify(mMock).foo(captor.capture());
+     *     Foo foo = captor.getValue();
+     *     assertFooMatchesExpectations(foo);
+     * }
+     *
+     * almost works, but not quite. This is because if the code under test calls foo() twice, the
+     * first call to checkFooCalled() matches both the calls, putting both calls into the captor,
+     * and then fails with TooManyActualInvocations. It also makes it harder to use other mockito
+     * features such as never(), inOrder(), etc.
+     *
+     * This approach isn't great because if the match fails, the error message is unhelpful
+     * (actual: "android.net.TetherOffloadRuleParcel@8c827b0" or some such), but at least it does
+     * work.
+     *
+     * See ConnectivityServiceTest#assertRoutesAdded for an alternative approach which solves the
+     * TooManyActualInvocations problem described above by forcing the caller of the custom assert
+     * method to specify all expected invocations in one call. This is useful when the stable
+     * parcelable class being asserted on has a corresponding Java object (eg., RouteInfo and
+     * RouteInfoParcelable), and the caller can just pass in a list of them. It not useful here
+     * because there is no such object.
+     */
+    private static class TetherOffloadRuleParcelMatcher implements
+            ArgumentMatcher<TetherOffloadRuleParcel> {
+        public final int upstreamIfindex;
+        public final InetAddress dst;
+        public final MacAddress dstMac;
+
+        TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
+            this.upstreamIfindex = upstreamIfindex;
+            this.dst = dst;
+            this.dstMac = dstMac;
+        }
+
+        public boolean matches(TetherOffloadRuleParcel parcel) {
+            return upstreamIfindex == parcel.inputInterfaceIndex
+                    && (TEST_IFACE_PARAMS.index == parcel.outputInterfaceIndex)
+                    && Arrays.equals(dst.getAddress(), parcel.destination)
+                    && (128 == parcel.prefixLength)
+                    && Arrays.equals(TEST_IFACE_PARAMS.macAddr.toByteArray(), parcel.srcL2Address)
+                    && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address);
+        }
+
+        public String toString() {
+            return String.format("TetherOffloadRuleParcelMatcher(%d, %s, %s",
+                    upstreamIfindex, dst.getHostAddress(), dstMac);
+        }
+    }
+
+    private TetherOffloadRuleParcel matches(
+            int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
+        return argThat(new TetherOffloadRuleParcelMatcher(upstreamIfindex, dst, dstMac));
+    }
+
     @Test
     public void addRemoveipv6ForwardingRules() throws Exception {
         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */);
@@ -537,13 +598,11 @@
 
         // Events on this interface are received and sent to netd.
         recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
-        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
-                eq(neighA.getAddress()), eq(myMac.toByteArray()), eq(macA.toByteArray()));
+        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
         reset(mNetd);
 
         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
-        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
-                eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
+        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
         reset(mNetd);
 
         // Link-local and multicast neighbors are ignored.
@@ -554,12 +613,12 @@
 
         // A neighbor that is no longer valid causes the rule to be removed.
         recvNewNeigh(myIfindex, neighA, NUD_FAILED, macA);
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighA.getAddress()));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
         reset(mNetd);
 
         // A neighbor that is deleted causes the rule to be removed.
         recvDelNeigh(myIfindex, neighB, NUD_STALE, macB);
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighB.getAddress()));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
         reset(mNetd);
 
         // Upstream changes result in deleting and re-adding the rules.
@@ -571,22 +630,16 @@
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName(UPSTREAM_IFACE2);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp);
-        inOrder.verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX2),
-                eq(neighA.getAddress()), eq(myMac.toByteArray()), eq(macA.toByteArray()));
-        inOrder.verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX),
-                    eq(neighA.getAddress()));
-        inOrder.verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX2),
-                eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
-        inOrder.verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX),
-                eq(neighB.getAddress()));
+        inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA));
+        inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
+        inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB));
+        inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
         reset(mNetd);
 
         // When the upstream is lost, rules are removed.
         dispatchTetherConnectionChanged(null, null);
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX2),
-                eq(neighA.getAddress()));
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX2),
-                eq(neighB.getAddress()));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB));
         reset(mNetd);
 
         // If the upstream is IPv4-only, no rules are added.
@@ -599,31 +652,27 @@
         lp.setInterfaceName(UPSTREAM_IFACE);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
-        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
-                eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
-        verify(mNetd, never()).tetherRuleAddDownstreamIpv6(anyInt(), anyInt(),
-                eq(neighA.getAddress()), any(), any());
+        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
+        verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
 
         // If upstream IPv6 connectivity is lost, rules are removed.
         reset(mNetd);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null);
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighB.getAddress()));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
 
         // When the interface goes down, rules are removed.
         lp.setInterfaceName(UPSTREAM_IFACE);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
         recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
-        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
-                eq(neighA.getAddress()), eq(myMac.toByteArray()), eq(macA.toByteArray()));
-        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
-                eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
+        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
+        verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
         reset(mNetd);
 
         mIpServer.stop();
         mLooper.dispatchAll();
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighA.getAddress()));
-        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighB.getAddress()));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
+        verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
         reset(mNetd);
     }
 
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 0a7850b..b3a30ab 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -17,8 +17,10 @@
 package com.android.server.connectivity.tethering;
 
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
 import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
 import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
@@ -353,6 +355,20 @@
         callbackTimeoutHelper(mCallbacklatch);
         assertEquals(0, mEnMgr.uiProvisionCount);
         mEnMgr.reset();
+        // 8. Test get value for invalid downstream type.
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.requestLatestTetheringEntitlementResult(TETHERING_WIFI_P2P, receiver, true);
+        mLooper.dispatchAll();
+        callbackTimeoutHelper(mCallbacklatch);
+        assertEquals(0, mEnMgr.uiProvisionCount);
+        mEnMgr.reset();
     }
 
     void callbackTimeoutHelper(final CountDownLatch latch) throws Exception {
@@ -471,6 +487,22 @@
         mLooper.dispatchAll();
         assertEquals(0, mEnMgr.uiProvisionCount);
         assertEquals(3, mEnMgr.silentProvisionCount);
+        assertFalse(mEnMgr.isCellularUpstreamPermitted());
+        mEnMgr.reset();
+        // 7. start ui provisioning, upstream is mobile, downstream is ethernet
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        mEnMgr.startProvisioningIfNeeded(TETHERING_ETHERNET, true);
+        mLooper.dispatchAll();
+        assertEquals(1, mEnMgr.uiProvisionCount);
+        assertEquals(0, mEnMgr.silentProvisionCount);
+        assertTrue(mEnMgr.isCellularUpstreamPermitted());
+        mEnMgr.reset();
+        // 8. downstream is invalid
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI_P2P, true);
+        mLooper.dispatchAll();
+        assertEquals(0, mEnMgr.uiProvisionCount);
+        assertEquals(0, mEnMgr.silentProvisionCount);
         mEnMgr.reset();
     }
 
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinatorTest.java
new file mode 100644
index 0000000..9121243
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinatorTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.connectivity.tethering;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.RouteInfo.RTN_UNICAST;
+import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
+import static android.net.ip.IpServer.STATE_TETHERED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.RouteInfo;
+import android.net.ip.IpServer;
+import android.net.util.SharedLog;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+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;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IPv6TetheringCoordinatorTest {
+    private static final String TEST_DNS_SERVER = "2001:4860:4860::8888";
+    private static final String TEST_INTERFACE = "test_rmnet0";
+    private static final String TEST_IPV6_ADDRESS = "2001:db8::1/64";
+    private static final String TEST_IPV4_ADDRESS = "192.168.100.1/24";
+
+    private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
+    private ArrayList<IpServer> mNotifyList;
+
+    @Mock private SharedLog mSharedLog;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
+        mNotifyList = new ArrayList<IpServer>();
+        mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mSharedLog);
+    }
+
+    private UpstreamNetworkState createDualStackUpstream(final int transportType) {
+        final Network network = mock(Network.class);
+        final NetworkCapabilities netCap =
+                new NetworkCapabilities.Builder().addTransportType(transportType).build();
+        final InetAddress dns = InetAddresses.parseNumericAddress(TEST_DNS_SERVER);
+        final LinkProperties linkProp = new LinkProperties();
+        linkProp.setInterfaceName(TEST_INTERFACE);
+        linkProp.addLinkAddress(new LinkAddress(TEST_IPV6_ADDRESS));
+        linkProp.addLinkAddress(new LinkAddress(TEST_IPV4_ADDRESS));
+        linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, TEST_INTERFACE, RTN_UNICAST));
+        linkProp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, TEST_INTERFACE,
+                    RTN_UNICAST));
+        linkProp.addDnsServer(dns);
+        return new UpstreamNetworkState(linkProp, netCap, network);
+    }
+
+    private void assertOnlyOneV6AddressAndNoV4(LinkProperties lp) {
+        assertEquals(lp.getInterfaceName(), TEST_INTERFACE);
+        assertFalse(lp.hasIpv4Address());
+        final List<LinkAddress> addresses = lp.getLinkAddresses();
+        assertEquals(addresses.size(), 1);
+        final LinkAddress v6Address = addresses.get(0);
+        assertEquals(v6Address, new LinkAddress(TEST_IPV6_ADDRESS));
+    }
+
+    @Test
+    public void testUpdateIpv6Upstream() throws Exception {
+        // 1. Add first IpServer.
+        final IpServer firstServer = mock(IpServer.class);
+        mNotifyList.add(firstServer);
+        mIPv6TetheringCoordinator.addActiveDownstream(firstServer, STATE_TETHERED);
+        verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
+        verifyNoMoreInteractions(firstServer);
+
+        // 2. Add second IpServer and it would not have ipv6 tethering.
+        final IpServer secondServer = mock(IpServer.class);
+        mNotifyList.add(secondServer);
+        mIPv6TetheringCoordinator.addActiveDownstream(secondServer, STATE_LOCAL_ONLY);
+        verifyNoMoreInteractions(secondServer);
+        reset(firstServer, secondServer);
+
+        // 3. No upstream.
+        mIPv6TetheringCoordinator.updateUpstreamNetworkState(null);
+        verify(secondServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
+        reset(firstServer, secondServer);
+
+        // 4. Update ipv6 mobile upstream.
+        final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR);
+        final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class);
+        mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream);
+        verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0),
+                lp.capture());
+        final LinkProperties v6OnlyLink = lp.getValue();
+        assertOnlyOneV6AddressAndNoV4(v6OnlyLink);
+        verifyNoMoreInteractions(firstServer);
+        verifyNoMoreInteractions(secondServer);
+        reset(firstServer, secondServer);
+
+        // 5. Remove first IpServer.
+        mNotifyList.remove(firstServer);
+        mIPv6TetheringCoordinator.removeActiveDownstream(firstServer);
+        verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
+        verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0),
+                lp.capture());
+        final LinkProperties localOnlyLink = lp.getValue();
+        assertNotNull(localOnlyLink);
+        assertNotEquals(localOnlyLink, v6OnlyLink);
+        reset(firstServer, secondServer);
+
+        // 6. Remove second IpServer.
+        mNotifyList.remove(secondServer);
+        mIPv6TetheringCoordinator.removeActiveDownstream(secondServer);
+        verifyNoMoreInteractions(firstServer);
+        verify(secondServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
+    }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/MockTetheringService.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/MockTetheringService.java
new file mode 100644
index 0000000..355ece9
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/MockTetheringService.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.connectivity.tethering;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Intent;
+import android.net.ITetheringConnector;
+import android.os.Binder;
+import android.os.IBinder;
+
+public class MockTetheringService extends TetheringService {
+    private final Tethering mTethering = mock(Tethering.class);
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new MockTetheringConnector(super.onBind(intent));
+    }
+
+    @Override
+    public Tethering makeTethering(TetheringDependencies deps) {
+        return mTethering;
+    }
+
+    public Tethering getTethering() {
+        return mTethering;
+    }
+
+    public class MockTetheringConnector extends Binder {
+        final IBinder mBase;
+        MockTetheringConnector(IBinder base) {
+            mBase = base;
+        }
+
+        public ITetheringConnector getTetheringConnector() {
+            return ITetheringConnector.Stub.asInterface(mBase);
+        }
+
+        public MockTetheringService getService() {
+            return MockTetheringService.this;
+        }
+    }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringServiceTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringServiceTest.java
new file mode 100644
index 0000000..d9d3e73
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringServiceTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.connectivity.tethering;
+
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Intent;
+import android.net.IIntResultListener;
+import android.net.ITetheringConnector;
+import android.net.ITetheringEventCallback;
+import android.net.TetheringRequestParcel;
+import android.os.ResultReceiver;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ServiceTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.connectivity.tethering.MockTetheringService.MockTetheringConnector;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class TetheringServiceTest {
+    private static final String TEST_IFACE_NAME = "test_wlan0";
+    private static final String TEST_CALLER_PKG = "test_pkg";
+    @Mock private ITetheringEventCallback mITetheringEventCallback;
+    @Rule public ServiceTestRule mServiceTestRule;
+    private Tethering mTethering;
+    private Intent mMockServiceIntent;
+    private ITetheringConnector mTetheringConnector;
+
+    private class TestTetheringResult extends IIntResultListener.Stub {
+        private int mResult = -1; // Default value that does not match any result code.
+        @Override
+        public void onResult(final int resultCode) {
+            mResult = resultCode;
+        }
+
+        public void assertResult(final int expected) {
+            assertEquals(expected, mResult);
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mServiceTestRule = new ServiceTestRule();
+        mMockServiceIntent = new Intent(
+                InstrumentationRegistry.getTargetContext(),
+                MockTetheringService.class);
+        final MockTetheringConnector mockConnector =
+                (MockTetheringConnector) mServiceTestRule.bindService(mMockServiceIntent);
+        mTetheringConnector = mockConnector.getTetheringConnector();
+        final MockTetheringService service = mockConnector.getService();
+        mTethering = service.getTethering();
+        verify(mTethering).startStateMachineUpdaters();
+        when(mTethering.hasTetherableConfiguration()).thenReturn(true);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mServiceTestRule.unbindService();
+    }
+
+    @Test
+    public void testTether() throws Exception {
+        when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
+        final TestTetheringResult result = new TestTetheringResult();
+        mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).tether(TEST_IFACE_NAME);
+        verifyNoMoreInteractions(mTethering);
+        result.assertResult(TETHER_ERROR_NO_ERROR);
+    }
+
+    @Test
+    public void testUntether() throws Exception {
+        when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
+        final TestTetheringResult result = new TestTetheringResult();
+        mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).untether(TEST_IFACE_NAME);
+        verifyNoMoreInteractions(mTethering);
+        result.assertResult(TETHER_ERROR_NO_ERROR);
+    }
+
+    @Test
+    public void testSetUsbTethering() throws Exception {
+        when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
+        final TestTetheringResult result = new TestTetheringResult();
+        mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).setUsbTethering(true /* enable */);
+        verifyNoMoreInteractions(mTethering);
+        result.assertResult(TETHER_ERROR_NO_ERROR);
+    }
+
+    @Test
+    public void testStartTethering() throws Exception {
+        final TestTetheringResult result = new TestTetheringResult();
+        final TetheringRequestParcel request = new TetheringRequestParcel();
+        request.tetheringType = TETHERING_WIFI;
+        mTetheringConnector.startTethering(request, TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).startTethering(eq(request), eq(result));
+        verifyNoMoreInteractions(mTethering);
+    }
+
+    @Test
+    public void testStopTethering() throws Exception {
+        final TestTetheringResult result = new TestTetheringResult();
+        mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).stopTethering(TETHERING_WIFI);
+        verifyNoMoreInteractions(mTethering);
+        result.assertResult(TETHER_ERROR_NO_ERROR);
+    }
+
+    @Test
+    public void testRequestLatestTetheringEntitlementResult() throws Exception {
+        final ResultReceiver result = new ResultReceiver(null);
+        mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
+                true /* showEntitlementUi */, TEST_CALLER_PKG);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI),
+                eq(result), eq(true) /* showEntitlementUi */);
+        verifyNoMoreInteractions(mTethering);
+    }
+
+    @Test
+    public void testRegisterTetheringEventCallback() throws Exception {
+        mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback,
+                TEST_CALLER_PKG);
+        verify(mTethering).registerTetheringEventCallback(eq(mITetheringEventCallback));
+        verifyNoMoreInteractions(mTethering);
+    }
+
+    @Test
+    public void testUnregisterTetheringEventCallback() throws Exception {
+        mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback,
+                TEST_CALLER_PKG);
+        verify(mTethering).unregisterTetheringEventCallback(
+                eq(mITetheringEventCallback));
+        verifyNoMoreInteractions(mTethering);
+    }
+
+    @Test
+    public void testStopAllTethering() throws Exception {
+        final TestTetheringResult result = new TestTetheringResult();
+        mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).untetherAll();
+        verifyNoMoreInteractions(mTethering);
+        result.assertResult(TETHER_ERROR_NO_ERROR);
+    }
+
+    @Test
+    public void testIsTetheringSupported() throws Exception {
+        final TestTetheringResult result = new TestTetheringResult();
+        mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, result);
+        verify(mTethering).hasTetherableConfiguration();
+        verifyNoMoreInteractions(mTethering);
+        result.assertResult(TETHER_ERROR_NO_ERROR);
+    }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index a59c6fd..3a580dd 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -140,7 +140,9 @@
 import com.android.testutils.MiscAssertsKt;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -439,6 +441,18 @@
         return buildMobileUpstreamState(false, true, true);
     }
 
+    // See FakeSettingsProvider#clearSettingsProvider() that this needs to be called before and
+    // after use.
+    @BeforeClass
+    public static void setupOnce() {
+        FakeSettingsProvider.clearSettingsProvider();
+    }
+
+    @AfterClass
+    public static void tearDownOnce() {
+        FakeSettingsProvider.clearSettingsProvider();
+    }
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/VpnDialogs/res/values-ky/strings.xml b/packages/VpnDialogs/res/values-ky/strings.xml
index 4e2f698..23c9be8 100644
--- a/packages/VpnDialogs/res/values-ky/strings.xml
+++ b/packages/VpnDialogs/res/values-ky/strings.xml
@@ -26,7 +26,7 @@
     <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> байт / <xliff:g id="NUMBER_1">%2$s</xliff:g> пакет"</string>
     <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ар дайым күйүк VPN\'ге туташа албай жатат"</string>
     <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> тармагына ар дайым туташып турсун деп жөндөлгөн, бирок учурда телефонуңуз ага туташа албай жатат. <xliff:g id="VPN_APP_1">%1$s</xliff:g> тармагына кайра туташканга чейин телефонуңуз жалпыга ачык тармакты пайдаланып турат."</string>
-    <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> тармагына ар дайым туташып турсун деп жөндөлгөн, бирок учурда телефонуңуз ага туташа албай жатат. VPN тармагына кайра туташмайынча, Интернет байланышыңыз жок болот."</string>
+    <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> тармагына ар дайым туташып турсун деп жөндөлгөн, бирок учурда телефонуңуз ага туташа албай жатат. VPN тармагына кайра туташмайынча, Интернет жок болот."</string>
     <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
     <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN жөндөөлөрүн өзгөртүү"</string>
     <string name="configure" msgid="4905518375574791375">"Конфигурациялоо"</string>
diff --git a/core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-ta/strings.xml
similarity index 65%
rename from core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml
rename to packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-ta/strings.xml
index 896993e..c896ee3 100644
--- a/core/tests/ResourceLoaderTests/resources/provider4/res/values/values.xml
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-ta/strings.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
   ~ Copyright (C) 2020 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,12 +13,9 @@
   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
-  -->
+   -->
 
-<resources>
-    <dimen name="test">400dp</dimen>
-    <string name="test">Four</string>
-
-    <string name="additional">Four</string>
-    <public type="string" name="additional" id="0x7f0400fe" />
-</resources>
\ No newline at end of file
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="display_cutout_emulation_overlay" msgid="7305489596221077240">"பஞ்ச் ஹோல் கட்அவுட்"</string>
+</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index c8b6d8df..132b692 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -43,12 +43,10 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.GraphicBuffer;
 import android.graphics.ParcelableColorSpace;
-import android.graphics.Point;
-import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.HardwareBuffer;
 import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.DisplayManagerInternal;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -66,7 +64,6 @@
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.MagnificationSpec;
-import android.view.SurfaceControl;
 import android.view.SurfaceControl.ScreenshotGraphicBuffer;
 import android.view.View;
 import android.view.WindowInfo;
@@ -1010,53 +1007,29 @@
             return;
         }
 
-        final Display display = DisplayManagerGlobal.getInstance()
-                .getRealDisplay(displayId);
-        if (display == null) {
-            sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
-                    callback);
+        // Private virtual displays are created by the ap and is not allowed to access by other
+        // aps.  We assume the contents on this display should not be captured.
+        final DisplayManager displayManager =
+                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+        final Display display = displayManager.getDisplay(displayId);
+        if ((display == null) || (display.getType() == Display.TYPE_VIRTUAL
+                && (display.getFlags() & Display.FLAG_PRIVATE) != 0)) {
+            sendScreenshotFailure(
+                    AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
             return;
         }
 
-        sendScreenshotSuccess(display, callback);
-    }
-
-    private ScreenshotGraphicBuffer takeScreenshotBuffer(Display display) {
-        final Point displaySize = new Point();
-        // TODO (b/145893483): calling new API with the display as a parameter
-        // when surface control supported.
-        final IBinder token = SurfaceControl.getInternalDisplayToken();
-        final Rect crop = new Rect(0, 0, displaySize.x, displaySize.y);
-        final int rotation = display.getRotation();
-        display.getRealSize(displaySize);
-
-        return SurfaceControl.screenshotToBuffer(token, crop, displaySize.x, displaySize.y,
-                false, rotation);
-    }
-
-    private void sendScreenshotSuccess(Display display, RemoteCallback callback) {
         final long identity = Binder.clearCallingIdentity();
         try {
             mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
-                final ScreenshotGraphicBuffer screenshotBuffer = takeScreenshotBuffer(display);
-                final GraphicBuffer graphicBuffer = screenshotBuffer.getGraphicBuffer();
-                try (HardwareBuffer hardwareBuffer =
-                             HardwareBuffer.createFromGraphicBuffer(graphicBuffer)) {
-                    final ParcelableColorSpace colorSpace =
-                            new ParcelableColorSpace(screenshotBuffer.getColorSpace());
-
-                    final Bundle payload = new Bundle();
-                    payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
-                            AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
-                    payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
-                            hardwareBuffer);
-                    payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
-                    payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
-                            SystemClock.uptimeMillis());
-
-                    // Send back the result.
-                    callback.sendResult(payload);
-                    hardwareBuffer.close();
+                final ScreenshotGraphicBuffer screenshotBuffer = LocalServices
+                        .getService(DisplayManagerInternal.class)
+                        .screenshotWithoutSecureLayer(displayId);
+                if (screenshotBuffer != null) {
+                    sendScreenshotSuccess(screenshotBuffer, callback);
+                } else {
+                    sendScreenshotFailure(
+                            AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
                 }
             }, null).recycleOnUse());
         } finally {
@@ -1064,6 +1037,29 @@
         }
     }
 
+    private void sendScreenshotSuccess(ScreenshotGraphicBuffer screenshotBuffer,
+            RemoteCallback callback) {
+        final GraphicBuffer graphicBuffer = screenshotBuffer.getGraphicBuffer();
+        try (HardwareBuffer hardwareBuffer =
+                     HardwareBuffer.createFromGraphicBuffer(graphicBuffer)) {
+            final ParcelableColorSpace colorSpace =
+                    new ParcelableColorSpace(screenshotBuffer.getColorSpace());
+
+            final Bundle payload = new Bundle();
+            payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
+                    AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
+            payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
+                    hardwareBuffer);
+            payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
+            payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
+                    SystemClock.uptimeMillis());
+
+            // Send back the result.
+            callback.sendResult(payload);
+            hardwareBuffer.close();
+        }
+    }
+
     private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode,
             RemoteCallback callback) {
         mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1b180e3..7230b00 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -197,7 +197,8 @@
 
     private final MainHandler mMainHandler;
 
-    private final SystemActionPerformer mSystemActionPerformer;
+    // Lazily initialized - access through getSystemActionPerfomer()
+    private SystemActionPerformer mSystemActionPerformer;
 
     private MagnificationController mMagnificationController;
 
@@ -295,8 +296,6 @@
         mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class);
         mPackageManager = mContext.getPackageManager();
         mSecurityPolicy = new AccessibilitySecurityPolicy(mContext, this);
-        mSystemActionPerformer =
-                new SystemActionPerformer(mContext, mWindowManagerService, null, this);
         mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
                 mWindowManagerService, this, mSecurityPolicy, this);
         mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
@@ -414,7 +413,12 @@
                                     && component.getPackageName().equals(packageName))
                             || userState.mCrashedServices.removeIf(component -> component != null
                                     && component.getPackageName().equals(packageName));
-                    if (reboundAService) {
+                    // Reloads the installed services info to make sure the rebound service could
+                    // get a new one.
+                    userState.mInstalledServices.clear();
+                    final boolean configurationChanged =
+                            readConfigurationForUserStateLocked(userState);
+                    if (reboundAService || configurationChanged) {
                         onUserStateChangedLocked(userState);
                     }
                     migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, packageName);
@@ -667,7 +671,7 @@
         mSecurityPolicy.enforceCallerIsRecentsOrHasPermission(
                 Manifest.permission.MANAGE_ACCESSIBILITY,
                 FUNCTION_REGISTER_SYSTEM_ACTION);
-        mSystemActionPerformer.registerSystemAction(actionId, action);
+        getSystemActionPerformer().registerSystemAction(actionId, action);
     }
 
     /**
@@ -680,7 +684,15 @@
         mSecurityPolicy.enforceCallerIsRecentsOrHasPermission(
                 Manifest.permission.MANAGE_ACCESSIBILITY,
                 FUNCTION_UNREGISTER_SYSTEM_ACTION);
-        mSystemActionPerformer.unregisterSystemAction(actionId);
+        getSystemActionPerformer().unregisterSystemAction(actionId);
+    }
+
+    private SystemActionPerformer getSystemActionPerformer() {
+        if (mSystemActionPerformer == null) {
+            mSystemActionPerformer =
+                    new SystemActionPerformer(mContext, mWindowManagerService, null, this);
+        }
+        return mSystemActionPerformer;
     }
 
     @Override
@@ -792,7 +804,7 @@
         synchronized (mLock) {
             mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient,
                     mContext, accessibilityServiceInfo, sIdCounter++, mMainHandler,
-                    mSecurityPolicy, this, mWindowManagerService, mSystemActionPerformer,
+                    mSecurityPolicy, this, mWindowManagerService, getSystemActionPerformer(),
                     mA11yWindowManager, flags);
             onUserStateChangedLocked(getCurrentUserStateLocked());
         }
@@ -1503,7 +1515,7 @@
                 if (service == null) {
                     service = new AccessibilityServiceConnection(userState, mContext, componentName,
                             installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
-                            this, mWindowManagerService, mSystemActionPerformer,
+                            this, mWindowManagerService, getSystemActionPerformer(),
                             mA11yWindowManager, mActivityTaskManagerService);
                 } else if (userState.mBoundServices.contains(service)) {
                     continue;
@@ -2741,7 +2753,7 @@
                     userState, mContext,
                     COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
                     AccessibilityManagerService.this, mWindowManagerService,
-                    mSystemActionPerformer, mA11yWindowManager, mActivityTaskManagerService) {
+                    getSystemActionPerformer(), mA11yWindowManager, mActivityTaskManagerService) {
                 @Override
                 public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
                     return true;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
new file mode 100644
index 0000000..3612e09
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.autofill.AutofillId;
+import android.view.inputmethod.InlineSuggestionsRequest;
+import android.view.inputmethod.InlineSuggestionsResponse;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.inputmethod.InputMethodManagerInternal;
+
+import java.util.Collections;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+
+/**
+ * Controls the interaction with the IME for the inline suggestion sessions.
+ */
+final class AutofillInlineSessionController {
+    @NonNull
+    private final InputMethodManagerInternal mInputMethodManagerInternal;
+    private final int mUserId;
+    @NonNull
+    private final ComponentName mComponentName;
+    @NonNull
+    private final Object mLock;
+    @NonNull
+    private final Handler mHandler;
+
+    @GuardedBy("mLock")
+    private AutofillInlineSuggestionsRequestSession mSession;
+
+    AutofillInlineSessionController(InputMethodManagerInternal inputMethodManagerInternal,
+            int userId, ComponentName componentName, Handler handler, Object lock) {
+        mInputMethodManagerInternal = inputMethodManagerInternal;
+        mUserId = userId;
+        mComponentName = componentName;
+        mHandler = handler;
+        mLock = lock;
+    }
+
+
+    /**
+     * Requests the IME to create an {@link InlineSuggestionsRequest} for {@code autofillId}.
+     *
+     * @param autofillId      the Id of the field for which the request is for.
+     * @param requestConsumer the callback which will be invoked when IME responded or if it times
+     *                        out waiting for IME response.
+     */
+    @GuardedBy("mLock")
+    void onCreateInlineSuggestionsRequestLocked(@NonNull AutofillId autofillId,
+            @NonNull Consumer<InlineSuggestionsRequest> requestConsumer, @NonNull Bundle uiExtras) {
+        // TODO(b/151123764): rename the method to better reflect what it does.
+        if (mSession != null) {
+            // Send an empty response to IME and destroy the existing session.
+            mSession.onInlineSuggestionsResponseLocked(mSession.getAutofillIdLocked(),
+                    new InlineSuggestionsResponse(Collections.EMPTY_LIST));
+            mSession.destroySessionLocked();
+        }
+        // TODO(b/151123764): consider reusing the same AutofillInlineSession object for the
+        // same field.
+        mSession = new AutofillInlineSuggestionsRequestSession(mInputMethodManagerInternal, mUserId,
+                mComponentName, mHandler, mLock, autofillId, requestConsumer, uiExtras);
+        mSession.onCreateInlineSuggestionsRequestLocked();
+
+    }
+
+    /**
+     * Returns the {@link InlineSuggestionsRequest} provided by IME for the last request.
+     *
+     * <p> The caller is responsible for making sure Autofill hears back from IME before calling
+     * this method, using the {@code requestConsumer} provided when calling {@link
+     * #onCreateInlineSuggestionsRequestLocked(AutofillId, Consumer, Bundle)}.
+     */
+    @GuardedBy("mLock")
+    Optional<InlineSuggestionsRequest> getInlineSuggestionsRequestLocked() {
+        if (mSession != null) {
+            return mSession.getInlineSuggestionsRequestLocked();
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Requests the IME to hide the current suggestions, if any. Returns true if the message is sent
+     * to the IME.
+     */
+    @GuardedBy("mLock")
+    boolean hideInlineSuggestionsUiLocked(@NonNull AutofillId autofillId) {
+        if (mSession != null) {
+            return mSession.onInlineSuggestionsResponseLocked(autofillId,
+                    new InlineSuggestionsResponse(Collections.EMPTY_LIST));
+        }
+        return false;
+    }
+
+    /**
+     * Requests showing the inline suggestion in the IME when the IME becomes visible and is focused
+     * on the {@code autofillId}.
+     *
+     * @return false if there is no session, or if the IME callback is not available in the session.
+     */
+    @GuardedBy("mLock")
+    boolean onInlineSuggestionsResponseLocked(@NonNull AutofillId autofillId,
+            @NonNull InlineSuggestionsResponse inlineSuggestionsResponse) {
+        // TODO(b/151123764): rename the method to better reflect what it does.
+        if (mSession != null) {
+            return mSession.onInlineSuggestionsResponseLocked(autofillId,
+                    inlineSuggestionsResponse);
+        }
+        return false;
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
new file mode 100644
index 0000000..ca230b6
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.autofill.Helper.sDebug;
+
+import android.annotation.BinderThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.inputmethod.InlineSuggestionsRequest;
+import android.view.inputmethod.InlineSuggestionsResponse;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.view.IInlineSuggestionsRequestCallback;
+import com.android.internal.view.IInlineSuggestionsResponseCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
+import com.android.server.inputmethod.InputMethodManagerInternal;
+
+import java.lang.ref.WeakReference;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+/**
+ * Maintains an inline suggestion session with the IME.
+ *
+ * <p> Each session corresponds to one request from the Autofill manager service to create an
+ * {@link InlineSuggestionsRequest}. It's responsible for receiving callbacks from the IME and
+ * sending {@link android.view.inputmethod.InlineSuggestionsResponse} to IME.
+ */
+final class AutofillInlineSuggestionsRequestSession {
+
+    private static final String TAG = AutofillInlineSuggestionsRequestSession.class.getSimpleName();
+    private static final int INLINE_REQUEST_TIMEOUT_MS = 200;
+
+    @NonNull
+    private final InputMethodManagerInternal mInputMethodManagerInternal;
+    private final int mUserId;
+    @NonNull
+    private final ComponentName mComponentName;
+    @NonNull
+    private final Object mLock;
+    @NonNull
+    private final Handler mHandler;
+    @NonNull
+    private final Bundle mUiExtras;
+
+    @GuardedBy("mLock")
+    @NonNull
+    private AutofillId mAutofillId;
+    @GuardedBy("mLock")
+    @Nullable
+    private Consumer<InlineSuggestionsRequest> mImeRequestConsumer;
+
+    @GuardedBy("mLock")
+    private boolean mImeRequestReceived;
+    @GuardedBy("mLock")
+    @Nullable
+    private InlineSuggestionsRequest mImeRequest;
+    @GuardedBy("mLock")
+    @Nullable
+    private IInlineSuggestionsResponseCallback mResponseCallback;
+    @GuardedBy("mLock")
+    @Nullable
+    private Runnable mTimeoutCallback;
+
+    @GuardedBy("mLock")
+    @Nullable
+    private AutofillId mImeCurrentFieldId;
+    @GuardedBy("mLock")
+    private boolean mImeInputStarted;
+    @GuardedBy("mLock")
+    private boolean mImeInputViewStarted;
+    @GuardedBy("mLock")
+    @Nullable
+    private InlineSuggestionsResponse mInlineSuggestionsResponse;
+    @GuardedBy("mLock")
+    private boolean mPreviousResponseIsNotEmpty;
+
+    @GuardedBy("mLock")
+    private boolean mDestroyed = false;
+
+    AutofillInlineSuggestionsRequestSession(
+            @NonNull InputMethodManagerInternal inputMethodManagerInternal, int userId,
+            @NonNull ComponentName componentName, @NonNull Handler handler, @NonNull Object lock,
+            @NonNull AutofillId autofillId,
+            @NonNull Consumer<InlineSuggestionsRequest> requestConsumer, @NonNull Bundle uiExtras) {
+        mInputMethodManagerInternal = inputMethodManagerInternal;
+        mUserId = userId;
+        mComponentName = componentName;
+        mHandler = handler;
+        mLock = lock;
+        mUiExtras = uiExtras;
+
+        mAutofillId = autofillId;
+        mImeRequestConsumer = requestConsumer;
+    }
+
+    @GuardedBy("mLock")
+    @NonNull
+    AutofillId getAutofillIdLocked() {
+        return mAutofillId;
+    }
+
+    /**
+     * Returns the {@link InlineSuggestionsRequest} provided by IME.
+     *
+     * <p> The caller is responsible for making sure Autofill hears back from IME before calling
+     * this method, using the {@link #mImeRequestConsumer}.
+     */
+    @GuardedBy("mLock")
+    Optional<InlineSuggestionsRequest> getInlineSuggestionsRequestLocked() {
+        if (mDestroyed) {
+            return Optional.empty();
+        }
+        return Optional.ofNullable(mImeRequest);
+    }
+
+    /**
+     * Requests showing the inline suggestion in the IME when the IME becomes visible and is focused
+     * on the {@code autofillId}.
+     *
+     * @return false if the IME callback is not available.
+     */
+    @GuardedBy("mLock")
+    boolean onInlineSuggestionsResponseLocked(@NonNull AutofillId autofillId,
+            @NonNull InlineSuggestionsResponse inlineSuggestionsResponse) {
+        if (mDestroyed) {
+            return false;
+        }
+        if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked called for:" + autofillId);
+        if (mImeRequest == null || mResponseCallback == null) {
+            return false;
+        }
+        // TODO(b/151123764): each session should only correspond to one field.
+        mAutofillId = autofillId;
+        mInlineSuggestionsResponse = inlineSuggestionsResponse;
+        maybeUpdateResponseToImeLocked();
+        return true;
+    }
+
+    /**
+     * This method must be called when the session is destroyed, to avoid further callbacks from/to
+     * the IME.
+     */
+    @GuardedBy("mLock")
+    void destroySessionLocked() {
+        mDestroyed = true;
+    }
+
+    /**
+     * Requests the IME to create an {@link InlineSuggestionsRequest}.
+     *
+     * <p> This method should only be called once per session.
+     */
+    @GuardedBy("mLock")
+    void onCreateInlineSuggestionsRequestLocked() {
+        if (sDebug) Log.d(TAG, "onCreateInlineSuggestionsRequestLocked called: " + mAutofillId);
+        if (mDestroyed) {
+            return;
+        }
+        mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(mUserId,
+                new InlineSuggestionsRequestInfo(mComponentName, mAutofillId, mUiExtras),
+                new InlineSuggestionsRequestCallbackImpl(this));
+        mTimeoutCallback = () -> {
+            Log.w(TAG, "Timed out waiting for IME callback InlineSuggestionsRequest.");
+            handleOnReceiveImeRequest(null, null);
+        };
+        mHandler.postDelayed(mTimeoutCallback, INLINE_REQUEST_TIMEOUT_MS);
+    }
+
+    /**
+     * Optionally sends inline response to the IME, depending on the current state.
+     */
+    @GuardedBy("mLock")
+    private void maybeUpdateResponseToImeLocked() {
+        if (sDebug) Log.d(TAG, "maybeUpdateResponseToImeLocked called");
+        if (mDestroyed || mResponseCallback == null) {
+            return;
+        }
+        if (!mImeInputViewStarted && mPreviousResponseIsNotEmpty) {
+            // 1. if previous response is not empty, and IME just become invisible, then send
+            // empty response to make sure existing responses don't stick around on the IME.
+            // Although the inline suggestions should disappear when IME hides which removes them
+            // from the view hierarchy, but we still send an empty response to be extra safe.
+
+            // TODO(b/149945531): clear the existing suggestions when IME is hide, once the bug is
+            //  fixed.
+            //if (sDebug) Log.d(TAG, "Send empty inline response");
+            //updateResponseToImeUncheckLocked(new InlineSuggestionsResponse(Collections
+            // .EMPTY_LIST));
+            //mPreviousResponseIsNotEmpty = false;
+        } else if (mImeInputViewStarted && mInlineSuggestionsResponse != null && match(mAutofillId,
+                mImeCurrentFieldId)) {
+            // 2. if IME is visible, and response is not null, send the response
+            boolean isEmptyResponse = mInlineSuggestionsResponse.getInlineSuggestions().isEmpty();
+            if (isEmptyResponse && !mPreviousResponseIsNotEmpty) {
+                // No-op if both the previous response and current response are empty.
+                return;
+            }
+            if (sDebug) {
+                Log.d(TAG, "Send inline response: "
+                        + mInlineSuggestionsResponse.getInlineSuggestions().size());
+            }
+            updateResponseToImeUncheckLocked(mInlineSuggestionsResponse);
+            // TODO(b/149945531): don't set the response to null so it's cached, once the bug is
+            //  fixed.
+            mInlineSuggestionsResponse = null;
+            mPreviousResponseIsNotEmpty = !isEmptyResponse;
+        }
+    }
+
+    /**
+     * Sends the {@code response} to the IME, assuming all the relevant checks are already done.
+     */
+    @GuardedBy("mLock")
+    private void updateResponseToImeUncheckLocked(InlineSuggestionsResponse response) {
+        if (mDestroyed) {
+            return;
+        }
+        try {
+            mResponseCallback.onInlineSuggestionsResponse(mAutofillId, response);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "RemoteException sending InlineSuggestionsResponse to IME");
+        }
+    }
+
+    /**
+     * Handles the {@code request} and {@code callback} received from the IME.
+     *
+     * <p> Should only invoked in the {@link #mHandler} thread.
+     */
+    private void handleOnReceiveImeRequest(@Nullable InlineSuggestionsRequest request,
+            @Nullable IInlineSuggestionsResponseCallback callback) {
+        synchronized (mLock) {
+            if (mDestroyed || mImeRequestReceived) {
+                return;
+            }
+            mImeRequestReceived = true;
+
+            if (mTimeoutCallback != null) {
+                if (sDebug) Log.d(TAG, "removing timeout callback");
+                mHandler.removeCallbacks(mTimeoutCallback);
+                mTimeoutCallback = null;
+            }
+            if (request != null && callback != null) {
+                mImeRequest = request;
+                mResponseCallback = callback;
+                handleOnReceiveImeStatusUpdated(mAutofillId, true, false);
+            }
+            if (mImeRequestConsumer != null) {
+                // Note that mImeRequest is only set if both request and callback are non-null.
+                mImeRequestConsumer.accept(mImeRequest);
+                mImeRequestConsumer = null;
+            }
+        }
+    }
+
+    /**
+     * Handles the IME status updates received from the IME.
+     *
+     * <p> Should only be invoked in the {@link #mHandler} thread.
+     */
+    private void handleOnReceiveImeStatusUpdated(boolean imeInputStarted,
+            boolean imeInputViewStarted) {
+        synchronized (mLock) {
+            if (mDestroyed) {
+                return;
+            }
+            if (mImeCurrentFieldId != null) {
+                boolean imeInputStartedChanged = (mImeInputStarted != imeInputStarted);
+                boolean imeInputViewStartedChanged = (mImeInputViewStarted != imeInputViewStarted);
+                mImeInputStarted = imeInputStarted;
+                mImeInputViewStarted = imeInputViewStarted;
+                if (imeInputStartedChanged || imeInputViewStartedChanged) {
+                    maybeUpdateResponseToImeLocked();
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles the IME status updates received from the IME.
+     *
+     * <p> Should only be invoked in the {@link #mHandler} thread.
+     */
+    private void handleOnReceiveImeStatusUpdated(@Nullable AutofillId imeFieldId,
+            boolean imeInputStarted, boolean imeInputViewStarted) {
+        synchronized (mLock) {
+            if (mDestroyed) {
+                return;
+            }
+            if (imeFieldId != null) {
+                mImeCurrentFieldId = imeFieldId;
+            }
+            handleOnReceiveImeStatusUpdated(imeInputStarted, imeInputViewStarted);
+        }
+    }
+
+    private static final class InlineSuggestionsRequestCallbackImpl extends
+            IInlineSuggestionsRequestCallback.Stub {
+
+        private final WeakReference<AutofillInlineSuggestionsRequestSession> mSession;
+
+        private InlineSuggestionsRequestCallbackImpl(
+                AutofillInlineSuggestionsRequestSession session) {
+            mSession = new WeakReference<>(session);
+        }
+
+        @BinderThread
+        @Override
+        public void onInlineSuggestionsUnsupported() throws RemoteException {
+            if (sDebug) Log.d(TAG, "onInlineSuggestionsUnsupported() called.");
+            final AutofillInlineSuggestionsRequestSession session = mSession.get();
+            if (session != null) {
+                session.mHandler.sendMessage(obtainMessage(
+                        AutofillInlineSuggestionsRequestSession::handleOnReceiveImeRequest, session,
+                        null, null));
+            }
+        }
+
+        @BinderThread
+        @Override
+        public void onInlineSuggestionsRequest(InlineSuggestionsRequest request,
+                IInlineSuggestionsResponseCallback callback) {
+            if (sDebug) Log.d(TAG, "onInlineSuggestionsRequest() received: " + request);
+            final AutofillInlineSuggestionsRequestSession session = mSession.get();
+            if (session != null) {
+                session.mHandler.sendMessage(obtainMessage(
+                        AutofillInlineSuggestionsRequestSession::handleOnReceiveImeRequest, session,
+                        request, callback));
+            }
+        }
+
+        @Override
+        public void onInputMethodStartInput(AutofillId imeFieldId) throws RemoteException {
+            if (sDebug) Log.d(TAG, "onInputMethodStartInput() received on " + imeFieldId);
+            final AutofillInlineSuggestionsRequestSession session = mSession.get();
+            if (session != null) {
+                session.mHandler.sendMessage(obtainMessage(
+                        AutofillInlineSuggestionsRequestSession::handleOnReceiveImeStatusUpdated,
+                        session, imeFieldId, true, false));
+            }
+        }
+
+        @Override
+        public void onInputMethodShowInputRequested(boolean requestResult) throws RemoteException {
+            if (sDebug) {
+                Log.d(TAG, "onInputMethodShowInputRequested() received: " + requestResult);
+            }
+        }
+
+        @BinderThread
+        @Override
+        public void onInputMethodStartInputView() {
+            if (sDebug) Log.d(TAG, "onInputMethodStartInputView() received");
+            final AutofillInlineSuggestionsRequestSession session = mSession.get();
+            if (session != null) {
+                session.mHandler.sendMessage(obtainMessage(
+                        AutofillInlineSuggestionsRequestSession::handleOnReceiveImeStatusUpdated,
+                        session, true, true));
+            }
+        }
+
+        @BinderThread
+        @Override
+        public void onInputMethodFinishInputView() {
+            if (sDebug) Log.d(TAG, "onInputMethodFinishInputView() received");
+            final AutofillInlineSuggestionsRequestSession session = mSession.get();
+            if (session != null) {
+                session.mHandler.sendMessage(obtainMessage(
+                        AutofillInlineSuggestionsRequestSession::handleOnReceiveImeStatusUpdated,
+                        session, true, false));
+            }
+        }
+
+        @Override
+        public void onInputMethodFinishInput() throws RemoteException {
+            if (sDebug) Log.d(TAG, "onInputMethodFinishInput() received");
+            final AutofillInlineSuggestionsRequestSession session = mSession.get();
+            if (session != null) {
+                session.mHandler.sendMessage(obtainMessage(
+                        AutofillInlineSuggestionsRequestSession::handleOnReceiveImeStatusUpdated,
+                        session, false, false));
+            }
+        }
+    }
+
+    private static boolean match(@Nullable AutofillId autofillId,
+            @Nullable AutofillId imeClientFieldId) {
+        // The IME doesn't have information about the virtual view id for the child views in the
+        // web view, so we are only comparing the parent view id here. This means that for cases
+        // where there are two input fields in the web view, they will have the same view id
+        // (although different virtual child id), and we will not be able to distinguish them.
+        return autofillId != null && imeClientFieldId != null
+                && autofillId.getViewId() == imeClientFieldId.getViewId();
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
deleted file mode 100644
index e2d5112..0000000
--- a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.autofill;
-
-import static com.android.server.autofill.Helper.sDebug;
-
-import android.annotation.BinderThread;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.inputmethod.InlineSuggestionsRequest;
-import android.view.inputmethod.InlineSuggestionsResponse;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.view.IInlineSuggestionsRequestCallback;
-import com.android.internal.view.IInlineSuggestionsResponseCallback;
-import com.android.internal.view.InlineSuggestionsRequestInfo;
-import com.android.server.inputmethod.InputMethodManagerInternal;
-
-import java.util.Collections;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
-
-/**
- * Maintains an autofill inline suggestion session that communicates with the IME.
- *
- * <p>
- * The same session may be reused for multiple input fields involved in the same autofill
- * {@link Session}. Therefore, one {@link InlineSuggestionsRequest} and one
- * {@link IInlineSuggestionsResponseCallback} may be used to generate and callback with inline
- * suggestions for different input fields.
- *
- * <p>
- * This class is the sole place in Autofill responsible for directly communicating with the IME. It
- * receives the IME input view start/finish events, with the associated IME field Id. It uses the
- * information to decide when to send the {@link InlineSuggestionsResponse} to IME. As a result,
- * some of the response will be cached locally and only be sent when the IME is ready to show them.
- *
- * <p>
- * See {@link android.inputmethodservice.InlineSuggestionSession} comments for InputMethodService
- * side flow.
- *
- * <p>
- * This class should hold the same lock as {@link Session} as they call into each other.
- */
-final class InlineSuggestionSession {
-
-    private static final String TAG = "AfInlineSuggestionSession";
-    private static final int INLINE_REQUEST_TIMEOUT_MS = 200;
-
-    @NonNull
-    private final InputMethodManagerInternal mInputMethodManagerInternal;
-    private final int mUserId;
-    @NonNull
-    private final ComponentName mComponentName;
-    @NonNull
-    private final Object mLock;
-    @NonNull
-    private final ImeStatusListener mImeStatusListener;
-    @NonNull
-    private final Handler mHandler;
-
-    /**
-     * To avoid the race condition, one should not access {@code mPendingImeResponse} without
-     * holding the {@code mLock}. For consuming the existing value, tt's recommended to use
-     * {@link #getPendingImeResponse()} to get a copy of the reference to avoid blocking call.
-     */
-    @GuardedBy("mLock")
-    @Nullable
-    private CompletableFuture<ImeResponse> mPendingImeResponse;
-
-    @GuardedBy("mLock")
-    @Nullable
-    private AutofillResponse mPendingAutofillResponse;
-
-    @GuardedBy("mLock")
-    private boolean mIsLastResponseNonEmpty = false;
-
-    @Nullable
-    @GuardedBy("mLock")
-    private AutofillId mImeFieldId = null;
-
-    @GuardedBy("mLock")
-    private boolean mImeInputViewStarted = false;
-
-    InlineSuggestionSession(InputMethodManagerInternal inputMethodManagerInternal,
-            int userId, ComponentName componentName, Handler handler, Object lock) {
-        mInputMethodManagerInternal = inputMethodManagerInternal;
-        mUserId = userId;
-        mComponentName = componentName;
-        mHandler = handler;
-        mLock = lock;
-        mImeStatusListener = new ImeStatusListener() {
-            @Override
-            public void onInputMethodStartInput(AutofillId imeFieldId) {
-                synchronized (mLock) {
-                    mImeFieldId = imeFieldId;
-                    mImeInputViewStarted = false;
-                }
-            }
-
-            @Override
-            public void onInputMethodStartInputView() {
-                synchronized (mLock) {
-                    mImeInputViewStarted = true;
-                    AutofillResponse pendingAutofillResponse = mPendingAutofillResponse;
-                    if (pendingAutofillResponse != null
-                            && pendingAutofillResponse.mAutofillId.equalsIgnoreSession(
-                            mImeFieldId)) {
-                        mPendingAutofillResponse = null;
-                        onInlineSuggestionsResponseLocked(pendingAutofillResponse.mAutofillId,
-                                pendingAutofillResponse.mResponse);
-                    }
-                }
-            }
-
-            @Override
-            public void onInputMethodFinishInputView() {
-                synchronized (mLock) {
-                    mImeInputViewStarted = false;
-                }
-            }
-
-            @Override
-            public void onInputMethodFinishInput() {
-                synchronized (mLock) {
-                    mImeFieldId = null;
-                }
-            }
-        };
-    }
-
-    public void onCreateInlineSuggestionsRequest(@NonNull AutofillId autofillId,
-            @NonNull Consumer<InlineSuggestionsRequest> requestConsumer) {
-        if (sDebug) Log.d(TAG, "onCreateInlineSuggestionsRequest called for " + autofillId);
-
-        synchronized (mLock) {
-            // Clean up all the state about the previous request.
-            hideInlineSuggestionsUi(autofillId);
-            mImeFieldId = null;
-            mImeInputViewStarted = false;
-            if (mPendingImeResponse != null && !mPendingImeResponse.isDone()) {
-                mPendingImeResponse.complete(null);
-            }
-            mPendingImeResponse = new CompletableFuture<>();
-            // TODO(b/146454892): pipe the uiExtras from the ExtServices.
-            mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(
-                    mUserId,
-                    new InlineSuggestionsRequestInfo(mComponentName, autofillId, new Bundle()),
-                    new InlineSuggestionsRequestCallbackImpl(autofillId, mPendingImeResponse,
-                            mImeStatusListener, requestConsumer, mHandler, mLock));
-        }
-    }
-
-    public Optional<InlineSuggestionsRequest> getInlineSuggestionsRequest() {
-        final CompletableFuture<ImeResponse> pendingImeResponse = getPendingImeResponse();
-        if (pendingImeResponse == null || !pendingImeResponse.isDone()) {
-            return Optional.empty();
-        }
-        return Optional.ofNullable(pendingImeResponse.getNow(null)).map(ImeResponse::getRequest);
-    }
-
-    public boolean hideInlineSuggestionsUi(@NonNull AutofillId autofillId) {
-        synchronized (mLock) {
-            if (mIsLastResponseNonEmpty) {
-                return onInlineSuggestionsResponseLocked(autofillId,
-                        new InlineSuggestionsResponse(Collections.EMPTY_LIST));
-            }
-            return false;
-        }
-    }
-
-    public boolean onInlineSuggestionsResponse(@NonNull AutofillId autofillId,
-            @NonNull InlineSuggestionsResponse inlineSuggestionsResponse) {
-        synchronized (mLock) {
-            return onInlineSuggestionsResponseLocked(autofillId, inlineSuggestionsResponse);
-        }
-    }
-
-    private boolean onInlineSuggestionsResponseLocked(@NonNull AutofillId autofillId,
-            @NonNull InlineSuggestionsResponse inlineSuggestionsResponse) {
-        final CompletableFuture<ImeResponse> completedImsResponse = getPendingImeResponse();
-        if (completedImsResponse == null || !completedImsResponse.isDone()) {
-            if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked without IMS request");
-            return false;
-        }
-        // There is no need to wait on the CompletableFuture since it should have been completed.
-        ImeResponse imeResponse = completedImsResponse.getNow(null);
-        if (imeResponse == null) {
-            if (sDebug) Log.d(TAG, "onInlineSuggestionsResponseLocked with pending IMS response");
-            return false;
-        }
-
-        // TODO(b/151846600): IME doesn't have access to the virtual id of the webview, so we
-        //  only compare the view id for now.
-        if (!mImeInputViewStarted || mImeFieldId == null
-                || autofillId.getViewId() != mImeFieldId.getViewId()) {
-            if (sDebug) {
-                Log.d(TAG,
-                        "onInlineSuggestionsResponseLocked not sent because input view is not "
-                                + "started for " + autofillId);
-            }
-            mPendingAutofillResponse = new AutofillResponse(autofillId, inlineSuggestionsResponse);
-            // TODO(b/149442582): Although we are not sending the response to IME right away, we
-            //  still return true to indicate that the response may be sent eventually, such that
-            //  the dropdown UI will not be shown. This may not be the desired behavior in the
-            //  auto-focus case where IME isn't shown after switching back to an activity. We may
-            //  revisit this.
-            return true;
-        }
-
-        try {
-            imeResponse.mCallback.onInlineSuggestionsResponse(autofillId,
-                    inlineSuggestionsResponse);
-            mIsLastResponseNonEmpty = !inlineSuggestionsResponse.getInlineSuggestions().isEmpty();
-            if (sDebug) {
-                Log.d(TAG, "Autofill sends inline response to IME: "
-                        + inlineSuggestionsResponse.getInlineSuggestions().size());
-            }
-            return true;
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException sending InlineSuggestionsResponse to IME");
-            return false;
-        }
-    }
-
-    @Nullable
-    @GuardedBy("mLock")
-    private CompletableFuture<ImeResponse> getPendingImeResponse() {
-        synchronized (mLock) {
-            return mPendingImeResponse;
-        }
-    }
-
-    private static final class InlineSuggestionsRequestCallbackImpl
-            extends IInlineSuggestionsRequestCallback.Stub {
-
-        private final Object mLock;
-        private final AutofillId mAutofillId;
-        @GuardedBy("mLock")
-        private final CompletableFuture<ImeResponse> mResponse;
-        @GuardedBy("mLock")
-        private final Consumer<InlineSuggestionsRequest> mRequestConsumer;
-        private final ImeStatusListener mImeStatusListener;
-        private final Handler mHandler;
-        private final Runnable mTimeoutCallback;
-
-        private InlineSuggestionsRequestCallbackImpl(AutofillId autofillId,
-                CompletableFuture<ImeResponse> response,
-                ImeStatusListener imeStatusListener,
-                Consumer<InlineSuggestionsRequest> requestConsumer,
-                Handler handler, Object lock) {
-            mAutofillId = autofillId;
-            mResponse = response;
-            mImeStatusListener = imeStatusListener;
-            mRequestConsumer = requestConsumer;
-            mLock = lock;
-
-            mHandler = handler;
-            mTimeoutCallback = () -> {
-                Log.w(TAG, "Timed out waiting for IME callback InlineSuggestionsRequest.");
-                completeIfNot(null);
-            };
-            mHandler.postDelayed(mTimeoutCallback, INLINE_REQUEST_TIMEOUT_MS);
-        }
-
-        private void completeIfNot(@Nullable ImeResponse response) {
-            synchronized (mLock) {
-                if (mResponse.isDone()) {
-                    return;
-                }
-                mResponse.complete(response);
-                mRequestConsumer.accept(response == null ? null : response.mRequest);
-                mHandler.removeCallbacks(mTimeoutCallback);
-            }
-        }
-
-        @BinderThread
-        @Override
-        public void onInlineSuggestionsUnsupported() throws RemoteException {
-            if (sDebug) Log.d(TAG, "onInlineSuggestionsUnsupported() called.");
-            completeIfNot(null);
-        }
-
-        @BinderThread
-        @Override
-        public void onInlineSuggestionsRequest(InlineSuggestionsRequest request,
-                IInlineSuggestionsResponseCallback callback) {
-            if (sDebug) Log.d(TAG, "onInlineSuggestionsRequest() received: " + request);
-            mImeStatusListener.onInputMethodStartInput(mAutofillId);
-            if (request != null && callback != null) {
-                completeIfNot(new ImeResponse(request, callback));
-            } else {
-                completeIfNot(null);
-            }
-        }
-
-        @Override
-        public void onInputMethodStartInput(AutofillId imeFieldId) throws RemoteException {
-            if (sDebug) Log.d(TAG, "onInputMethodStartInput() received on " + imeFieldId);
-            mImeStatusListener.onInputMethodStartInput(imeFieldId);
-        }
-
-        @Override
-        public void onInputMethodShowInputRequested(boolean requestResult) throws RemoteException {
-            if (sDebug) {
-                Log.d(TAG, "onInputMethodShowInputRequested() received: " + requestResult);
-            }
-            // TODO(b/151123764): use this signal to adjust the timeout on Autofill side waiting for
-            //  IME to show.
-        }
-
-        @BinderThread
-        @Override
-        public void onInputMethodStartInputView() {
-            if (sDebug) Log.d(TAG, "onInputMethodStartInputView() received");
-            mImeStatusListener.onInputMethodStartInputView();
-        }
-
-        @BinderThread
-        @Override
-        public void onInputMethodFinishInputView() {
-            if (sDebug) Log.d(TAG, "onInputMethodFinishInputView() received");
-            mImeStatusListener.onInputMethodFinishInputView();
-        }
-
-        @Override
-        public void onInputMethodFinishInput() throws RemoteException {
-            if (sDebug) Log.d(TAG, "onInputMethodFinishInput() received");
-            mImeStatusListener.onInputMethodFinishInput();
-        }
-    }
-
-    private interface ImeStatusListener {
-        void onInputMethodStartInput(AutofillId imeFieldId);
-
-        void onInputMethodStartInputView();
-
-        void onInputMethodFinishInputView();
-
-        void onInputMethodFinishInput();
-    }
-
-    /**
-     * A data class wrapping Autofill responses for the inline suggestion request.
-     */
-    private static class AutofillResponse {
-        @NonNull
-        final AutofillId mAutofillId;
-
-        @NonNull
-        final InlineSuggestionsResponse mResponse;
-
-        AutofillResponse(@NonNull AutofillId autofillId,
-                @NonNull InlineSuggestionsResponse response) {
-            mAutofillId = autofillId;
-            mResponse = response;
-        }
-
-    }
-
-    /**
-     * A data class wrapping IME responses for the create inline suggestions request.
-     */
-    private static class ImeResponse {
-        @NonNull
-        final InlineSuggestionsRequest mRequest;
-
-        @NonNull
-        final IInlineSuggestionsResponseCallback mCallback;
-
-        ImeResponse(@NonNull InlineSuggestionsRequest request,
-                @NonNull IInlineSuggestionsResponseCallback callback) {
-            mRequest = request;
-            mCallback = callback;
-        }
-
-        InlineSuggestionsRequest getRequest() {
-            return mRequest;
-        }
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index e942b27..4ecffd8 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -304,7 +304,7 @@
     private boolean mForAugmentedAutofillOnly;
 
     @Nullable
-    private final InlineSuggestionSession mInlineSuggestionSession;
+    private final AutofillInlineSessionController mInlineSessionController;
 
     /**
      * Receiver of assist data from the app's {@link Activity}.
@@ -645,37 +645,33 @@
     }
 
     /**
-     * Returns whether inline suggestions are enabled for Autofill.
+     * Returns whether inline suggestions are supported by Autofill provider (not augmented
+     * Autofill provider).
      */
-    private boolean isInlineSuggestionsEnabledLocked() {
-        return mService.isInlineSuggestionsEnabled()
-                || mService.getRemoteInlineSuggestionRenderServiceLocked() != null;
+    private boolean isInlineSuggestionsEnabledByAutofillProviderLocked() {
+        return mService.isInlineSuggestionsEnabled();
+    }
+
+    private boolean isInlineSuggestionRenderServiceAvailable() {
+        return mService.getRemoteInlineSuggestionRenderServiceLocked() != null;
     }
 
     /**
-     * Ask the IME to make an inline suggestions request if enabled.
-     */
-    private void maybeRequestInlineSuggestionsRequestThenFillLocked(@NonNull ViewState viewState,
-            int newState, int flags) {
-        if (isInlineSuggestionsEnabledLocked()) {
-            Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
-                    mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ true);
-            if (inlineSuggestionsRequestConsumer != null) {
-                mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId,
-                        inlineSuggestionsRequestConsumer);
-            }
-        } else {
-            mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ false);
-        }
-        requestNewFillResponseLocked(viewState, newState, flags);
-    }
-
-    /**
-     * Reads a new structure and then request a new fill response from the fill service.
+     * Clears the existing response for the partition, reads a new structure, and then requests a
+     * new fill response from the fill service.
+     *
+     * <p> Also asks the IME to make an inline suggestions request if it's enabled.
      */
     @GuardedBy("mLock")
     private void requestNewFillResponseLocked(@NonNull ViewState viewState, int newState,
             int flags) {
+        final FillResponse existingResponse = viewState.getResponse();
+        if (existingResponse != null) {
+            setViewStatesLocked(
+                    existingResponse,
+                    ViewState.STATE_INITIAL,
+                    /* clearResponse= */ true);
+        }
         mExpiredResponse = false;
         if (mForAugmentedAutofillOnly || mRemoteFillService == null) {
             if (sVerbose) {
@@ -717,6 +713,22 @@
         // structure is taken. This causes only one fill request per bust of focus changes.
         cancelCurrentRequestLocked();
 
+        // Only ask IME to create inline suggestions request if Autofill provider supports it and
+        // the render service is available.
+        if (isInlineSuggestionsEnabledByAutofillProviderLocked()
+                && isInlineSuggestionRenderServiceAvailable()) {
+            Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
+                    mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ true);
+            if (inlineSuggestionsRequestConsumer != null) {
+                // TODO(b/146454892): pipe the uiExtras from the ExtServices.
+                mInlineSessionController.onCreateInlineSuggestionsRequestLocked(mCurrentViewId,
+                        inlineSuggestionsRequestConsumer, Bundle.EMPTY);
+            }
+        } else {
+            mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ false);
+        }
+
+        // Now request the assist structure data.
         try {
             final Bundle receiverExtras = new Bundle();
             receiverExtras.putInt(EXTRA_REQUEST_ID, requestId);
@@ -766,8 +778,8 @@
         mForAugmentedAutofillOnly = forAugmentedAutofillOnly;
         setClientLocked(client);
 
-        mInlineSuggestionSession = new InlineSuggestionSession(inputMethodManagerInternal, userId,
-                componentName, handler, mLock);
+        mInlineSessionController = new AutofillInlineSessionController(inputMethodManagerInternal,
+                userId, componentName, handler, mLock);
 
         mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
@@ -2322,8 +2334,7 @@
         if ((flags & FLAG_MANUAL_REQUEST) != 0) {
             mForAugmentedAutofillOnly = false;
             if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags);
-            maybeRequestInlineSuggestionsRequestThenFillLocked(viewState,
-                    ViewState.STATE_RESTARTED_SESSION, flags);
+            requestNewFillResponseLocked(viewState, ViewState.STATE_RESTARTED_SESSION, flags);
             return true;
         }
 
@@ -2333,8 +2344,7 @@
                 Slog.d(TAG, "Starting partition or augmented request for view id " + id + ": "
                         + viewState.getStateAsString());
             }
-            maybeRequestInlineSuggestionsRequestThenFillLocked(viewState,
-                    ViewState.STATE_STARTED_PARTITION, flags);
+            requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_PARTITION, flags);
             return true;
         } else {
             if (sVerbose) {
@@ -2458,8 +2468,7 @@
                 // View is triggering autofill.
                 mCurrentViewId = viewState.id;
                 viewState.update(value, virtualBounds, flags);
-                maybeRequestInlineSuggestionsRequestThenFillLocked(viewState,
-                        ViewState.STATE_STARTED_SESSION, flags);
+                requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_SESSION, flags);
                 break;
             case ACTION_VALUE_CHANGED:
                 if (mCompatMode && (viewState.getState() & ViewState.STATE_URL_BAR) != 0) {
@@ -2553,7 +2562,7 @@
                     if (sVerbose) Slog.v(TAG, "Exiting view " + id);
                     mUi.hideFillUi(this);
                     hideAugmentedAutofillLocked(viewState);
-                    mInlineSuggestionSession.hideInlineSuggestionsUi(mCurrentViewId);
+                    mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
                     mCurrentViewId = null;
                 }
                 break;
@@ -2771,7 +2780,7 @@
     private boolean requestShowInlineSuggestionsLocked(@NonNull FillResponse response,
             @Nullable String filterText) {
         final Optional<InlineSuggestionsRequest> inlineSuggestionsRequest =
-                mInlineSuggestionSession.getInlineSuggestionsRequest();
+                mInlineSessionController.getInlineSuggestionsRequestLocked();
         if (!inlineSuggestionsRequest.isPresent()) {
             Log.w(TAG, "InlineSuggestionsRequest unavailable");
             return false;
@@ -2793,7 +2802,8 @@
                         inlineSuggestionsRequest.get(), response, filterText, mCurrentViewId,
                         this, () -> {
                             synchronized (mLock) {
-                                mInlineSuggestionSession.hideInlineSuggestionsUi(mCurrentViewId);
+                                mInlineSessionController.hideInlineSuggestionsUiLocked(
+                                        mCurrentViewId);
                             }
                         }, remoteRenderService);
         if (inlineSuggestionsResponse == null) {
@@ -2801,7 +2811,7 @@
             return false;
         }
 
-        return mInlineSuggestionSession.onInlineSuggestionsResponse(mCurrentViewId,
+        return mInlineSessionController.onInlineSuggestionsResponseLocked(mCurrentViewId,
                 inlineSuggestionsResponse);
     }
 
@@ -3098,8 +3108,13 @@
                             focusedId,
                             currentValue, inlineSuggestionsRequest,
                             /*inlineSuggestionsCallback=*/
-                            response -> mInlineSuggestionSession.onInlineSuggestionsResponse(
-                                    mCurrentViewId, response),
+                            response -> {
+                                synchronized (mLock) {
+                                    return mInlineSessionController
+                                            .onInlineSuggestionsResponseLocked(
+                                            mCurrentViewId, response);
+                                }
+                            },
                             /*onErrorCallback=*/ () -> {
                                 synchronized (mLock) {
                                     cancelAugmentedAutofillLocked();
@@ -3107,18 +3122,22 @@
                             }, mService.getRemoteInlineSuggestionRenderServiceLocked());
                 };
 
-        // There are 3 cases when augmented autofill should ask IME for a new request:
-        // 1. standard autofill provider is None
-        // 2. standard autofill provider doesn't support inline (and returns null response)
-        // 3. standard autofill provider supports inline, but isn't called because the field
-        // doesn't want autofill
-        if (mForAugmentedAutofillOnly || !isInlineSuggestionsEnabledLocked()) {
+        // When the inline suggestion render service is available, there are 2 cases when
+        // augmented autofill should ask IME for inline suggestion request, because standard
+        // autofill flow didn't:
+        // 1. the field is augmented autofill only (when standard autofill provider is None or
+        // when it returns null response)
+        // 2. standard autofill provider doesn't support inline suggestion
+        if (isInlineSuggestionRenderServiceAvailable()
+                && (mForAugmentedAutofillOnly
+                || !isInlineSuggestionsEnabledByAutofillProviderLocked())) {
             if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
-            mInlineSuggestionSession.onCreateInlineSuggestionsRequest(mCurrentViewId,
-                    /*requestConsumer=*/ requestAugmentedAutofill);
+            // TODO(b/146454892): pipe the uiExtras from the ExtServices.
+            mInlineSessionController.onCreateInlineSuggestionsRequestLocked(mCurrentViewId,
+                    /*requestConsumer=*/ requestAugmentedAutofill, Bundle.EMPTY);
         } else {
             requestAugmentedAutofill.accept(
-                    mInlineSuggestionSession.getInlineSuggestionsRequest().orElse(null));
+                    mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null));
         }
         if (mAugmentedAutofillDestroyer == null) {
             mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
@@ -3223,7 +3242,7 @@
     }
 
     /**
-     * Sets the state of all views in the given dataset and response.
+     * Sets the state and response of all views in the given dataset.
      */
     @GuardedBy("mLock")
     private void setViewStatesLocked(@Nullable FillResponse response, @NonNull Dataset dataset,
@@ -3238,10 +3257,10 @@
             if (datasetId != null) {
                 viewState.setDatasetId(datasetId);
             }
-            if (response != null) {
-                viewState.setResponse(response);
-            } else if (clearResponse) {
+            if (clearResponse) {
                 viewState.setResponse(null);
+            } else if (response != null) {
+                viewState.setResponse(response);
             }
         }
     }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 052026c..a8bc2b4 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -91,7 +91,6 @@
     ],
 
     libs: [
-        "android_system_server_stubs_current",
         "services.net",
         "android.hardware.light-V2.0-java",
         "android.hardware.power-java",
@@ -101,6 +100,7 @@
         "android.net.ipsec.ike.stubs.module_libs_api",
         "app-compat-annotations",
         "framework-tethering-stubs-module_libs_api",
+        "service-permission-stubs",
     ],
 
     required: [
@@ -126,6 +126,7 @@
         "android.hardware.rebootescrow-java",
         "android.hardware.soundtrigger-V2.3-java",
         "android.hidl.manager-V1.2-java",
+        "capture_state_listener-aidl-java",
         "dnsresolver_aidl_interface-V2-java",
         "netd_event_listener_interface-java",
         "overlayable_policy_aidl-java",
diff --git a/services/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java
index aedafbb..94f5741 100644
--- a/services/core/java/android/os/UserManagerInternal.java
+++ b/services/core/java/android/os/UserManagerInternal.java
@@ -23,6 +23,8 @@
 import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
 
+import com.android.server.pm.RestrictionsSet;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -57,21 +59,18 @@
      * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set
      * restrictions enforced by the user.
      *
-     * @param originatingUserId user id of the user where the restriction originated.
-     * @param restrictions a bundle of user restrictions.
-     * @param restrictionOwnerType determines which admin {@code userId} corresponds to.
-     *             The admin can be either
-     *             {@link UserManagerInternal#OWNER_TYPE_DEVICE_OWNER},
-     *             {@link UserManagerInternal#OWNER_TYPE_PROFILE_OWNER},
-     *             {@link UserManagerInternal#OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE}
-     *             or {@link UserManagerInternal#OWNER_TYPE_NO_OWNER}.
-     *             If the admin is a DEVICE_OWNER or a PROFILE_OWNER_ORG_OWNED_DEVICE then
-     *             a restriction may be applied globally depending on which restriction it is,
-     *             otherwise it will be applied just on the current user.
-     * @see OwnerType
+     * @param originatingUserId user id of the user where the restrictions originated.
+     * @param global            a bundle of global user restrictions. Global restrictions are
+     *                          restrictions that apply device-wide: to the managed profile,
+     *                          primary profile and secondary users and any profile created in
+     *                          any secondary user.
+     * @param local             a restriction set of local user restrictions. The key is the user
+     *                          id of the user whom the restrictions are targeting.
+     * @param isDeviceOwner     whether {@code originatingUserId} corresponds to device owner
+     *                          user id.
      */
     public abstract void setDevicePolicyUserRestrictions(int originatingUserId,
-            @Nullable Bundle restrictions, @OwnerType int restrictionOwnerType);
+            @Nullable Bundle global, @Nullable RestrictionsSet local, boolean isDeviceOwner);
 
     /**
      * Returns the "base" user restrictions.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4ab035e7..8a1de1f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3153,7 +3153,7 @@
             }
         }
 
-        nai.clatd.setNat64Prefix(prefix);
+        nai.clatd.setNat64PrefixFromDns(prefix);
         handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
     }
 
@@ -5865,9 +5865,9 @@
             @NonNull LinkProperties oldLp) {
         int netId = networkAgent.network.netId;
 
-        // The NetworkAgentInfo does not know whether clatd is running on its network or not, or
-        // whether there is a NAT64 prefix. Before we do anything else, make sure its LinkProperties
-        // are accurate.
+        // The NetworkAgent does not know whether clatd is running on its network or not, or whether
+        // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure
+        // the LinkProperties for the network are accurate.
         networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
 
         updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities,
@@ -6313,7 +6313,8 @@
                 && !nai.networkAgentConfig.allowBypass
                 && nc.getOwnerUid() != Process.SYSTEM_UID
                 && lp.getInterfaceName() != null
-                && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
+                && (lp.hasIPv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute())
+                && (lp.hasIPv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
     }
 
     private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 8ccff76..a9c3079 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -2598,8 +2598,6 @@
     @Override
     @NonNull
     public List<LocationRequest> getTestProviderCurrentRequests(String provider) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
-
         LocationProviderManager manager = getLocationProviderManager(provider);
         if (manager == null) {
             throw new IllegalArgumentException("provider doesn't exist: " + provider);
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index d9e7c38..e77458c 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -315,28 +315,31 @@
         // causing any elapsed time to be deducted from all existing packages before we add new
         // packages. This maintains the invariant that the elapsed time for ALL (new and existing)
         // packages is the same.
-        syncState("observing new packages");
+        mLongTaskHandler.post(() -> {
+            syncState("observing new packages");
 
-        synchronized (mLock) {
-            ObserverInternal oldObserver = mAllObservers.get(observer.getName());
-            if (oldObserver == null) {
-                Slog.d(TAG, observer.getName() + " started monitoring health "
-                        + "of packages " + packageNames);
-                mAllObservers.put(observer.getName(),
-                        new ObserverInternal(observer.getName(), packages));
-            } else {
-                Slog.d(TAG, observer.getName() + " added the following "
-                        + "packages to monitor " + packageNames);
-                oldObserver.updatePackagesLocked(packages);
+            synchronized (mLock) {
+                ObserverInternal oldObserver = mAllObservers.get(observer.getName());
+                if (oldObserver == null) {
+                    Slog.d(TAG, observer.getName() + " started monitoring health "
+                            + "of packages " + packageNames);
+                    mAllObservers.put(observer.getName(),
+                            new ObserverInternal(observer.getName(), packages));
+                } else {
+                    Slog.d(TAG, observer.getName() + " added the following "
+                            + "packages to monitor " + packageNames);
+                    oldObserver.updatePackagesLocked(packages);
+                }
             }
-        }
 
-        // Register observer in case not already registered
-        registerHealthObserver(observer);
+            // Register observer in case not already registered
+            registerHealthObserver(observer);
 
-        // Sync after we add the new packages to the observers. We may have received packges
-        // requiring an earlier schedule than we are currently scheduled for.
-        syncState("updated observers");
+            // Sync after we add the new packages to the observers. We may have received packges
+            // requiring an earlier schedule than we are currently scheduled for.
+            syncState("updated observers");
+        });
+
     }
 
     /**
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 808d322..bfcde97 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -98,8 +98,8 @@
 
     private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
     private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device";
-
-    private static final String DEVICE_CONFIG_DISABLE_FLAG = "disable_rescue_party";
+    private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
+            "persist.device_config.configuration.disable_rescue_party";
 
     private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
             | ApplicationInfo.FLAG_SYSTEM;
@@ -118,8 +118,7 @@
 
         // We're disabled if the DeviceConfig disable flag is set to true.
         // This is in case that an emergency rollback of the feature is needed.
-        if (DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_CONFIGURATION, DEVICE_CONFIG_DISABLE_FLAG, false)) {
+        if (SystemProperties.getBoolean(PROP_DEVICE_CONFIG_DISABLE_FLAG, false)) {
             Slog.v(TAG, "Disabled because of DeviceConfig flag");
             return true;
         }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 9018caa..9aefc8d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -234,6 +234,7 @@
     private static final String FUSE_ENABLED = "fuse_enabled";
     private static final boolean DEFAULT_FUSE_ENABLED = true;
 
+    @GuardedBy("mLock")
     private final Set<Integer> mFuseMountedUser = new ArraySet<>();
 
     public static class Lifecycle extends SystemService {
@@ -810,7 +811,7 @@
                 }
                 case H_VOLUME_STATE_CHANGED: {
                     final SomeArgs args = (SomeArgs) msg.obj;
-                    onVolumeStateChangedInternal((VolumeInfo) args.arg1, (int) args.arg2,
+                    onVolumeStateChangedAsync((VolumeInfo) args.arg1, (int) args.arg2,
                             (int) args.arg3);
                 }
             }
@@ -1337,6 +1338,7 @@
                     args.arg2 = oldState;
                     args.arg3 = newState;
                     mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
+                    onVolumeStateChangedLocked(vol, oldState, newState);
                 }
             }
         }
@@ -1509,11 +1511,45 @@
         return true;
     }
 
-    private void onVolumeStateChangedInternal(VolumeInfo vol, int oldState, int newState) {
-        synchronized (mLock) {
-            if (vol.type == VolumeInfo.TYPE_EMULATED && newState != VolumeInfo.STATE_MOUNTED) {
+
+    private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
+        if (vol.type == VolumeInfo.TYPE_EMULATED) {
+            if (newState != VolumeInfo.STATE_MOUNTED) {
                 mFuseMountedUser.remove(vol.getMountUserId());
+            } else {
+                final int userId = vol.getMountUserId();
+                mFuseMountedUser.add(userId);
+                // Async remount app storage so it won't block the main thread.
+                new Thread(() -> {
+                    Map<Integer, String> pidPkgMap = null;
+                    // getProcessesWithPendingBindMounts() could fail when a new app process is
+                    // starting and it's not planning to mount storage dirs in zygote, but it's
+                    // rare, so we retry 5 times and hope we can get the result successfully.
+                    for (int i = 0; i < 5; i++) {
+                        try {
+                            pidPkgMap = LocalServices.getService(ActivityManagerInternal.class)
+                                    .getProcessesWithPendingBindMounts(vol.getMountUserId());
+                            break;
+                        } catch (IllegalStateException e) {
+                            Slog.i(TAG, "Some processes are starting, retry");
+                            // Wait 100ms and retry so hope the pending process is started.
+                            SystemClock.sleep(100);
+                        }
+                    }
+                    if (pidPkgMap != null) {
+                        remountAppStorageDirs(pidPkgMap, userId);
+                    } else {
+                        Slog.wtf(TAG, "Not able to getStorageNotOptimizedProcesses() after"
+                                + " 5 retries");
+                    }
+                }).start();
             }
+        }
+    }
+
+
+    private void onVolumeStateChangedAsync(VolumeInfo vol, int oldState, int newState) {
+        synchronized (mLock) {
             // Remember that we saw this volume so we're ready to accept user
             // metadata, or so we can annoy them when a private volume is ejected
             if (!TextUtils.isEmpty(vol.fsUuid)) {
@@ -2161,35 +2197,6 @@
                 }
             });
             Slog.i(TAG, "Mounted volume " + vol);
-            if (vol.type == VolumeInfo.TYPE_EMULATED) {
-                final int userId = vol.getMountUserId();
-                mFuseMountedUser.add(userId);
-                // Async remount app storage so it won't block the main thread.
-                new Thread(() -> {
-                    Map<Integer, String> pidPkgMap = null;
-                    // getProcessesWithPendingBindMounts() could fail when a new app process is
-                    // starting and it's not planning to mount storage dirs in zygote, but it's
-                    // rare, so we retry 5 times and hope we can get the result successfully.
-                    for (int i = 0; i < 5; i++) {
-                        try {
-                            pidPkgMap = LocalServices.getService(ActivityManagerInternal.class)
-                                    .getProcessesWithPendingBindMounts(vol.getMountUserId());
-                            break;
-                        } catch (IllegalStateException e) {
-                            Slog.i(TAG, "Some processes are starting, retry");
-                            // Wait 100ms and retry so hope the pending process is started.
-                            SystemClock.sleep(100);
-                        }
-                    }
-                    if (pidPkgMap != null) {
-                        remountAppStorageDirs(pidPkgMap, userId);
-                    } else {
-                        Slog.wtf(TAG, "Not able to getStorageNotOptimizedProcesses() after"
-                                + " 5 retries");
-                    }
-
-                }).start();
-            }
         } catch (Exception e) {
             Slog.wtf(TAG, e);
         }
@@ -4445,9 +4452,11 @@
         @Override
         public boolean prepareStorageDirs(int userId, Set<String> packageList,
                 String processName) {
-            if (!mFuseMountedUser.contains(userId)) {
-                Slog.w(TAG, "User " + userId + " is not unlocked yet so skip mounting obb");
-                return false;
+            synchronized (mLock) {
+                if (!mFuseMountedUser.contains(userId)) {
+                    Slog.w(TAG, "User " + userId + " is not unlocked yet so skip mounting obb");
+                    return false;
+                }
             }
             try {
                 final IVold vold = IVold.Stub.asInterface(
@@ -4459,9 +4468,8 @@
                             String.format("/storage/emulated/%d/Android/data/%s/",
                                     userId, pkg);
 
-                    int appUid =
-                            UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
                     // Create package obb and data dir if it doesn't exist.
+                    int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
                     File file = new File(packageObbDir);
                     if (!file.exists()) {
                         vold.setupAppDir(packageObbDir, appUid);
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index 059eb6a..df16058 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -32,7 +32,7 @@
             "name": "CtsWindowManagerDeviceTestCases",
             "options": [
                 {
-                    "include-filter": "android.server.wm.ToastTest"
+                    "include-filter": "android.server.wm.ToastWindowTest"
                 }
             ],
             "file_patterns": ["NotificationManagerService\\.java"]
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 061ff42..58972a5 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -123,6 +123,8 @@
             "android.hardware.neuralnetworks@1.0::IDevice",
             "android.hardware.power.stats@1.0::IPowerStats",
             "android.hardware.sensors@1.0::ISensors",
+            "android.hardware.sensors@2.0::ISensors",
+            "android.hardware.sensors@2.1::ISensors",
             "android.hardware.vr@1.0::IVr",
             "android.system.suspend@1.0::ISystemSuspend"
     );
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 7aaf9be..e1f9a7a 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -137,12 +137,12 @@
 
         @Override
         public File getAdbKeysFile() {
-            return mDebuggingManager.getUserKeyFile();
+            return mDebuggingManager == null ? null : mDebuggingManager.getUserKeyFile();
         }
 
         @Override
         public File getAdbTempKeysFile() {
-            return mDebuggingManager.getAdbTempKeysFile();
+            return mDebuggingManager == null ? null : mDebuggingManager.getAdbTempKeysFile();
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7523710d..21760cd 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1440,7 +1440,7 @@
                                 active.mPackageName = r.packageName;
                                 active.mUid = r.appInfo.uid;
                                 active.mShownWhileScreenOn = mScreenOn;
-                                if (r.app != null) {
+                                if (r.app != null && r.app.uidRecord != null) {
                                     active.mAppOnTop = active.mShownWhileTop =
                                             r.app.uidRecord.getCurProcState()
                                                     <= ActivityManager.PROCESS_STATE_TOP;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 689f64d0..e41ba0e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12121,8 +12121,6 @@
 
     void dumpAllowedAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
-        boolean needSep = false;
-
         pw.println("ACTIVITY MANAGER ALLOWED ASSOCIATION STATE (dumpsys activity allowed-associations)");
         boolean printed = false;
         if (mAllowedAssociations != null) {
@@ -12130,21 +12128,16 @@
                 final String pkg = mAllowedAssociations.keyAt(i);
                 final ArraySet<String> asc =
                         mAllowedAssociations.valueAt(i).getAllowedPackageAssociations();
-                boolean printedHeader = false;
+                if (!printed) {
+                    pw.println("  Allowed associations (by restricted package):");
+                    printed = true;
+                }
+                pw.print("  * ");
+                pw.print(pkg);
+                pw.println(":");
                 for (int j = 0; j < asc.size(); j++) {
                     if (dumpPackage == null || pkg.equals(dumpPackage)
                             || asc.valueAt(j).equals(dumpPackage)) {
-                        if (!printed) {
-                            pw.println("  Allowed associations (by restricted package):");
-                            printed = true;
-                            needSep = true;
-                        }
-                        if (!printedHeader) {
-                            pw.print("  * ");
-                            pw.print(pkg);
-                            pw.println(":");
-                            printedHeader = true;
-                        }
                         pw.print("      Allow: ");
                         pw.println(asc.valueAt(j));
                     }
@@ -17698,7 +17691,7 @@
 
             proc.setReportedForegroundServiceTypes(fgServiceTypes);
             ProcessChangeItem item = enqueueProcessChangeItemLocked(proc.pid, proc.info.uid);
-            item.changes = ProcessChangeItem.CHANGE_FOREGROUND_SERVICES;
+            item.changes |= ProcessChangeItem.CHANGE_FOREGROUND_SERVICES;
             item.foregroundServiceTypes = fgServiceTypes;
         }
         if (oomAdj) {
@@ -18376,7 +18369,18 @@
                     }
                 }
 
-                proc.thread.dumpHeap(managed, mallocInfo, runGc, path, fd, finishCallback);
+                Process.enableFreezer(false);
+
+                final RemoteCallback intermediateCallback = new RemoteCallback(
+                        new RemoteCallback.OnResultListener() {
+                        @Override
+                        public void onResult(Bundle result) {
+                            finishCallback.sendResult(result);
+                            Process.enableFreezer(true);
+                        }
+                    }, null);
+
+                proc.thread.dumpHeap(managed, mallocInfo, runGc, path, fd, intermediateCallback);
                 fd = null;
                 return true;
             }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 1412112..dbcb3da 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2385,7 +2385,7 @@
                     "Changes in " + app + ": " + changes);
             ActivityManagerService.ProcessChangeItem item =
                     mService.enqueueProcessChangeItemLocked(app.pid, app.info.uid);
-            item.changes = changes;
+            item.changes |= changes;
             item.foregroundActivities = app.repForegroundActivities;
             item.capability = app.setCapability;
             if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 595275d..786e9cf 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -97,6 +97,7 @@
 import android.system.Os;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.LongSparseArray;
 import android.util.Pair;
@@ -137,6 +138,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Activity manager code dealing with processes.
@@ -1846,11 +1848,13 @@
                 runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
             }
 
-            // Enable heap pointer tagging, unless disabled by the app manifest, target sdk level,
-            // or the compat feature.
-            if (app.info.allowsNativeHeapPointerTagging()
-                    && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
-                runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+            if (Zygote.nativeSupportsTaggedPointers()) {
+                // Enable heap pointer tagging if supported by the kernel, unless disabled by the
+                // app manifest, target sdk level, or compat feature.
+                if (app.info.allowsNativeHeapPointerTagging()
+                        && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
+                    runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+                }
             }
 
             runtimeFlags |= decideGwpAsanLevel(app);
@@ -2127,18 +2131,11 @@
         for (String packageName : packages) {
             String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
             long inode = pmInt.getCeDataInode(packageName, userId);
-            if (inode != 0) {
-                result.put(packageName, Pair.create(volumeUuid, inode));
+            if (inode == 0) {
+                Slog.w(TAG, packageName + " inode == 0 (b/152760674)");
+                return null;
             }
-        }
-        if (mAppDataIsolationWhitelistedApps != null) {
-            for (String packageName : mAppDataIsolationWhitelistedApps) {
-                String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
-                long inode = pmInt.getCeDataInode(packageName, userId);
-                if (inode != 0) {
-                    result.put(packageName, Pair.create(volumeUuid, inode));
-                }
-            }
+            result.put(packageName, Pair.create(volumeUuid, inode));
         }
 
         return result;
@@ -2160,35 +2157,56 @@
                 app.setHasForegroundActivities(true);
             }
 
+            final Map<String, Pair<String, Long>> pkgDataInfoMap;
+            final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
+            boolean bindMountAppStorageDirs = false;
+            boolean bindMountAppsData = mAppDataIsolationEnabled
+                    && UserHandle.isApp(app.uid)
+                    && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
+
+            // Get all packages belongs to the same shared uid. sharedPackages is empty array
+            // if it doesn't have shared uid.
+            final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
+            final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+                    app.info.packageName, app.userId);
+            final String[] targetPackagesList = sharedPackages.length == 0
+                    ? new String[]{app.info.packageName} : sharedPackages;
+
+            pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
+            if (pkgDataInfoMap == null) {
+                // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
+                // tmp free pass.
+                bindMountAppsData = false;
+            }
+
+            // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
+            // it won't be mounted twice.
+            final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
+            for (String pkg : targetPackagesList) {
+                whitelistedApps.remove(pkg);
+            }
+
+            whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
+                    whitelistedApps.toArray(new String[0]), uid);
+            if (whitelistedAppDataInfoMap == null) {
+                // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
+                // tmp free pass.
+                bindMountAppsData = false;
+            }
+
+            int userId = UserHandle.getUserId(uid);
             StorageManagerInternal storageManagerInternal = LocalServices.getService(
                     StorageManagerInternal.class);
-            final Map<String, Pair<String, Long>> pkgDataInfoMap;
-            boolean bindMountAppStorageDirs = false;
-
-            if (mAppDataIsolationEnabled && UserHandle.isApp(app.uid)
-                    && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info)) {
-                // Get all packages belongs to the same shared uid. sharedPackages is empty array
-                // if it doesn't have shared uid.
-                final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
-                final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
-                        app.info.packageName, app.userId);
-                pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
-                        ? new String[]{app.info.packageName} : sharedPackages, uid);
-
-                int userId = UserHandle.getUserId(uid);
-                if (mVoldAppDataIsolationEnabled
-                        && !storageManagerInternal.isExternalStorageService(uid)) {
-                    bindMountAppStorageDirs = true;
-                    if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
-                            app.processName)) {
-                        // Cannot prepare Android/app and Android/obb directory,
-                        // so we won't mount it in zygote.
-                        app.bindMountPending = true;
-                        bindMountAppStorageDirs = false;
-                    }
+            if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid)
+                    && !storageManagerInternal.isExternalStorageService(uid)) {
+                bindMountAppStorageDirs = true;
+                if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
+                        app.processName)) {
+                    // Cannot prepare Android/app and Android/obb directory,
+                    // so we won't mount it in zygote.
+                    app.bindMountPending = true;
+                    bindMountAppStorageDirs = false;
                 }
-            } else {
-                pkgDataInfoMap = null;
             }
 
             final Process.ProcessStartResult startResult;
@@ -2206,7 +2224,8 @@
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
                         /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
-                        app.mDisabledCompatChanges, pkgDataInfoMap, bindMountAppStorageDirs,
+                        app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
+                        bindMountAppsData, bindMountAppStorageDirs,
                         new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
@@ -2214,7 +2233,7 @@
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                         isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
-                        bindMountAppStorageDirs,
+                        whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                         new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkSlow(startTime, "startProcess: returned from zygote!");
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 8e6ef75..31bccea 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -5853,10 +5853,6 @@
         if (pkg == null) {
             return false;
         }
-        if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.Q) {
-            return false;
-        }
-
         String[] requestedPermissions = pkg.requestedPermissions;
         if (requestedPermissions == null) {
             return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index b546120..c2c79d3 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -324,7 +324,7 @@
     }
 
     /*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
-        //Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
+        //Log.i(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
         synchronized (mDeviceStateLock) {
             if (on) {
                 // do not accept SCO ON if SCO audio is not connected
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f6cdaeb..30e765f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1331,10 +1331,10 @@
     private void updateDefaultVolumes() {
         for (int stream = 0; stream < mStreamStates.length; stream++) {
             if (stream != mStreamVolumeAlias[stream]) {
-                AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
-                        AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
+                AudioSystem.DEFAULT_STREAM_VOLUME[stream] = (rescaleIndex(
+                        AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]] * 10,
                         mStreamVolumeAlias[stream],
-                        stream);
+                        stream) + 5) / 10;
             }
         }
     }
@@ -2332,8 +2332,7 @@
     }
 
     private void enforceModifyAudioRoutingPermission() {
-        if (mContext.checkCallingOrSelfPermission(
-                android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission");
         }
@@ -4610,6 +4609,117 @@
         observeDevicesForStreams(-1);
     }
 
+    /**
+     * @see AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int)
+     * @param device the audio device to be affected
+     * @param deviceVolumeBehavior one of the device behaviors
+     */
+    public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device,
+            @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior, @Nullable String pkgName) {
+        // verify permissions
+        enforceModifyAudioRoutingPermission();
+        // verify arguments
+        Objects.requireNonNull(device);
+        AudioManager.enforceValidVolumeBehavior(deviceVolumeBehavior);
+        if (pkgName == null) {
+            pkgName = "";
+        }
+        // translate Java device type to native device type (for the devices masks for full / fixed)
+        final int type;
+        switch (device.getType()) {
+            case AudioDeviceInfo.TYPE_HDMI:
+                type = AudioSystem.DEVICE_OUT_HDMI;
+                break;
+            case AudioDeviceInfo.TYPE_HDMI_ARC:
+                type = AudioSystem.DEVICE_OUT_HDMI_ARC;
+                break;
+            case AudioDeviceInfo.TYPE_LINE_DIGITAL:
+                type = AudioSystem.DEVICE_OUT_SPDIF;
+                break;
+            case AudioDeviceInfo.TYPE_AUX_LINE:
+                type = AudioSystem.DEVICE_OUT_LINE;
+                break;
+            default:
+                // unsupported for now
+                throw new IllegalArgumentException("Unsupported device type " + device.getType());
+        }
+        // update device masks based on volume behavior
+        switch (deviceVolumeBehavior) {
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE:
+                mFullVolumeDevices.remove(type);
+                mFixedVolumeDevices.remove(type);
+                break;
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED:
+                mFullVolumeDevices.remove(type);
+                mFixedVolumeDevices.add(type);
+                break;
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL:
+                mFullVolumeDevices.add(type);
+                mFixedVolumeDevices.remove(type);
+                break;
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
+                throw new IllegalArgumentException("Absolute volume unsupported for now");
+        }
+        // log event and caller
+        sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "Volume behavior " + deviceVolumeBehavior
+                        + " for dev=0x" + Integer.toHexString(type) + " by pkg:" + pkgName));
+        // make sure we have a volume entry for this device, and that volume is updated according
+        // to volume behavior
+        checkAddAllFixedVolumeDevices(type, "setDeviceVolumeBehavior:" + pkgName);
+    }
+
+    /**
+     * @see AudioManager#getDeviceVolumeBehavior(AudioDeviceAttributes)
+     * @param device the audio output device type
+     * @return the volume behavior for the device
+     */
+    public @AudioManager.DeviceVolumeBehavior int getDeviceVolumeBehavior(
+            @NonNull AudioDeviceAttributes device) {
+        // verify permissions
+        enforceModifyAudioRoutingPermission();
+        // translate Java device type to native device type (for the devices masks for full / fixed)
+        final int type;
+        switch (device.getType()) {
+            case AudioDeviceInfo.TYPE_HEARING_AID:
+                type = AudioSystem.DEVICE_OUT_HEARING_AID;
+                break;
+            case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
+                type = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
+                break;
+            case AudioDeviceInfo.TYPE_HDMI:
+                type = AudioSystem.DEVICE_OUT_HDMI;
+                break;
+            case AudioDeviceInfo.TYPE_HDMI_ARC:
+                type = AudioSystem.DEVICE_OUT_HDMI_ARC;
+                break;
+            case AudioDeviceInfo.TYPE_LINE_DIGITAL:
+                type = AudioSystem.DEVICE_OUT_SPDIF;
+                break;
+            case AudioDeviceInfo.TYPE_AUX_LINE:
+                type = AudioSystem.DEVICE_OUT_LINE;
+                break;
+            default:
+                // unsupported for now
+                throw new IllegalArgumentException("Unsupported device type " + device.getType());
+        }
+        if ((mFullVolumeDevices.contains(type))) {
+            return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL;
+        }
+        if ((mFixedVolumeDevices.contains(type))) {
+            return AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED;
+        }
+        if ((mAbsVolumeMultiModeCaseDevices.contains(type))) {
+            return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE;
+        }
+        if (type == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
+                && mDeviceBroker.isAvrcpAbsoluteVolumeSupported()) {
+            return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE;
+        }
+        return AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE;
+    }
+
     /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
     /*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
     /**
@@ -4779,7 +4889,9 @@
             } catch (IllegalArgumentException e) {
                 // Volume Groups without attributes are not controllable through set/get volume
                 // using attributes. Do not append them.
-                Log.d(TAG, "volume group " + avg.name() + " for internal policy needs");
+                if (DEBUG_VOL) {
+                    Log.d(TAG, "volume group " + avg.name() + " for internal policy needs");
+                }
                 continue;
             }
             sVolumeGroupStates.append(avg.getId(), new VolumeGroupState(avg));
@@ -4800,7 +4912,9 @@
     }
 
     private void readVolumeGroupsSettings() {
-        Log.v(TAG, "readVolumeGroupsSettings");
+        if (DEBUG_VOL) {
+            Log.v(TAG, "readVolumeGroupsSettings");
+        }
         for (int i = 0; i < sVolumeGroupStates.size(); i++) {
             final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
             vgs.readSettings();
@@ -4810,7 +4924,9 @@
 
     // Called upon crash of AudioServer
     private void restoreVolumeGroups() {
-        Log.v(TAG, "restoreVolumeGroups");
+        if (DEBUG_VOL) {
+            Log.v(TAG, "restoreVolumeGroups");
+        }
         for (int i = 0; i < sVolumeGroupStates.size(); i++) {
             final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
             vgs.applyAllVolumes();
@@ -4846,7 +4962,9 @@
 
         private VolumeGroupState(AudioVolumeGroup avg) {
             mAudioVolumeGroup = avg;
-            Log.v(TAG, "VolumeGroupState for " + avg.toString());
+            if (DEBUG_VOL) {
+                Log.v(TAG, "VolumeGroupState for " + avg.toString());
+            }
             for (final AudioAttributes aa : avg.getAudioAttributes()) {
                 if (!aa.equals(AudioProductStrategy.sDefaultAttributes)) {
                     mAudioAttributes = aa;
@@ -4949,16 +5067,21 @@
                     final int device = mIndexMap.keyAt(i);
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
                         index = mIndexMap.valueAt(i);
-                        Log.v(TAG, "applyAllVolumes: restore index " + index + " for group "
-                                + mAudioVolumeGroup.name() + " and device "
-                                + AudioSystem.getOutputDeviceName(device));
+                        if (DEBUG_VOL) {
+                            Log.v(TAG, "applyAllVolumes: restore index " + index + " for group "
+                                    + mAudioVolumeGroup.name() + " and device "
+                                    + AudioSystem.getOutputDeviceName(device));
+                        }
                         setVolumeIndexInt(index, device, 0 /*flags*/);
                     }
                 }
                 // apply default volume last: by convention , default device volume will be used
+                // by audio policy manager if no explicit volume is present for a given device type
                 index = getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
-                Log.v(TAG, "applyAllVolumes: restore default device index " + index + " for group "
-                        + mAudioVolumeGroup.name());
+                if (DEBUG_VOL) {
+                    Log.v(TAG, "applyAllVolumes: restore default device index " + index
+                            + " for group " + mAudioVolumeGroup.name());
+                }
                 setVolumeIndexInt(index, AudioSystem.DEVICE_OUT_DEFAULT, 0 /*flags*/);
             }
         }
@@ -4967,9 +5090,11 @@
             if (mUseFixedVolume) {
                 return;
             }
-            Log.v(TAG, "persistVolumeGroup: storing index " + getIndex(device) + " for group "
-                    + mAudioVolumeGroup.name() + " and device "
-                    + AudioSystem.getOutputDeviceName(device));
+            if (DEBUG_VOL) {
+                Log.v(TAG, "persistVolumeGroup: storing index " + getIndex(device) + " for group "
+                        + mAudioVolumeGroup.name() + " and device "
+                        + AudioSystem.getOutputDeviceName(device));
+            }
             boolean success = Settings.System.putIntForUser(mContentResolver,
                     getSettingNameForDevice(device),
                     getIndex(device),
@@ -4999,12 +5124,12 @@
                     index = Settings.System.getIntForUser(
                             mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
                     if (index == -1) {
-                        Log.e(TAG, "readSettings: No index stored for group "
-                                + mAudioVolumeGroup.name() + ", device " + name);
                         continue;
                     }
-                    Log.v(TAG, "readSettings: found stored index " + getValidIndex(index)
-                             + " for group " + mAudioVolumeGroup.name() + ", device: " + name);
+                    if (DEBUG_VOL) {
+                        Log.v(TAG, "readSettings: found stored index " + getValidIndex(index)
+                                 + " for group " + mAudioVolumeGroup.name() + ", device: " + name);
+                    }
                     mIndexMap.put(device, getValidIndex(index));
                 }
             }
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 36332c0..93d1bed 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -58,6 +58,7 @@
     }
 
     // List of clients having issued a SCO start request
+    @GuardedBy("BtHelper.this")
     private final @NonNull ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>();
 
     // BluetoothHeadset API to control SCO connection
@@ -356,9 +357,8 @@
         // client is created.
         final long ident = Binder.clearCallingIdentity();
         try {
-            eventSource += " client count before=" + client.getCount();
             AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
-            client.incCount(scoAudioMode);
+            client.requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
         } catch (NullPointerException e) {
             Log.e(TAG, "Null ScoClient", e);
         }
@@ -375,9 +375,15 @@
         // and this must be done on behalf of system server to make sure permissions are granted.
         final long ident = Binder.clearCallingIdentity();
         if (client != null) {
-            eventSource += " client count before=" + client.getCount();
             AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
-            client.decCount();
+            client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
+                    SCO_MODE_VIRTUAL_CALL);
+            // If a disconnection is pending, the client will be removed whne clearAllScoClients()
+            // is called form receiveBtEvent()
+            if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ
+                    && mScoAudioState != SCO_STATE_DEACTIVATING) {
+                client.remove(false /*stop */, true /*unregister*/);
+            }
         }
         Binder.restoreCallingIdentity(ident);
     }
@@ -657,25 +663,33 @@
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
     /*package*/ synchronized void scoClientDied(Object obj) {
         final ScoClient client = (ScoClient) obj;
+        client.remove(true /*stop*/, false /*unregister*/);
         Log.w(TAG, "SCO client died");
-        int index = mScoClients.indexOf(client);
-        if (index < 0) {
-            Log.w(TAG, "unregistered SCO client died");
-        } else {
-            client.clearCount(true);
-            mScoClients.remove(client);
-        }
     }
 
     private class ScoClient implements IBinder.DeathRecipient {
         private IBinder mCb; // To be notified of client's death
         private int mCreatorPid;
-        private int mStartcount; // number of SCO connections started by this client
 
         ScoClient(IBinder cb) {
             mCb = cb;
             mCreatorPid = Binder.getCallingPid();
-            mStartcount = 0;
+        }
+
+        public void registerDeathRecipient() {
+            try {
+                mCb.linkToDeath(this, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "ScoClient could not link to " + mCb + " binder death");
+            }
+        }
+
+        public void unregisterDeathRecipient() {
+            try {
+                mCb.unlinkToDeath(this, 0);
+            } catch (NoSuchElementException e) {
+                Log.w(TAG, "ScoClient could not not unregistered to binder");
+            }
         }
 
         @Override
@@ -685,70 +699,6 @@
             mDeviceBroker.postScoClientDied(this);
         }
 
-        // @GuardedBy("AudioDeviceBroker.mSetModeLock")
-        // @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
-        @GuardedBy("BtHelper.this")
-        void incCount(int scoAudioMode) {
-            if (!requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode)) {
-                Log.e(TAG, "Request sco connected with scoAudioMode("
-                        + scoAudioMode + ") failed");
-                return;
-            }
-            if (mStartcount == 0) {
-                try {
-                    mCb.linkToDeath(this, 0);
-                } catch (RemoteException e) {
-                    // client has already died!
-                    Log.w(TAG, "ScoClient  incCount() could not link to "
-                            + mCb + " binder death");
-                }
-            }
-            mStartcount++;
-        }
-
-        // @GuardedBy("AudioDeviceBroker.mSetModeLock")
-        // @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
-        @GuardedBy("BtHelper.this")
-        void decCount() {
-            if (mStartcount == 0) {
-                Log.w(TAG, "ScoClient.decCount() already 0");
-            } else {
-                mStartcount--;
-                if (mStartcount == 0) {
-                    try {
-                        mCb.unlinkToDeath(this, 0);
-                    } catch (NoSuchElementException e) {
-                        Log.w(TAG, "decCount() going to 0 but not registered to binder");
-                    }
-                }
-                if (!requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0)) {
-                    Log.w(TAG, "Request sco disconnected with scoAudioMode(0) failed");
-                }
-            }
-        }
-
-        // @GuardedBy("AudioDeviceBroker.mSetModeLock")
-        // @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
-        @GuardedBy("BtHelper.this")
-        void clearCount(boolean stopSco) {
-            if (mStartcount != 0) {
-                try {
-                    mCb.unlinkToDeath(this, 0);
-                } catch (NoSuchElementException e) {
-                    Log.w(TAG, "clearCount() mStartcount: "
-                            + mStartcount + " != 0 but not registered to binder");
-                }
-            }
-            mStartcount = 0;
-            if (stopSco) {
-                requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
-            }
-        }
-
-        int getCount() {
-            return mStartcount;
-        }
-
         IBinder getBinder() {
             return mCb;
         }
@@ -757,23 +707,14 @@
             return mCreatorPid;
         }
 
-        private int totalCount() {
-            int count = 0;
-            for (ScoClient mScoClient : mScoClients) {
-                count += mScoClient.getCount();
-            }
-            return count;
-        }
-
         // @GuardedBy("AudioDeviceBroker.mSetModeLock")
         //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
         @GuardedBy("BtHelper.this")
         private boolean requestScoState(int state, int scoAudioMode) {
             checkScoAudioState();
-            int clientCount = totalCount();
-            if (clientCount != 0) {
+            if (mScoClients.size() != 1) {
                 Log.i(TAG, "requestScoState: state=" + state + ", scoAudioMode=" + scoAudioMode
-                        + ", clientCount=" + clientCount);
+                        + ", num SCO clients=" + mScoClients.size());
                 return true;
             }
             if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
@@ -842,12 +783,14 @@
                         mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
                         break;
+                    case SCO_STATE_ACTIVE_INTERNAL:
+                        Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return");
+                        break;
                     default:
                         Log.w(TAG, "requestScoState: failed to connect in state "
                                 + mScoAudioState + ", scoAudioMode=" + scoAudioMode);
                         broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                         return false;
-
                 }
             } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                 switch (mScoAudioState) {
@@ -893,6 +836,18 @@
             }
             return true;
         }
+
+        @GuardedBy("BtHelper.this")
+        void remove(boolean stop, boolean unregister) {
+            if (unregister) {
+                unregisterDeathRecipient();
+            }
+            if (stop) {
+                requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
+                        SCO_MODE_VIRTUAL_CALL);
+            }
+            mScoClients.remove(this);
+        }
     }
 
     //-----------------------------------------------------
@@ -946,6 +901,7 @@
     }
 
 
+    @GuardedBy("BtHelper.this")
     private ScoClient getScoClient(IBinder cb, boolean create) {
         for (ScoClient existingClient : mScoClients) {
             if (existingClient.getBinder() == cb) {
@@ -954,6 +910,7 @@
         }
         if (create) {
             ScoClient newClient = new ScoClient(cb);
+            newClient.registerDeathRecipient();
             mScoClients.add(newClient);
             return newClient;
         }
@@ -964,18 +921,16 @@
     //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
     @GuardedBy("BtHelper.this")
     private void clearAllScoClients(int exceptPid, boolean stopSco) {
-        ScoClient savedClient = null;
+        final ArrayList<ScoClient> clients = new ArrayList<ScoClient>();
         for (ScoClient cl : mScoClients) {
             if (cl.getPid() != exceptPid) {
-                cl.clearCount(stopSco);
-            } else {
-                savedClient = cl;
+                clients.add(cl);
             }
         }
-        mScoClients.clear();
-        if (savedClient != null) {
-            mScoClients.add(savedClient);
+        for (ScoClient cl : clients) {
+            cl.remove(stopSco, true /*unregister*/);
         }
+
     }
 
     private boolean getBluetoothHeadset() {
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index 65f2218..32c6cc3 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -150,14 +150,14 @@
         final AudioRecordingConfiguration config = createRecordingConfiguration(
                 uid, session, source, recordingInfo,
                 portId, silenced, activeSource, clientEffects, effects);
-        if (source == MediaRecorder.AudioSource.REMOTE_SUBMIX) {
+        if (source == MediaRecorder.AudioSource.REMOTE_SUBMIX
+                && (event == AudioManager.RECORD_CONFIG_EVENT_START
+                        || event == AudioManager.RECORD_CONFIG_EVENT_UPDATE)) {
             final AudioDeviceInfo device = config.getAudioDevice();
-            if (AudioSystem.LEGACY_REMOTE_SUBMIX_ADDRESS.equals(device.getAddress())) {
+            if (device != null
+                    && AudioSystem.LEGACY_REMOTE_SUBMIX_ADDRESS.equals(device.getAddress())) {
                 mLegacyRemoteSubmixRiid.set(riid);
-                if (event == AudioManager.RECORD_CONFIG_EVENT_START
-                        || event == AudioManager.RECORD_CONFIG_EVENT_UPDATE) {
-                    mLegacyRemoteSubmixActive.set(true);
-                }
+                mLegacyRemoteSubmixActive.set(true);
             }
         }
         if (MediaRecorder.isSystemOnlyAudioSource(source)) {
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index 45b9383..4431abe 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -17,6 +17,7 @@
 package com.android.server.biometrics;
 
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -43,6 +44,7 @@
 import android.os.IBinder;
 import android.os.IHwBinder;
 import android.os.IRemoteCallback;
+import android.os.Looper;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
@@ -52,6 +54,8 @@
 import android.os.UserManager;
 import android.util.Slog;
 
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.FrameworkStatsLog;
@@ -93,7 +97,22 @@
     protected final Map<Integer, Long> mAuthenticatorIds =
             Collections.synchronizedMap(new HashMap<>());
     protected final AppOpsManager mAppOps;
-    protected final H mHandler = new H();
+
+    /**
+     * Handler which all subclasses should post events to.
+     */
+    protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(android.os.Message msg) {
+            switch (msg.what) {
+                case MSG_USER_SWITCHING:
+                    handleUserSwitching(msg.arg1);
+                    break;
+                default:
+                    Slog.w(getTag(), "Unknown message:" + msg.what);
+            }
+        }
+    };
 
     private final IBinder mToken = new Binder(); // Used for internal enumeration
     private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
@@ -483,23 +502,6 @@
         void resetLockout(byte[] token) throws RemoteException;
     }
 
-    /**
-     * Handler which all subclasses should post events to.
-     */
-    protected final class H extends Handler {
-        @Override
-        public void handleMessage(android.os.Message msg) {
-            switch (msg.what) {
-                case MSG_USER_SWITCHING:
-                    handleUserSwitching(msg.arg1);
-                    break;
-
-                default:
-                    Slog.w(getTag(), "Unknown message:" + msg.what);
-            }
-        }
-    }
-
     private final Runnable mOnTaskStackChangedRunnable = new Runnable() {
         @Override
         public void run() {
@@ -647,8 +649,9 @@
         mContext = context;
         mStatusBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-        mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
-                com.android.internal.R.string.config_keyguardComponent)).getPackageName();
+        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
+                context.getResources().getString(R.string.config_keyguardComponent));
+        mKeyguardPackage = keyguardComponent != null ? keyguardComponent.getPackageName() : null;
         mAppOps = context.getSystemService(AppOpsManager.class);
         mActivityTaskManager = ((ActivityTaskManager) context.getSystemService(
                 Context.ACTIVITY_TASK_SERVICE)).getService();
@@ -671,8 +674,8 @@
 
         // All client lifecycle must be managed on the handler.
         mHandler.post(() -> {
-            handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
-                    0 /*vendorCode */);
+            Slog.e(getTag(), "Sending BIOMETRIC_ERROR_HW_UNAVAILABLE after HAL crash");
+            handleError(getHalDeviceId(), BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
         });
 
         FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
@@ -798,9 +801,10 @@
     }
 
     protected void handleEnumerate(BiometricAuthenticator.Identifier identifier, int remaining) {
-        ClientMonitor client = getCurrentClient();
-
-        client.onEnumerationResult(identifier, remaining);
+        ClientMonitor client = mCurrentClient;
+        if (client != null) {
+            client.onEnumerationResult(identifier, remaining);
+        }
 
         // All templates in the HAL for this user were enumerated
         if (remaining == 0) {
@@ -818,7 +822,7 @@
                 }
                 removeClient(client);
                 startCleanupUnknownHALTemplates();
-            } else {
+            } else if (client != null) {
                 removeClient(client);
             }
         }
@@ -898,12 +902,16 @@
 
     protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName,
             int callingUid, int callingPid, int callingUserId, boolean fromClient) {
+
+        if (DEBUG) Slog.v(getTag(), "cancelAuthentication(" + opPackageName + ")");
         if (fromClient) {
             // Only check this if cancel was called from the client (app). If cancel was called
             // from BiometricService, it means the dialog was dismissed due to user interaction.
             if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
                     callingUserId)) {
-                if (DEBUG) Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
+                if (DEBUG) {
+                    Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
+                }
                 return;
             }
         }
@@ -1059,7 +1067,8 @@
      * @param newClient the new client that wants to connect
      * @param initiatedByClient true for authenticate, remove and enroll
      */
-    private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
+    @VisibleForTesting
+    void startClient(ClientMonitor newClient, boolean initiatedByClient) {
         ClientMonitor currentClient = mCurrentClient;
         if (currentClient != null) {
             if (DEBUG) Slog.v(getTag(), "request stop current client " +
@@ -1122,18 +1131,27 @@
             Slog.e(getTag(), "Trying to start null client!");
             return;
         }
+
         if (DEBUG) Slog.v(getTag(), "starting client "
                 + mCurrentClient.getClass().getSuperclass().getSimpleName()
                 + "(" + mCurrentClient.getOwnerString() + ")"
                 + " targetUserId: " + mCurrentClient.getTargetUserId()
                 + " currentUserId: " + mCurrentUserId
                 + " cookie: " + cookie + "/" + mCurrentClient.getCookie());
+
         if (cookie != mCurrentClient.getCookie()) {
             Slog.e(getTag(), "Mismatched cookie");
             return;
         }
-        notifyClientActiveCallbacks(true);
-        mCurrentClient.start();
+
+        int status = mCurrentClient.start();
+        if (status == 0) {
+            notifyClientActiveCallbacks(true);
+        } else {
+            mCurrentClient.onError(getHalDeviceId(), BIOMETRIC_ERROR_HW_UNAVAILABLE,
+                    0 /* vendorCode */);
+            removeClient(mCurrentClient);
+        }
     }
 
     protected void removeClient(ClientMonitor client) {
@@ -1145,7 +1163,7 @@
             }
         }
         if (mCurrentClient != null) {
-            if (DEBUG) Slog.v(getTag(), "Done with client: " + client.getOwnerString());
+            if (DEBUG) Slog.v(getTag(), "Done with client: " + mCurrentClient.getOwnerString());
             mCurrentClient = null;
         }
         if (mPendingClient == null) {
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 3ecf87c..ad73b64 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -382,8 +382,10 @@
             checkPermission(MANAGE_BIOMETRIC);
             updateActiveGroup(userId, opPackageName);
 
-            mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
-                    UserHandle.CURRENT);
+            mHandler.post(() -> {
+                mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
+                        UserHandle.CURRENT);
+            });
 
             final boolean restricted = isRestricted();
             final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 82465f8..741cb5b 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -81,7 +81,7 @@
         RUNNING,      // start() called, and the stacked iface is known to be up.
     }
 
-    private IpPrefix mNat64Prefix;
+    private IpPrefix mNat64PrefixFromDns;
     private String mBaseIface;
     private String mIface;
     private Inet6Address mIPv6Address;
@@ -100,7 +100,7 @@
      * currently connected and where the NetworkAgent has not disabled 464xlat. It is the signal to
      * enable NAT64 prefix discovery.
      *
-     * @param network the NetworkAgentInfo corresponding to the network.
+     * @param nai the NetworkAgentInfo corresponding to the network.
      * @return true if the network requires clat, false otherwise.
      */
     @VisibleForTesting
@@ -180,7 +180,7 @@
 
         String addrStr = null;
         try {
-            addrStr = mNetd.clatdStart(baseIface, mNat64Prefix.toString());
+            addrStr = mNetd.clatdStart(baseIface, getNat64Prefix().toString());
         } catch (RemoteException | ServiceSpecificException e) {
             Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e);
         }
@@ -213,12 +213,10 @@
         }
         mIface = null;
         mBaseIface = null;
-        mState = State.IDLE;
         if (requiresClat(mNetwork)) {
             mState = State.DISCOVERING;
         } else {
             stopPrefixDiscovery();
-            mState = State.IDLE;
         }
     }
 
@@ -285,6 +283,7 @@
     private void stopPrefixDiscovery() {
         try {
             mDnsResolver.stopPrefix64Discovery(getNetId());
+            mState = State.IDLE;
         } catch (RemoteException | ServiceSpecificException e) {
             Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
         }
@@ -294,32 +293,52 @@
      * Starts/stops NAT64 prefix discovery and clatd as necessary.
      */
     public void update() {
-        // TODO: turn this class into a proper StateMachine. // http://b/126113090
-        if (requiresClat(mNetwork)) {
-            if (!isPrefixDiscoveryStarted()) {
-                startPrefixDiscovery();
-            } else if (shouldStartClat(mNetwork)) {
-                // NAT64 prefix detected. Start clatd.
-                // TODO: support the NAT64 prefix changing after it's been discovered. There is no
-                // need to support this at the moment because it cannot happen without changes to
-                // the Dns64Configuration code in netd.
-                start();
-            } else {
-                // NAT64 prefix removed. Stop clatd and go back into DISCOVERING state.
-                stop();
-            }
-        } else {
-            // Network no longer requires clat. Stop clat and prefix discovery.
-            if (isStarted()) {
-                stop();
-            } else if (isPrefixDiscoveryStarted()) {
-                leaveStartedState();
-            }
+        // TODO: turn this class into a proper StateMachine. http://b/126113090
+        switch (mState) {
+            case IDLE:
+                if (requiresClat(mNetwork)) {
+                    // Network is detected to be IPv6-only.
+                    // TODO: consider going to STARTING directly if the NAT64 prefix is already
+                    // known. This would however result in clatd running without prefix discovery
+                    // running, which might be a surprising combination.
+                    startPrefixDiscovery();  // Enters DISCOVERING state.
+                    return;
+                }
+                break;
+
+            case DISCOVERING:
+                if (shouldStartClat(mNetwork)) {
+                    // NAT64 prefix detected. Start clatd.
+                    start();  // Enters STARTING state.
+                    return;
+                }
+                if (!requiresClat(mNetwork)) {
+                    // IPv4 address added. Go back to IDLE state.
+                    stopPrefixDiscovery();
+                    return;
+                }
+                break;
+
+            case STARTING:
+            case RUNNING:
+                // NAT64 prefix removed, or IPv4 address added.
+                // Stop clatd and go back into DISCOVERING or idle.
+                if (!shouldStartClat(mNetwork)) {
+                    stop();
+                }
+                break;
+                // TODO: support the NAT64 prefix changing after it's been discovered. There is
+                // no need to support this at the moment because it cannot happen without
+                // changes to the Dns64Configuration code in netd.
         }
     }
 
-    public void setNat64Prefix(IpPrefix nat64Prefix) {
-        mNat64Prefix = nat64Prefix;
+    private IpPrefix getNat64Prefix() {
+        return mNat64PrefixFromDns;
+    }
+
+    public void setNat64PrefixFromDns(IpPrefix prefix) {
+        mNat64PrefixFromDns = prefix;
     }
 
     /**
@@ -328,7 +347,7 @@
      * has no idea that 464xlat is running on top of it.
      */
     public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) {
-        lp.setNat64Prefix(mNat64Prefix);
+        lp.setNat64Prefix(getNat64Prefix());
 
         if (!isRunning()) {
             return;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 61b18ee..962f337 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -80,6 +80,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -398,78 +399,93 @@
      */
     @Override
     public void notifyChange(Uri[] uris, IContentObserver observer,
-            boolean observerWantsSelfNotifications, int flags, int userHandle,
+            boolean observerWantsSelfNotifications, int flags, int userId,
             int targetSdkVersion, String callingPackage) {
-        final ObserverCollector collector = new ObserverCollector();
-        for (Uri uri : uris) {
-            notifyChange(uri, observer, observerWantsSelfNotifications, flags, userHandle,
-                    targetSdkVersion, callingPackage, collector);
-        }
-        final long token = clearCallingIdentity();
-        try {
-            collector.dispatch();
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    public void notifyChange(Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, int flags, int userHandle,
-            int targetSdkVersion, String callingPackage, ObserverCollector collector) {
-        if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
-                + " from observer " + observer + ", flags " + Integer.toHexString(flags));
-
-        if (uri == null) {
-            throw new NullPointerException("Uri must not be null");
+        if (DEBUG) {
+            Slog.d(TAG, "Notifying update of " + Arrays.toString(uris) + " for user " + userId
+                    + ", observer " + observer + ", flags " + Integer.toHexString(flags));
         }
 
         final int callingUid = Binder.getCallingUid();
         final int callingPid = Binder.getCallingPid();
-        final int callingUserHandle = UserHandle.getCallingUserId();
+        final int callingUserId = UserHandle.getCallingUserId();
 
-        userHandle = handleIncomingUser(uri, callingPid, callingUid,
-                Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true, userHandle);
+        // Set of notification events that we need to dispatch
+        final ObserverCollector collector = new ObserverCollector();
 
-        final String msg = LocalServices.getService(ActivityManagerInternal.class)
-                .checkContentProviderAccess(uri.getAuthority(), userHandle);
-        if (msg != null) {
-            if (targetSdkVersion >= Build.VERSION_CODES.O) {
-                throw new SecurityException(msg);
-            } else {
-                if (msg.startsWith("Failed to find provider")) {
-                    // Sigh, we need to quietly let apps targeting older API
-                    // levels notify on non-existent providers.
-                } else {
-                    Log.w(TAG, "Ignoring notify for " + uri + " from " + callingUid + ": " + msg);
-                    return;
+        // Set of content provider authorities that we've validated the caller
+        // has access to, mapped to the package name hosting that provider
+        final ArrayMap<Pair<String, Integer>, String> validatedProviders = new ArrayMap<>();
+
+        for (Uri uri : uris) {
+            // Validate that calling app has access to this provider
+            final int resolvedUserId = handleIncomingUser(uri, callingPid, callingUid,
+                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true, userId);
+            final Pair<String, Integer> provider = Pair.create(uri.getAuthority(), resolvedUserId);
+            if (!validatedProviders.containsKey(provider)) {
+                final String msg = LocalServices.getService(ActivityManagerInternal.class)
+                        .checkContentProviderAccess(uri.getAuthority(), resolvedUserId);
+                if (msg != null) {
+                    if (targetSdkVersion >= Build.VERSION_CODES.O) {
+                        throw new SecurityException(msg);
+                    } else {
+                        if (msg.startsWith("Failed to find provider")) {
+                            // Sigh, we need to quietly let apps targeting older API
+                            // levels notify on non-existent providers.
+                        } else {
+                            Log.w(TAG, "Ignoring notify for " + uri + " from "
+                                    + callingUid + ": " + msg);
+                            continue;
+                        }
+                    }
                 }
+
+                // Remember that we've validated this access
+                final String packageName = getProviderPackageName(uri, resolvedUserId);
+                validatedProviders.put(provider, packageName);
+            }
+
+            // No concerns raised above, so caller has access; let's collect the
+            // notifications that should be dispatched
+            synchronized (mRootNode) {
+                final int segmentCount = ObserverNode.countUriSegments(uri);
+                mRootNode.collectObserversLocked(uri, segmentCount, 0, observer,
+                        observerWantsSelfNotifications, flags, resolvedUserId, collector);
             }
         }
 
-        // This makes it so that future permission checks will be in the context of this
-        // process rather than the caller's process. We will restore this before returning.
-        long identityToken = clearCallingIdentity();
+        final long token = clearCallingIdentity();
         try {
-            synchronized (mRootNode) {
-                mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
-                        flags, userHandle, collector);
-            }
-            if ((flags&ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) {
-                SyncManager syncManager = getSyncManager();
-                if (syncManager != null) {
-                    syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle,
-                            callingUid,
-                            uri.getAuthority(), getSyncExemptionForCaller(callingUid),
-                            callingUid, callingPid, callingPackage);
+            // Actually dispatch all the notifications we collected
+            collector.dispatch();
+
+            for (int i = 0; i < validatedProviders.size(); i++) {
+                final String authority = validatedProviders.keyAt(i).first;
+                final int resolvedUserId = validatedProviders.keyAt(i).second;
+                final String packageName = validatedProviders.valueAt(i);
+
+                // Kick off sync adapters for any authorities we touched
+                if ((flags & ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) {
+                    SyncManager syncManager = getSyncManager();
+                    if (syncManager != null) {
+                        syncManager.scheduleLocalSync(null /* all accounts */, callingUserId,
+                                callingUid,
+                                authority, getSyncExemptionForCaller(callingUid),
+                                callingUid, callingPid, callingPackage);
+                    }
+                }
+
+                // Invalidate caches for any authorities we touched
+                synchronized (mCache) {
+                    for (Uri uri : uris) {
+                        if (Objects.equals(uri.getAuthority(), authority)) {
+                            invalidateCacheLocked(resolvedUserId, packageName, uri);
+                        }
+                    }
                 }
             }
-
-            synchronized (mCache) {
-                final String providerPackageName = getProviderPackageName(uri, userHandle);
-                invalidateCacheLocked(userHandle, providerPackageName, uri);
-            }
         } finally {
-            restoreCallingIdentity(identityToken);
+            Binder.restoreCallingIdentity(token);
         }
     }
 
@@ -1533,7 +1549,7 @@
             }
         }
 
-        private String getUriSegment(Uri uri, int index) {
+        public static String getUriSegment(Uri uri, int index) {
             if (uri != null) {
                 if (index == 0) {
                     return uri.getAuthority();
@@ -1545,7 +1561,7 @@
             }
         }
 
-        private int countUriSegments(Uri uri) {
+        public static int countUriSegments(Uri uri) {
             if (uri == null) {
                 return 0;
             }
@@ -1669,14 +1685,21 @@
             }
         }
 
+        @VisibleForTesting
+        public void collectObserversLocked(Uri uri, int index,
+                IContentObserver observer, boolean observerWantsSelfNotifications, int flags,
+                int targetUserHandle, ObserverCollector collector) {
+            collectObserversLocked(uri, countUriSegments(uri), index, observer,
+                    observerWantsSelfNotifications, flags, targetUserHandle, collector);
+        }
+
         /**
          * targetUserHandle is either a hard user handle or is USER_ALL
          */
-        public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
-                                           boolean observerWantsSelfNotifications, int flags,
-                                           int targetUserHandle, ObserverCollector collector) {
+        public void collectObserversLocked(Uri uri, int segmentCount, int index,
+                IContentObserver observer, boolean observerWantsSelfNotifications, int flags,
+                int targetUserHandle, ObserverCollector collector) {
             String segment = null;
-            int segmentCount = countUriSegments(uri);
             if (index >= segmentCount) {
                 // This is the leaf node, notify all observers
                 if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName);
@@ -1696,7 +1719,7 @@
                 ObserverNode node = mChildren.get(i);
                 if (segment == null || node.mName.equals(segment)) {
                     // We found the child,
-                    node.collectObserversLocked(uri, index + 1, observer,
+                    node.collectObserversLocked(uri, segmentCount, index + 1, observer,
                             observerWantsSelfNotifications, flags, targetUserHandle, collector);
                     if (segment != null) {
                         break;
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 6178e6c..f4d7f9a 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -200,7 +200,7 @@
     // Context-sensitive brightness configurations require keeping track of the foreground app's
     // package name and category, which is done by registering a TaskStackListener to call back to
     // us onTaskStackChanged, and then using the ActivityTaskManager to get the foreground app's
-    // package namd and PackageManager to get its category (so might as well cache them).
+    // package name and PackageManager to get its category (so might as well cache them).
     private String mForegroundAppPackageName;
     private String mPendingForegroundAppPackageName;
     private @ApplicationInfo.Category int mForegroundAppCategory;
@@ -210,6 +210,7 @@
     private PackageManager mPackageManager;
     private Context mContext;
 
+    private DisplayDeviceConfig mDisplayDeviceConfig;
     private final Injector mInjector;
 
     AutomaticBrightnessController(Callbacks callbacks, Looper looper,
@@ -218,12 +219,14 @@
             float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
             long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
             boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds, Context context) {
+            HysteresisLevels screenBrightnessThresholds, Context context, DisplayDeviceConfig
+            displayDeviceConfig) {
         this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
                 lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
                 lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
                 darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
-                ambientBrightnessThresholds, screenBrightnessThresholds, context);
+                ambientBrightnessThresholds, screenBrightnessThresholds, context,
+                displayDeviceConfig);
     }
 
     @VisibleForTesting
@@ -233,7 +236,8 @@
             float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
             long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
             boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds, Context context) {
+            HysteresisLevels screenBrightnessThresholds, Context context, DisplayDeviceConfig
+            displayDeviceConfig) {
         mInjector = injector;
         mContext = context;
         mCallbacks = callbacks;
@@ -260,7 +264,7 @@
         mScreenBrightnessThresholds = screenBrightnessThresholds;
         mShortTermModelValid = true;
         mShortTermModelAnchor = -1;
-
+        mDisplayDeviceConfig = displayDeviceConfig;
         mHandler = new AutomaticBrightnessHandler(looper);
         mAmbientLightRingBuffer =
             new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 63a8d7c..3516981 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayViewport;
 import android.os.IBinder;
+import android.view.Display;
 import android.view.DisplayAddress;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -36,6 +37,7 @@
     private final DisplayAdapter mDisplayAdapter;
     private final IBinder mDisplayToken;
     private final String mUniqueId;
+    private DisplayDeviceConfig mDisplayDeviceConfig;
 
     // The display device does not manage these properties itself, they are set by
     // the display manager service.  The display device shouldn't really be looking at these.
@@ -67,6 +69,16 @@
         return mDisplayAdapter;
     }
 
+    /*
+     * Gets the DisplayDeviceConfig for this DisplayDevice.
+     * Returns null for this device but is overridden in LocalDisplayDevice.
+     *
+     * @return The DisplayDeviceConfig.
+     */
+    public DisplayDeviceConfig getDisplayDeviceConfig() {
+        return mDisplayDeviceConfig;
+    }
+
     /**
      * Gets the Surface Flinger display token for this display.
      *
@@ -78,6 +90,13 @@
     }
 
     /**
+     * Gets the id of the display to mirror.
+     */
+    public int getDisplayIdToMirrorLocked() {
+        return Display.DEFAULT_DISPLAY;
+    }
+
+    /**
      * Gets the name of the display device.
      *
      * @return The display device name.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a232051..a87fb8b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -57,6 +57,7 @@
 import android.hardware.display.IDisplayManager;
 import android.hardware.display.IDisplayManagerCallback;
 import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
 import android.hardware.display.WifiDisplayStatus;
 import android.hardware.input.InputManagerInternal;
 import android.media.projection.IMediaProjection;
@@ -794,8 +795,8 @@
     }
 
     private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
-            IMediaProjection projection, int callingUid, String packageName, String name, int width,
-            int height, int densityDpi, Surface surface, int flags, String uniqueId) {
+            IMediaProjection projection, int callingUid, String packageName, Surface surface,
+            int flags, VirtualDisplayConfig virtualDisplayConfig) {
         synchronized (mSyncRoot) {
             if (mVirtualDisplayAdapter == null) {
                 Slog.w(TAG, "Rejecting request to create private virtual display "
@@ -804,8 +805,8 @@
             }
 
             DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
-                    callback, projection, callingUid, packageName, name, width, height, densityDpi,
-                    surface, flags, uniqueId);
+                    callback, projection, callingUid, packageName, surface, flags,
+                    virtualDisplayConfig);
             if (device == null) {
                 return -1;
             }
@@ -1361,7 +1362,8 @@
         return null;
     }
 
-    private SurfaceControl.ScreenshotGraphicBuffer screenshotInternal(int displayId) {
+    private SurfaceControl.ScreenshotGraphicBuffer screenshotInternal(int displayId,
+            boolean captureSecureLayer) {
         synchronized (mSyncRoot) {
             final IBinder token = getDisplayToken(displayId);
             if (token == null) {
@@ -1373,9 +1375,15 @@
             }
 
             final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
-            return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(),
-                    displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
-                    false /* useIdentityTransform */, 0 /* rotation */);
+            if (captureSecureLayer) {
+                return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(),
+                        displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
+                        false /* useIdentityTransform */, 0 /* rotation */);
+            } else {
+                return SurfaceControl.screenshotToBuffer(token, new Rect(),
+                        displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
+                        false /* useIdentityTransform */, 0 /* rotation */);
+            }
         }
     }
 
@@ -1480,8 +1488,8 @@
         if (!ownContent) {
             if (display != null && !display.hasContentLocked()) {
                 // If the display does not have any content of its own, then
-                // automatically mirror the default logical display contents.
-                display = null;
+                // automatically mirror the requested logical display contents if possible.
+                display = mLogicalDisplays.get(device.getDisplayIdToMirrorLocked());
             }
             if (display == null) {
                 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
@@ -1729,6 +1737,28 @@
         }
     }
 
+    @VisibleForTesting
+    int getDisplayIdToMirrorInternal(int displayId) {
+        synchronized (mSyncRoot) {
+            LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
+                return displayDevice.getDisplayIdToMirrorLocked();
+            }
+            return Display.INVALID_DISPLAY;
+        }
+    }
+
+    @VisibleForTesting
+    Surface getVirtualDisplaySurfaceInternal(IBinder appToken) {
+        synchronized (mSyncRoot) {
+            if (mVirtualDisplayAdapter == null) {
+                return null;
+            }
+            return mVirtualDisplayAdapter.getVirtualDisplaySurfaceLocked(appToken);
+        }
+    }
+
     private final class DisplayManagerHandler extends Handler {
         public DisplayManagerHandler(Looper looper) {
             super(looper, null, true /*async*/);
@@ -2050,10 +2080,8 @@
         }
 
         @Override // Binder call
-        public int createVirtualDisplay(IVirtualDisplayCallback callback,
-                IMediaProjection projection, String packageName, String name,
-                int width, int height, int densityDpi, Surface surface, int flags,
-                String uniqueId) {
+        public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
+                IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
             final int callingUid = Binder.getCallingUid();
             if (!validatePackageName(callingUid, packageName)) {
                 throw new SecurityException("packageName must match the calling uid");
@@ -2061,13 +2089,12 @@
             if (callback == null) {
                 throw new IllegalArgumentException("appToken must not be null");
             }
-            if (TextUtils.isEmpty(name)) {
-                throw new IllegalArgumentException("name must be non-null and non-empty");
+            if (virtualDisplayConfig == null) {
+                throw new IllegalArgumentException("virtualDisplayConfig must not be null");
             }
-            if (width <= 0 || height <= 0 || densityDpi <= 0) {
-                throw new IllegalArgumentException("width, height, and densityDpi must be "
-                        + "greater than 0");
-            }
+            final Surface surface = virtualDisplayConfig.getSurface();
+            int flags = virtualDisplayConfig.getFlags();
+
             if (surface != null && surface.isSingleBuffered()) {
                 throw new IllegalArgumentException("Surface can't be single-buffered");
             }
@@ -2128,7 +2155,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
-                        name, width, height, densityDpi, surface, flags, uniqueId);
+                        surface, flags, virtualDisplayConfig);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -2449,7 +2476,8 @@
                     }
                 };
                 mDisplayPowerController = new DisplayPowerController(
-                        mContext, callbacks, handler, sensorManager, blanker);
+                        mContext, callbacks, handler, sensorManager, blanker,
+                        mDisplayDevices.get(Display.DEFAULT_DISPLAY));
                 mSensorManager = sensorManager;
             }
 
@@ -2474,7 +2502,12 @@
 
         @Override
         public SurfaceControl.ScreenshotGraphicBuffer screenshot(int displayId) {
-            return screenshotInternal(displayId);
+            return screenshotInternal(displayId, true);
+        }
+
+        @Override
+        public SurfaceControl.ScreenshotGraphicBuffer screenshotWithoutSecureLayer(int displayId) {
+            return screenshotInternal(displayId, false);
         }
 
         @Override
@@ -2483,6 +2516,17 @@
         }
 
         @Override
+        public Point getDisplayPosition(int displayId) {
+            synchronized (mSyncRoot) {
+                LogicalDisplay display = mLogicalDisplays.get(displayId);
+                if (display != null) {
+                    return display.getDisplayPosition();
+                }
+                return null;
+            }
+        }
+
+        @Override
         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
             if (listener == null) {
                 throw new IllegalArgumentException("listener must not be null");
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 197842e..f82ec82 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -161,6 +161,9 @@
     // The display blanker.
     private final DisplayBlanker mBlanker;
 
+    // The display device.
+    private final DisplayDevice mDisplayDevice;
+
     // Tracker for brightness changes.
     private final BrightnessTracker mBrightnessTracker;
 
@@ -348,11 +351,11 @@
     @Nullable
     private BrightnessConfiguration mBrightnessConfiguration;
 
-    // The last brightness that was set by the user and not temporary. Set to -1 when a brightness
-    // has yet to be recorded.
+    // The last brightness that was set by the user and not temporary. Set to
+    // PowerManager.BRIGHTNESS_INVALID_FLOAT when a brightness has yet to be recorded.
     private float mLastUserSetScreenBrightness;
 
-    // The screen brightenss setting has changed but not taken effect yet. If this is different
+    // The screen brightness setting has changed but not taken effect yet. If this is different
     // from the current screen brightness setting then this is coming from something other than us
     // and should be considered a user interaction.
     private float mPendingScreenBrightnessSetting;
@@ -377,8 +380,8 @@
     private float mPendingAutoBrightnessAdjustment;
 
     // The temporary auto brightness adjustment. Typically set when a user is interacting with the
-    // adjustment slider but hasn't settled on a choice yet. Set to Float.NaN when there's no
-    // temporary adjustment set.
+    // adjustment slider but hasn't settled on a choice yet. Set to
+    // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
     private float mTemporaryAutoBrightnessAdjustment;
 
     // Animators.
@@ -386,27 +389,29 @@
     private ObjectAnimator mColorFadeOffAnimator;
     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
 
-    private BrightnessSynchronizer mBrightnessSynchronizer;
 
     /**
      * Creates the display power controller.
      */
     public DisplayPowerController(Context context,
             DisplayPowerCallbacks callbacks, Handler handler,
-            SensorManager sensorManager, DisplayBlanker blanker) {
+            SensorManager sensorManager, DisplayBlanker blanker, DisplayDevice displayDevice) {
         mHandler = new DisplayControllerHandler(handler.getLooper());
         mBrightnessTracker = new BrightnessTracker(context, null);
         mSettingsObserver = new SettingsObserver(mHandler);
         mCallbacks = callbacks;
-        mBrightnessSynchronizer = new BrightnessSynchronizer(context);
         mBatteryStats = BatteryStatsService.getService();
         mSensorManager = sensorManager;
         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
         mBlanker = blanker;
         mContext = context;
+        mDisplayDevice = displayDevice;
 
         PowerManager pm =  context.getSystemService(PowerManager.class);
+        DisplayDeviceConfig displayDeviceConfig = mDisplayDevice.getDisplayDeviceConfig();
+
         final Resources resources = context.getResources();
+
         final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness(
                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM));
 
@@ -498,7 +503,7 @@
                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
                         initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
-                        screenBrightnessThresholds, context);
+                        screenBrightnessThresholds, context, displayDeviceConfig);
             } else {
                 mUseSoftwareAutoBrightnessConfig = false;
             }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 8eb7710..6132467 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -203,6 +203,8 @@
         private Spline mNitsToHalBrightness;
         private boolean mHalBrightnessSupport;
 
+        private DisplayDeviceConfig mDisplayDeviceConfig;
+
         LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
                 SurfaceControl.DisplayInfo info, SurfaceControl.DisplayConfig[] configs,
                 int activeConfigId, SurfaceControl.DesiredDisplayConfigSpecs configSpecs,
@@ -224,7 +226,7 @@
             mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
             mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
             mHalBrightnessSupport = SurfaceControl.getDisplayBrightnessSupport(displayToken);
-
+            mDisplayDeviceConfig = null;
             // Defer configuration file loading
             BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
                     LocalDisplayDevice::loadDisplayConfigurationBrightnessMapping, this));
@@ -373,17 +375,23 @@
             return true;
         }
 
+        @Override
+        public DisplayDeviceConfig getDisplayDeviceConfig() {
+            return mDisplayDeviceConfig;
+        }
+
         private void loadDisplayConfigurationBrightnessMapping() {
             Spline nitsToHal = null;
             Spline sysToNits = null;
 
             // Load the mapping from nits to HAL brightness range (display-device-config.xml)
             DisplayDeviceConfig config = DisplayDeviceConfig.create(mPhysicalDisplayId);
+            mDisplayDeviceConfig = config;
             if (config == null) {
                 return;
             }
-            final float[] halNits = config.getNits();
-            final float[] halBrightness = config.getBrightness();
+            final float[] halNits = mDisplayDeviceConfig.getNits();
+            final float[] halBrightness = mDisplayDeviceConfig.getBrightness();
             if (halNits == null || halBrightness == null) {
                 return;
             }
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 3a5aa93..0261f38 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -16,6 +16,7 @@
 
 package com.android.server.display;
 
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManagerInternal;
 import android.view.Display;
@@ -98,6 +99,11 @@
     private int mDisplayOffsetY;
 
     /**
+     * The position of the display projection sent to SurfaceFlinger
+     */
+    private final Point mDisplayPosition = new Point();
+
+    /**
      * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode
      * is used.
      * @see #isDisplayScalingDisabled()
@@ -335,6 +341,16 @@
     }
 
     /**
+     * Returns the position of the display's projection.
+     *
+     * @return The x, y coordinates of the display. The return object must be treated as immutable.
+     */
+    Point getDisplayPosition() {
+        // Allocate a new object to avoid a data race.
+        return new Point(mDisplayPosition);
+    }
+
+    /**
      * Applies the layer stack and transformation to the given display device
      * so that it shows the contents of this logical display.
      *
@@ -445,6 +461,8 @@
         } else {  // Surface.ROTATION_270
             mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX);
         }
+
+        mDisplayPosition.set(mTempDisplayRect.left, mTempDisplayRect.top);
         device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect);
     }
 
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index f4f2ead..ccd8848 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -28,6 +28,7 @@
 
 import android.content.Context;
 import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
 import android.os.Handler;
@@ -84,22 +85,24 @@
     }
 
     public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
-            IMediaProjection projection, int ownerUid, String ownerPackageName, String name,
-            int width, int height, int densityDpi, Surface surface, int flags, String uniqueId) {
+            IMediaProjection projection, int ownerUid, String ownerPackageName, Surface surface,
+            int flags, VirtualDisplayConfig virtualDisplayConfig) {
+        String name = virtualDisplayConfig.getName();
         boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
         IBinder appToken = callback.asBinder();
         IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
         final String baseUniqueId =
                 UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
         final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
+        String uniqueId = virtualDisplayConfig.getUniqueId();
         if (uniqueId == null) {
             uniqueId = baseUniqueId + uniqueIndex;
         } else {
             uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
         }
         VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
-                ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags,
-                new Callback(callback, mHandler), uniqueId, uniqueIndex);
+                ownerUid, ownerPackageName, surface, flags, new Callback(callback, mHandler),
+                uniqueId, uniqueIndex, virtualDisplayConfig);
 
         mVirtualDisplayDevices.put(appToken, device);
 
@@ -127,6 +130,14 @@
         }
     }
 
+    @VisibleForTesting
+    Surface getVirtualDisplaySurfaceLocked(IBinder appToken) {
+        VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
+        if (device != null) {
+            return device.getSurfaceLocked();
+        }
+        return null;
+    }
 
     public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
         VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
@@ -214,20 +225,21 @@
         private int mUniqueIndex;
         private Display.Mode mMode;
         private boolean mIsDisplayOn;
+        private int mDisplayIdToMirror;
 
         public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
-                int ownerUid, String ownerPackageName,
-                String name, int width, int height, int densityDpi, Surface surface, int flags,
-                Callback callback, String uniqueId, int uniqueIndex) {
+                int ownerUid, String ownerPackageName, Surface surface, int flags,
+                Callback callback, String uniqueId, int uniqueIndex,
+                VirtualDisplayConfig virtualDisplayConfig) {
             super(VirtualDisplayAdapter.this, displayToken, uniqueId);
             mAppToken = appToken;
             mOwnerUid = ownerUid;
             mOwnerPackageName = ownerPackageName;
-            mName = name;
-            mWidth = width;
-            mHeight = height;
-            mMode = createMode(width, height, REFRESH_RATE);
-            mDensityDpi = densityDpi;
+            mName = virtualDisplayConfig.getName();
+            mWidth = virtualDisplayConfig.getWidth();
+            mHeight = virtualDisplayConfig.getHeight();
+            mMode = createMode(mWidth, mHeight, REFRESH_RATE);
+            mDensityDpi = virtualDisplayConfig.getDensityDpi();
             mSurface = surface;
             mFlags = flags;
             mCallback = callback;
@@ -235,6 +247,7 @@
             mPendingChanges |= PENDING_SURFACE_CHANGE;
             mUniqueIndex = uniqueIndex;
             mIsDisplayOn = surface != null;
+            mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror();
         }
 
         @Override
@@ -260,6 +273,16 @@
         }
 
         @Override
+        public int getDisplayIdToMirrorLocked() {
+            return mDisplayIdToMirror;
+        }
+
+        @VisibleForTesting
+        Surface getSurfaceLocked() {
+            return mSurface;
+        }
+
+        @Override
         public boolean hasStableUniqueId() {
             return false;
         }
@@ -332,6 +355,7 @@
             pw.println("mFlags=" + mFlags);
             pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
             pw.println("mStopped=" + mStopped);
+            pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror);
         }
 
 
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index ad3c8a6..d8acf0e 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -809,11 +809,11 @@
         locationRequest.setProvider(provider);
 
         // Ignore location settings if in emergency mode. This is only allowed for
-        // isUserEmergency request (introduced in HAL v2.0), or DBH request in HAL v1.1.
+        // isUserEmergency request (introduced in HAL v2.0), or HAL v1.1.
         if (mNIHandler.getInEmergency()) {
             GnssConfiguration.HalInterfaceVersion halVersion =
                     mGnssConfiguration.getHalInterfaceVersion();
-            if (isUserEmergency || (halVersion.mMajor < 2 && !independentFromGnss)) {
+            if (isUserEmergency || halVersion.mMajor < 2) {
                 locationRequest.setLocationSettingsIgnored(true);
                 durationMillis *= EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER;
             }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 0bba172..1931079 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -54,11 +54,9 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -70,10 +68,8 @@
     private static final String TAG = "MR2ServiceImpl";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    /**
-     * TODO: Change this with the real request ID from MediaRouter2 when
-     * MediaRouter2 needs to get notified for the failures.
-     */
+    // TODO: (In Android S or later) if we add callback methods for generic failures
+    //       in MediaRouter2, remove this constant and replace the usages with the real request IDs.
     private static final long DUMMY_REQUEST_ID = -1;
 
     private final Context mContext;
@@ -493,7 +489,7 @@
         }
     }
 
-    //TODO: Review this is handling multi-user properly.
+    //TODO(b/136703681): Review this is handling multi-user properly.
     void switchUser() {
         synchronized (mLock) {
             int userId = ActivityManager.getCurrentUser();
@@ -568,7 +564,9 @@
 
         UserRecord userRecord = routerRecord.mUserRecord;
         userRecord.mRouterRecords.remove(routerRecord);
-        //TODO: update discovery request
+        userRecord.mHandler.sendMessage(
+                obtainMessage(UserHandler::updateDiscoveryPreferenceOnHandler,
+                        userRecord.mHandler));
         routerRecord.dispose();
         disposeUserIfNeededLocked(userRecord); // since router removed from user
     }
@@ -793,7 +791,7 @@
         }
 
         long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
-        //TODO: Use MediaRouter2's OnCreateSessionListener to send proper session hints.
+        //TODO(b/152851868): Use MediaRouter2's OnCreateSessionListener to send session hints.
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::requestCreateSessionOnHandler,
                         routerRecord.mUserRecord.mHandler,
@@ -810,7 +808,7 @@
             return;
         }
 
-        // Can be null if the session is system's.
+        // Can be null if the session is system's or RCN.
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
 
@@ -831,7 +829,7 @@
             return;
         }
 
-        // Can be null if the session is system's.
+        // Can be null if the session is system's or RCN.
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
 
@@ -852,7 +850,7 @@
             return;
         }
 
-        // Can be null if the session is system's.
+        // Can be null if the session is system's or RCN.
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
 
@@ -1146,38 +1144,26 @@
             return mSessionToRouterMap.get(uniqueSessionId);
         }
 
-        //TODO: notify session info updates
         private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) {
             int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId());
-            MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
+            MediaRoute2ProviderInfo currentInfo = provider.getProviderInfo();
             MediaRoute2ProviderInfo prevInfo =
                     (providerInfoIndex < 0) ? null : mLastProviderInfos.get(providerInfoIndex);
+            if (Objects.equals(prevInfo, currentInfo)) return;
 
-            if (Objects.equals(prevInfo, providerInfo)) return;
-
+            List<MediaRoute2Info> addedRoutes = new ArrayList<>();
+            List<MediaRoute2Info> removedRoutes = new ArrayList<>();
+            List<MediaRoute2Info> changedRoutes = new ArrayList<>();
             if (prevInfo == null) {
-                mLastProviderInfos.add(providerInfo);
-                Collection<MediaRoute2Info> addedRoutes = providerInfo.getRoutes();
-                if (addedRoutes.size() > 0) {
-                    sendMessage(PooledLambda.obtainMessage(UserHandler::notifyRoutesAddedToRouters,
-                            this, getRouters(), new ArrayList<>(addedRoutes)));
-                }
-            } else if (providerInfo == null) {
+                mLastProviderInfos.add(currentInfo);
+                addedRoutes.addAll(currentInfo.getRoutes());
+            } else if (currentInfo == null) {
                 mLastProviderInfos.remove(prevInfo);
-                Collection<MediaRoute2Info> removedRoutes = prevInfo.getRoutes();
-                if (removedRoutes.size() > 0) {
-                    sendMessage(PooledLambda.obtainMessage(
-                            UserHandler::notifyRoutesRemovedToRouters,
-                            this, getRouters(), new ArrayList<>(removedRoutes)));
-                }
+                removedRoutes.addAll(prevInfo.getRoutes());
             } else {
-                mLastProviderInfos.set(providerInfoIndex, providerInfo);
-                List<MediaRoute2Info> addedRoutes = new ArrayList<>();
-                List<MediaRoute2Info> removedRoutes = new ArrayList<>();
-                List<MediaRoute2Info> changedRoutes = new ArrayList<>();
-
-                final Collection<MediaRoute2Info> currentRoutes = providerInfo.getRoutes();
-                final Set<String> updatedRouteIds = new HashSet<>();
+                mLastProviderInfos.set(providerInfoIndex, currentInfo);
+                final Collection<MediaRoute2Info> prevRoutes = prevInfo.getRoutes();
+                final Collection<MediaRoute2Info> currentRoutes = currentInfo.getRoutes();
 
                 for (MediaRoute2Info route : currentRoutes) {
                     if (!route.isValid()) {
@@ -1185,37 +1171,33 @@
                         continue;
                     }
                     MediaRoute2Info prevRoute = prevInfo.getRoute(route.getOriginalId());
-
-                    if (prevRoute != null) {
-                        if (!Objects.equals(prevRoute, route)) {
-                            changedRoutes.add(route);
-                        }
-                        updatedRouteIds.add(route.getId());
-                    } else {
+                    if (prevRoute == null) {
                         addedRoutes.add(route);
+                    } else if (!Objects.equals(prevRoute, route)) {
+                        changedRoutes.add(route);
                     }
                 }
 
                 for (MediaRoute2Info prevRoute : prevInfo.getRoutes()) {
-                    if (!updatedRouteIds.contains(prevRoute.getId())) {
+                    if (currentInfo.getRoute(prevRoute.getOriginalId()) == null) {
                         removedRoutes.add(prevRoute);
                     }
                 }
+            }
 
-                List<IMediaRouter2> routers = getRouters();
-                List<IMediaRouter2Manager> managers = getManagers();
-                if (addedRoutes.size() > 0) {
-                    notifyRoutesAddedToRouters(routers, addedRoutes);
-                    notifyRoutesAddedToManagers(managers, addedRoutes);
-                }
-                if (removedRoutes.size() > 0) {
-                    notifyRoutesRemovedToRouters(routers, removedRoutes);
-                    notifyRoutesRemovedToManagers(managers, removedRoutes);
-                }
-                if (changedRoutes.size() > 0) {
-                    notifyRoutesChangedToRouters(routers, changedRoutes);
-                    notifyRoutesChangedToManagers(managers, changedRoutes);
-                }
+            List<IMediaRouter2> routers = getRouters();
+            List<IMediaRouter2Manager> managers = getManagers();
+            if (addedRoutes.size() > 0) {
+                notifyRoutesAddedToRouters(routers, addedRoutes);
+                notifyRoutesAddedToManagers(managers, addedRoutes);
+            }
+            if (removedRoutes.size() > 0) {
+                notifyRoutesRemovedToRouters(routers, removedRoutes);
+                notifyRoutesRemovedToManagers(managers, removedRoutes);
+            }
+            if (changedRoutes.size() > 0) {
+                notifyRoutesChangedToRouters(routers, changedRoutes);
+                notifyRoutesChangedToManagers(managers, changedRoutes);
             }
         }
 
@@ -1250,7 +1232,7 @@
                     route.getOriginalId(), sessionHints);
         }
 
-        // routerRecord can be null if the session is system's.
+        // routerRecord can be null if the session is system's or RCN.
         private void selectRouteOnHandler(long uniqueRequestId, @Nullable RouterRecord routerRecord,
                 @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
             if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route,
@@ -1268,7 +1250,7 @@
                     route.getOriginalId());
         }
 
-        // routerRecord can be null if the session is system's.
+        // routerRecord can be null if the session is system's or RCN.
         private void deselectRouteOnHandler(long uniqueRequestId,
                 @Nullable RouterRecord routerRecord,
                 @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
@@ -1288,7 +1270,7 @@
                     route.getOriginalId());
         }
 
-        // routerRecord can be null if the session is system's.
+        // routerRecord can be null if the session is system's or RCN.
         private void transferToRouteOnHandler(long uniqueRequestId,
                 @Nullable RouterRecord routerRecord,
                 @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
@@ -1307,6 +1289,8 @@
                     route.getOriginalId());
         }
 
+        // routerRecord is null if and only if the session is created without the request, which
+        // includes the system's session and RCN cases.
         private boolean checkArgumentsForSessionControl(@Nullable RouterRecord routerRecord,
                 @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route,
                 @NonNull String description) {
@@ -1323,12 +1307,6 @@
                 return true;
             }
 
-            //TODO: Handle RCN case.
-            if (routerRecord == null) {
-                Slog.w(TAG, "Ignoring " + description + " route from unknown router.");
-                return false;
-            }
-
             RouterRecord matchingRecord = mSessionToRouterMap.get(uniqueSessionId);
             if (matchingRecord != routerRecord) {
                 Slog.w(TAG, "Ignoring " + description + " route from non-matching router. "
@@ -1403,7 +1381,8 @@
 
         private void onSessionCreatedOnHandler(@NonNull MediaRoute2Provider provider,
                 long uniqueRequestId, @NonNull RoutingSessionInfo sessionInfo) {
-            notifySessionCreatedToManagers(getManagers(), sessionInfo);
+            notifySessionCreatedToManagers(getManagers(),
+                    toOriginalRequestId(uniqueRequestId), sessionInfo);
 
             if (uniqueRequestId == REQUEST_ID_NONE) {
                 // The session is created without any matching request.
@@ -1457,7 +1436,7 @@
         private void onSessionInfoChangedOnHandler(@NonNull MediaRoute2Provider provider,
                 @NonNull RoutingSessionInfo sessionInfo) {
             List<IMediaRouter2Manager> managers = getManagers();
-            notifySessionInfosChangedToManagers(managers);
+            notifySessionInfoChangedToManagers(managers, sessionInfo);
 
             // For system provider, notify all routers.
             if (provider == mSystemProvider) {
@@ -1480,7 +1459,7 @@
         private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider,
                 @NonNull RoutingSessionInfo sessionInfo) {
             List<IMediaRouter2Manager> managers = getManagers();
-            notifySessionInfosChangedToManagers(managers);
+            notifySessionInfoChangedToManagers(managers, sessionInfo);
 
             RouterRecord routerRecord = mSessionToRouterMap.get(sessionInfo.getId());
             if (routerRecord == null) {
@@ -1558,7 +1537,8 @@
         private void notifySessionCreationFailedToRouter(@NonNull RouterRecord routerRecord,
                 int requestId) {
             try {
-                routerRecord.mRouter.notifySessionCreated(requestId, /* sessionInfo= */ null);
+                routerRecord.mRouter.notifySessionCreated(requestId,
+                        /* sessionInfo= */ null);
             } catch (RemoteException ex) {
                 Slog.w(TAG, "Failed to notify router of the session creation failure."
                         + " Router probably died.", ex);
@@ -1731,10 +1711,10 @@
         }
 
         private void notifySessionCreatedToManagers(@NonNull List<IMediaRouter2Manager> managers,
-                @NonNull RoutingSessionInfo sessionInfo) {
+                int requestId, @NonNull RoutingSessionInfo sessionInfo) {
             for (IMediaRouter2Manager manager : managers) {
                 try {
-                    manager.notifySessionCreated(sessionInfo);
+                    manager.notifySessionCreated(requestId, sessionInfo);
                 } catch (RemoteException ex) {
                     Slog.w(TAG, "notifySessionCreatedToManagers: "
                             + "failed to notify. Manager probably died.", ex);
@@ -1742,11 +1722,12 @@
             }
         }
 
-        private void notifySessionInfosChangedToManagers(
-                @NonNull List<IMediaRouter2Manager> managers) {
+        private void notifySessionInfoChangedToManagers(
+                @NonNull List<IMediaRouter2Manager> managers,
+                @NonNull RoutingSessionInfo sessionInfo) {
             for (IMediaRouter2Manager manager : managers) {
                 try {
-                    manager.notifySessionsUpdated();
+                    manager.notifySessionUpdated(sessionInfo);
                 } catch (RemoteException ex) {
                     Slog.w(TAG, "notifySessionInfosChangedToManagers: "
                             + "failed to notify. Manager probably died.", ex);
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
new file mode 100644
index 0000000..0bdf3f2
--- /dev/null
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.net;
+
+import static android.net.NetworkTemplate.getCollapsedRatType;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.telephony.Annotation;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+
+/**
+ * Helper class that watches for events that are triggered per subscription.
+ */
+// TODO (b/152176562): Write tests to verify subscription changes generate corresponding
+//  register/unregister calls.
+public class NetworkStatsSubscriptionsMonitor extends
+        SubscriptionManager.OnSubscriptionsChangedListener {
+
+    /**
+     * Interface that this monitor uses to delegate event handling to NetworkStatsService.
+     */
+    public interface Delegate {
+        /**
+         * Notify that the collapsed RAT type has been changed for any subscription. The method
+         * will also be triggered for any existing sub when start and stop monitoring.
+         *
+         * @param subscriberId IMSI of the subscription.
+         * @param collapsedRatType collapsed RAT type.
+         *                         @see android.net.NetworkTemplate#getCollapsedRatType(int).
+         */
+        void onCollapsedRatTypeChanged(@NonNull String subscriberId,
+                @Annotation.NetworkType int collapsedRatType);
+    }
+    private final Delegate mDelegate;
+
+    /**
+     * Receivers that watches for {@link ServiceState} changes for each subscription, to
+     * monitor the transitioning between Radio Access Technology(RAT) types for each sub.
+     */
+    @NonNull
+    private final CopyOnWriteArrayList<RatTypeListener> mRatListeners =
+            new CopyOnWriteArrayList<>();
+
+    @NonNull
+    private final SubscriptionManager mSubscriptionManager;
+    @NonNull
+    private final TelephonyManager mTeleManager;
+
+    @NonNull
+    private final Executor mExecutor;
+
+    NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor,
+            @NonNull Delegate delegate) {
+        super();
+        mSubscriptionManager = (SubscriptionManager) context.getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        mExecutor = executor;
+        mDelegate = delegate;
+    }
+
+    @Override
+    public void onSubscriptionsChanged() {
+        // Collect active subId list, hidden subId such as opportunistic subscriptions are
+        // also needed to track CBRS.
+        final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
+
+        for (final int subId : newSubs) {
+            final RatTypeListener match = CollectionUtils.find(mRatListeners,
+                    it -> it.mSubId == subId);
+            if (match != null) continue;
+
+            // Create listener for every newly added sub. Also store subscriberId into it to
+            // prevent binder call to telephony when querying RAT.
+            final String subscriberId = mTeleManager.getSubscriberId(subId);
+            if (TextUtils.isEmpty(subscriberId)) {
+                Log.wtf(NetworkStatsService.TAG,
+                        "Empty subscriberId for newly added sub: " + subId);
+            }
+            final RatTypeListener listener =
+                    new RatTypeListener(mExecutor, this, subId, subscriberId);
+            mRatListeners.add(listener);
+
+            // Register listener to the telephony manager that associated with specific sub.
+            mTeleManager.createForSubscriptionId(subId)
+                    .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
+        }
+
+        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
+            // If the new list contains the subId of the listener, keeps it.
+            final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId);
+            if (match != null) continue;
+
+            handleRemoveRatTypeListener(listener);
+        }
+    }
+
+    @NonNull
+    private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) {
+        final ArrayList<Integer> ret = new ArrayList<>();
+        final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList();
+        for (int id : ids) ret.add(id);
+        return ret;
+    }
+
+    /**
+     * Get a collapsed RatType for the given subscriberId.
+     *
+     * @param subscriberId the target subscriberId
+     * @return collapsed RatType for the given subscriberId
+     */
+    public int getRatTypeForSubscriberId(@NonNull String subscriberId) {
+        final RatTypeListener match = CollectionUtils.find(mRatListeners,
+                it -> TextUtils.equals(subscriberId, it.mSubscriberId));
+        return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+    }
+
+    /**
+     * Start monitoring events that triggered per subscription.
+     */
+    public void start() {
+        mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this);
+    }
+
+    /**
+     * Unregister subscription changes and all listeners for each subscription.
+     */
+    public void stop() {
+        mSubscriptionManager.removeOnSubscriptionsChangedListener(this);
+
+        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
+            handleRemoveRatTypeListener(listener);
+        }
+    }
+
+    private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
+        mTeleManager.createForSubscriptionId(listener.mSubId)
+                .listen(listener, PhoneStateListener.LISTEN_NONE);
+        mRatListeners.remove(listener);
+
+        // Removal of subscriptions doesn't generate RAT changed event, fire it for every
+        // RatTypeListener.
+        mDelegate.onCollapsedRatTypeChanged(
+                listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+    }
+
+    static class RatTypeListener extends PhoneStateListener {
+        // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}.
+        @NonNull
+        private final int mSubId;
+
+        // IMSI to identifying the corresponding network from {@link NetworkState}.
+        // See {@link TelephonyManager#getSubscriberId}.
+        @NonNull
+        private final String mSubscriberId;
+
+        private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        @NonNull
+        private final NetworkStatsSubscriptionsMonitor mMonitor;
+
+        RatTypeListener(@NonNull Executor executor,
+                @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
+                @NonNull String subscriberId) {
+            super(executor);
+            mSubId = subId;
+            mSubscriberId = subscriberId;
+            mMonitor = monitor;
+        }
+
+        @Override
+        public void onServiceStateChanged(@NonNull ServiceState ss) {
+            final int networkType = ss.getDataNetworkType();
+            final int collapsedRatType = getCollapsedRatType(networkType);
+            if (collapsedRatType == mLastCollapsedRatType) return;
+
+            if (NetworkStatsService.LOGD) {
+                Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): "
+                        + mLastCollapsedRatType + " -> " + collapsedRatType);
+            }
+            mLastCollapsedRatType = collapsedRatType;
+            mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index 2ed6e16..bfc76df 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -250,26 +250,36 @@
 
             for (int i = mHistoryFiles.size() - 1; i >= 0; i--) {
                 final AtomicFile currentOldestFile = mHistoryFiles.get(i);
-                final long creationTime = Long.parseLong(currentOldestFile.getBaseFile().getName());
-                if (DEBUG) {
-                    Slog.d(TAG, "File " + currentOldestFile.getBaseFile().getName()
-                            + " created on " + creationTime);
-                }
-                if (creationTime <= retentionBoundary.getTimeInMillis()) {
+                try {
+                    final long creationTime = Long.parseLong(
+                            currentOldestFile.getBaseFile().getName());
                     if (DEBUG) {
-                        Slog.d(TAG, "Removed " + currentOldestFile.getBaseFile().getName());
+                        Slog.d(TAG, "File " + currentOldestFile.getBaseFile().getName()
+                                + " created on " + creationTime);
                     }
-                    currentOldestFile.delete();
-                    // TODO: delete all relevant bitmaps, once they exist
-                    mHistoryFiles.removeLast();
-                } else {
-                    // all remaining files are newer than the cut off; schedule jobs to delete
-                    scheduleDeletion(currentOldestFile.getBaseFile(), creationTime, retentionDays);
+                    if (creationTime <= retentionBoundary.getTimeInMillis()) {
+                        deleteFile(currentOldestFile);
+                    } else {
+                        // all remaining files are newer than the cut off; schedule jobs to delete
+                        scheduleDeletion(
+                                currentOldestFile.getBaseFile(), creationTime, retentionDays);
+                    }
+                } catch (NumberFormatException e) {
+                    deleteFile(currentOldestFile);
                 }
             }
         }
     }
 
+    private void deleteFile(AtomicFile file) {
+        if (DEBUG) {
+            Slog.d(TAG, "Removed " + file.getBaseFile().getName());
+        }
+        file.delete();
+        // TODO: delete all relevant bitmaps, once they exist
+        mHistoryFiles.removeLast();
+    }
+
     private void scheduleDeletion(File file, long creationTime, int retentionDays) {
         final long deletionTime = creationTime + (retentionDays * HISTORY_RETENTION_MS);
         scheduleDeletion(file, deletionTime);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4aeddc8..f9fc82b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -107,7 +107,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -155,6 +154,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.ShortcutInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -214,7 +214,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
-import android.util.FeatureFlagUtils;
 import android.util.IntArray;
 import android.util.Log;
 import android.util.Pair;
@@ -1730,6 +1729,11 @@
     }
 
     @VisibleForTesting
+    void setShortcutHelper(ShortcutHelper helper) {
+        mShortcutHelper = helper;
+    }
+
+    @VisibleForTesting
     void setHints(int hints) {
         mListenerHints = hints;
     }
@@ -2740,15 +2744,15 @@
         return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
     }
 
-    private ToastRecord getToastRecord(int pid, String packageName, IBinder token,
+    private ToastRecord getToastRecord(int uid, int pid, String packageName, IBinder token,
             @Nullable CharSequence text, @Nullable ITransientNotification callback, int duration,
             Binder windowToken, int displayId,
             @Nullable ITransientNotificationCallback textCallback) {
         if (callback == null) {
-            return new TextToastRecord(this, mStatusBar, pid, packageName, token, text, duration,
-                    windowToken, displayId, textCallback);
+            return new TextToastRecord(this, mStatusBar, uid, pid, packageName, token, text,
+                    duration, windowToken, displayId, textCallback);
         } else {
-            return new CustomToastRecord(this, pid, packageName, token, callback, duration,
+            return new CustomToastRecord(this, uid, pid, packageName, token, callback, duration,
                     windowToken, displayId);
         }
     }
@@ -2873,8 +2877,8 @@
 
                         Binder windowToken = new Binder();
                         mWindowManagerInternal.addWindowToken(windowToken, TYPE_TOAST, displayId);
-                        record = getToastRecord(callingPid, pkg, token, text, callback, duration,
-                                windowToken, displayId, textCallback);
+                        record = getToastRecord(callingUid, callingPid, pkg, token, text, callback,
+                                duration, windowToken, displayId, textCallback);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
                         keepProcessAliveForToastIfNeededLocked(callingPid);
@@ -3459,10 +3463,14 @@
             ArrayList<ConversationChannelWrapper> conversations =
                     mPreferencesHelper.getConversations(onlyImportant);
             for (ConversationChannelWrapper conversation : conversations) {
-                conversation.setShortcutInfo(mShortcutHelper.getValidShortcutInfo(
-                        conversation.getNotificationChannel().getConversationId(),
-                        conversation.getPkg(),
-                        UserHandle.of(UserHandle.getUserId(conversation.getUid()))));
+                if (mShortcutHelper == null) {
+                    conversation.setShortcutInfo(null);
+                } else {
+                    conversation.setShortcutInfo(mShortcutHelper.getValidShortcutInfo(
+                            conversation.getNotificationChannel().getConversationId(),
+                            conversation.getPkg(),
+                            UserHandle.of(UserHandle.getUserId(conversation.getUid()))));
+                }
             }
             return new ParceledListSlice<>(conversations);
         }
@@ -3482,10 +3490,14 @@
             ArrayList<ConversationChannelWrapper> conversations =
                     mPreferencesHelper.getConversations(pkg, uid);
             for (ConversationChannelWrapper conversation : conversations) {
-                conversation.setShortcutInfo(mShortcutHelper.getValidShortcutInfo(
-                        conversation.getNotificationChannel().getConversationId(),
-                        pkg,
-                        UserHandle.of(UserHandle.getUserId(uid))));
+                if (mShortcutHelper == null) {
+                    conversation.setShortcutInfo(null);
+                } else {
+                    conversation.setShortcutInfo(mShortcutHelper.getValidShortcutInfo(
+                            conversation.getNotificationChannel().getConversationId(),
+                            pkg,
+                            UserHandle.of(UserHandle.getUserId(uid))));
+                }
             }
             return new ParceledListSlice<>(conversations);
         }
@@ -5604,18 +5616,16 @@
 
         mUsageStats.registerEnqueuedByApp(pkg);
 
+        final StatusBarNotification n = new StatusBarNotification(
+                pkg, opPkg, id, tag, notificationUid, callingPid, notification,
+                user, null, System.currentTimeMillis());
+
         // setup local book-keeping
         String channelId = notification.getChannelId();
         if (mIsTelevision && (new Notification.TvExtender(notification)).getChannelId() != null) {
             channelId = (new Notification.TvExtender(notification)).getChannelId();
         }
-        String shortcutId = notification.getShortcutId();
-        if (FeatureFlagUtils.isEnabled(getContext(),
-                FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ)
-            && shortcutId == null
-            && notification.getNotificationStyle() == Notification.MessagingStyle.class) {
-            shortcutId = id + tag + NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
-        }
+        String shortcutId = n.getShortcutId(getContext());
         final NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel(
                 pkg, notificationUid, channelId, shortcutId,
                 true /* parent ok */, false /* includeDeleted */);
@@ -5643,9 +5653,6 @@
             return;
         }
 
-        final StatusBarNotification n = new StatusBarNotification(
-                pkg, opPkg, id, tag, notificationUid, callingPid, notification,
-                user, null, System.currentTimeMillis());
         final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
         r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
         r.setPostSilently(postSilently);
@@ -5680,8 +5687,10 @@
             }
         }
 
-        r.setShortcutInfo(mShortcutHelper.getValidShortcutInfo(
-                notification.getShortcutId(), pkg, user));
+        ShortcutInfo info = mShortcutHelper != null
+                ? mShortcutHelper.getValidShortcutInfo(notification.getShortcutId(), pkg, user)
+                : null;
+        r.setShortcutInfo(info);
 
         if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r,
                 r.getSbn().getOverrideGroupKey() != null)) {
@@ -6212,10 +6221,13 @@
                     cancelNotificationLocked(
                             r, mSendDelete, mReason, mRank, mCount, wasPosted, listenerName);
                     cancelGroupChildrenLocked(r, mCallingUid, mCallingPid, listenerName,
-                            mSendDelete, childrenFlagChecker);
+                            mSendDelete, childrenFlagChecker, mReason);
                     updateLightsLocked();
-                    mShortcutHelper.maybeListenForShortcutChangesForBubbles(r, true /* isRemoved */,
-                            mHandler);
+                    if (mShortcutHelper != null) {
+                        mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
+                                true /* isRemoved */,
+                                mHandler);
+                    }
                 } else {
                     // No notification was found, assume that it is snoozed and cancel it.
                     if (mReason != REASON_SNOOZED) {
@@ -6453,9 +6465,11 @@
                                 + n.getPackageName());
                     }
 
-                    mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
-                            false /* isRemoved */,
-                            mHandler);
+                    if (mShortcutHelper != null) {
+                        mShortcutHelper.maybeListenForShortcutChangesForBubbles(r,
+                                false /* isRemoved */,
+                                mHandler);
+                    }
 
                     maybeRecordInterruptionLocked(r);
 
@@ -6667,7 +6681,7 @@
         // notification was a summary and its group key changed.
         if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) {
             cancelGroupChildrenLocked(old, callingUid, callingPid, null, false /* sendDelete */,
-                    null);
+                    null, REASON_APP_CANCEL);
         }
     }
 
@@ -7872,7 +7886,7 @@
             final int M = canceledNotifications.size();
             for (int i = 0; i < M; i++) {
                 cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
-                        listenerName, false /* sendDelete */, flagChecker);
+                        listenerName, false /* sendDelete */, flagChecker, reason);
             }
             updateLightsLocked();
         }
@@ -7943,7 +7957,7 @@
     // Warning: The caller is responsible for invoking updateLightsLocked().
     @GuardedBy("mNotificationLock")
     private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
-            String listenerName, boolean sendDelete, FlagChecker flagChecker) {
+            String listenerName, boolean sendDelete, FlagChecker flagChecker, int reason) {
         Notification n = r.getNotification();
         if (!n.isGroupSummary()) {
             return;
@@ -7957,30 +7971,33 @@
         }
 
         cancelGroupChildrenByListLocked(mNotificationList, r, callingUid, callingPid, listenerName,
-                sendDelete, true, flagChecker);
+                sendDelete, true, flagChecker, reason);
         cancelGroupChildrenByListLocked(mEnqueuedNotifications, r, callingUid, callingPid,
-                listenerName, sendDelete, false, flagChecker);
+                listenerName, sendDelete, false, flagChecker, reason);
     }
 
     @GuardedBy("mNotificationLock")
     private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList,
             NotificationRecord parentNotification, int callingUid, int callingPid,
-            String listenerName, boolean sendDelete, boolean wasPosted, FlagChecker flagChecker) {
+            String listenerName, boolean sendDelete, boolean wasPosted, FlagChecker flagChecker,
+            int reason) {
         final String pkg = parentNotification.getSbn().getPackageName();
         final int userId = parentNotification.getUserId();
-        final int reason = REASON_GROUP_SUMMARY_CANCELED;
+        final int childReason = REASON_GROUP_SUMMARY_CANCELED;
         for (int i = notificationList.size() - 1; i >= 0; i--) {
             final NotificationRecord childR = notificationList.get(i);
             final StatusBarNotification childSbn = childR.getSbn();
             if ((childSbn.isGroup() && !childSbn.getNotification().isGroupSummary()) &&
                     childR.getGroupKey().equals(parentNotification.getGroupKey())
                     && (childR.getFlags() & FLAG_FOREGROUND_SERVICE) == 0
-                    && (flagChecker == null || flagChecker.apply(childR.getFlags()))) {
+                    && (flagChecker == null || flagChecker.apply(childR.getFlags()))
+                    && (!childR.getChannel().isImportantConversation()
+                            || reason != REASON_CANCEL)) {
                 EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(),
-                        childSbn.getTag(), userId, 0, 0, reason, listenerName);
+                        childSbn.getTag(), userId, 0, 0, childReason, listenerName);
                 notificationList.remove(i);
                 mNotificationsByKey.remove(childR.getKey());
-                cancelNotificationLocked(childR, sendDelete, reason, wasPosted, listenerName);
+                cancelNotificationLocked(childR, sendDelete, childReason, wasPosted, listenerName);
             }
         }
     }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 54a0f9f..192df41 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -1383,9 +1383,8 @@
                 || !Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) {
             return false;
         }
-        if (mShortcutInfo == null
-                && !FeatureFlagUtils.isEnabled(
-                        mContext, FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ)) {
+        if (mShortcutInfo == null && Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0) == 1) {
             return false;
         }
         if (mIsNotConversationOverride) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 32cfaf6..8154988 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -20,6 +20,7 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
+import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
@@ -46,7 +47,6 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.FeatureFlagUtils;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
@@ -180,8 +180,8 @@
         updateBadgingEnabled();
         updateBubblesEnabled();
         syncChannelsBypassingDnd(mContext.getUserId());
-        mAllowInvalidShortcuts = FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ);
+        mAllowInvalidShortcuts = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0) == 0;
     }
 
     public void readXml(XmlPullParser parser, boolean forRestore, int userId)
@@ -1798,6 +1798,7 @@
                         .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES);
                 final PackagePreferences r = mPackagePreferences.valueAt(i);
                 event.writeInt(r.uid);
+                event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                 event.writeInt(r.importance);
                 event.writeInt(r.visibility);
                 event.writeInt(r.lockedAppFields);
@@ -1825,6 +1826,7 @@
                     StatsEvent.Builder event = StatsEvent.newBuilder()
                             .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES);
                     event.writeInt(r.uid);
+                    event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                     event.writeString(channel.getId());
                     event.writeString(channel.getName().toString());
                     event.writeString(channel.getDescription());
@@ -1856,6 +1858,7 @@
                     StatsEvent.Builder event = StatsEvent.newBuilder()
                             .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES);
                     event.writeInt(r.uid);
+                    event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                     event.writeString(groupChannel.getId());
                     event.writeString(groupChannel.getName().toString());
                     event.writeString(groupChannel.getDescription());
diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
index aca6f48..2b91a00 100644
--- a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
@@ -23,6 +23,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.server.notification.NotificationManagerService;
@@ -35,11 +36,10 @@
 
     public final ITransientNotification callback;
 
-    public CustomToastRecord(
-            NotificationManagerService notificationManager, int pid, String packageName,
-            IBinder token, ITransientNotification callback, int duration, Binder windowToken,
-            int displayId) {
-        super(notificationManager, pid, packageName, token, duration, windowToken, displayId);
+    public CustomToastRecord(NotificationManagerService notificationManager, int uid, int pid,
+            String packageName, IBinder token, ITransientNotification callback, int duration,
+            Binder windowToken, int displayId) {
+        super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId);
         this.callback = checkNotNull(callback);
     }
 
@@ -74,8 +74,8 @@
     public String toString() {
         return "CustomToastRecord{"
                 + Integer.toHexString(System.identityHashCode(this))
+                + " " + pid + ":" +  pkg + "/" + UserHandle.formatUid(uid)
                 + " token=" + token
-                + " packageName=" + pkg
                 + " callback=" + callback
                 + " duration=" + getDuration()
                 + "}";
diff --git a/services/core/java/com/android/server/notification/toast/TextToastRecord.java b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
index 3c231b4..544520e 100644
--- a/services/core/java/com/android/server/notification/toast/TextToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/TextToastRecord.java
@@ -23,6 +23,7 @@
 import android.app.ITransientNotificationCallback;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.server.notification.NotificationManagerService;
@@ -41,10 +42,10 @@
     private final ITransientNotificationCallback mCallback;
 
     public TextToastRecord(NotificationManagerService notificationManager,
-            @Nullable StatusBarManagerInternal statusBarManager, int pid, String packageName,
-            IBinder token, CharSequence text, int duration, Binder windowToken, int displayId,
-            @Nullable ITransientNotificationCallback callback) {
-        super(notificationManager, pid, packageName, token, duration, windowToken, displayId);
+            @Nullable StatusBarManagerInternal statusBarManager, int uid, int pid,
+            String packageName, IBinder token, CharSequence text, int duration, Binder windowToken,
+            int displayId, @Nullable ITransientNotificationCallback callback) {
+        super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId);
         mStatusBar = statusBarManager;
         mCallback = callback;
         this.text = checkNotNull(text);
@@ -59,7 +60,7 @@
             Slog.w(TAG, "StatusBar not available to show text toast for package " + pkg);
             return false;
         }
-        mStatusBar.showToast(pkg, token, text, windowToken, getDuration(), mCallback);
+        mStatusBar.showToast(uid, pkg, token, text, windowToken, getDuration(), mCallback);
         return true;
     }
 
@@ -75,8 +76,8 @@
     public String toString() {
         return "TextToastRecord{"
                 + Integer.toHexString(System.identityHashCode(this))
+                + " " + pid + ":" +  pkg + "/" + UserHandle.formatUid(uid)
                 + " token=" + token
-                + " packageName=" + pkg
                 + " text=" + text
                 + " duration=" + getDuration()
                 + "}";
diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java
index ef75a6f..7915f70 100644
--- a/services/core/java/com/android/server/notification/toast/ToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java
@@ -28,6 +28,7 @@
  * Represents a toast, a transient notification.
  */
 public abstract class ToastRecord {
+    public final int uid;
     public final int pid;
     public final String pkg;
     public final IBinder token;
@@ -36,11 +37,10 @@
     protected final NotificationManagerService mNotificationManager;
     private int mDuration;
 
-    protected ToastRecord(
-            NotificationManagerService notificationManager,
-            int pid, String pkg, IBinder token, int duration,
-            Binder windowToken, int displayId) {
+    protected ToastRecord(NotificationManagerService notificationManager, int uid, int pid,
+            String pkg, IBinder token, int duration, Binder windowToken, int displayId) {
         this.mNotificationManager = notificationManager;
+        this.uid = uid;
         this.pid = pid;
         this.pkg = pkg;
         this.token = token;
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
index e8e3834..7df8fc7 100644
--- a/services/core/java/com/android/server/om/IdmapDaemon.java
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -18,20 +18,19 @@
 
 import static android.content.Context.IDMAP_SERVICE;
 
-import static com.android.server.om.OverlayManagerService.DEBUG;
 import static com.android.server.om.OverlayManagerService.TAG;
 
 import android.os.IBinder;
 import android.os.IIdmap2;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
+import android.os.SystemClock;
+import android.os.SystemService;
 import android.util.Slog;
 
 import com.android.server.FgThread;
 
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -45,13 +44,14 @@
 
     // The amount of time in milliseconds to wait when attempting to connect to idmap service.
     private static final int SERVICE_CONNECT_TIMEOUT_MS = 5000;
+    private static final int SERVICE_CONNECT_INTERVAL_SLEEP_MS = 200;
 
-    private static final Object IDMAP_TOKEN = new Object();
     private static final String IDMAP_DAEMON = "idmap2d";
 
     private static IdmapDaemon sInstance;
     private volatile IIdmap2 mService;
     private final AtomicInteger mOpenedCount = new AtomicInteger();
+    private final Object mIdmapToken = new Object();
 
     /**
      * An {@link AutoCloseable} connection to the idmap service. When the connection is closed or
@@ -62,14 +62,14 @@
         private boolean mOpened = true;
 
         private Connection() {
-            synchronized (IDMAP_TOKEN) {
+            synchronized (mIdmapToken) {
                 mOpenedCount.incrementAndGet();
             }
         }
 
         @Override
         public void close() {
-            synchronized (IDMAP_TOKEN) {
+            synchronized (mIdmapToken) {
                 if (!mOpened) {
                     return;
                 }
@@ -82,7 +82,7 @@
                 }
 
                 FgThread.getHandler().postDelayed(() -> {
-                    synchronized (IDMAP_TOKEN) {
+                    synchronized (mIdmapToken) {
                         // Only stop the service if the service does not have an open connection.
                         if (mService == null || mOpenedCount.get() != 0) {
                             return;
@@ -91,7 +91,7 @@
                         stopIdmapService();
                         mService = null;
                     }
-                }, IDMAP_TOKEN, SERVICE_TIMEOUT_MS);
+                }, mIdmapToken, SERVICE_TIMEOUT_MS);
             }
         }
     }
@@ -104,14 +104,14 @@
     }
 
     String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
-            int userId) throws Exception {
-        try (Connection connection = connect()) {
+            int userId) throws TimeoutException, RemoteException {
+        try (Connection c = connect()) {
             return mService.createIdmap(targetPath, overlayPath, policies, enforce, userId);
         }
     }
 
-    boolean removeIdmap(String overlayPath, int userId) throws Exception {
-        try (Connection connection = connect()) {
+    boolean removeIdmap(String overlayPath, int userId) throws TimeoutException, RemoteException {
+        try (Connection c = connect()) {
             return mService.removeIdmap(overlayPath, userId);
         }
     }
@@ -119,76 +119,54 @@
     boolean verifyIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
              int userId)
             throws Exception {
-        try (Connection connection = connect()) {
+        try (Connection c = connect()) {
             return mService.verifyIdmap(targetPath, overlayPath, policies, enforce, userId);
         }
     }
 
-    String getIdmapPath(String overlayPath, int userId) throws Exception {
-        try (Connection connection = connect()) {
+    String getIdmapPath(String overlayPath, int userId) throws TimeoutException, RemoteException {
+        try (Connection c = connect()) {
             return mService.getIdmapPath(overlayPath, userId);
         }
     }
 
-    private static void startIdmapService() {
-        SystemProperties.set("ctl.start", IDMAP_DAEMON);
+    private IBinder getIdmapService() throws TimeoutException, RemoteException {
+        SystemService.start(IDMAP_DAEMON);
+
+        final long endMillis = SystemClock.elapsedRealtime() + SERVICE_CONNECT_TIMEOUT_MS;
+        while (SystemClock.elapsedRealtime() <= endMillis) {
+            final IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
+            if (binder != null) {
+                binder.linkToDeath(
+                        () -> Slog.w(TAG, String.format("service '%s' died", IDMAP_SERVICE)), 0);
+                return binder;
+            }
+
+            try {
+                Thread.sleep(SERVICE_CONNECT_INTERVAL_SLEEP_MS);
+            } catch (InterruptedException ignored) {
+            }
+        }
+
+        throw new TimeoutException(
+            String.format("Failed to connect to '%s' in %d milliseconds", IDMAP_SERVICE,
+                    SERVICE_CONNECT_TIMEOUT_MS));
     }
 
     private static void stopIdmapService() {
-        SystemProperties.set("ctl.stop", IDMAP_DAEMON);
+        SystemService.stop(IDMAP_DAEMON);
     }
 
-    private Connection connect() throws Exception {
-        synchronized (IDMAP_TOKEN) {
-            FgThread.getHandler().removeCallbacksAndMessages(IDMAP_TOKEN);
+    private Connection connect() throws TimeoutException, RemoteException {
+        synchronized (mIdmapToken) {
+            FgThread.getHandler().removeCallbacksAndMessages(mIdmapToken);
             if (mService != null) {
                 // Not enough time has passed to stop the idmap service. Reuse the existing
                 // interface.
                 return new Connection();
             }
 
-            // Start the idmap service if it is not currently running.
-            startIdmapService();
-
-            // Block until the service is found.
-            FutureTask<IBinder> bindIdmap = new FutureTask<>(() -> {
-                while (true) {
-                    try {
-                        IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
-                        if (binder != null) {
-                            return binder;
-                        }
-                    } catch (Exception e) {
-                        Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not retrieved; "
-                                + e.getMessage());
-                    }
-                    Thread.sleep(100);
-                }
-            });
-
-            IBinder binder;
-            try {
-                FgThread.getHandler().postAtFrontOfQueue(bindIdmap);
-                binder = bindIdmap.get(SERVICE_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-            } catch (Exception rethrow) {
-                Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not found;");
-                throw rethrow;
-            }
-
-            try {
-                binder.linkToDeath(() -> {
-                    Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died");
-                }, 0);
-            } catch (RemoteException rethrow) {
-                Slog.e(TAG, "service '" + IDMAP_SERVICE + "' failed to be bound");
-                throw rethrow;
-            }
-
-            mService = IIdmap2.Stub.asInterface(binder);
-            if (DEBUG) {
-                Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
-            }
-
+            mService = IIdmap2.Stub.asInterface(getIdmapService());
             return new Connection();
         }
     }
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index b9d6561..1e4dc7b 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -30,7 +30,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.os.Binder;
 import android.os.Environment;
@@ -137,7 +137,8 @@
     /**
      * Called by package manager service to scan apex package files when device boots up.
      *
-     * @param packageParser The package parser which supports caches.
+     * @param packageParser The package parser to support apex package parsing and caching parsed
+     *                      results.
      * @param executorService An executor to support parallel package parsing.
      */
     abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
@@ -505,7 +506,13 @@
                         }
                         factoryPackagesSet.add(packageInfo.packageName);
                     }
-                } else if (throwable instanceof PackageParser.PackageParserException) {
+                } else if (throwable instanceof PackageParserException) {
+                    final PackageParserException e = (PackageParserException) throwable;
+                    // Skip parsing non-coreApp apex file if system is in minimal boot state.
+                    if (e.error == PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED) {
+                        Slog.w(TAG, "Scan apex failed, not a coreApp:" + ai.modulePath);
+                        continue;
+                    }
                     throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable);
                 } else {
                     throw new IllegalStateException("Unexpected exception occurred while parsing "
@@ -522,7 +529,8 @@
                     "APEX packages have not been scanned");
             boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
             boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0;
-            for (PackageInfo packageInfo: mAllPackagesCache) {
+            for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
+                final PackageInfo packageInfo = mAllPackagesCache.get(i);
                 if (!packageInfo.packageName.equals(packageName)) {
                     continue;
                 }
@@ -581,7 +589,8 @@
             if (!isApexSupported()) return false;
             Preconditions.checkState(mAllPackagesCache != null,
                     "APEX packages have not been scanned");
-            for (PackageInfo packageInfo : mAllPackagesCache) {
+            for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
+                final PackageInfo packageInfo = mAllPackagesCache.get(i);
                 if (packageInfo.packageName.equals(packageName)) {
                     return true;
                 }
@@ -839,7 +848,8 @@
                 IndentingPrintWriter ipw) {
             ipw.println();
             ipw.increaseIndent();
-            for (PackageInfo pi : packagesCache) {
+            for (int i = 0, size = packagesCache.size(); i < size; i++) {
+                final PackageInfo pi = packagesCache.get(i);
                 if (packageName != null && !packageName.equals(pi.packageName)) {
                     continue;
                 }
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 805d918..09b782d 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -674,7 +674,8 @@
             Trace.endSection();
 
             if (callingPkgSetting != null) {
-                if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
+                if (callingPkgSetting.pkg != null
+                        && !mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
                     if (DEBUG_LOGGING) {
                         log(callingSetting, targetPkgSetting, "DISABLED");
                     }
@@ -682,7 +683,8 @@
                 }
             } else {
                 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
-                    if (!mFeatureConfig.packageIsEnabled(callingSharedPkgSettings.valueAt(i).pkg)) {
+                    final AndroidPackage pkg = callingSharedPkgSettings.valueAt(i).pkg;
+                    if (pkg != null && !mFeatureConfig.packageIsEnabled(pkg)) {
                         if (DEBUG_LOGGING) {
                             log(callingSetting, targetPkgSetting, "DISABLED");
                         }
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index f497f11..f1e1433 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -54,6 +54,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.IntentResolver;
 import com.android.server.pm.parsing.PackageInfoUtils;
@@ -207,33 +208,57 @@
     }
 
     /** Returns the given activity */
-    ParsedActivity getActivity(ComponentName component) {
+    @Nullable
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public ParsedActivity getActivity(@NonNull ComponentName component) {
         synchronized (mLock) {
             return mActivities.mActivities.get(component);
         }
     }
 
     /** Returns the given provider */
-    ParsedProvider getProvider(ComponentName component) {
+    @Nullable
+    ParsedProvider getProvider(@NonNull ComponentName component) {
         synchronized (mLock) {
             return mProviders.mProviders.get(component);
         }
     }
 
     /** Returns the given receiver */
-    ParsedActivity getReceiver(ComponentName component) {
+    @Nullable
+    ParsedActivity getReceiver(@NonNull ComponentName component) {
         synchronized (mLock) {
             return mReceivers.mActivities.get(component);
         }
     }
 
     /** Returns the given service */
-    ParsedService getService(ComponentName component) {
+    @Nullable
+    ParsedService getService(@NonNull ComponentName component) {
         synchronized (mLock) {
             return mServices.mServices.get(component);
         }
     }
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public boolean componentExists(@NonNull ComponentName componentName) {
+        synchronized (mLock) {
+            ParsedMainComponent component = mActivities.mActivities.get(componentName);
+            if (component != null) {
+                return true;
+            }
+            component = mReceivers.mActivities.get(componentName);
+            if (component != null) {
+                return true;
+            }
+            component = mServices.mServices.get(componentName);
+            if (component != null) {
+                return true;
+            }
+            return mProviders.mProviders.get(componentName) != null;
+        }
+    }
+
     @Nullable
     List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
             @PrivateResolveFlags int privateResolveFlags, int userId) {
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 4087675..28c8642d 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -294,6 +294,12 @@
                         .getAllCrossProfilePackages().contains(packageName));
     }
 
+    private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) {
+        return mInjector.withCleanCallingIdentity(() ->
+                mInjector.getDevicePolicyManagerInternal()
+                        .getDefaultCrossProfilePackages().contains(packageName));
+    }
+
     private List<UserHandle> getTargetUserProfilesUnchecked(
             String packageName, @UserIdInt int userId) {
         return mInjector.withCleanCallingIdentity(() -> {
@@ -528,6 +534,9 @@
 
     @Override
     public boolean canConfigureInteractAcrossProfiles(String packageName) {
+        if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) {
+            return false;
+        }
         if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
             return false;
         }
@@ -546,7 +555,35 @@
             return false;
         }
         return hasRequestedAppOpPermission(
-                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
+                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
+                && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
+    }
+
+    private boolean isPlatformSignedAppWithNonUserConfigurablePermission(
+            String packageName, int[] profileIds) {
+        return !isCrossProfilePackageWhitelistedByDefault(packageName)
+                && isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds);
+    }
+
+    /**
+     * Only platform-signed apps can be granted INTERACT_ACROSS_PROFILES automatically without user
+     * consent.
+     *
+     * Returns true if the app is automatically granted the permission in at least one profile.
+     */
+    private boolean isPlatformSignedAppWithAutomaticProfilesPermission(
+            String packageName, int[] profileIds) {
+        for (int userId : profileIds) {
+            final int uid = mInjector.getPackageManagerInternal().getPackageUidInternal(
+                    packageName, /* flags= */ 0, userId);
+            if (uid == -1) {
+                continue;
+            }
+            if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     private boolean hasOtherProfileWithPackageInstalled(String packageName, @UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index f37af3a..9fb468e 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -724,6 +724,30 @@
     }
 
     /**
+     * Deletes all snapshots of credential encrypted user data, where the snapshot id is not
+     * included in {@code retainSnapshotIds}.
+     *
+     * @param userId id of the user whose user data snapshots to delete.
+     * @param retainSnapshotIds ids of the snapshots that should not be deleted.
+     *
+     * @return {@code true} if the operation was successful, or {@code false} if a remote call
+     * shouldn't be continued. See {@link #checkBeforeRemote}.
+     *
+     * @throws InstallerException if failed to delete user data snapshot.
+     */
+    public boolean destroyCeSnapshotsNotSpecified(@UserIdInt int userId,
+            int[] retainSnapshotIds) throws InstallerException {
+        if (!checkBeforeRemote()) return false;
+
+        try {
+            mInstalld.destroyCeSnapshotsNotSpecified(null, userId, retainSnapshotIds);
+            return true;
+        } catch (Exception e) {
+            throw InstallerException.from(e);
+        }
+    }
+
+    /**
      * Migrates obb data from its legacy location {@code /data/media/obb} to
      * {@code /data/media/0/Android/obb}. This call is idempotent and a fast no-op if data has
      * already been migrated.
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 1b271a7..1d5c304 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -47,6 +47,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutQueryWrapper;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
 import android.content.pm.UserInfo;
@@ -698,13 +699,19 @@
         }
 
         @Override
-        public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
-                String packageName, List shortcutIds, List<LocusId> locusIds,
-                ComponentName componentName, int flags, UserHandle targetUser) {
+        public ParceledListSlice getShortcuts(@NonNull final String callingPackage,
+                @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser) {
             ensureShortcutPermission(callingPackage);
             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
                 return new ParceledListSlice<>(Collections.EMPTY_LIST);
             }
+
+            final long changedSince = query.getChangedSince();
+            final String packageName = query.getPackage();
+            final List<String> shortcutIds = query.getShortcutIds();
+            final List<LocusId> locusIds = query.getLocusIds();
+            final ComponentName componentName = query.getActivity();
+            final int flags = query.getQueryFlags();
             if (shortcutIds != null && packageName == null) {
                 throw new IllegalArgumentException(
                         "To query by shortcut ID, package name must also be set");
@@ -723,16 +730,17 @@
         }
 
         @Override
-        public void registerShortcutChangeCallback(String callingPackage, long changedSince,
-                String packageName, List shortcutIds, List<LocusId> locusIds,
-                ComponentName componentName, int flags, IShortcutChangeCallback callback) {
+        public void registerShortcutChangeCallback(@NonNull final String callingPackage,
+                @NonNull final ShortcutQueryWrapper query,
+                @NonNull final IShortcutChangeCallback callback) {
+
             ensureShortcutPermission(callingPackage);
 
-            if (shortcutIds != null && packageName == null) {
+            if (query.getShortcutIds() != null && query.getPackage() == null) {
                 throw new IllegalArgumentException(
                         "To query by shortcut ID, package name must also be set");
             }
-            if (locusIds != null && packageName == null) {
+            if (query.getLocusIds() != null && query.getPackage() == null) {
                 throw new IllegalArgumentException(
                         "To query by locus ID, package name must also be set");
             }
@@ -744,10 +752,7 @@
                 user = null;
             }
 
-            // TODO: When ShortcutQueryWrapper (ag/10323729) is available, pass that directly.
-            ShortcutChangeHandler.QueryInfo query = new ShortcutChangeHandler.QueryInfo(
-                    changedSince, packageName, shortcutIds, locusIds, componentName, flags, user);
-            mShortcutChangeHandler.addShortcutChangeCallback(callback, query);
+            mShortcutChangeHandler.addShortcutChangeCallback(callback, query, user);
         }
 
         @Override
@@ -1081,9 +1086,11 @@
                     new RemoteCallbackList<>();
 
             public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback,
-                    QueryInfo query) {
+                    ShortcutQueryWrapper query, UserHandle user) {
                 mCallbacks.unregister(callback);
-                mCallbacks.register(callback, query);
+                mCallbacks.register(callback, new QueryInfo(query.getChangedSince(),
+                        query.getPackage(), query.getShortcutIds(), query.getLocusIds(),
+                        query.getActivity(), query.getQueryFlags(), user));
             }
 
             public synchronized void removeShortcutChangeCallback(
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index e625aef..e7d0c41 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -401,7 +401,8 @@
             return DEX_OPT_FAILED;
         }
         String classLoaderContext = null;
-        if (dexUseInfo.isUnknownClassLoaderContext() || dexUseInfo.isVariableClassLoaderContext()) {
+        if (dexUseInfo.isUnsupportedClassLoaderContext()
+                || dexUseInfo.isVariableClassLoaderContext()) {
             // If we have an unknown (not yet set), or a variable class loader chain. Just extract
             // the dex file.
             compilerFilter = "extract";
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 8ff7ea9..57908f3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -82,6 +82,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
+import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import libcore.io.IoUtils;
@@ -105,6 +106,7 @@
 import java.util.Objects;
 import java.util.Random;
 import java.util.function.IntPredicate;
+import java.util.function.Supplier;
 
 /** The service responsible for installing packages. */
 public class PackageInstallerService extends IPackageInstaller.Stub implements
@@ -194,7 +196,8 @@
         }
     };
 
-    public PackageInstallerService(Context context, PackageManagerService pm) {
+    public PackageInstallerService(Context context, PackageManagerService pm,
+            Supplier<PackageParser2> apexParserSupplier) {
         mContext = context;
         mPm = pm;
         mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class);
@@ -213,7 +216,7 @@
         mSessionsDir.mkdirs();
 
         mApexManager = ApexManager.getInstance();
-        mStagingManager = new StagingManager(this, context);
+        mStagingManager = new StagingManager(this, context, apexParserSupplier);
     }
 
     boolean okToSendBroadcasts()  {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1248ec0..f07fa50 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1830,7 +1830,9 @@
             throws PackageManagerException {
         final List<File> addedFiles = getAddedApksLocked();
         if (addedFiles.isEmpty()) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                    String.format("Session: %d. No packages staged in %s", sessionId,
+                          stageDir.getAbsolutePath()));
         }
 
         if (ArrayUtils.size(addedFiles) > 1) {
@@ -1921,7 +1923,9 @@
 
         final List<File> addedFiles = getAddedApksLocked();
         if (addedFiles.isEmpty() && removeSplitList.size() == 0) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                    String.format("Session: %d. No packages staged in %s", sessionId,
+                          stageDir.getAbsolutePath()));
         }
 
         // Verify that all staged packages are internally consistent
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8850f29..f693555 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -417,6 +417,7 @@
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 /**
  * Keep track of all those APKs everywhere.
@@ -674,7 +675,7 @@
 
     final ServiceThread mHandlerThread;
 
-    final PackageHandler mHandler;
+    final Handler mHandler;
 
     private final ProcessLoggingHandler mProcessLoggingHandler;
 
@@ -1033,6 +1034,62 @@
         }
     }
 
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static class TestParams {
+        public ApexManager apexManager;
+        public @Nullable String appPredictionServicePackage;
+        public ArtManagerService artManagerService;
+        public @Nullable String configuratorPackage;
+        public int defParseFlags;
+        public DexManager dexManager;
+        public List<ScanPartition> dirsToScanAsSystem;
+        public @Nullable String documenterPackage;
+        public boolean factoryTest;
+        public ArrayMap<String, FeatureInfo> availableFeatures;
+        public Handler handler;
+        public ServiceThread handlerThread;
+        public @Nullable String incidentReportApproverPackage;
+        public IncrementalManager incrementalManager;
+        public PackageInstallerService installerService;
+        public InstantAppRegistry instantAppRegistry;
+        public InstantAppResolverConnection instantAppResolverConnection;
+        public ComponentName instantAppResolverSettingsComponent;
+        public @Nullable IntentFilterVerifier<ParsedIntentInfo> intentFilterVerifier;
+        public @Nullable ComponentName intentFilterVerifierComponent;
+        public boolean isPreNmr1Upgrade;
+        public boolean isPreNupgrade;
+        public boolean isPreQupgrade;
+        public boolean isUpgrade;
+        public DisplayMetrics Metrics;
+        public ModuleInfoProvider moduleInfoProvider;
+        public MoveCallbacks moveCallbacks;
+        public boolean onlyCore;
+        public OverlayConfig overlayConfig;
+        public PackageDexOptimizer packageDexOptimizer;
+        public PackageParser2.Callback packageParserCallback;
+        public IPermissionManager permissionManagerService;
+        public PendingPackageBroadcasts pendingPackageBroadcasts;
+        public PackageManagerInternal pmInternal;
+        public ProcessLoggingHandler processLoggingHandler;
+        public ProtectedPackages protectedPackages;
+        public @NonNull String requiredInstallerPackage;
+        public @NonNull String requiredPermissionControllerPackage;
+        public @NonNull String requiredUninstallerPackage;
+        public @Nullable String requiredVerifierPackage;
+        public String[] separateProcesses;
+        public @NonNull String servicesExtensionPackageName;
+        public @Nullable String setupWizardPackage;
+        public @NonNull String sharedSystemSharedLibraryPackageName;
+        public @Nullable String storageManagerPackage;
+        public @Nullable String defaultTextClassifierPackage;
+        public @Nullable String systemTextClassifierPackage;
+        public ViewCompiler viewCompiler;
+        public @Nullable String wellbeingPackage;
+        public @Nullable String retailDemoPackage;
+        public ComponentName resolveComponentName;
+        public ArrayMap<String, AndroidPackage> packages;
+    }
+
     private final AppsFilter mAppsFilter;
 
     final PackageParser2.Callback mPackageParserCallback;
@@ -1396,7 +1453,8 @@
     }
 
     // Set of pending broadcasts for aggregating enable/disable of components.
-    static class PendingPackageBroadcasts {
+    @VisibleForTesting(visibility = Visibility.PACKAGE)
+    public static class PendingPackageBroadcasts {
         // for each user id, a map of <package name -> components within that package>
         final SparseArray<ArrayMap<String, ArrayList<String>>> mUidMap;
 
@@ -1459,7 +1517,7 @@
             return map;
         }
     }
-    final PendingPackageBroadcasts mPendingBroadcasts = new PendingPackageBroadcasts();
+    final PendingPackageBroadcasts mPendingBroadcasts;
 
     static final int SEND_PENDING_BROADCAST = 1;
     static final int INIT_COPY = 5;
@@ -2676,6 +2734,82 @@
         }
     }
 
+    /**
+     * A extremely minimal constructor designed to start up a PackageManagerService instance for
+     * testing.
+     *
+     * It is assumed that all methods under test will mock the internal fields and thus
+     * none of the initialization is needed.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public PackageManagerService(@NonNull Injector injector, @NonNull TestParams testParams) {
+        mInjector = injector;
+        mInjector.bootstrap(this);
+        mAppsFilter = injector.getAppsFilter();
+        mComponentResolver = injector.getComponentResolver();
+        mContext = injector.getContext();
+        mInstaller = injector.getInstaller();
+        mInstallLock = injector.getInstallLock();
+        mLock = injector.getLock();
+        mPermissionManager = injector.getPermissionManagerServiceInternal();
+        mSettings = injector.getSettings();
+        mUserManager = injector.getUserManagerService();
+
+        mApexManager = testParams.apexManager;
+        mArtManagerService = testParams.artManagerService;
+        mAvailableFeatures = testParams.availableFeatures;
+        mDefParseFlags = testParams.defParseFlags;
+        mDexManager = testParams.dexManager;
+        mDirsToScanAsSystem = testParams.dirsToScanAsSystem;
+        mFactoryTest = testParams.factoryTest;
+        mHandler = testParams.handler;
+        mHandlerThread = testParams.handlerThread;
+        mIncrementalManager = testParams.incrementalManager;
+        mInstallerService = testParams.installerService;
+        mInstantAppRegistry = testParams.instantAppRegistry;
+        mInstantAppResolverConnection = testParams.instantAppResolverConnection;
+        mInstantAppResolverSettingsComponent = testParams.instantAppResolverSettingsComponent;
+        mIntentFilterVerifier = testParams.intentFilterVerifier;
+        mIntentFilterVerifierComponent = testParams.intentFilterVerifierComponent;
+        mIsPreNMR1Upgrade = testParams.isPreNmr1Upgrade;
+        mIsPreNUpgrade = testParams.isPreNupgrade;
+        mIsPreQUpgrade = testParams.isPreQupgrade;
+        mIsUpgrade = testParams.isUpgrade;
+        mMetrics = testParams.Metrics;
+        mModuleInfoProvider = testParams.moduleInfoProvider;
+        mMoveCallbacks = testParams.moveCallbacks;
+        mOnlyCore = testParams.onlyCore;
+        mOverlayConfig = testParams.overlayConfig;
+        mPackageDexOptimizer = testParams.packageDexOptimizer;
+        mPackageParserCallback = testParams.packageParserCallback;
+        mPendingBroadcasts = testParams.pendingPackageBroadcasts;
+        mPermissionManagerService = testParams.permissionManagerService;
+        mPmInternal = testParams.pmInternal;
+        mProcessLoggingHandler = testParams.processLoggingHandler;
+        mProtectedPackages = testParams.protectedPackages;
+        mSeparateProcesses = testParams.separateProcesses;
+        mViewCompiler = testParams.viewCompiler;
+        mRequiredVerifierPackage = testParams.requiredVerifierPackage;
+        mRequiredInstallerPackage = testParams.requiredInstallerPackage;
+        mRequiredUninstallerPackage = testParams.requiredUninstallerPackage;
+        mRequiredPermissionControllerPackage = testParams.requiredPermissionControllerPackage;
+        mSetupWizardPackage = testParams.setupWizardPackage;
+        mStorageManagerPackage = testParams.storageManagerPackage;
+        mDefaultTextClassifierPackage = testParams.defaultTextClassifierPackage;
+        mSystemTextClassifierPackageName = testParams.systemTextClassifierPackage;
+        mWellbeingPackage = testParams.wellbeingPackage;
+        mRetailDemoPackage = testParams.retailDemoPackage;
+        mDocumenterPackage = testParams.documenterPackage;
+        mConfiguratorPackage = testParams.configuratorPackage;
+        mAppPredictionServicePackage = testParams.appPredictionServicePackage;
+        mIncidentReportApproverPackage = testParams.incidentReportApproverPackage;
+        mServicesExtensionPackageName = testParams.servicesExtensionPackageName;
+        mSharedSystemSharedLibraryPackageName = testParams.sharedSystemSharedLibraryPackageName;
+
+        mResolveComponentName = testParams.resolveComponentName;
+        mPackages.putAll(testParams.packages);
+    }
+
     public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
         PackageManager.invalidatePackageInfoCache();
         PackageManager.disableApplicationInfoCache();
@@ -2683,6 +2817,8 @@
 
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
                 Trace.TRACE_TAG_PACKAGE_MANAGER);
+        mPendingBroadcasts = new PendingPackageBroadcasts();
+
         mInjector = injector;
         mInjector.bootstrap(this);
         mLock = injector.getLock();
@@ -3436,7 +3572,11 @@
                 }
             }
 
-            mInstallerService = new PackageInstallerService(mContext, this);
+            // Prepare a supplier of package parser for the staging manager to parse apex file
+            // during the staging installation.
+            final Supplier<PackageParser2> apexParserSupplier = () -> new PackageParser2(
+                    mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback);
+            mInstallerService = new PackageInstallerService(mContext, this, apexParserSupplier);
             final Pair<ComponentName, String> instantAppResolverComponent =
                     getInstantAppResolverLPr();
             if (instantAppResolverComponent != null) {
@@ -5168,7 +5308,7 @@
 
             AndroidPackage pkg = a == null ? null : mPackages.get(a.getPackageName());
             if (pkg != null && mSettings.isEnabledAndMatchLPr(pkg, a, flags, userId)) {
-                PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+                PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
                 if (ps == null) return null;
                 if (shouldFilterApplicationLocked(
                         ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {
@@ -9544,6 +9684,20 @@
     @Override
     public void notifyDexLoad(String loadingPackageName, Map<String, String> classLoaderContextMap,
             String loaderIsa) {
+        if (PLATFORM_PACKAGE_NAME.equals(loadingPackageName)
+                && Binder.getCallingUid() != Process.SYSTEM_UID) {
+            Slog.w(TAG, "Non System Server process reporting dex loads as system server. uid="
+                    + Binder.getCallingUid());
+            // Do not record dex loads from processes pretending to be system server.
+            // Only the system server should be assigned the package "android", so reject calls
+            // that don't satisfy the constraint.
+            //
+            // notifyDexLoad is a PM API callable from the app process. So in theory, apps could
+            // craft calls to this API and pretend to be system server. Doing so poses no particular
+            // danger for dex load reporting or later dexopt, however it is a sensible check to do
+            // in order to verify the expectations.
+            return;
+        }
         int userId = UserHandle.getCallingUserId();
         ApplicationInfo ai = getApplicationInfo(loadingPackageName, /*flags*/ 0, userId);
         if (ai == null) {
@@ -11170,7 +11324,7 @@
                     Slog.i(TAG, "Using ABIS and native lib paths from settings : " +
                             parsedPackage.getPackageName() + " " +
                             AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage)
-                            + ", " 
+                            + ", "
                             + AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage));
                 }
             }
@@ -15609,6 +15763,12 @@
                         // these install state changes will be persisted in the
                         // upcoming call to mSettings.writeLPr().
                     }
+
+                    if (allUsers != null) {
+                        for (int currentUserId : allUsers) {
+                            ps.resetOverrideComponentLabelIcon(currentUserId);
+                        }
+                    }
                 }
 
                 // Retrieve the overlays for shared libraries of the package.
@@ -17393,31 +17553,26 @@
                 + " Activities needs verification ...");
 
         int count = 0;
-        boolean handlesWebUris = false;
-        final boolean alreadyVerified;
+
         synchronized (mLock) {
             // If this is a new install and we see that we've already run verification for this
             // package, we have nothing to do: it means the state was restored from backup.
-            final IntentFilterVerificationInfo ivi =
-                    mSettings.getIntentFilterVerificationLPr(packageName);
-            alreadyVerified = (ivi != null);
-            if (!replacing && alreadyVerified) {
-                if (DEBUG_DOMAIN_VERIFICATION) {
-                    Slog.i(TAG, "Package " + packageName + " already verified: status="
-                            + ivi.getStatusString());
+            if (!replacing) {
+                IntentFilterVerificationInfo ivi =
+                        mSettings.getIntentFilterVerificationLPr(packageName);
+                if (ivi != null) {
+                    if (DEBUG_DOMAIN_VERIFICATION) {
+                        Slog.i(TAG, "Package " + packageName+ " already verified: status="
+                                + ivi.getStatusString());
+                    }
+                    return;
                 }
-                return;
             }
 
-            // If any filters need to be verified, then all need to be.  In addition, we need to
-            // know whether an updating app has any web navigation intent filters, to re-
-            // examine handling policy even if not re-verifying.
+            // If any filters need to be verified, then all need to be.
             boolean needToVerify = false;
             for (ParsedActivity a : activities) {
                 for (ParsedIntentInfo filter : a.getIntents()) {
-                    if (filter.handlesWebUris(true)) {
-                        handlesWebUris = true;
-                    }
                     if (filter.needsVerification()
                             && needsNetworkVerificationLPr(a.getPackageName())) {
                         if (DEBUG_DOMAIN_VERIFICATION) {
@@ -17425,23 +17580,19 @@
                                     "Intent filter needs verification, so processing all filters");
                         }
                         needToVerify = true;
-                        // It's safe to break out here because filter.needsVerification()
-                        // can only be true if filter.handlesWebUris(true) returns true, so
-                        // we've already noted that.
                         break;
                     }
                 }
             }
 
-            // Note whether this app publishes any web navigation handling support at all,
-            // and whether there are any web-nav filters that fit the profile for running
-            // a verification pass now.
             if (needToVerify) {
+                final boolean needsVerification = needsNetworkVerificationLPr(packageName);
                 final int verificationId = mIntentFilterVerificationToken++;
                 for (ParsedActivity a : activities) {
                     for (ParsedIntentInfo filter : a.getIntents()) {
-                        if (filter.handlesWebUris(true)
-                                && needsNetworkVerificationLPr(a.getPackageName())) {
+                        // Run verification against hosts mentioned in any web-nav intent filter,
+                        // even if the filter matches non-web schemes as well
+                        if (needsVerification && filter.handlesWebUris(false)) {
                             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                     "Verification needed for IntentFilter:" + filter.toString());
                             mIntentFilterVerifier.addOneIntentFilterVerification(
@@ -17454,23 +17605,13 @@
         }
 
         if (count > 0) {
-            // count > 0 means that we're running a full verification pass
             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                     + " IntentFilter verification" + (count > 1 ? "s" : "")
                     +  " for userId:" + userId);
             mIntentFilterVerifier.startVerifications(userId);
-        } else if (alreadyVerified && handlesWebUris) {
-            // App used autoVerify in the past, no longer does, but still handles web
-            // navigation starts.
-            if (DEBUG_DOMAIN_VERIFICATION) {
-                Slog.d(TAG, "App changed web filters but no longer verifying - resetting policy");
-            }
-            synchronized (mLock) {
-                clearIntentFilterVerificationsLPw(packageName, userId);
-            }
         } else {
             if (DEBUG_DOMAIN_VERIFICATION) {
-                Slog.d(TAG, "No web filters or no prior verify policy for " + packageName);
+                Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
             }
         }
     }
@@ -20177,6 +20318,86 @@
     }
 
     @Override
+    public void overrideLabelAndIcon(@NonNull ComponentName componentName,
+            @NonNull String nonLocalizedLabel, int icon, int userId) {
+        if (TextUtils.isEmpty(nonLocalizedLabel)) {
+            throw new IllegalArgumentException("Override label should be a valid String");
+        }
+        updateComponentLabelIcon(componentName, nonLocalizedLabel, icon, userId);
+    }
+
+    @Override
+    public void restoreLabelAndIcon(@NonNull ComponentName componentName, int userId) {
+        updateComponentLabelIcon(componentName, null, null, userId);
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public void updateComponentLabelIcon(/*@NonNull*/ ComponentName componentName,
+            @Nullable String nonLocalizedLabel, @Nullable Integer icon, int userId) {
+        if (componentName == null) {
+            throw new IllegalArgumentException("Must specify a component");
+        }
+
+        boolean componentExists = mComponentResolver.componentExists(componentName);
+        if (!componentExists) {
+            throw new IllegalArgumentException("Component " + componentName + " not found");
+        }
+
+        int callingUid = Binder.getCallingUid();
+
+        String componentPkgName = componentName.getPackageName();
+        int componentUid = getPackageUid(componentPkgName, 0, userId);
+        if (!UserHandle.isSameApp(callingUid, componentUid)) {
+            throw new SecurityException("The calling UID (" + callingUid + ")"
+                    + " does not match the target UID");
+        }
+
+        String allowedCallerPkg = mContext.getString(R.string.config_overrideComponentUiPackage);
+        if (TextUtils.isEmpty(allowedCallerPkg)) {
+            throw new SecurityException(
+                    "There is no package defined as allowed to change a component's label or icon");
+        }
+
+        int allowedCallerUid = getPackageUid(allowedCallerPkg, PackageManager.MATCH_SYSTEM_ONLY,
+                userId);
+        if (allowedCallerUid == -1 || !UserHandle.isSameApp(callingUid, allowedCallerUid)) {
+            throw new SecurityException("The calling UID (" + callingUid + ")"
+                    + " is not allowed to change a component's label or icon");
+        }
+
+        synchronized (mLock) {
+            AndroidPackage pkg = mPackages.get(componentPkgName);
+            PackageSetting pkgSetting = getPackageSetting(componentPkgName);
+            if (pkg == null || pkgSetting == null
+                    || (!pkg.isSystem() && !pkgSetting.getPkgState().isUpdatedSystemApp())) {
+                throw new SecurityException(
+                        "Changing the label is not allowed for " + componentName);
+            }
+
+            if (!pkgSetting.overrideNonLocalizedLabelAndIcon(componentName, nonLocalizedLabel,
+                    icon, userId)) {
+                // Nothing changed
+                return;
+            }
+        }
+
+        ArrayList<String> components = mPendingBroadcasts.get(userId, componentPkgName);
+        if (components == null) {
+            components = new ArrayList<>();
+            mPendingBroadcasts.put(userId, componentPkgName, components);
+        }
+
+        String className = componentName.getClassName();
+        if (!components.contains(className)) {
+            components.add(className);
+        }
+
+        if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
+            mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
+        }
+    }
+
+    @Override
     public void setComponentEnabledSetting(ComponentName componentName,
             int newState, int flags, int userId) {
         if (!mUserManager.exists(userId)) return;
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 9a8692d..432d7f3 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -26,6 +26,7 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionsState;
 import com.android.server.pm.pkg.PackageStateUnserialized;
@@ -43,6 +44,7 @@
 public class PackageSetting extends PackageSettingBase {
     int appId;
 
+    @Nullable
     public AndroidPackage pkg;
     /**
      * WARNING. The object reference is important. We perform integer equality and NOT
@@ -68,7 +70,8 @@
     @NonNull
     private PackageStateUnserialized pkgState = new PackageStateUnserialized();
 
-    PackageSetting(String name, String realName, File codePath, File resourcePath,
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public PackageSetting(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
             long pVersionCode, int pkgFlags, int privateFlags,
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 7cb3df5..00a5fe76 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -21,6 +21,9 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.PackageManager;
@@ -697,6 +700,26 @@
         return userState.harmfulAppWarning;
     }
 
+    /**
+     * @see PackageUserState#overrideLabelAndIcon(ComponentName, String, Integer)
+     *
+     * @param userId the specific user to change the label/icon for
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public boolean overrideNonLocalizedLabelAndIcon(@NonNull ComponentName component,
+            @Nullable String label, @Nullable Integer icon, @UserIdInt int userId) {
+        return modifyUserState(userId).overrideLabelAndIcon(component, label, icon);
+    }
+
+    /**
+     * @see PackageUserState#resetOverrideComponentLabelIcon()
+     *
+     * @param userId the specific user to reset
+     */
+    public void resetOverrideComponentLabelIcon(@UserIdInt int userId) {
+        modifyUserState(userId).resetOverrideComponentLabelIcon();
+    }
+
     protected PackageSettingBase updateFrom(PackageSettingBase other) {
         super.copyFrom(other);
         this.codePath = other.codePath;
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index ec9746d..3e2ab05 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -18,9 +18,11 @@
 
 import android.content.pm.ApplicationInfo;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.pm.permission.PermissionsState;
 
-abstract class SettingBase {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public abstract class SettingBase {
     int pkgFlags;
     int pkgPrivateFlags;
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f6ca87d..f6e4e1f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -91,6 +91,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
@@ -418,6 +419,21 @@
     /** Settings and other information about permissions */
     final PermissionSettings mPermissions;
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public Settings(Map<String, PackageSetting> pkgSettings) {
+        mLock = new Object();
+        mPackages.putAll(pkgSettings);
+        mSystemDir = null;
+        mPermissions = null;
+        mRuntimePermissionsPersistence = null;
+        mSettingsFilename = null;
+        mBackupSettingsFilename = null;
+        mPackageListFilename = null;
+        mStoppedPackagesFilename = null;
+        mBackupStoppedPackagesFilename = null;
+        mKernelMappingFilename = null;
+    }
+
     Settings(File dataDir, PermissionSettings permission,
             Object lock) {
         mLock = lock;
@@ -1275,7 +1291,6 @@
             return false;
         }
         ps.clearDomainVerificationStatusForUser(userId);
-        ps.setIntentFilterVerificationInfo(null);
         return true;
     }
 
@@ -4328,8 +4343,9 @@
         return userState.isMatch(componentInfo, flags);
     }
 
-    boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedMainComponent component, int flags,
-            int userId) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedMainComponent component,
+            int flags, int userId) {
         final PackageSetting ps = mPackages.get(component.getPackageName());
         if (ps == null) return false;
 
@@ -4651,6 +4667,10 @@
                 pw.print(prefix); pw.print("  privateFlags="); printFlags(pw,
                         privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println();
             }
+            if (pkg.hasPreserveLegacyExternalStorage()) {
+                pw.print(prefix); pw.print("  hasPreserveLegacyExternalStorage=true");
+                pw.println();
+            }
             pw.print(prefix); pw.print("  forceQueryable="); pw.print(ps.pkg.isForceQueryable());
             if (ps.forceQueryableOverride) {
                 pw.print(" (override=true)");
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 8768ab0..8d53d15 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2385,6 +2385,30 @@
         }
     }
 
+    public boolean isSharingShortcut(int callingUserId, @NonNull String callingPackage,
+            @NonNull String packageName, @NonNull String shortcutId, int userId,
+            @NonNull IntentFilter filter) {
+        verifyCaller(callingPackage, callingUserId);
+        enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
+                "isSharingShortcut");
+
+        synchronized (mLock) {
+            throwIfUserLockedL(userId);
+            throwIfUserLockedL(callingUserId);
+
+            final List<ShortcutManager.ShareShortcutInfo> matchedTargets =
+                    getPackageShortcutsLocked(packageName, userId)
+                            .getMatchingShareTargets(filter);
+            final int matchedSize = matchedTargets.size();
+            for (int i = 0; i < matchedSize; i++) {
+                if (matchedTargets.get(i).getShortcutInfo().getId().equals(shortcutId)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     @GuardedBy("mLock")
     private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName,
             @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) {
@@ -2969,6 +2993,18 @@
                     callingPackage, intentFilter, userId).getList();
         }
 
+        @Override
+        public boolean isSharingShortcut(int callingUserId, @NonNull String callingPackage,
+                @NonNull String packageName, @NonNull String shortcutId, int userId,
+                @NonNull IntentFilter filter) {
+            Preconditions.checkStringNotEmpty(callingPackage, "callingPackage");
+            Preconditions.checkStringNotEmpty(packageName, "packageName");
+            Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
+
+            return ShortcutService.this.isSharingShortcut(callingUserId, callingPackage,
+                    packageName, shortcutId, userId, filter);
+        }
+
         private void updateCachedShortcutsInternal(int launcherUserId,
                 @NonNull String callingPackage, @NonNull String packageName,
                 @NonNull List<String> shortcutIds, int userId, boolean doCache) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 60292b4..8f6bd02 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -35,11 +35,11 @@
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.content.rollback.IRollbackManager;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
@@ -68,8 +68,10 @@
 import com.android.internal.content.PackageHelper;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
+import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.rollback.WatchdogRollbackLogger;
 
 import java.io.File;
@@ -80,6 +82,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
+import java.util.function.Supplier;
 
 /**
  * This class handles staged install sessions, i.e. install sessions that require packages to
@@ -94,6 +97,7 @@
     private final PowerManager mPowerManager;
     private final Context mContext;
     private final PreRebootVerificationHandler mPreRebootVerificationHandler;
+    private final Supplier<PackageParser2> mPackageParserSupplier;
 
     @GuardedBy("mStagedSessions")
     private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
@@ -105,9 +109,11 @@
     private final List<String> mFailedPackageNames = new ArrayList<>();
     private String mNativeFailureReason;
 
-    StagingManager(PackageInstallerService pi, Context context) {
+    StagingManager(PackageInstallerService pi, Context context,
+            Supplier<PackageParser2> packageParserSupplier) {
         mPi = pi;
         mContext = context;
+        mPackageParserSupplier = packageParserSupplier;
 
         mApexManager = ApexManager.getInstance();
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -223,17 +229,21 @@
         final List<String> apexPackageNames = new ArrayList<>();
         for (ApexInfo apexInfo : apexInfoList.apexInfos) {
             final PackageInfo packageInfo;
-            int flags = PackageManager.GET_META_DATA;
-            PackageParser.Package pkg;
-            try {
+            final int flags = PackageManager.GET_META_DATA;
+            try (PackageParser2 packageParser = mPackageParserSupplier.get()) {
                 File apexFile = new File(apexInfo.modulePath);
-                PackageParser pp = new PackageParser();
-                pkg = pp.parsePackage(apexFile, flags, false);
+                final ParsedPackage parsedPackage = packageParser.parsePackage(
+                        apexFile, flags, false);
+                packageInfo = PackageInfoWithoutStateUtils.generate(parsedPackage, apexInfo, flags);
+                if (packageInfo == null) {
+                    throw new PackageManagerException(
+                            SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+                            "Unable to generate package info: " + apexInfo.modulePath);
+                }
             } catch (PackageParserException e) {
                 throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                         "Failed to parse APEX package " + apexInfo.modulePath, e);
             }
-            packageInfo = PackageParser.generatePackageInfo(pkg, apexInfo, flags);
             final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName,
                     ApexManager.MATCH_ACTIVE_PACKAGE);
             if (activePackage == null) {
@@ -254,8 +264,9 @@
     private int retrieveRollbackIdForCommitSession(int sessionId) throws PackageManagerException {
         RollbackManager rm = mContext.getSystemService(RollbackManager.class);
 
-        List<RollbackInfo> rollbacks = rm.getRecentlyCommittedRollbacks();
-        for (RollbackInfo rollback : rollbacks) {
+        final List<RollbackInfo> rollbacks = rm.getRecentlyCommittedRollbacks();
+        for (int i = 0, size = rollbacks.size(); i < size; i++) {
+            final RollbackInfo rollback = rollbacks.get(i);
             if (rollback.getCommittedSessionId() == sessionId) {
                 return rollback.getRollbackId();
             }
@@ -388,7 +399,8 @@
                     }
                 }
             }
-            for (PackageInstallerSession childSession : childrenSessions) {
+            for (int i = 0, size = childrenSessions.size(); i < size; i++) {
+                final PackageInstallerSession childSession = childrenSessions.get(i);
                 if (sessionContainsApex(childSession)) {
                     apexSessions.add(childSession);
                 }
@@ -402,15 +414,15 @@
         IRollbackManager rm = IRollbackManager.Stub.asInterface(
                 ServiceManager.getService(Context.ROLLBACK_SERVICE));
 
-        for (PackageInstallerSession apexSession : apexSessions) {
-            String packageName = apexSession.getPackageName();
+        for (int i = 0, sessionsSize = apexSessions.size(); i < sessionsSize; i++) {
+            final String packageName = apexSessions.get(i).getPackageName();
             // Perform any snapshots or restores for the APEX itself
             snapshotAndRestoreApexUserData(packageName, allUsers, rm);
 
             // Process the apks inside the APEX
-            List<String> apksInApex = mApexManager.getApksInApex(packageName);
-            for (String apk: apksInApex) {
-                snapshotAndRestoreApkInApexUserData(apk, allUsers, rm);
+            final List<String> apksInApex = mApexManager.getApksInApex(packageName);
+            for (int j = 0, apksSize = apksInApex.size(); j < apksSize; j++) {
+                snapshotAndRestoreApkInApexUserData(apksInApex.get(j), allUsers, rm);
             }
         }
     }
@@ -637,7 +649,8 @@
                     0 /* UserHandle.SYSTEM */);
             PackageInstallerSession apkSession = mPi.getSession(apkSessionId);
             apkSession.open();
-            for (String apkFilePath : apkFilePaths) {
+            for (int i = 0, size = apkFilePaths.size(); i < size; i++) {
+                final String apkFilePath = apkFilePaths.get(i);
                 File apkFile = new File(apkFilePath);
                 ParcelFileDescriptor pfd = ParcelFileDescriptor.open(apkFile,
                         ParcelFileDescriptor.MODE_READ_ONLY);
@@ -705,9 +718,9 @@
                         "Unable to prepare multi-package session for staged session");
             }
 
-            for (PackageInstallerSession sessionToClone : childSessions) {
-                PackageInstallerSession apkChildSession =
-                        createAndWriteApkSession(sessionToClone, preReboot);
+            for (int i = 0, size = childSessions.size(); i < size; i++) {
+                final PackageInstallerSession apkChildSession = createAndWriteApkSession(
+                        childSessions.get(i), preReboot);
                 try {
                     apkParentSession.addChildSessionId(apkChildSession.sessionId);
                 } catch (IllegalStateException e) {
@@ -1206,10 +1219,9 @@
             // multi-package sessions, find all the child sessions that contain an APEX.
             if (hasApex) {
                 try {
-                    final List<PackageInfo> apexPackages =
-                            submitSessionToApexService(session);
-                    for (PackageInfo apexPackage : apexPackages) {
-                        validateApexSignature(apexPackage);
+                    final List<PackageInfo> apexPackages = submitSessionToApexService(session);
+                    for (int i = 0, size = apexPackages.size(); i < size; i++) {
+                        validateApexSignature(apexPackages.get(i));
                     }
                 } catch (PackageManagerException e) {
                     session.setStagedSessionFailed(e.error, e.getMessage());
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d2443fa..323ffcf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1716,27 +1716,6 @@
         }
     }
 
-    private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId,
-            @Nullable Bundle restrictions,
-            @UserManagerInternal.OwnerType int restrictionOwnerType) {
-        final Bundle global = new Bundle();
-        final Bundle local = new Bundle();
-
-        // Sort restrictions into local and global ensuring they don't overlap.
-        UserRestrictionsUtils.sortToGlobalAndLocal(restrictions, restrictionOwnerType, global,
-                local);
-        boolean isDeviceOwner = restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
-
-        RestrictionsSet localRestrictionsSet;
-        if (UserRestrictionsUtils.isEmpty(local)) {
-            localRestrictionsSet = new RestrictionsSet();
-        } else {
-            localRestrictionsSet = new RestrictionsSet(originatingUserId, local);
-        }
-        setDevicePolicyUserRestrictionsInner(originatingUserId, global, localRestrictionsSet,
-                isDeviceOwner);
-    }
-
     /**
      * See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
      */
@@ -4754,10 +4733,10 @@
     private class LocalService extends UserManagerInternal {
         @Override
         public void setDevicePolicyUserRestrictions(@UserIdInt int originatingUserId,
-                @Nullable Bundle restrictions,
-                @OwnerType int restrictionOwnerType) {
+                @NonNull Bundle global, @NonNull RestrictionsSet local,
+                boolean isDeviceOwner) {
             UserManagerService.this.setDevicePolicyUserRestrictionsInner(originatingUserId,
-                    restrictions, restrictionOwnerType);
+                    global, local, isDeviceOwner);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index eec6e02..c0502b8 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -233,6 +233,13 @@
     );
 
     /**
+     * Special user restrictions that profile owner of an organization-owned managed profile can
+     * set on the parent profile instance to apply them on the personal profile.
+     */
+    private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS =
+            Sets.newArraySet();
+
+    /**
      * User restrictions that default to {@code true} for managed profile owners.
      *
      * NB: {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} is also set by default but it is
@@ -416,7 +423,8 @@
      * @return true if a restriction is settable by profile owner of an organization owned device.
      */
     public static boolean canProfileOwnerOfOrganizationOwnedDeviceChange(String restriction) {
-        return PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(restriction);
+        return PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(restriction)
+                || PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS.contains(restriction);
     }
 
     /**
@@ -427,31 +435,9 @@
     }
 
     /**
-     * Takes restrictions that can be set by device owner, and sort them into what should be applied
-     * globally and what should be applied only on the current user.
-     */
-    public static void sortToGlobalAndLocal(@Nullable Bundle in,
-            @UserManagerInternal.OwnerType int restrictionOwnerType, @NonNull Bundle global,
-            @NonNull Bundle local) {
-        if (in == null || in.size() == 0) {
-            return;
-        }
-        for (String key : in.keySet()) {
-            if (!in.getBoolean(key)) {
-                continue;
-            }
-            if (isGlobal(restrictionOwnerType, key)) {
-                global.putBoolean(key, true);
-            } else {
-                local.putBoolean(key, true);
-            }
-        }
-    }
-
-    /**
      * Whether given user restriction should be enforced globally.
      */
-    private static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType,
+    public static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType,
             String key) {
         return ((restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER) && (
                 PRIMARY_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)))
@@ -463,6 +449,14 @@
     }
 
     /**
+     * Whether given user restriction should be enforced locally.
+     */
+    public static boolean isLocal(@UserManagerInternal.OwnerType int restrictionOwnerType,
+            String key) {
+        return !isGlobal(restrictionOwnerType, key);
+    }
+
+    /**
      * @return true if two Bundles contain the same user restriction.
      * A null bundle and an empty bundle are considered to be equal.
      */
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 117cc5e..ebdf856 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -17,13 +17,17 @@
 package com.android.server.pm.dex;
 
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
 import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
 
+import static java.util.function.Function.identity;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackagePartitions;
 import android.os.FileUtils;
 import android.os.RemoteException;
 import android.os.SystemProperties;
@@ -45,6 +49,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -66,13 +71,12 @@
  */
 public class DexManager {
     private static final String TAG = "DexManager";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB = "pm.dexopt.priv-apps-oob";
     private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST =
             "pm.dexopt.priv-apps-oob-list";
 
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
     private final Context mContext;
 
     // Maps package name to code locations.
@@ -103,19 +107,6 @@
     private static int DEX_SEARCH_FOUND_SPLIT = 2;  // dex file is a split apk
     private static int DEX_SEARCH_FOUND_SECONDARY = 3;  // dex file is a secondary dex
 
-    /**
-     * We do not record packages that have no secondary dex files or that are not used by other
-     * apps. This is an optimization to reduce the amount of data that needs to be written to
-     * disk (apps will not usually be shared so this trims quite a bit the number we record).
-     *
-     * To make this behaviour transparent to the callers which need use information on packages,
-     * DexManager will return this DEFAULT instance from
-     * {@link DexManager#getPackageUseInfoOrDefault}. It has no data about secondary dex files and
-     * is marked as not being used by other apps. This reflects the intended behaviour when we don't
-     * find the package in the underlying data file.
-     */
-    private final static PackageUseInfo DEFAULT_USE_INFO = new PackageUseInfo();
-
     public DexManager(Context context, IPackageManager pms, PackageDexOptimizer pdo,
             Installer installer, Object installLock) {
         mContext = context;
@@ -190,10 +181,14 @@
                 boolean primaryOrSplit = searchResult.mOutcome == DEX_SEARCH_FOUND_PRIMARY ||
                         searchResult.mOutcome == DEX_SEARCH_FOUND_SPLIT;
 
-                if (primaryOrSplit && !isUsedByOtherApps) {
+                if (primaryOrSplit && !isUsedByOtherApps
+                        && !PLATFORM_PACKAGE_NAME.equals(searchResult.mOwningPackageName)) {
                     // If the dex file is the primary apk (or a split) and not isUsedByOtherApps
                     // do not record it. This case does not bring any new usable information
                     // and can be safely skipped.
+                    // Note this is just an optimization that makes things easier to read in the
+                    // package-dex-use file since we don't need to pollute it with redundant info.
+                    // However, we always record system server packages.
                     continue;
                 }
 
@@ -211,7 +206,7 @@
                     // async write to disk to make sure we don't loose the data in case of a reboot.
 
                     if (mPackageDexUsage.record(searchResult.mOwningPackageName,
-                            dexPath, loaderUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit,
+                            dexPath, loaderUserId, loaderIsa, primaryOrSplit,
                             loadingAppInfo.packageName, classLoaderContext)) {
                         mPackageDexUsage.maybeWriteAsync();
                     }
@@ -227,6 +222,23 @@
     }
 
     /**
+     * Check if the dexPath belongs to system server.
+     * System server can load code from different location, so we cast a wide-net here, and
+     * assume that if the paths is on any of the registered system partitions then it can be loaded
+     * by system server.
+     */
+    private boolean isSystemServerDexPathSupportedForOdex(String dexPath) {
+        ArrayList<PackagePartitions.SystemPartition> partitions =
+                PackagePartitions.getOrderedPartitions(identity());
+        for (int i = 0; i < partitions.size(); i++) {
+            if (partitions.get(i).containsPath(dexPath)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Read the dex usage from disk and populate the code cache locations.
      * @param existingPackages a map containing information about what packages
      *          are available to what users. Only packages in this list will be
@@ -364,7 +376,9 @@
 
         try {
             mPackageDexUsage.read();
-            mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
+            List<String> packagesToKeepDataAbout = new ArrayList<>();
+            mPackageDexUsage.syncData(
+                    packageToUsersMap, packageToCodePaths, packagesToKeepDataAbout);
         } catch (Exception e) {
             mPackageDexUsage.clear();
             Slog.w(TAG, "Exception while loading package dex usage. "
@@ -391,8 +405,17 @@
      * to access the package use.
      */
     public PackageUseInfo getPackageUseInfoOrDefault(String packageName) {
+        // We do not record packages that have no secondary dex files or that are not used by other
+        // apps. This is an optimization to reduce the amount of data that needs to be written to
+        // disk (apps will not usually be shared so this trims quite a bit the number we record).
+        //
+        // To make this behaviour transparent to the callers which need use information on packages,
+        // DexManager will return this DEFAULT instance from
+        // {@link DexManager#getPackageUseInfoOrDefault}. It has no data about secondary dex files
+        // and is marked as not being used by other apps. This reflects the intended behaviour when
+        // we don't find the package in the underlying data file.
         PackageUseInfo useInfo = mPackageDexUsage.getPackageUseInfo(packageName);
-        return useInfo == null ? DEFAULT_USE_INFO : useInfo;
+        return useInfo == null ? new PackageUseInfo(packageName) : useInfo;
     }
 
     /**
@@ -542,7 +565,7 @@
     // TODO(calin): questionable API in the presence of class loaders context. Needs amends as the
     // compilation happening here will use a pessimistic context.
     public RegisterDexModuleResult registerDexModule(ApplicationInfo info, String dexPath,
-            boolean isUsedByOtherApps, int userId) {
+            boolean isSharedModule, int userId) {
         // Find the owning package record.
         DexSearchResult searchResult = getDexPackage(info, dexPath, userId);
 
@@ -559,11 +582,14 @@
 
         // We found the package. Now record the usage for all declared ISAs.
         boolean update = false;
+        // If this is a shared module set the loading package to an arbitrary package name
+        // so that we can mark that module as usedByOthers.
+        String loadingPackage = isSharedModule ? ".shared.module" : searchResult.mOwningPackageName;
         for (String isa : getAppDexInstructionSets(info.primaryCpuAbi, info.secondaryCpuAbi)) {
             boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName,
-                    dexPath, userId, isa, isUsedByOtherApps, /*primaryOrSplit*/ false,
+                    dexPath, userId, isa, /*primaryOrSplit*/ false,
                     searchResult.mOwningPackageName,
-                    PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT);
+                    PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT);
             update |= newUpdate;
         }
         if (update) {
@@ -603,12 +629,6 @@
      */
     private DexSearchResult getDexPackage(
             ApplicationInfo loadingAppInfo, String dexPath, int userId) {
-        // Ignore framework code.
-        // TODO(calin): is there a better way to detect it?
-        if (dexPath.startsWith("/system/framework/")) {
-            return new DexSearchResult("framework", DEX_SEARCH_NOT_FOUND);
-        }
-
         // First, check if the package which loads the dex file actually owns it.
         // Most of the time this will be true and we can return early.
         PackageCodeLocations loadingPackageCodeLocations =
@@ -631,6 +651,28 @@
             }
         }
 
+        // We could not find the owning package amongst regular apps.
+        // If the loading package is system server, see if the dex file resides
+        // on any of the potentially system server owning location and if so,
+        // assuming system server ownership.
+        //
+        // Note: We don't have any way to detect which code paths are actually
+        // owned by system server. We can only assume that such paths are on
+        // system partitions.
+        if (PLATFORM_PACKAGE_NAME.equals(loadingAppInfo.packageName)) {
+            if (isSystemServerDexPathSupportedForOdex(dexPath)) {
+                // We record system server dex files as secondary dex files.
+                // The reason is that we only record the class loader context for secondary dex
+                // files and we expect that all primary apks are loaded with an empty class loader.
+                // System server dex files may be loaded in non-empty class loader so we need to
+                // keep track of their context.
+                return new DexSearchResult(PLATFORM_PACKAGE_NAME, DEX_SEARCH_FOUND_SECONDARY);
+            } else {
+                Slog.wtf(TAG, "System server loads dex files outside paths supported for odex: "
+                        + dexPath);
+            }
+        }
+
         if (DEBUG) {
             // TODO(calin): Consider checking for /data/data symlink.
             // /data/data/ symlinks /data/user/0/ and there's nothing stopping apps
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 08763e7..10760f5 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -39,10 +39,12 @@
 import java.io.Reader;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -51,25 +53,21 @@
  * Stat file which store usage information about dex files.
  */
 public class PackageDexUsage extends AbstractStatsBase<Void> {
-    private final static String TAG = "PackageDexUsage";
+    private static final String TAG = "PackageDexUsage";
 
-    // We support previous version to ensure that the usage list remains valid cross OTAs.
-    private final static int PACKAGE_DEX_USAGE_SUPPORTED_VERSION_1 = 1;
-    // Version 2 added:
-    //  - the list of packages that load the dex files
-    //  - class loader contexts for secondary dex files
-    //  - usage for all code paths (including splits)
-    private final static int PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2 = 2;
+    // We are currently at version 2.
+    // Version 1 was introduced in Nougat and Version 2 in Oreo.
+    // We dropped version 1 support in R since all devices should have updated
+    // already.
+    private static final int PACKAGE_DEX_USAGE_VERSION = 2;
 
-    private final static int PACKAGE_DEX_USAGE_VERSION = PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2;
-
-    private final static String PACKAGE_DEX_USAGE_VERSION_HEADER =
+    private static final String PACKAGE_DEX_USAGE_VERSION_HEADER =
             "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__";
 
-    private final static String SPLIT_CHAR = ",";
-    private final static String CODE_PATH_LINE_CHAR = "+";
-    private final static String DEX_LINE_CHAR = "#";
-    private final static String LOADING_PACKAGE_CHAR = "@";
+    private static final String SPLIT_CHAR = ",";
+    private static final String CODE_PATH_LINE_CHAR = "+";
+    private static final String DEX_LINE_CHAR = "#";
+    private static final String LOADING_PACKAGE_CHAR = "@";
 
     // One of the things we record about dex files is the class loader context that was used to
     // load them. That should be stable but if it changes we don't keep track of variable contexts.
@@ -77,10 +75,6 @@
     // skip optimizations on that dex files.
     /*package*/ static final String VARIABLE_CLASS_LOADER_CONTEXT =
             "=VariableClassLoaderContext=";
-    // The markers used for unknown class loader contexts. This can happen if the dex file was
-    // recorded in a previous version and we didn't have a chance to update its usage.
-    /*package*/ static final String UNKNOWN_CLASS_LOADER_CONTEXT =
-            "=UnknownClassLoaderContext=";
 
     // The marker used for unsupported class loader contexts (no longer written, may occur in old
     // files so discarded on read). Note: this matches
@@ -126,7 +120,7 @@
      *         has been seen before.
      */
     /* package */ boolean record(String owningPackageName, String dexPath, int ownerUserId,
-            String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit,
+            String loaderIsa, boolean primaryOrSplit,
             String loadingPackageName, String classLoaderContext) {
         if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
             throw new IllegalArgumentException("loaderIsa " + loaderIsa + " is unsupported");
@@ -135,20 +129,22 @@
             throw new IllegalArgumentException("Null classLoaderContext");
         }
         if (classLoaderContext.equals(UNSUPPORTED_CLASS_LOADER_CONTEXT)) {
+            Slog.e(TAG, "Unsupported context?");
             return false;
         }
 
+        boolean isUsedByOtherApps = !owningPackageName.equals(loadingPackageName);
+
         synchronized (mPackageUseInfoMap) {
             PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(owningPackageName);
             if (packageUseInfo == null) {
                 // This is the first time we see the package.
-                packageUseInfo = new PackageUseInfo();
+                packageUseInfo = new PackageUseInfo(owningPackageName);
                 if (primaryOrSplit) {
                     // If we have a primary or a split apk, set isUsedByOtherApps.
                     // We do not need to record the loaderIsa or the owner because we compile
                     // primaries for all users and all ISAs.
-                    packageUseInfo.mergeCodePathUsedByOtherApps(dexPath, isUsedByOtherApps,
-                            owningPackageName, loadingPackageName);
+                    packageUseInfo.mergePrimaryCodePaths(dexPath, loadingPackageName);
                 } else {
                     // For secondary dex files record the loaderISA and the owner. We'll need
                     // to know under which user to compile and for what ISA.
@@ -164,9 +160,8 @@
                 // We already have data on this package. Amend it.
                 if (primaryOrSplit) {
                     // We have a possible update on the primary apk usage. Merge
-                    // isUsedByOtherApps information and return if there was an update.
-                    return packageUseInfo.mergeCodePathUsedByOtherApps(
-                            dexPath, isUsedByOtherApps, owningPackageName, loadingPackageName);
+                    // dex path information and return if there was an update.
+                    return packageUseInfo.mergePrimaryCodePaths(dexPath, loadingPackageName);
                 } else {
                     DexUseInfo newData = new DexUseInfo(
                             isUsedByOtherApps, ownerUserId, classLoaderContext, loaderIsa);
@@ -281,7 +276,7 @@
 
             // Write the code paths used by other apps.
             for (Map.Entry<String, Set<String>> codeEntry :
-                    packageUseInfo.mCodePathsUsedByOtherApps.entrySet()) {
+                    packageUseInfo.mPrimaryCodePaths.entrySet()) {
                 String codePath = codeEntry.getKey();
                 Set<String> loadingPackages = codeEntry.getValue();
                 fpw.println(CODE_PATH_LINE_CHAR + codePath);
@@ -339,7 +334,9 @@
             version = Integer.parseInt(
                     versionLine.substring(PACKAGE_DEX_USAGE_VERSION_HEADER.length()));
             if (!isSupportedVersion(version)) {
-                throw new IllegalStateException("Unexpected version: " + version);
+                Slog.w(TAG, "Unexpected package-dex-use version: " + version
+                        + ". Not reading from it");
+                return;
             }
         }
 
@@ -377,9 +374,8 @@
                     throw new IllegalStateException("Invalid PackageDexUsage line: " + line);
                 }
 
-                // In version 2 we added the loading packages and class loader context.
-                Set<String> loadingPackages = maybeReadLoadingPackages(in, version);
-                String classLoaderContext = maybeReadClassLoaderContext(in, version);
+                Set<String> loadingPackages = readLoadingPackages(in, version);
+                String classLoaderContext = readClassLoaderContext(in, version);
 
                 if (UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(classLoaderContext)) {
                     // We used to record use of unsupported class loaders, but we no longer do.
@@ -410,34 +406,16 @@
                 }
                 currentPackageData.mDexUseInfoMap.put(dexPath, dexUseInfo);
             } else if (line.startsWith(CODE_PATH_LINE_CHAR)) {
-                // This is a code path used by other apps line.
-                if (version < PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
-                    throw new IllegalArgumentException("Unexpected code path line when parsing " +
-                            "PackageDexUseData: " + line);
-                }
-
                 // Expects 2 lines:
                 //    +code_paths
                 //    @loading_packages
                 String codePath = line.substring(CODE_PATH_LINE_CHAR.length());
-                Set<String> loadingPackages = maybeReadLoadingPackages(in, version);
-                currentPackageData.mCodePathsUsedByOtherApps.put(codePath, loadingPackages);
+                Set<String> loadingPackages = readLoadingPackages(in, version);
+                currentPackageData.mPrimaryCodePaths.put(codePath, loadingPackages);
             } else {
                 // This is a package line.
-                if (version >= PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
-                    currentPackage = line;
-                    currentPackageData = new PackageUseInfo();
-                } else {
-                    // Old version (<2)
-                    // We expect it to be: `packageName,isUsedByOtherApps`.
-                    String[] elems = line.split(SPLIT_CHAR);
-                    if (elems.length != 2) {
-                        throw new IllegalStateException("Invalid PackageDexUsage line: " + line);
-                    }
-                    currentPackage = elems[0];
-                    currentPackageData = new PackageUseInfo();
-                    currentPackageData.mUsedByOtherAppsBeforeUpgrade = readBoolean(elems[1]);
-                }
+                currentPackage = line;
+                currentPackageData = new PackageUseInfo(currentPackage);
                 data.put(currentPackage, currentPackageData);
             }
         }
@@ -449,46 +427,31 @@
     }
 
     /**
-     * Reads the class loader context encoding from the buffer {@code in} if
-     * {@code version} is at least {PACKAGE_DEX_USAGE_VERSION}.
+     * Reads the class loader context encoding from the buffer {@code in}.
      */
-    private String maybeReadClassLoaderContext(BufferedReader in, int version) throws IOException {
-        String context = null;
-        if (version >= PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
-            context = in.readLine();
-            if (context == null) {
-                throw new IllegalStateException("Could not find the classLoaderContext line.");
-            }
+    private String readClassLoaderContext(BufferedReader in, int version) throws IOException {
+        String context = in.readLine();
+        if (context == null) {
+            throw new IllegalStateException("Could not find the classLoaderContext line.");
         }
-        // The context might be empty if we didn't have the chance to update it after a version
-        // upgrade. In this case return the special marker so that we recognize this is an unknown
-        // context.
-        return context == null ? UNKNOWN_CLASS_LOADER_CONTEXT : context;
+        return context;
     }
 
     /**
-     * Reads the list of loading packages from the buffer {@code in} if
-     * {@code version} is at least {PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2}.
+     * Reads the list of loading packages from the buffer {@code in}.
      */
-    private Set<String> maybeReadLoadingPackages(BufferedReader in, int version)
+    private Set<String> readLoadingPackages(BufferedReader in, int version)
             throws IOException {
-        if (version >= PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2) {
-            String line = in.readLine();
-            if (line == null) {
-                throw new IllegalStateException("Could not find the loadingPackages line.");
-            }
-            // We expect that most of the times the list of loading packages will be empty.
-            if (line.length() == LOADING_PACKAGE_CHAR.length()) {
-                return Collections.emptySet();
-            } else {
-                Set<String> result = new HashSet<>();
-                Collections.addAll(result,
-                        line.substring(LOADING_PACKAGE_CHAR.length()).split(SPLIT_CHAR));
-                return result;
-            }
-        } else {
-            return Collections.emptySet();
+        String line = in.readLine();
+        if (line == null) {
+            throw new IllegalStateException("Could not find the loadingPackages line.");
         }
+        Set<String> result = new HashSet<>();
+        if (line.length() != LOADING_PACKAGE_CHAR.length()) {
+            Collections.addAll(result,
+                    line.substring(LOADING_PACKAGE_CHAR.length()).split(SPLIT_CHAR));
+        }
+        return result;
     }
 
     /**
@@ -501,21 +464,26 @@
     }
 
     private boolean isSupportedVersion(int version) {
-        return version == PACKAGE_DEX_USAGE_SUPPORTED_VERSION_1
-                || version == PACKAGE_DEX_USAGE_SUPPORTED_VERSION_2;
+        return version == PACKAGE_DEX_USAGE_VERSION;
     }
 
     /**
      * Syncs the existing data with the set of available packages by removing obsolete entries.
      */
     /*package*/ void syncData(Map<String, Set<Integer>> packageToUsersMap,
-            Map<String, Set<String>> packageToCodePaths) {
+            Map<String, Set<String>> packageToCodePaths,
+            List<String> packagesToKeepDataAbout) {
         synchronized (mPackageUseInfoMap) {
             Iterator<Map.Entry<String, PackageUseInfo>> pIt =
                     mPackageUseInfoMap.entrySet().iterator();
             while (pIt.hasNext()) {
                 Map.Entry<String, PackageUseInfo> pEntry = pIt.next();
                 String packageName = pEntry.getKey();
+                if (packagesToKeepDataAbout.contains(packageName)) {
+                    // This is a package for which we should keep the data even if it's not
+                    // in the list of user packages.
+                    continue;
+                }
                 PackageUseInfo packageUseInfo = pEntry.getValue();
                 Set<Integer> users = packageToUsersMap.get(packageName);
                 if (users == null) {
@@ -536,22 +504,31 @@
 
                     // Sync the code paths.
                     Set<String> codePaths = packageToCodePaths.get(packageName);
-                    Iterator<Map.Entry<String, Set<String>>> codeIt =
-                        packageUseInfo.mCodePathsUsedByOtherApps.entrySet().iterator();
-                    while (codeIt.hasNext()) {
-                        if (!codePaths.contains(codeIt.next().getKey())) {
-                            codeIt.remove();
+
+                    Iterator<Map.Entry<String, Set<String>>> recordedIt =
+                            packageUseInfo.mPrimaryCodePaths.entrySet().iterator();
+                    while (recordedIt.hasNext()) {
+                        Map.Entry<String, Set<String>> entry = recordedIt.next();
+                        String recordedCodePath = entry.getKey();
+                        if (!codePaths.contains(recordedCodePath)) {
+                            // Clean up a non existing code path.
+                            recordedIt.remove();
+                        } else {
+                            // Clean up a non existing loading package.
+                            Set<String> recordedLoadingPackages = entry.getValue();
+                            Iterator<String> recordedLoadingPackagesIt =
+                                    recordedLoadingPackages.iterator();
+                            while (recordedLoadingPackagesIt.hasNext()) {
+                                String recordedLoadingPackage = recordedLoadingPackagesIt.next();
+                                if (!packagesToKeepDataAbout.contains(recordedLoadingPackage)
+                                        && !packageToUsersMap.containsKey(recordedLoadingPackage)) {
+                                    recordedLoadingPackagesIt.remove();
+                                }
+                            }
                         }
                     }
 
-                    // In case the package was marked as used by other apps in a previous version
-                    // propagate the flag to all the code paths.
-                    // See mUsedByOtherAppsBeforeUpgrade docs on why it is important to do it.
-                    if (packageUseInfo.mUsedByOtherAppsBeforeUpgrade) {
-                        for (String codePath : codePaths) {
-                            packageUseInfo.mergeCodePathUsedByOtherApps(codePath, true, null, null);
-                        }
-                    } else if (!packageUseInfo.isAnyCodePathUsedByOtherApps()
+                    if (!packageUseInfo.isAnyCodePathUsedByOtherApps()
                         && packageUseInfo.mDexUseInfoMap.isEmpty()) {
                         // The package is not used by other apps and we removed all its dex files
                         // records. Remove the entire package record as well.
@@ -712,35 +689,26 @@
      * Stores data on how a package and its dex files are used.
      */
     public static class PackageUseInfo {
+        // The name of the package this info belongs to.
+        private final String mPackageName;
         // The app's code paths that are used by other apps.
         // The key is the code path and the value is the set of loading packages.
-        private final Map<String, Set<String>> mCodePathsUsedByOtherApps;
+        private final Map<String, Set<String>> mPrimaryCodePaths;
         // Map dex paths to their data (isUsedByOtherApps, owner id, loader isa).
         private final Map<String, DexUseInfo> mDexUseInfoMap;
 
-        // Keeps track of whether or not this package was used by other apps before
-        // we upgraded to VERSION 4 which records the info for each code path separately.
-        // This is unwanted complexity but without it we risk to profile guide compile
-        // something that supposed to be shared. For example:
-        //   1) we determine that chrome is used by another app
-        //   2) we take an OTA which upgrades the way we keep track of usage data
-        //   3) chrome doesn't get used until the background job executes
-        //   4) as part of the backgound job we now think that chrome is not used by others
-        //      and we speed-profile.
-        //   5) as a result the next time someone uses chrome it will extract from apk since
-        //      the compiled code will be private.
-        private boolean mUsedByOtherAppsBeforeUpgrade;
-
-        /*package*/ PackageUseInfo() {
-            mCodePathsUsedByOtherApps = new HashMap<>();
+        /*package*/ PackageUseInfo(String packageName) {
+            mPrimaryCodePaths = new HashMap<>();
             mDexUseInfoMap = new HashMap<>();
+            mPackageName = packageName;
         }
 
         // Creates a deep copy of the `other`.
         private PackageUseInfo(PackageUseInfo other) {
-            mCodePathsUsedByOtherApps = new HashMap<>();
-            for (Map.Entry<String, Set<String>> e : other.mCodePathsUsedByOtherApps.entrySet()) {
-                mCodePathsUsedByOtherApps.put(e.getKey(), new HashSet<>(e.getValue()));
+            mPackageName = other.mPackageName;
+            mPrimaryCodePaths = new HashMap<>();
+            for (Map.Entry<String, Set<String>> e : other.mPrimaryCodePaths.entrySet()) {
+                mPrimaryCodePaths.put(e.getKey(), new HashSet<>(e.getValue()));
             }
 
             mDexUseInfoMap = new HashMap<>();
@@ -749,28 +717,29 @@
             }
         }
 
-        private boolean mergeCodePathUsedByOtherApps(String codePath, boolean isUsedByOtherApps,
-                String owningPackageName, String loadingPackage) {
-            if (!isUsedByOtherApps) {
-                // Nothing to update if the the code path is not used by other apps.
-                return false;
-            }
-
-            boolean newCodePath = false;
-            Set<String> loadingPackages = mCodePathsUsedByOtherApps.get(codePath);
+        private boolean mergePrimaryCodePaths(String codePath, String loadingPackage) {
+            Set<String> loadingPackages = mPrimaryCodePaths.get(codePath);
             if (loadingPackages == null) {
                 loadingPackages = new HashSet<>();
-                mCodePathsUsedByOtherApps.put(codePath, loadingPackages);
-                newCodePath = true;
+                mPrimaryCodePaths.put(codePath, loadingPackages);
             }
-            boolean newLoadingPackage = loadingPackage != null
-                    && !loadingPackage.equals(owningPackageName)
-                    && loadingPackages.add(loadingPackage);
-            return newCodePath || newLoadingPackage;
+            return loadingPackages.add(loadingPackage);
         }
 
         public boolean isUsedByOtherApps(String codePath) {
-            return mCodePathsUsedByOtherApps.containsKey(codePath);
+            if (mPrimaryCodePaths.containsKey(codePath)) {
+                Set<String> loadingPackages = mPrimaryCodePaths.get(codePath);
+                if (loadingPackages.contains(mPackageName)) {
+                    // If the owning package is in the list then this code path
+                    // is used by others if there are other packages in the list.
+                    return loadingPackages.size() > 1;
+                } else {
+                    // The owning package is not in the loading packages. So if
+                    // the list is non-empty then the code path is used by others.
+                    return !loadingPackages.isEmpty();
+                }
+            }
+            return false;
         }
 
         public Map<String, DexUseInfo> getDexUseInfoMap() {
@@ -778,11 +747,11 @@
         }
 
         public Set<String> getLoadingPackages(String codePath) {
-            return mCodePathsUsedByOtherApps.getOrDefault(codePath, null);
+            return mPrimaryCodePaths.getOrDefault(codePath, null);
         }
 
         public boolean isAnyCodePathUsedByOtherApps() {
-            return !mCodePathsUsedByOtherApps.isEmpty();
+            return !mPrimaryCodePaths.isEmpty();
         }
 
         /**
@@ -790,16 +759,16 @@
          * Returns whether or not there was an update.
          */
         /*package*/ boolean clearCodePathUsedByOtherApps() {
-            // Update mUsedByOtherAppsBeforeUpgrade as well to be consistent with
-            // the new data. This is not saved to disk so we don't need to return it.
-            mUsedByOtherAppsBeforeUpgrade = true;
-
-            if (mCodePathsUsedByOtherApps.isEmpty()) {
-                return false;
-            } else {
-                mCodePathsUsedByOtherApps.clear();
-                return true;
+            boolean updated = false;
+            List<String> retainOnlyOwningPackage = new ArrayList<>(1);
+            retainOnlyOwningPackage.add(mPackageName);
+            for (Map.Entry<String, Set<String>> entry : mPrimaryCodePaths.entrySet()) {
+                // Remove or loading packages but the owning one.
+                if (entry.getValue().retainAll(retainOnlyOwningPackage)) {
+                    updated = true;
+                }
             }
+            return updated;
         }
     }
 
@@ -847,11 +816,9 @@
             boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages);
 
             String oldClassLoaderContext = mClassLoaderContext;
-            if (isUnknownOrUnsupportedContext(mClassLoaderContext)) {
-                // Can happen if we read a previous version.
+            if (isUnsupportedContext(mClassLoaderContext)) {
                 mClassLoaderContext = dexUseInfo.mClassLoaderContext;
-            } else if (!isUnknownOrUnsupportedContext(dexUseInfo.mClassLoaderContext)
-                        && !Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
+            } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
                 // We detected a context change.
                 mClassLoaderContext = VARIABLE_CLASS_LOADER_CONTEXT;
             }
@@ -862,11 +829,8 @@
                     || !Objects.equals(oldClassLoaderContext, mClassLoaderContext);
         }
 
-        private static boolean isUnknownOrUnsupportedContext(String context) {
-            // TODO: Merge UNKNOWN_CLASS_LOADER_CONTEXT & UNSUPPORTED_CLASS_LOADER_CONTEXT cases
-            // into UNSUPPORTED_CLASS_LOADER_CONTEXT.
-            return UNKNOWN_CLASS_LOADER_CONTEXT.equals(context)
-                    || UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context);
+        private static boolean isUnsupportedContext(String context) {
+            return UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context);
         }
 
         public boolean isUsedByOtherApps() {
@@ -887,10 +851,8 @@
 
         public String getClassLoaderContext() { return mClassLoaderContext; }
 
-        public boolean isUnknownClassLoaderContext() {
-            // The class loader context may be unknown if we loaded the data from a previous version
-            // which didn't save the context.
-            return isUnknownOrUnsupportedContext(mClassLoaderContext);
+        public boolean isUnsupportedClassLoaderContext() {
+            return isUnsupportedContext(mClassLoaderContext);
         }
 
         public boolean isVariableClassLoaderContext() {
diff --git a/services/core/java/com/android/server/pm/dex/SystemServerDexLoadReporter.java b/services/core/java/com/android/server/pm/dex/SystemServerDexLoadReporter.java
new file mode 100644
index 0000000..807c82d
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/SystemServerDexLoadReporter.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.pm.dex;
+
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+
+import android.content.pm.IPackageManager;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+
+import dalvik.system.BaseDexClassLoader;
+import dalvik.system.VMRuntime;
+
+import java.util.Map;
+
+/**
+ * Reports dex file use to the package manager on behalf of system server.
+ */
+public class SystemServerDexLoadReporter implements BaseDexClassLoader.Reporter {
+    private static final String TAG = "SystemServerDexLoadReporter";
+
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final IPackageManager mPackageManager;
+
+    private SystemServerDexLoadReporter(IPackageManager pm) {
+        mPackageManager = pm;
+    }
+
+    @Override
+    public void report(Map<String, String> classLoaderContextMap) {
+        if (DEBUG) {
+            Slog.i(TAG, "Reporting "  + classLoaderContextMap);
+        }
+        if (classLoaderContextMap.isEmpty()) {
+            Slog.wtf(TAG, "Bad call to DexLoadReporter: empty classLoaderContextMap");
+            return;
+        }
+
+        try {
+            mPackageManager.notifyDexLoad(
+                    PLATFORM_PACKAGE_NAME,
+                    classLoaderContextMap,
+                    VMRuntime.getRuntime().vmInstructionSet());
+        } catch (RemoteException ignored) {
+            // We're in system server, it can't happen.
+        }
+    }
+
+    /**
+     * Configures system server dex file reporting.
+     * <p>The method will install a reporter in the BaseDexClassLoader and also
+     * force the reporting of any dex files already loaded by the system server.
+     */
+    public static void configureSystemServerDexReporter(IPackageManager pm) {
+        Slog.i(TAG, "Configuring system server dex reporter");
+
+        SystemServerDexLoadReporter reporter = new SystemServerDexLoadReporter(pm);
+        BaseDexClassLoader.setReporter(reporter);
+        ClassLoader currrentClassLoader = reporter.getClass().getClassLoader();
+        if (currrentClassLoader instanceof BaseDexClassLoader) {
+            ((BaseDexClassLoader) currrentClassLoader).reportClassLoaderChain();
+        } else {
+            Slog.wtf(TAG, "System server class loader is not a BaseDexClassLoader. type="
+                    + currrentClassLoader.getClass().getName());
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 5a1e8e2..137e0aa 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -48,6 +48,7 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Pair;
 import android.util.Slog;
 
 import com.android.internal.util.ArrayUtils;
@@ -271,7 +272,7 @@
 
         ActivityInfo info =
                 PackageInfoWithoutStateUtils.generateActivityInfoUnchecked(a, applicationInfo);
-        assignSharedFieldsForComponentInfo(info, a, pkgSetting);
+        assignSharedFieldsForComponentInfo(info, a, pkgSetting, userId);
         return info;
     }
 
@@ -306,7 +307,7 @@
 
         ServiceInfo info =
                 PackageInfoWithoutStateUtils.generateServiceInfoUnchecked(s, applicationInfo);
-        assignSharedFieldsForComponentInfo(info, s, pkgSetting);
+        assignSharedFieldsForComponentInfo(info, s, pkgSetting, userId);
         return info;
     }
 
@@ -333,7 +334,7 @@
         }
         ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfoUnchecked(p, flags,
                 applicationInfo);
-        assignSharedFieldsForComponentInfo(info, p, pkgSetting);
+        assignSharedFieldsForComponentInfo(info, p, pkgSetting, userId);
         return info;
     }
 
@@ -358,7 +359,7 @@
         info.nativeLibraryDir = pkg.getNativeLibraryDir();
         info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
 
-        assignStateFieldsForPackageItemInfo(info, i, pkgSetting);
+        assignStateFieldsForPackageItemInfo(info, i, pkgSetting, userId);
 
         return info;
     }
@@ -426,8 +427,9 @@
     }
 
     private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo,
-            @NonNull ParsedMainComponent mainComponent, @Nullable PackageSetting pkgSetting) {
-        assignStateFieldsForPackageItemInfo(componentInfo, mainComponent, pkgSetting);
+            @NonNull ParsedMainComponent mainComponent, @Nullable PackageSetting pkgSetting,
+            int userId) {
+        assignStateFieldsForPackageItemInfo(componentInfo, mainComponent, pkgSetting, userId);
         componentInfo.descriptionRes = mainComponent.getDescriptionRes();
         componentInfo.directBootAware = mainComponent.isDirectBootAware();
         componentInfo.enabled = mainComponent.isEnabled();
@@ -436,8 +438,12 @@
 
     private static void assignStateFieldsForPackageItemInfo(
             @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component,
-            @Nullable PackageSetting pkgSetting) {
-        // TODO(b/135203078): Add setting related state
+            @Nullable PackageSetting pkgSetting, int userId) {
+        Pair<CharSequence, Integer> labelAndIcon =
+                ParsedComponentStateUtils.getNonLocalizedLabelAndIcon(component, pkgSetting,
+                        userId);
+        packageItemInfo.nonLocalizedLabel = labelAndIcon.first;
+        packageItemInfo.icon = labelAndIcon.second;
     }
 
     @CheckResult
diff --git a/services/core/java/com/android/server/pm/parsing/ParsedComponentStateUtils.java b/services/core/java/com/android/server/pm/parsing/ParsedComponentStateUtils.java
new file mode 100644
index 0000000..54466ac
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/ParsedComponentStateUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.util.Pair;
+
+import com.android.server.pm.PackageSetting;
+
+/**
+ * For exposing internal fields to the rest of the server, enforcing that any overridden state from
+ * a {@link com.android.server.pm.PackageSetting} is applied.
+ *
+ * TODO(chiuwinson): The fields on ParsedComponent are not actually hidden. Will need to find a
+ *   way to enforce the mechanism now that they exist in core instead of server. Can't rely on
+ *   package-private.
+ *
+ * @hide
+ */
+public class ParsedComponentStateUtils {
+
+    @NonNull
+    public static Pair<CharSequence, Integer> getNonLocalizedLabelAndIcon(ParsedComponent component,
+            @Nullable PackageSetting pkgSetting, int userId) {
+        CharSequence label = component.getNonLocalizedLabel();
+        int icon = component.getIcon();
+
+        Pair<String, Integer> overrideLabelIcon = pkgSetting == null ? null :
+                pkgSetting.readUserState(userId)
+                        .getOverrideLabelIconForComponent(component.getComponentName());
+        if (overrideLabelIcon != null) {
+            if (overrideLabelIcon.first != null) {
+                label = overrideLabelIcon.first;
+            }
+            if (overrideLabelIcon.second != null) {
+                icon = overrideLabelIcon.second;
+            }
+        }
+
+        return Pair.create(label, icon);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdater.java b/services/core/java/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdater.java
new file mode 100644
index 0000000..ee3c406
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdater.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.pm.parsing.library;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+/**
+ * Updates a package to remove dependency on com.google.android.maps library.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class ComGoogleAndroidMapsUpdater extends PackageSharedLibraryUpdater {
+
+    private static final String LIBRARY_NAME = "com.google.android.maps";
+
+    @Override
+    public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
+        parsedPackage.removeUsesLibrary(LIBRARY_NAME);
+        parsedPackage.removeUsesOptionalLibrary(LIBRARY_NAME);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
index 1d018c4..1405a7d 100644
--- a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
+++ b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
@@ -45,6 +45,9 @@
     static {
         final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>();
 
+        // Remove com.google.android.maps library.
+        packageUpdaters.add(new ComGoogleAndroidMapsUpdater());
+
         // Automatically add the org.apache.http.legacy library to the app classpath if the app
         // targets < P.
         packageUpdaters.add(new OrgApacheHttpLegacyUpdater());
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index a726d39..e3faffa 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -882,7 +882,7 @@
 
     public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default browser for user:" + userId);
-        grantPermissionsToSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
+        grantPermissionsToSystemPackage(packageName, userId, FOREGROUND_LOCATION_PERMISSIONS);
     }
 
     private String getDefaultSystemHandlerActivityPackage(String intentAction, int userId) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 7eb3f01..d89605a 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -542,12 +542,6 @@
         void unregisterPointerEventListener(PointerEventListener listener, int displayId);
 
         /**
-         * Retrieves the {@param outBounds} from the stack matching the {@param windowingMode} and
-         * {@param activityType}.
-         */
-        void getStackBounds(int windowingMode, int activityType, Rect outBounds);
-
-        /**
          * @return The currently active input method window.
          */
         WindowState getInputMethodWindowLw();
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b41bc5c..cd6c5bf 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -513,10 +513,7 @@
 
     // The screen brightness setting override from the window manager
     // to allow the current foreground activity to override the brightness.
-    // Use -1 to disable.
-    private int mScreenBrightnessOverrideFromWindowManager = -1;
-
-    private float mScreenBrightnessOverrideFromWindowManagerFloat =
+    private float mScreenBrightnessOverrideFromWindowManager =
             PowerManager.BRIGHTNESS_INVALID_FLOAT;
 
     // The window manager has determined the user to be inactive via other means.
@@ -2846,7 +2843,7 @@
                 screenBrightnessOverride = mScreenBrightnessSettingDefault;
             } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                 autoBrightness = false;
-                screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManagerFloat;
+                screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
             } else {
                 autoBrightness = (mScreenBrightnessModeSetting ==
                         Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
@@ -2927,8 +2924,8 @@
         return !mIsVrModeEnabled && mScreenBrightnessBoostInProgress;
     }
 
-    private static boolean isValidBrightness(int value) {
-        return value >= 0 && value <= 255;
+    private static boolean isValidBrightness(float value) {
+        return value >= PowerManager.BRIGHTNESS_MIN && value <= PowerManager.BRIGHTNESS_MAX;
     }
 
     @VisibleForTesting
@@ -3583,13 +3580,11 @@
         }
     }
 
-    // TODO(brightnessfloat): change to float
-    private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
+    private void setScreenBrightnessOverrideFromWindowManagerInternal(float brightness) {
         synchronized (mLock) {
-            if (mScreenBrightnessOverrideFromWindowManager != brightness) {
+            if (!BrightnessSynchronizer.floatEquals(mScreenBrightnessOverrideFromWindowManager,
+                    brightness)) {
                 mScreenBrightnessOverrideFromWindowManager = brightness;
-                mScreenBrightnessOverrideFromWindowManagerFloat =
-                        BrightnessSynchronizer.brightnessIntToFloat(mContext, brightness);
                 mDirty |= DIRTY_SETTINGS;
                 updatePowerStateLocked();
             }
@@ -3890,8 +3885,8 @@
                     + isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")");
             pw.println("  mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting);
             pw.println("  mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
-            pw.println("  mScreenBrightnessOverrideFromWindowManagerFloat="
-                    + mScreenBrightnessOverrideFromWindowManagerFloat);
+            pw.println("  mScreenBrightnessOverrideFromWindowManager="
+                    + mScreenBrightnessOverrideFromWindowManager);
             pw.println("  mUserActivityTimeoutOverrideFromWindowManager="
                     + mUserActivityTimeoutOverrideFromWindowManager);
             pw.println("  mUserInactiveOverrideFromWindowManager="
@@ -4231,7 +4226,7 @@
             proto.write(
                     PowerServiceSettingsAndConfigurationDumpProto
                             .SCREEN_BRIGHTNESS_OVERRIDE_FROM_WINDOW_MANAGER,
-                    mScreenBrightnessOverrideFromWindowManagerFloat);
+                    mScreenBrightnessOverrideFromWindowManager);
             proto.write(
                     PowerServiceSettingsAndConfigurationDumpProto
                             .USER_ACTIVITY_TIMEOUT_OVERRIDE_FROM_WINDOW_MANAGER_MS,
@@ -5430,10 +5425,10 @@
     @VisibleForTesting
     final class LocalService extends PowerManagerInternal {
         @Override
-        public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
-            if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
-                    || screenBrightness > PowerManager.BRIGHTNESS_ON) {
-                screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+        public void setScreenBrightnessOverrideFromWindowManager(float screenBrightness) {
+            if (screenBrightness < PowerManager.BRIGHTNESS_MIN
+                    || screenBrightness > PowerManager.BRIGHTNESS_MAX) {
+                screenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
             }
             setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
         }
diff --git a/services/core/java/com/android/server/power/TEST_MAPPING b/services/core/java/com/android/server/power/TEST_MAPPING
index 74958b6..cf1bfc3 100644
--- a/services/core/java/com/android/server/power/TEST_MAPPING
+++ b/services/core/java/com/android/server/power/TEST_MAPPING
@@ -21,10 +21,7 @@
       "options": [
         {"include-filter": "com.android.server.power"},
         {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
-        {"exclude-annotation": "androidx.test.filters.FlakyTest"},
-        {
-          "exclude-filter": "com.android.server.power.PowerManagerServiceTest#testWakefulnessAwake_ShouldWakeUpWhenPluggedIn"
-        }
+        {"exclude-annotation": "androidx.test.filters.FlakyTest"}
       ]
     }
   ],
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 5f871ad4..83e99b0 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -505,6 +505,11 @@
             rollbackIds[i] = mRollbacks.get(i).info.getRollbackId();
         }
         ApexManager.getInstance().destroyCeSnapshotsNotSpecified(userId, rollbackIds);
+        try {
+            mInstaller.destroyCeSnapshotsNotSpecified(userId, rollbackIds);
+        } catch (Installer.InstallerException ie) {
+            Slog.e(TAG, "Failed to delete snapshots for user: " + userId, ie);
+        }
     }
 
     @WorkerThread
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 841aca5..225bd82 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Environment;
 import android.os.IBinder;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -37,6 +38,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -131,12 +133,17 @@
         // duplicate the same loading logic here.
 
         // Load certificates trusted by the device manufacturer.
-        loadCertificatesFromDirectory("/product/etc/security/fsverity");
+        // NB: Directories need to be synced with system/security/fsverity_init/fsverity_init.cpp.
+        final String relativeDir = "etc/security/fsverity";
+        loadCertificatesFromDirectory(Environment.getRootDirectory().toPath()
+                .resolve(relativeDir));
+        loadCertificatesFromDirectory(Environment.getProductDirectory().toPath()
+                .resolve(relativeDir));
     }
 
-    private void loadCertificatesFromDirectory(String path) {
+    private void loadCertificatesFromDirectory(Path path) {
         try {
-            File[] files = new File(path).listFiles();
+            File[] files = path.toFile().listFiles();
             if (files == null) {
                 return;
             }
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java b/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
new file mode 100644
index 0000000..7977e93
--- /dev/null
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.soundtrigger_middleware;
+
+import android.media.ICaptureStateListener;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.util.concurrent.Semaphore;
+import java.util.function.Consumer;
+
+/**
+ * This is a never-give-up listener for sound trigger external capture state notifications, as
+ * published by the audio policy service.
+ *
+ * This class will constantly try to connect to the service over a background thread and tolerate
+ * its death. The client will be notified by a single provided function that is called in a
+ * synchronized manner.
+ * For simplicity, there is currently no way to stop the tracker. This is possible to add if the
+ * need ever arises.
+ */
+class ExternalCaptureStateTracker {
+    private static final String TAG = "CaptureStateTracker";
+    /** Our client's listener. */
+    private final Consumer<Boolean> mListener;
+    /** This semaphore will get a permit every time we need to reconnect. */
+    private final Semaphore mNeedToConnect = new Semaphore(1);
+
+    /**
+     * Constructor. Will start a background thread to do the work.
+     *
+     * @param listener A client provided listener that will be called on state
+     *                 changes. May be
+     *                 called multiple consecutive times with the same value. Never
+     *                 called
+     *                 concurrently.
+     */
+    ExternalCaptureStateTracker(Consumer<Boolean> listener) {
+        mListener = listener;
+        new Thread(this::run).start();
+    }
+
+    /**
+     * Routine for the background thread. Keeps trying to reconnect.
+     */
+    private void run() {
+        while (true) {
+            mNeedToConnect.acquireUninterruptibly();
+            connect();
+        }
+    }
+
+    /**
+     * Connect to the service, install listener and death notifier.
+     */
+    private native void connect();
+
+    /**
+     * Called by native code to invoke the client listener.
+     *
+     * @param active true when external capture is active.
+     */
+    private void setCaptureState(boolean active) {
+        mListener.accept(active);
+    }
+
+    /**
+     * Called by native code when the remote service died.
+     */
+    private void binderDied() {
+        Log.w(TAG, "Audio policy service died");
+        mNeedToConnect.release();
+    }
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java b/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
new file mode 100644
index 0000000..5def762
--- /dev/null
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.soundtrigger_middleware;
+
+import android.media.ICaptureStateListener;
+import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
+
+/**
+ * This interface unifies ISoundTriggerMiddlewareService with ICaptureStateListener.
+ */
+public interface ISoundTriggerMiddlewareInternal extends ISoundTriggerMiddlewareService,
+        ICaptureStateListener {
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java
index 9f4b09a..d76b1bf 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java
@@ -50,7 +50,7 @@
  *
  * @hide
  */
-public class SoundTriggerMiddlewareImpl implements ISoundTriggerMiddlewareService {
+public class SoundTriggerMiddlewareImpl implements ISoundTriggerMiddlewareInternal {
     static private final String TAG = "SoundTriggerMiddlewareImpl";
     private final SoundTriggerModule[] mModules;
 
@@ -124,7 +124,7 @@
     }
 
     @Override
-    public void setExternalCaptureState(boolean active) {
+    public void setCaptureState(boolean active) {
         for (SoundTriggerModule module : mModules) {
             module.setExternalCaptureState(active);
         }
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
index fa78cb0..04ba6bf 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
@@ -62,11 +62,11 @@
  * String, Object, Object[])}, {@link #logVoidReturnWithObject(Object, String, Object[])} and {@link
  * #logExceptionWithObject(Object, String, Exception, Object[])}.
  */
-public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareService, Dumpable {
+public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInternal, Dumpable {
     private static final String TAG = "SoundTriggerMiddlewareLogging";
-    private final @NonNull ISoundTriggerMiddlewareService mDelegate;
+    private final @NonNull ISoundTriggerMiddlewareInternal mDelegate;
 
-    public SoundTriggerMiddlewareLogging(@NonNull ISoundTriggerMiddlewareService delegate) {
+    public SoundTriggerMiddlewareLogging(@NonNull ISoundTriggerMiddlewareInternal delegate) {
         mDelegate = delegate;
     }
 
@@ -96,12 +96,12 @@
     }
 
     @Override
-    public void setExternalCaptureState(boolean active) throws RemoteException {
+    public void setCaptureState(boolean active) throws RemoteException {
         try {
-            mDelegate.setExternalCaptureState(active);
-            logVoidReturn("setExternalCaptureState", active);
+            mDelegate.setCaptureState(active);
+            logVoidReturn("setCaptureState", active);
         } catch (Exception e) {
-            logException("setExternalCaptureState", e, active);
+            logException("setCaptureState", e, active);
             throw e;
         }
     }
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index 0d8fc76..929d92f 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -63,14 +63,21 @@
     static private final String TAG = "SoundTriggerMiddlewareService";
 
     @NonNull
-    private final ISoundTriggerMiddlewareService mDelegate;
+    private final ISoundTriggerMiddlewareInternal mDelegate;
 
     /**
      * Constructor for internal use only. Could be exposed for testing purposes in the future.
      * Users should access this class via {@link Lifecycle}.
      */
-    private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareService delegate) {
+    private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareInternal delegate) {
         mDelegate = Objects.requireNonNull(delegate);
+        new ExternalCaptureStateTracker(active -> {
+            try {
+                mDelegate.setCaptureState(active);
+            } catch (RemoteException e) {
+                throw e.rethrowAsRuntimeException();
+            }
+        });
     }
 
     @Override
@@ -86,11 +93,6 @@
         return new ModuleService(mDelegate.attach(handle, callback));
     }
 
-    @Override
-    public void setExternalCaptureState(boolean active) throws RemoteException {
-        mDelegate.setExternalCaptureState(active);
-    }
-
     @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         if (mDelegate instanceof Dumpable) {
             ((Dumpable) mDelegate).dump(fout);
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 06f2d65..da1b7f3 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -105,7 +105,7 @@
  *
  * {@hide}
  */
-public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddlewareService, Dumpable {
+public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddlewareInternal, Dumpable {
     private static final String TAG = "SoundTriggerMiddlewareValidation";
 
     private enum ModuleState {
@@ -114,12 +114,14 @@
         DEAD
     };
 
-    private final @NonNull ISoundTriggerMiddlewareService mDelegate;
+    private Boolean mCaptureState;
+
+    private final @NonNull ISoundTriggerMiddlewareInternal mDelegate;
     private final @NonNull Context mContext;
     private Map<Integer, Set<ModuleService>> mModules;
 
     public SoundTriggerMiddlewareValidation(
-            @NonNull ISoundTriggerMiddlewareService delegate, @NonNull Context context) {
+            @NonNull ISoundTriggerMiddlewareInternal delegate, @NonNull Context context) {
         mDelegate = delegate;
         mContext = context;
     }
@@ -213,23 +215,22 @@
     }
 
     @Override
-    public void setExternalCaptureState(boolean active) {
-        // Permission check.
-        checkPreemptPermissions();
-        // Input validation (always valid).
-
-        // State validation (always valid).
-
+    public void setCaptureState(boolean active) {
+        // This is an internal call. No permissions needed.
+        //
         // Normally, we would acquire a lock here. However, we do not access any state here so it
         // is safe to not lock. This call is typically done from a different context than all the
         // other calls and may result in a deadlock if we lock here (between the audio server and
         // the system server).
-
-        // From here on, every exception isn't client's fault.
         try {
-            mDelegate.setExternalCaptureState(active);
+            mDelegate.setCaptureState(active);
         } catch (Exception e) {
             throw handleException(e);
+        } finally {
+            // It is safe to lock here - local operation.
+            synchronized (this) {
+                mCaptureState = active;
+            }
         }
     }
 
@@ -252,16 +253,6 @@
     /**
      * Throws a {@link SecurityException} if caller permanently doesn't have the given permission,
      * or a {@link ServiceSpecificException} with a {@link Status#TEMPORARY_PERMISSION_DENIED} if
-     * caller temporarily doesn't have the right permissions to preempt active sound trigger
-     * sessions.
-     */
-    void checkPreemptPermissions() {
-        enforcePermission(Manifest.permission.PREEMPT_SOUND_TRIGGER);
-    }
-
-    /**
-     * Throws a {@link SecurityException} if caller permanently doesn't have the given permission,
-     * or a {@link ServiceSpecificException} with a {@link Status#TEMPORARY_PERMISSION_DENIED} if
      * caller temporarily doesn't have the given permission.
      *
      * @param permission The permission to check.
@@ -290,8 +281,11 @@
                 "This implementation is not inteded to be used directly with Binder.");
     }
 
-    @Override public void dump(PrintWriter pw) {
+    @Override
+    public void dump(PrintWriter pw) {
         synchronized (this) {
+            pw.printf("Capture state is %s\n", mCaptureState == null ? "uninitialized"
+                    : (mCaptureState ? "active" : "inactive"));
             if (mModules != null) {
                 for (int handle : mModules.keySet()) {
                     pw.println("=========================================");
@@ -806,4 +800,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 155b2e0..e9da2c4 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -29,6 +29,7 @@
 import static android.util.MathUtils.abs;
 import static android.util.MathUtils.constrain;
 
+import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
 import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
@@ -750,6 +751,7 @@
             StatsEvent.Builder e = StatsEvent.newBuilder();
             e.setAtomId(atomTag);
             e.writeInt(entry.uid);
+            e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
             if (withFgbg) {
                 e.writeInt(entry.set);
             }
@@ -920,6 +922,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(traffic.getUid())
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeLong(traffic.getRxBytes())
                     .writeLong(traffic.getTxBytes())
                     .build();
@@ -1006,6 +1009,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeLong(userTimeUs)
                     .writeLong(systemTimeUs)
                     .build();
@@ -1036,6 +1040,7 @@
                     StatsEvent e = StatsEvent.newBuilder()
                             .setAtomId(atomTag)
                             .writeInt(uid)
+                            .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                             .writeInt(freqIndex)
                             .writeLong(cpuFreqTimeMs[freqIndex])
                             .build();
@@ -1066,6 +1071,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeLong(cpuActiveTimesMs)
                     .build();
             pulledData.add(e);
@@ -1094,6 +1100,7 @@
                 StatsEvent e = StatsEvent.newBuilder()
                         .setAtomId(atomTag)
                         .writeInt(uid)
+                        .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                         .writeInt(i)
                         .writeLong(cpuClusterTimesMs[i])
                         .build();
@@ -1289,6 +1296,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(processMemoryState.uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(processMemoryState.processName)
                     .writeInt(processMemoryState.oomScore)
                     .writeLong(memoryStat.pgfault)
@@ -1331,6 +1339,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(managedProcess.uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(managedProcess.processName)
                     // RSS high-water mark in bytes.
                     .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
@@ -1350,6 +1359,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(snapshot.uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(processCmdlines.valueAt(i))
                     // RSS high-water mark in bytes.
                     .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
@@ -1384,6 +1394,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(managedProcess.uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(managedProcess.processName)
                     .writeInt(managedProcess.pid)
                     .writeInt(managedProcess.oomScore)
@@ -1409,6 +1420,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(snapshot.uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(processCmdlines.valueAt(i))
                     .writeInt(pid)
                     .writeInt(-1001)  // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.
@@ -1481,6 +1493,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(getUidForPid(allocations.pid))
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(readCmdlineFromProcfs(allocations.pid))
                     .writeInt((int) (allocations.totalSizeInBytes / 1024))
                     .writeInt(allocations.count)
@@ -1593,6 +1606,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(callStat.workSourceUid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(callStat.className)
                     .writeString(callStat.methodName)
                     .writeLong(callStat.callCount)
@@ -1669,6 +1683,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(entry.workSourceUid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeString(entry.handlerClassName)
                     .writeString(entry.threadName)
                     .writeString(entry.messageName)
@@ -2112,6 +2127,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeLong(fgCharsRead)
                     .writeLong(fgCharsWrite)
                     .writeLong(fgBytesRead)
@@ -2177,6 +2193,7 @@
                 StatsEvent e = StatsEvent.newBuilder()
                         .setAtomId(atomTag)
                         .writeInt(st.uid)
+                        .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                         .writeString(st.name)
                         .writeLong(st.base_utime)
                         .writeLong(st.base_stime)
@@ -2235,6 +2252,7 @@
                 StatsEvent.Builder e = StatsEvent.newBuilder();
                 e.setAtomId(atomTag);
                 e.writeInt(processCpuUsage.uid);
+                e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                 e.writeInt(processCpuUsage.processId);
                 e.writeInt(threadCpuUsage.threadId);
                 e.writeString(processCpuUsage.processName);
@@ -2326,6 +2344,7 @@
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
                     .writeInt(bs.uidObj.getUid())
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                     .writeLong(milliAmpHrsToNanoAmpSecs(bs.totalPowerMah))
                     .build();
             pulledData.add(e);
@@ -2530,6 +2549,7 @@
                         StatsEvent e = StatsEvent.newBuilder()
                                 .setAtomId(atomTag)
                                 .writeInt(pkg.applicationInfo.uid)
+                                .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
                                 .writeString(holderName)
                                 .writeString(roleName)
                                 .build();
@@ -2613,6 +2633,7 @@
                         e.setAtomId(atomTag);
                         e.writeString(permName);
                         e.writeInt(pkg.applicationInfo.uid);
+                        e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                         if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE) {
                             e.writeString("");
                         }
@@ -2967,6 +2988,7 @@
         StatsEvent.Builder e = StatsEvent.newBuilder();
         e.setAtomId(atomTag);
         e.writeInt(uid);
+        e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
         e.writeString(packageName);
         if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
             e.writeString(attributionTag);
@@ -3015,8 +3037,9 @@
             StatsEvent.Builder e = StatsEvent.newBuilder();
             e.setAtomId(atomTag);
             e.writeInt(message.getUid());
+            e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
             e.writeString(message.getPackageName());
-            e.writeString(message.getOp());
+            e.writeString("");
             if (message.getAttributionTag() == null) {
                 e.writeString("");
             } else {
@@ -3024,6 +3047,7 @@
             }
             e.writeString(message.getMessage());
             e.writeInt(message.getSamplingStrategy());
+            e.writeInt(AppOpsManager.strOpToOp(message.getOp()));
 
             pulledData.add(e.build());
         } catch (Throwable t) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index d88dccb..26497d8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -131,7 +131,7 @@
      * @see com.android.internal.statusbar.IStatusBar#showToast(String, IBinder, CharSequence,
      * IBinder, int, ITransientNotificationCallback)
      */
-    void showToast(String packageName, IBinder token, CharSequence text,
+    void showToast(int uid, String packageName, IBinder token, CharSequence text,
             IBinder windowToken, int duration,
             @Nullable ITransientNotificationCallback textCallback);
 
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 78ef68c..d7a0c987 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -502,12 +502,12 @@
         }
 
         @Override
-        public void showToast(String packageName, IBinder token, CharSequence text,
+        public void showToast(int uid, String packageName, IBinder token, CharSequence text,
                 IBinder windowToken, int duration,
                 @Nullable ITransientNotificationCallback callback) {
             if (mBar != null) {
                 try {
-                    mBar.showToast(packageName, token, text, windowToken, duration, callback);
+                    mBar.showToast(uid, packageName, token, text, windowToken, duration, callback);
                 } catch (RemoteException ex) { }
             }
         }
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 7786833..c2ecd41 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -176,8 +176,12 @@
     private void setUpAdbFiles(PersistentData persistentData) {
         AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
 
-        writeBytesToFile(persistentData.mAdbKeys, adbManager.getAdbKeysFile().toPath());
-        writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());
+        if (adbManager.getAdbKeysFile() != null) {
+            writeBytesToFile(persistentData.mAdbKeys, adbManager.getAdbKeysFile().toPath());
+        }
+        if (adbManager.getAdbTempKeysFile() != null) {
+            writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());
+        }
     }
 
     private void configureUser() {
@@ -310,12 +314,6 @@
             AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
             File adbKeys = adbManager.getAdbKeysFile();
             File adbTempKeys = adbManager.getAdbTempKeysFile();
-            if (adbKeys == null && adbTempKeys == null) {
-                // This should only be accessible on eng builds that haven't yet set up ADB keys
-                getErrPrintWriter()
-                    .println("No ADB keys stored; not enabling test harness mode");
-                return 1;
-            }
 
             try {
                 byte[] adbKeysBytes = getBytesFromFile(adbKeys);
diff --git a/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
index 8bd1035..165419a 100644
--- a/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
+++ b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
@@ -22,7 +22,7 @@
 
 import com.android.internal.util.IndentingPrintWriter;
 
-import java.util.LinkedList;
+import java.util.ArrayDeque;
 
 /**
  * A class that behaves like the following definition, except it stores the history of values set
@@ -50,11 +50,18 @@
  */
 public final class ReferenceWithHistory<V> {
 
-    /** The size the history linked list is allowed to grow to. */
+    private static final Object NULL_MARKER = "{null marker}";
+
+    /** The maximum number of references to store. */
     private final int mMaxHistorySize;
 
+    /**
+     * The history storage. Note that ArrayDeque doesn't support {@code null} so this stores Object
+     * and not V. Use {@link #packNullIfRequired(Object)} and {@link #unpackNullIfRequired(Object)}
+     * to convert to / from the storage object.
+     */
     @Nullable
-    private LinkedList<V> mValues;
+    private ArrayDeque<Object> mValues;
 
     /**
      * Creates an instance that records, at most, the specified number of values.
@@ -69,22 +76,31 @@
     /** Returns the current value, or {@code null} if it has never been set. */
     @Nullable
     public V get() {
-        return (mValues == null || mValues.isEmpty()) ? null : mValues.getFirst();
+        if (mValues == null || mValues.isEmpty()) {
+            return null;
+        }
+        Object value = mValues.getFirst();
+        return unpackNullIfRequired(value);
     }
 
-    /** Sets the current value. Returns the previous value, or {@code null}. */
+    /**
+     * Sets the current value. Returns the previous value, which can be {@code null} if the
+     * reference has never been set, or if the reference has been set to {@code null}.
+     */
     @Nullable
     public V set(@Nullable V newValue) {
         if (mValues == null) {
-            mValues = new LinkedList<>();
+            mValues = new ArrayDeque<>(mMaxHistorySize);
+        }
+
+        if (mValues.size() >= mMaxHistorySize) {
+            mValues.removeLast();
         }
 
         V previous = get();
 
-        mValues.addFirst(newValue);
-        if (mValues.size() > mMaxHistorySize) {
-            mValues.removeLast();
-        }
+        Object nullSafeValue = packNullIfRequired(newValue);
+        mValues.addFirst(nullSafeValue);
         return previous;
     }
 
@@ -96,8 +112,8 @@
             ipw.println("{Empty}");
         } else {
             int i = 0;
-            for (V value : mValues) {
-                ipw.println(i + ": " + value);
+            for (Object value : mValues) {
+                ipw.println(i + ": " + unpackNullIfRequired(value));
                 i++;
             }
         }
@@ -115,4 +131,23 @@
     public String toString() {
         return String.valueOf(get());
     }
+
+    /**
+     * Turns a non-nullable Object into a nullable value. See also
+     * {@link #packNullIfRequired(Object)}.
+     */
+    @SuppressWarnings("unchecked")
+    @Nullable
+    private V unpackNullIfRequired(@NonNull Object value) {
+        return value == NULL_MARKER ? null : (V) value;
+    }
+
+    /**
+     * Turns a nullable value into a non-nullable Object. See also
+     * {@link #unpackNullIfRequired(Object)}.
+     */
+    @NonNull
+    private Object packNullIfRequired(@Nullable V value) {
+        return value == null ? NULL_MARKER : value;
+    }
 }
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index a16dbb7..3f2b5c2 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -11,6 +11,7 @@
 import android.graphics.PixelFormat;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
 import android.media.ImageReader;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -295,10 +296,12 @@
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
 
+            final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                    DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi);
+            builder.setUniqueId(UNIQUE_DISPLAY_ID);
+            builder.setFlags(flags);
             mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */,
-                    DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi,
-                    null /* surface */, flags, null /* callback */, null /* handler */,
-                    UNIQUE_DISPLAY_ID);
+                    builder.build(), null /* callback */, null /* handler */);
 
             if (mVirtualDisplay != null) {
                 updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ddf166e..63952b0 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1904,7 +1904,7 @@
                     final WallpaperData fallback =
                             new WallpaperData(wallpaper.userId, getWallpaperDir(wallpaper.userId),
                             WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
-                    ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
+                    ensureSaneWallpaperData(fallback);
                     bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
                     mWaitingForUnlock = true;
                 }
@@ -2425,7 +2425,7 @@
         if (cropHint == null) {
             cropHint = new Rect(0, 0, 0, 0);
         } else {
-            if (cropHint.isEmpty()
+            if (cropHint.width() < 0 || cropHint.height() < 0
                     || cropHint.left < 0
                     || cropHint.top < 0) {
                 throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
@@ -3077,7 +3077,7 @@
                     wallpaper = new WallpaperData(userId, getWallpaperDir(userId),
                             WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
                     mLockWallpaperMap.put(userId, wallpaper);
-                    ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
+                    ensureSaneWallpaperData(wallpaper);
                 } else {
                     // sanity fallback: we're in bad shape, but establishing a known
                     // valid system+lock WallpaperData will keep us from dying.
@@ -3085,7 +3085,7 @@
                     wallpaper = new WallpaperData(userId, getWallpaperDir(userId),
                             WALLPAPER, WALLPAPER_CROP);
                     mWallpaperMap.put(userId, wallpaper);
-                    ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
+                    ensureSaneWallpaperData(wallpaper);
                 }
             }
         }
@@ -3196,10 +3196,10 @@
         }
 
         ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
-        ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
+        ensureSaneWallpaperData(wallpaper);
         WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
         if (lockWallpaper != null) {
-            ensureSaneWallpaperData(lockWallpaper, DEFAULT_DISPLAY);
+            ensureSaneWallpaperData(lockWallpaper);
         }
     }
 
@@ -3215,15 +3215,11 @@
         }
     }
 
-    private void ensureSaneWallpaperData(WallpaperData wallpaper, int displayId) {
-        final DisplayData size = getDisplayDataOrCreate(displayId);
-
-        if (displayId == DEFAULT_DISPLAY) {
-            // crop, if not previously specified
-            if (wallpaper.cropHint.width() <= 0
-                    || wallpaper.cropHint.height() <= 0) {
-                wallpaper.cropHint.set(0, 0, size.mWidth, size.mHeight);
-            }
+    private void ensureSaneWallpaperData(WallpaperData wallpaper) {
+        // Only overwrite cropHint if the rectangle is invalid.
+        if (wallpaper.cropHint.width() < 0
+                || wallpaper.cropHint.height() < 0) {
+            wallpaper.cropHint.set(0, 0, 0, 0);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c1c8440..c47d215 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -42,7 +42,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.content.Intent.ACTION_MAIN;
 import static android.content.Intent.CATEGORY_HOME;
@@ -109,7 +108,6 @@
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
 import static android.view.WindowManager.TRANSIT_UNSET;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -196,6 +194,7 @@
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
 import static com.android.server.wm.TaskPersister.DEBUG;
 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
@@ -5811,18 +5810,8 @@
     }
 
     @VisibleForTesting
-    boolean shouldAnimate(int transit) {
-        if (task != null && !task.shouldAnimate()) {
-            return false;
-        }
-        final boolean isSplitScreenPrimary =
-                getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-        final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
-
-        // We animate always if it's not split screen primary, and only some special cases in split
-        // screen primary because it causes issues with stack clipping when we run an un-minimize
-        // animation at the same time.
-        return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
+    boolean shouldAnimate() {
+        return task == null || task.shouldAnimate();
     }
 
     /**
@@ -5918,7 +5907,8 @@
 
     @Override
     void prepareSurfaces() {
-        final boolean show = isVisible() || isAnimating(PARENTS);
+        final boolean show = isVisible() || isAnimatingExcluding(PARENTS,
+                ANIMATION_TYPE_SCREEN_ROTATION);
 
         if (mSurfaceControl != null) {
             if (show && !mLastSurfaceShowing) {
@@ -7411,7 +7401,17 @@
      */
     boolean isResumedActivityOnDisplay() {
         final DisplayContent display = getDisplay();
-        return display != null && this == display.mTaskContainers.getResumedActivity();
+        if (display == null) {
+            return false;
+        }
+        for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+            final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
+            if (resumedActivity != null) {
+                return resumedActivity == this;
+            }
+        }
+        return false;
     }
 
 
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 10b335e..78d2afc 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -20,7 +20,6 @@
 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
@@ -685,9 +684,7 @@
             return;
         }
 
-        setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
-                false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
-                false /* creating */);
+        setWindowingMode(windowingMode, false /* creating */);
     }
 
     /**
@@ -709,27 +706,22 @@
      * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending
      *         on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the
      *         previous non-transient mode if this stack is currently in a transient mode.
-     * @param animate Can be used to prevent animation.
-     * @param showRecents Controls whether recents is shown on the other side of a split while
-     *         entering split mode.
-     * @param enteringSplitScreenMode {@code true} if entering split mode.
-     * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when
-     *         many operations (which can effect visibility) are being performed in bulk.
      * @param creating {@code true} if this is being run during ActivityStack construction.
      */
-    void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
-            boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
+    void setWindowingMode(int preferredWindowingMode, boolean creating) {
         mWmService.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
-                preferredWindowingMode, animate, showRecents, enteringSplitScreenMode,
-                deferEnsuringVisibility, creating));
+                preferredWindowingMode, creating));
     }
 
-    private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode, boolean animate,
-            boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility,
+    private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode,
             boolean creating) {
+        final TaskDisplayArea taskDisplayArea = getDisplayArea();
+        if (taskDisplayArea == null) {
+            Slog.d(TAG, "taskDisplayArea is null, bail early");
+            return;
+        }
         final int currentMode = getWindowingMode();
         final int currentOverrideMode = getRequestedOverrideWindowingMode();
-        final TaskDisplayArea taskDisplayArea = getDisplayArea();
         final Task topTask = getTopMostTask();
         int windowingMode = preferredWindowingMode;
         if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED
@@ -753,12 +745,9 @@
 
         final boolean alreadyInSplitScreenMode = taskDisplayArea.isSplitScreenModeActivated();
 
-        // Don't send non-resizeable notifications if the windowing mode changed was a side effect
-        // of us entering split-screen mode.
-        final boolean sendNonResizeableNotification = !enteringSplitScreenMode;
         // Take any required action due to us not supporting the preferred windowing mode.
         if (alreadyInSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
-                && sendNonResizeableNotification && isActivityTypeStandardOrUndefined()) {
+                && isActivityTypeStandardOrUndefined()) {
             final boolean preferredSplitScreen =
                     preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                     || preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -794,7 +783,7 @@
         if (currentMode == WINDOWING_MODE_PINNED) {
             mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
         }
-        if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN
+        if (likelyResolvedMode != WINDOWING_MODE_FULLSCREEN
                 && topActivity != null && !topActivity.noDisplay
                 && topActivity.isNonResizableOrForcedResizable(likelyResolvedMode)) {
             // Inform the user that they are starting an app that may not work correctly in
@@ -806,7 +795,7 @@
 
         mAtmService.deferWindowLayout();
         try {
-            if (!animate && topActivity != null) {
+            if (topActivity != null) {
                 mStackSupervisor.mNoAnimActivities.add(topActivity);
             }
             super.setWindowingMode(windowingMode);
@@ -845,36 +834,11 @@
                         false /*preserveWindows*/, true /*deferResume*/);
             }
         } finally {
-            if (showRecents && !alreadyInSplitScreenMode && isOnHomeDisplay()
-                    && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                // Make sure recents stack exist when creating a dock stack as it normally needs to
-                // be on the other side of the docked stack and we make visibility decisions based
-                // on that.
-                // TODO: This is only here to help out with the case where recents stack doesn't
-                // exist yet. For that case the initial size of the split-screen stack will be the
-                // the one where the home stack is visible since recents isn't visible yet, but the
-                // divider will be off. I think we should just make the initial bounds that of home
-                // so that the divider matches and remove this logic.
-                // TODO: This is currently only called when entering split-screen while in another
-                // task, and from the tests
-                // TODO (b/78247419): Fix the rotation animation from fullscreen to minimized mode
-                final boolean isRecentsComponentHome =
-                        mAtmService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser);
-                final ActivityStack recentStack = taskDisplayArea.getOrCreateStack(
-                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
-                        isRecentsComponentHome ? ACTIVITY_TYPE_HOME : ACTIVITY_TYPE_RECENTS,
-                        true /* onTop */);
-                recentStack.moveToFront("setWindowingMode");
-                // If task moved to docked stack - show recents if needed.
-                mWmService.showRecentApps();
-            }
             mAtmService.continueWindowLayout();
         }
 
-        if (!deferEnsuringVisibility) {
-            mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
-            mRootWindowContainer.resumeFocusedStacksTopActivities();
-        }
+        mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+        mRootWindowContainer.resumeFocusedStacksTopActivities();
     }
 
     @Override
@@ -1119,8 +1083,8 @@
 
     @Override
     public boolean isAttached() {
-        final DisplayContent display = getDisplay();
-        return display != null && !display.isRemoved();
+        final TaskDisplayArea taskDisplayArea = getDisplayArea();
+        return taskDisplayArea != null && !taskDisplayArea.isRemoved();
     }
 
     // TODO: Should each user have there own stacks?
@@ -3553,9 +3517,8 @@
         }
     }
 
-    void reparent(DisplayContent newParent, boolean onTop) {
-        // Real parent of stack is within display object, so we have to delegate re-parenting there.
-        newParent.moveStackToDisplay(this, onTop);
+    void reparent(TaskDisplayArea newParent, boolean onTop) {
+        reparent(newParent, onTop ? POSITION_TOP : POSITION_BOTTOM);
     }
 
     private void updateSurfaceBounds() {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 2c7ce91..1e5a924 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -80,8 +80,6 @@
 import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
 import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED;
 import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT;
-import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
-import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -140,7 +138,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.os.TransferPipe;
-import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
@@ -382,72 +379,6 @@
 
     private boolean mInitialized;
 
-    private final MoveTaskToFullscreenHelper mMoveTaskToFullscreenHelper =
-            new MoveTaskToFullscreenHelper();
-    private class MoveTaskToFullscreenHelper {
-        private DisplayContent mToDisplay;
-        private boolean mOnTop;
-        private Task mTopTask;
-        private boolean mSchedulePictureInPictureModeChange;
-
-        void process(ActivityStack fromStack, DisplayContent toDisplay, boolean onTop,
-                boolean schedulePictureInPictureModeChange) {
-            mSchedulePictureInPictureModeChange = schedulePictureInPictureModeChange;
-            mToDisplay = toDisplay;
-            mOnTop = onTop;
-            mTopTask = fromStack.getTopMostTask();
-
-            final PooledConsumer c = PooledLambda.obtainConsumer(
-                    MoveTaskToFullscreenHelper::processLeafTask, this, PooledLambda.__(Task.class));
-            fromStack.forAllLeafTasks(c, false /* traverseTopToBottom */);
-            c.recycle();
-            mToDisplay = null;
-            mTopTask = null;
-        }
-
-        private void processLeafTask(Task task) {
-            // This is a one level task that we don't need to create stack for reparenting to.
-            if (task.isRootTask() && DisplayContent.alwaysCreateStack(WINDOWING_MODE_FULLSCREEN,
-                    task.getActivityType())) {
-                final ActivityStack stack = (ActivityStack) task;
-                stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-                if (mToDisplay.getDisplayId() != stack.getDisplayId()) {
-                    mToDisplay.moveStackToDisplay(stack, mOnTop);
-                } else if (mOnTop) {
-                    mToDisplay.mTaskContainers.positionStackAtTop(stack,
-                            false /* includingParents */);
-                } else {
-                    mToDisplay.mTaskContainers.positionStackAtBottom(stack);
-                }
-                return;
-            }
-
-            final ActivityStack toStack = mToDisplay.mTaskContainers.getOrCreateStack(
-                    null, mTmpOptions, task, task.getActivityType(), mOnTop);
-            if (task == toStack) {
-                // The task was reused as the root task.
-                return;
-            }
-
-            if (mOnTop) {
-                final boolean isTopTask = task == mTopTask;
-                // Defer resume until all the tasks have been moved to the fullscreen stack
-                task.reparent(toStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, isTopTask /*animate*/,
-                        DEFER_RESUME, mSchedulePictureInPictureModeChange,
-                        "moveTasksToFullscreenStack - onTop");
-                MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
-                        task.effectiveUid, task.realActivity.flattenToString());
-            } else {
-                // Position the tasks in the fullscreen stack in order at the bottom of the
-                // stack. Also defer resume until all the tasks have been moved to the
-                // fullscreen stack.
-                task.reparent(toStack, ON_TOP, REPARENT_LEAVE_STACK_IN_PLACE,
-                        !ANIMATE, DEFER_RESUME, mSchedulePictureInPictureModeChange,
-                        "moveTasksToFullscreenStack - NOT_onTop");
-            }
-        }
-    }
-
     /**
      * Description of a request to start a new activity, which has been held
      * due to app switches being disabled.
@@ -566,8 +497,8 @@
     }
 
     void moveRecentsStackToFront(String reason) {
-        final ActivityStack recentsStack = mRootWindowContainer.getDefaultDisplay().getStack(
-                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
+        final ActivityStack recentsStack = mRootWindowContainer.getDefaultTaskDisplayArea()
+                .getStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
         if (recentsStack != null) {
             recentsStack.moveToFront(reason);
         }
@@ -1418,7 +1349,7 @@
                     mRootWindowContainer.getLaunchStack(null, options, task, ON_TOP);
 
             if (stack != currentStack) {
-                moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason);
+                moveHomeStackToFrontIfNeeded(flags, stack.getDisplayArea(), reason);
                 task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, DEFER_RESUME,
                         reason);
                 currentStack = stack;
@@ -1437,7 +1368,7 @@
         }
 
         if (!reparented) {
-            moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplay(), reason);
+            moveHomeStackToFrontIfNeeded(flags, currentStack.getDisplayArea(), reason);
         }
 
         final ActivityRecord r = task.getTopNonFinishingActivity();
@@ -1451,15 +1382,16 @@
                 currentStack, forceNonResizeable);
     }
 
-    private void moveHomeStackToFrontIfNeeded(int flags, DisplayContent display, String reason) {
-        final ActivityStack focusedStack = display.getFocusedStack();
+    private void moveHomeStackToFrontIfNeeded(int flags, TaskDisplayArea taskDisplayArea,
+            String reason) {
+        final ActivityStack focusedStack = taskDisplayArea.getFocusedStack();
 
-        if ((display.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+        if ((taskDisplayArea.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                 && (flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0)
                 || (focusedStack != null && focusedStack.isActivityTypeRecents())) {
-            // We move home stack to front when we are on a fullscreen display and caller has
+            // We move home stack to front when we are on a fullscreen display area and caller has
             // requested the home activity to move with it. Or the previous stack is recents.
-            display.mTaskContainers.moveHomeStackToFront(reason);
+            taskDisplayArea.moveHomeStackToFront(reason);
         }
     }
 
@@ -1501,55 +1433,6 @@
         mResizingTasksDuringAnimation.clear();
     }
 
-    /**
-     * TODO: This should just change the windowing mode and resize vs. actually moving task around.
-     * Can do that once we are no longer using static stack ids.
-     */
-    private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack,
-            int toDisplayId, boolean onTop) {
-
-        mService.deferWindowLayout();
-        try {
-            final int windowingMode = fromStack.getWindowingMode();
-            final DisplayContent toDisplay =
-                    mRootWindowContainer.getDisplayContent(toDisplayId);
-
-            if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                // We are moving all tasks from the docked stack to the fullscreen stack,
-                // which is dismissing the docked stack, so resize all other stacks to
-                // fullscreen here already so we don't end up with resize trashing.
-                for (int i = toDisplay.getStackCount() - 1; i >= 0; --i) {
-                    final ActivityStack otherStack = toDisplay.getStackAt(i);
-                    if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
-                        continue;
-                    }
-                    otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
-                }
-            }
-
-            // If we are moving from the pinned stack, then the animation takes care of updating
-            // the picture-in-picture mode.
-            final boolean schedulePictureInPictureModeChange =
-                    windowingMode == WINDOWING_MODE_PINNED;
-
-            if (fromStack.hasChild()) {
-                mTmpOptions.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
-                mMoveTaskToFullscreenHelper.process(
-                        fromStack, toDisplay, onTop, schedulePictureInPictureModeChange);
-            }
-
-            mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
-            mRootWindowContainer.resumeFocusedStacksTopActivities();
-        } finally {
-            mService.continueWindowLayout();
-        }
-    }
-
-    void moveTasksToFullscreenStackLocked(ActivityStack fromStack, boolean onTop) {
-        mWindowManager.inSurfaceTransaction(() ->
-                moveTasksToFullscreenStackInSurfaceTransaction(fromStack, DEFAULT_DISPLAY, onTop));
-    }
-
     void setSplitScreenResizing(boolean resizing) {
         if (resizing == mDockedStackResizing) {
             return;
@@ -1559,26 +1442,46 @@
         mWindowManager.setDockedStackResizing(resizing);
     }
 
+    private void removePinnedStackInSurfaceTransaction(ActivityStack stack) {
+        /**
+         * Workaround: Force-stop all the activities in the pinned stack before we reparent them
+         * to the fullscreen stack.  This is to guarantee that when we are removing a stack,
+         * that the client receives onStop() before it is reparented.  We do this by detaching
+         * the stack from the display so that it will be considered invisible when
+         * ensureActivitiesVisible() is called, and all of its activities will be marked
+         * invisible as well and added to the stopping list.  After which we process the
+         * stopping list by handling the idle.
+         */
+        stack.cancelAnimation();
+        stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
+        stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+        stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, false /* set */);
+        activityIdleInternal(null /* idleActivity */, false /* fromTimeout */,
+                true /* processPausingActivities */, null /* configuration */);
+
+        // Reparent all the tasks to the bottom of the display
+        final DisplayContent toDisplay =
+                mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);
+
+        mService.deferWindowLayout();
+        try {
+            stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+            if (toDisplay.getDisplayId() != stack.getDisplayId()) {
+                stack.reparent(toDisplay.getDefaultTaskDisplayArea(), false /* onTop */);
+            } else {
+                toDisplay.mTaskContainers.positionStackAtBottom(stack);
+            }
+
+            mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+            mRootWindowContainer.resumeFocusedStacksTopActivities();
+        } finally {
+            mService.continueWindowLayout();
+        }
+    }
+
     private void removeStackInSurfaceTransaction(ActivityStack stack) {
         if (stack.getWindowingMode() == WINDOWING_MODE_PINNED) {
-            /**
-             * Workaround: Force-stop all the activities in the pinned stack before we reparent them
-             * to the fullscreen stack.  This is to guarantee that when we are removing a stack,
-             * that the client receives onStop() before it is reparented.  We do this by detaching
-             * the stack from the display so that it will be considered invisible when
-             * ensureActivitiesVisible() is called, and all of its activities will be marked
-             * invisible as well and added to the stopping list.  After which we process the
-             * stopping list by handling the idle.
-             */
-            stack.cancelAnimation();
-            stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
-            stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
-            stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, false /* set */);
-            activityIdleInternal(null /* idleActivity */, false /* fromTimeout */,
-                    true /* processPausingActivities */, null /* configuration */);
-
-            // Move all the tasks to the bottom of the fullscreen stack
-            moveTasksToFullscreenStackLocked(stack, !ON_TOP);
+            removePinnedStackInSurfaceTransaction(stack);
         } else {
             final PooledConsumer c = PooledLambda.obtainConsumer(
                     ActivityStackSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
@@ -2613,7 +2516,7 @@
                 // from whatever is started from the recents activity, so move the home stack
                 // forward.
                 // TODO (b/115289124): Multi-display supports for recents.
-                mRootWindowContainer.getDefaultDisplay().mTaskContainers.moveHomeStackToFront(
+                mRootWindowContainer.getDefaultTaskDisplayArea().moveHomeStackToFront(
                         "startActivityFromRecents");
             }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 0a0049d..d777f3f 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -189,9 +189,10 @@
         mSupervisor.beginDeferResume();
         final ActivityStack homeStack;
         try {
+            // TODO(multi-display-area): Support starting home in a task display area
             // Make sure home stack exist on display.
-            homeStack = display.mTaskContainers.getOrCreateStack(WINDOWING_MODE_FULLSCREEN,
-                    ACTIVITY_TYPE_HOME, ON_TOP);
+            homeStack = display.getDefaultTaskDisplayArea().getOrCreateStack(
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
         } finally {
             mSupervisor.endDeferResume();
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 682e991..c253cd2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2802,6 +2802,9 @@
                     false /* includingParents */);
         }
         WindowContainerTransaction wct = new WindowContainerTransaction();
+        // Clear out current windowing mode before reparenting to split taks.
+        wct.setWindowingMode(
+                task.getStack().mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_UNDEFINED);
         wct.reparent(task.getStack().mRemoteToken.toWindowContainerToken(),
                 primarySplitTask.mRemoteToken.toWindowContainerToken(), toTop);
         mWindowOrganizerController.applyTransaction(wct);
@@ -3321,33 +3324,12 @@
                     Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
                     return;
                 }
-                // Place the task in the right stack if it isn't there already based on
-                // the requested bounds.
-                // The stack transition logic is:
-                // - a null bounds on a freeform task moves that task to fullscreen
-                // - a non-null bounds on a non-freeform (fullscreen OR docked) task moves
-                //   that task to freeform
-                // - otherwise the task is not moved
-                ActivityStack stack = task.getStack();
                 if (!task.getWindowConfiguration().canResizeTask()) {
                     throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
                 }
-                if (bounds == null && stack.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
-                    stack = stack.getDisplayArea().getOrCreateStack(
-                            WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), ON_TOP);
-                } else if (bounds != null && stack.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
-                    stack = stack.getDisplayArea().getOrCreateStack(
-                            WINDOWING_MODE_FREEFORM, stack.getActivityType(), ON_TOP);
-                }
 
                 // Reparent the task to the right stack if necessary
                 boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0;
-                if (stack != task.getStack()) {
-                    // Defer resume until the task is resized below
-                    task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
-                            DEFER_RESUME, "resizeTask");
-                    preserveWindow = false;
-                }
 
                 // After reparenting (which only resizes the task to the stack bounds), resize the
                 // task to the actual bounds provided
@@ -4019,28 +4001,6 @@
         }
     }
 
-    @Override
-    // TODO: API should just be about changing windowing modes...
-    public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
-        enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
-                "moveTasksToFullscreenStack()");
-        synchronized (mGlobalLock) {
-            final long origId = Binder.clearCallingIdentity();
-            try {
-                final ActivityStack stack = mRootWindowContainer.getStack(fromStackId);
-                if (stack != null){
-                    if (!stack.isActivityTypeStandardOrUndefined()) {
-                        throw new IllegalArgumentException(
-                                "You can't move tasks from non-standard stacks.");
-                    }
-                    mStackSupervisor.moveTasksToFullscreenStackLocked(stack, onTop);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
-        }
-    }
-
     /**
      * Moves the top activity in the input stackId to the pinned stack.
      *
@@ -4280,9 +4240,9 @@
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
-                final Task primary = dc.getRootSplitScreenPrimaryTask();
-                final Task secondary = dc.getTask(t -> t.mCreatedByOrganizer && t.isRootTask()
+                final TaskDisplayArea tc = mRootWindowContainer.getDefaultTaskDisplayArea();
+                final Task primary = tc.getRootSplitScreenPrimaryTask();
+                final Task secondary = tc.getTask(t -> t.mCreatedByOrganizer && t.isRootTask()
                         && t.inSplitScreenSecondaryWindowingMode());
                 if (primary == null || secondary == null) {
                     return;
@@ -4298,7 +4258,7 @@
                 if (otherRect == null) {
                     // Temporary estimation... again this is just for tests.
                     otherRect = new Rect(secondary.getBounds());
-                    if (dc.getBounds().width() > dc.getBounds().height()) {
+                    if (tc.getBounds().width() > tc.getBounds().height()) {
                         otherRect.left = primaryRect.right + 6;
                     } else {
                         otherRect.top = primaryRect.bottom + 6;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index f86aeb2..78ee1de7 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -76,7 +76,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 
 import android.annotation.DrawableRes;
@@ -1807,15 +1806,11 @@
     }
 
     int getAppStackClipMode() {
-        // When dismiss keyguard animation occurs, clip before the animation to prevent docked
-        // app from showing beyond the divider
-        if (mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
-                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
-            return STACK_CLIP_BEFORE_ANIM;
-        }
         return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
                 || mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
                 || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
+                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
+                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
                 ? STACK_CLIP_NONE
                 : STACK_CLIP_AFTER_ANIM;
     }
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 90fdf19..edd14b7 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -253,6 +253,12 @@
             super.prepareSurfaces();
             getBounds(mTmpDimBoundsRect);
 
+            // If SystemUI is dragging for recents, we want to reset the dim state so any dim layer
+            // on the display level fades out.
+            if (forAllTasks(task -> !task.canAffectSystemUiFlags())) {
+                mDimmer.resetDimStates();
+            }
+
             if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
                 scheduleAnimation();
             }
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index 682a142..e8becfa 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -54,7 +54,7 @@
  *      - DisplayArea.Root
  *        - Magnification
  *          - DisplayArea.Tokens (Wallpapers are attached here)
- *          - TaskContainers
+ *          - TaskDisplayArea
  *          - DisplayArea.Tokens (windows above Tasks up to IME are attached here)
  *          - ImeContainers
  *          - DisplayArea.Tokens (windows above IME up to TYPE_ACCESSIBILITY_OVERLAY attached here)
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0108140..2816633 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -503,6 +503,9 @@
     /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
     final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
 
+    /** Windows whose client's insets states are not up-to-date. */
+    final ArrayList<WindowState> mWinInsetsChanged = new ArrayList<>();
+
     private ScreenRotationAnimation mScreenRotationAnimation;
 
     /**
@@ -571,13 +574,6 @@
 
     private RootWindowContainer mRootWindowContainer;
 
-    /**
-     * All of the stacks on this display. Order matters, topmost stack is in front of all other
-     * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
-     * changing the list should also call {@link #onStackOrderChanged()}.
-     */
-    private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
-
     /** Array of all UIDs that are present on the display. */
     private IntArray mDisplayAccessUIDs = new IntArray();
 
@@ -708,7 +704,10 @@
         }
 
         // Sets mBehindIme for each window. Windows behind IME can get IME insets.
-        w.mBehindIme = mTmpWindowsBehindIme;
+        if (w.mBehindIme != mTmpWindowsBehindIme) {
+            w.mBehindIme = mTmpWindowsBehindIme;
+            mWinInsetsChanged.add(w);
+        }
         if (w == mInputMethodWindow) {
             mTmpWindowsBehindIme = true;
         }
@@ -816,8 +815,10 @@
 
             if (w.mHasSurface && isDisplayed) {
                 final int type = w.mAttrs.type;
-                if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
-                        || mWmService.mPolicy.isKeyguardShowing()) {
+                if (type == TYPE_SYSTEM_DIALOG
+                        || type == TYPE_SYSTEM_ERROR
+                        || (type == TYPE_NOTIFICATION_SHADE
+                            &&  mWmService.mPolicy.isKeyguardShowing())) {
                     mTmpApplySurfaceChangesTransactionState.syswin = true;
                 }
                 if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
@@ -1080,8 +1081,7 @@
             return null;
         }
         mShellRoots.put(windowType, root);
-        SurfaceControl out = new SurfaceControl();
-        out.copyFrom(rootLeash);
+        SurfaceControl out = new SurfaceControl(rootLeash);
         return out;
     }
 
@@ -2053,63 +2053,58 @@
         return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
     }
 
-    ActivityStack getRootHomeTask() {
-        return mTaskContainers.getRootHomeTask();
-    }
-
-    /** @return The primary split-screen task, and {@code null} otherwise. */
-    @Nullable ActivityStack getRootSplitScreenPrimaryTask() {
-        return mTaskContainers.getRootSplitScreenPrimaryTask();
-    }
-
-    ActivityStack getRootPinnedTask() {
-        return mTaskContainers.getRootPinnedTask();
-    }
-
-    boolean hasPinnedTask() {
-        return mTaskContainers.getRootPinnedTask() != null;
-    }
-
     /**
      * Returns the topmost stack on the display that is compatible with the input windowing mode and
      * activity type. Null is no compatible stack on the display.
      */
     ActivityStack getStack(int windowingMode, int activityType) {
-        return mTaskContainers.getStack(windowingMode, activityType);
+        for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final ActivityStack stack = getTaskDisplayAreaAt(tdaNdx)
+                    .getStack(windowingMode, activityType);
+            if (stack != null) {
+                return stack;
+            }
+        }
+        return null;
+    }
+
+    protected int getTaskDisplayAreaCount() {
+        // TODO(multi-display-area): Report actual display area count
+        return 1;
+    }
+
+    protected TaskDisplayArea getTaskDisplayAreaAt(int index) {
+        // TODO(multi-display-area): Report actual display area values
+        return mTaskContainers;
+    }
+
+    ActivityStack getStack(int rootTaskId) {
+        for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final ActivityStack stack = getTaskDisplayAreaAt(tdaNdx).getStack(rootTaskId);
+            if (stack != null) {
+                return stack;
+            }
+        }
+        return null;
     }
 
     protected int getStackCount() {
-        return mTaskContainers.mChildren.size();
-    }
-
-    protected ActivityStack getStackAt(int index) {
-        return mTaskContainers.mChildren.get(index);
-    }
-
-    int getIndexOf(ActivityStack stack) {
-        return mTaskContainers.getIndexOf(stack);
-    }
-
-    void removeStack(ActivityStack stack) {
-        mTaskContainers.removeChild(stack);
-    }
-
-    @VisibleForTesting
-    WindowList<ActivityStack> getStacks() {
-        return mTaskContainers.mChildren;
+        int totalStackCount = 0;
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            totalStackCount += getTaskDisplayAreaAt(i).getStackCount();
+        }
+        return totalStackCount;
     }
 
     @VisibleForTesting
     ActivityStack getTopStack() {
-        return mTaskContainers.getTopStack();
-    }
-
-    ArrayList<Task> getVisibleTasks() {
-        return mTaskContainers.getVisibleTasks();
-    }
-
-    SurfaceControl getSplitScreenDividerAnchor() {
-        return mTaskContainers.getSplitScreenDividerAnchor();
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getTaskDisplayAreaAt(i).getTopStack();
+            if (stack != null) {
+                return stack;
+            }
+        }
+        return null;
     }
 
     /**
@@ -2400,8 +2395,13 @@
         out.set(mDisplayFrames.mStable);
     }
 
-    void moveStackToDisplay(ActivityStack stack, boolean onTop) {
-        stack.reparent(mTaskContainers, onTop ? POSITION_TOP: POSITION_BOTTOM);
+    /**
+     * Get the default display area on the display dedicated to app windows. This one should be used
+     * only as a fallback location for activity launches when no target display area is specified,
+     * or for cases when multi-instance is not supported yet (like Split-screen, PiP or Recents).
+     */
+    TaskDisplayArea getDefaultTaskDisplayArea() {
+        return mTaskContainers;
     }
 
     @Override
@@ -2464,7 +2464,7 @@
      */
     Task findTaskForResizePoint(int x, int y) {
         final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
-        return mTmpTaskForResizePointSearchResult.process(mTaskContainers, x, y, delta);
+        return mTmpTaskForResizePointSearchResult.process(getDefaultTaskDisplayArea(), x, y, delta);
     }
 
     void updateTouchExcludeRegion() {
@@ -2480,7 +2480,7 @@
             final PooledConsumer c = PooledLambda.obtainConsumer(
                     DisplayContent::processTaskForTouchExcludeRegion, this,
                     PooledLambda.__(Task.class), focusedTask, delta);
-            mTaskContainers.forAllTasks(c);
+            forAllTasks(c);
             c.recycle();
 
             // If we removed the focused task above, add it back and only leave its
@@ -2503,8 +2503,9 @@
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
         amendWindowTapExcludeRegion(mTouchExcludeRegion);
-        // TODO(multi-display): Support docked stacks on secondary displays.
-        if (mDisplayId == DEFAULT_DISPLAY && mTaskContainers.isSplitScreenModeActivated()) {
+        // TODO(multi-display): Support docked stacks on secondary displays & task containers.
+        if (mDisplayId == DEFAULT_DISPLAY
+                && getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
             mDividerControllerLocked.getTouchRegion(mTmpRect);
             mTmpRegion.set(mTmpRect);
             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
@@ -2660,9 +2661,8 @@
     }
 
     void prepareFreezingTaskBounds() {
-        for (int stackNdx = mTaskContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = mTaskContainers.getChildAt(stackNdx);
-            stack.prepareFreezingTaskBounds();
+        for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            getTaskDisplayAreaAt(tdaNdx).prepareFreezingTaskBounds();
         }
     }
 
@@ -2768,8 +2768,8 @@
         final ActivityStack focusedStack = getFocusedStack();
         if (focusedStack != null) {
             proto.write(FOCUSED_ROOT_TASK_ID, focusedStack.getRootTaskId());
-            final ActivityRecord focusedActivity = focusedStack.getDisplay().mTaskContainers
-                    .getResumedActivity();
+            final ActivityRecord focusedActivity = focusedStack.getDisplayArea()
+                    .getFocusedActivity();
             if (focusedActivity != null) {
                 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
             }
@@ -2827,13 +2827,6 @@
         if (mLastFocus != mCurrentFocus) {
             pw.print("  mLastFocus="); pw.println(mLastFocus);
         }
-        if (mTaskContainers.mPreferredTopFocusableStack != null) {
-            pw.println(prefix + "mPreferredTopFocusableStack="
-                    + mTaskContainers.mPreferredTopFocusableStack);
-        }
-        if (mTaskContainers.mLastFocusedStack != null) {
-            pw.println(prefix + "mLastFocusedStack=" + mTaskContainers.mLastFocusedStack);
-        }
         if (mLosingFocus.size() > 0) {
             pw.println();
             pw.println("  Windows losing focus:");
@@ -2867,10 +2860,9 @@
         }
 
         pw.println();
-        pw.println(prefix + "Application tokens in top down Z order:");
-        for (int stackNdx = mTaskContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = mTaskContainers.getChildAt(stackNdx);
-            stack.dump(pw, prefix + "  ", dumpAll);
+        pw.println(prefix + "Task display areas in top down Z order:");
+        for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            getTaskDisplayAreaAt(tdaNdx).dump(pw, prefix + "  ", dumpAll);
         }
 
         pw.println();
@@ -2899,20 +2891,22 @@
         pw.println();
 
         // Dump stack references
-        final ActivityStack homeStack = getRootHomeTask();
+        final ActivityStack homeStack = getDefaultTaskDisplayArea().getRootHomeTask();
         if (homeStack != null) {
             pw.println(prefix + "homeStack=" + homeStack.getName());
         }
-        final ActivityStack pinnedStack = getRootPinnedTask();
+        final ActivityStack pinnedStack = getDefaultTaskDisplayArea().getRootPinnedTask();
         if (pinnedStack != null) {
             pw.println(prefix + "pinnedStack=" + pinnedStack.getName());
         }
-        final ActivityStack splitScreenPrimaryStack = getRootSplitScreenPrimaryTask();
+        final ActivityStack splitScreenPrimaryStack = getDefaultTaskDisplayArea()
+                .getRootSplitScreenPrimaryTask();
         if (splitScreenPrimaryStack != null) {
             pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName());
         }
-        final ActivityStack recentsStack =
-                getStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
+        // TODO: Support recents on non-default task containers
+        final ActivityStack recentsStack = getDefaultTaskDisplayArea().getStack(
+                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
         if (recentsStack != null) {
             pw.println(prefix + "recentsStack=" + recentsStack.getName());
         }
@@ -2946,12 +2940,6 @@
         return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
     }
 
-    /** Returns true if the stack in the windowing mode is visible. */
-    boolean isStackVisible(int windowingMode) {
-        final ActivityStack stack = mTaskContainers.getTopStackInWindowingMode(windowingMode);
-        return stack != null && stack.isVisible();
-    }
-
     /** Find the visible, touch-deliverable window under the given point */
     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
         final int x = (int) xf;
@@ -3564,6 +3552,10 @@
                         onWallpaper, goingToShade, subtle));
             }
         }, true /* traverseTopToBottom */);
+        for (int i = mShellRoots.size() - 1; i >= 0; --i) {
+            mShellRoots.valueAt(i).startAnimation(policy.createHiddenByKeyguardExit(
+                    onWallpaper, goingToShade, subtle));
+        }
     }
 
     /** @return {@code true} if there is window to wait before enabling the screen. */
@@ -4036,7 +4028,9 @@
         }
 
         // Initialize state of exiting applications.
-        mTaskContainers.setExitingTokensHasVisible(hasVisible);
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            getTaskDisplayAreaAt(i).setExitingTokensHasVisible(hasVisible);
+        }
     }
 
     void removeExistingTokensIfPossible() {
@@ -4048,7 +4042,9 @@
         }
 
         // Time to remove any exiting applications?
-        mTaskContainers.removeExistingAppTokensIfPossible();
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            getTaskDisplayAreaAt(i).removeExistingAppTokensIfPossible();
+        }
     }
 
     @Override
@@ -4358,7 +4354,7 @@
             // We skip IME windows so they're processed just above their target, except
             // in split-screen mode where we process the IME containers above the docked divider.
             return dc.mInputMethodTarget != null
-                    && !dc.mTaskContainers.isSplitScreenModeActivated();
+                    && !dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
         }
 
         /** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
@@ -4509,7 +4505,9 @@
     }
 
     void assignStackOrdering() {
-        mTaskContainers.assignStackOrdering(getPendingTransaction());
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            getTaskDisplayAreaAt(i).assignStackOrdering(getPendingTransaction());
+        }
     }
 
     /**
@@ -5036,13 +5034,15 @@
                 || windowingMode == WINDOWING_MODE_MULTI_WINDOW);
     }
 
-    ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
-        return mTaskContainers.createStack(windowingMode, activityType, onTop, null /* info */,
-                null /* intent */, false /* createdByOrganizer */);
-    }
-
+    @Nullable
     ActivityStack getFocusedStack() {
-        return mTaskContainers.getFocusedStack();
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getTaskDisplayAreaAt(i).getFocusedStack();
+            if (stack != null) {
+                return stack;
+            }
+        }
+        return null;
     }
 
     /**
@@ -5050,11 +5050,15 @@
      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
      */
     void removeStacksInWindowingModes(int... windowingModes) {
-        mTaskContainers.removeStacksInWindowingModes(windowingModes);
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            getTaskDisplayAreaAt(i).removeStacksInWindowingModes(windowingModes);
+        }
     }
 
     void removeStacksWithActivityTypes(int... activityTypes) {
-        mTaskContainers.removeStacksWithActivityTypes(activityTypes);
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            getTaskDisplayAreaAt(i).removeStacksWithActivityTypes(activityTypes);
+        }
     }
 
     ActivityRecord topRunningActivity() {
@@ -5071,7 +5075,14 @@
      * @return The top running activity. {@code null} if none is available.
      */
     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
-        return mTaskContainers.topRunningActivity(considerKeyguardState);
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            final ActivityRecord activity = getTaskDisplayAreaAt(i)
+                    .topRunningActivity(considerKeyguardState);
+            if (activity != null) {
+                return activity;
+            }
+        }
+        return null;
     }
 
     boolean updateDisplayOverrideConfigurationLocked() {
@@ -5183,7 +5194,7 @@
         // The display may be about to rotate seamlessly, and the animation of closing apps may
         // still animate in old rotation. So make sure the outdated animation won't show on the
         // rotated display.
-        mTaskContainers.forAllActivities(a -> {
+        forAllActivities(a -> {
             if (a.nowVisible && a != mFixedRotationLaunchingApp
                     && a.getWindowConfiguration().getRotation() != newRotation) {
                 final WindowContainer<?> w = a.getAnimatingContainer();
@@ -5244,40 +5255,17 @@
 
     void remove() {
         mRemoving = true;
-        final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
         ActivityStack lastReparentedStack = null;
-        mTaskContainers.mPreferredTopFocusableStack = null;
 
-        // Stacks could be reparented from the removed display to other display. While
-        // reparenting the last stack of the removed display, the remove display is ready to be
-        // released (no more ActivityStack). But, we cannot release it at that moment or the
-        // related WindowContainer will also be removed. So, we set display as removed after
-        // reparenting stack finished.
-        final DisplayContent toDisplay = mRootWindowContainer.getDefaultDisplay();
         mRootWindowContainer.mStackSupervisor.beginDeferResume();
         try {
-            int numStacks = getStackCount();
-            // Keep the order from bottom to top.
-            for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
-                final ActivityStack stack = getStackAt(stackNdx);
-                // Always finish non-standard type stacks.
-                if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
-                    stack.finishAllActivitiesImmediately();
-                } else {
-                    // If default display is in split-window mode, set windowing mode of the stack
-                    // to split-screen secondary. Otherwise, set the windowing mode to undefined by
-                    // default to let stack inherited the windowing mode from the new display.
-                    final int windowingMode = toDisplay.mTaskContainers.isSplitScreenModeActivated()
-                            ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
-                            : WINDOWING_MODE_UNDEFINED;
-                    stack.reparent(toDisplay, true /* onTop */);
-                    stack.setWindowingMode(windowingMode);
-                    lastReparentedStack = stack;
+            int numTaskContainers = getTaskDisplayAreaCount();
+            for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
+                final ActivityStack lastReparentedStackFromArea = getTaskDisplayAreaAt(tdaNdx)
+                        .remove();
+                if (lastReparentedStackFromArea != null) {
+                    lastReparentedStack = lastReparentedStackFromArea;
                 }
-                // Stacks may be removed from this display. Ensure each stack will be processed and
-                // the loop will end.
-                stackNdx -= numStacks - getStackCount();
-                numStacks = getStackCount();
             }
         } finally {
             mRootWindowContainer.mStackSupervisor.endDeferResume();
@@ -5304,12 +5292,27 @@
             return;
         }
 
-        final ActivityStack stack = getStackCount() == 1 ? getStackAt(0) : null;
-        if (stack != null && stack.isActivityTypeHome() && !stack.hasChild()) {
-            // Release this display if an empty home stack is the only thing left.
-            // Since it is the last stack, this display will be released along with the stack
-            // removal.
-            stack.removeIfPossible();
+        // Check if all task display areas have only the empty home stacks left.
+        boolean onlyEmptyHomeStacksLeft = true;
+        for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final TaskDisplayArea taskDisplayArea = getTaskDisplayAreaAt(tdaNdx);
+            if (taskDisplayArea.getStackCount() != 1) {
+                onlyEmptyHomeStacksLeft = false;
+                break;
+            }
+            final ActivityStack stack = taskDisplayArea.getStackAt(0);
+            if (!stack.isActivityTypeHome() || stack.hasChild()) {
+                onlyEmptyHomeStacksLeft = false;
+                break;
+            }
+        }
+        if (onlyEmptyHomeStacksLeft) {
+            // Release this display if only empty home stack(s) are left. This display will be
+            // released along with the stack(s) removal.
+            for (int tdaNdx = getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final ActivityStack s = getTaskDisplayAreaAt(tdaNdx).getStackAt(0);
+                s.removeIfPossible();
+            }
         } else if (getTopStack() == null) {
             removeIfPossible();
             mRootWindowContainer.mStackSupervisor
@@ -5368,10 +5371,9 @@
 
     void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
             boolean preserveWindows, boolean notifyClients) {
-        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = getStackAt(stackNdx);
-            stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
-                    notifyClients);
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            getTaskDisplayAreaAt(i).ensureActivitiesVisible(starting, configChanges,
+                    preserveWindows, notifyClients);
         }
     }
 
@@ -5383,42 +5385,19 @@
         mSleeping = asleep;
     }
 
-    /**
-     * Adds a listener to be notified whenever the stack order in the display changes. Currently
-     * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
-     * current animation when the system state changes.
-     */
-    void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
-        if (!mStackOrderChangedCallbacks.contains(listener)) {
-            mStackOrderChangedCallbacks.add(listener);
-        }
-    }
-
-    /**
-     * Removes a previously registered stack order change listener.
-     */
-    void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
-        mStackOrderChangedCallbacks.remove(listener);
-    }
-
-    /**
-     * Notifies of a stack order change
-     * @param stack The stack which triggered the order change
-     */
-    void onStackOrderChanged(ActivityStack stack) {
-        for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
-            mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
-        }
-    }
-
     void setDisplayToSingleTaskInstance() {
-        final int childCount = getStackCount();
-        if (childCount > 1) {
+        final int taskDisplayAreaCount = getTaskDisplayAreaCount();
+        if (taskDisplayAreaCount > 1) {
+            throw new IllegalArgumentException(
+                    "Display already has multiple task display areas. display=" + this);
+        }
+        final int stackCount = getDefaultTaskDisplayArea().getStackCount();
+        if (stackCount > 1) {
             throw new IllegalArgumentException("Display already has multiple stacks. display="
                     + this);
         }
-        if (childCount > 0) {
-            final ActivityStack stack = getStackAt(0);
+        if (stackCount > 0) {
+            final ActivityStack stack = getDefaultTaskDisplayArea().getStackAt(0);
             if (stack.getChildCount() > 1) {
                 throw new IllegalArgumentException("Display stack already has multiple tasks."
                         + " display=" + this + " stack=" + stack);
@@ -5439,22 +5418,6 @@
     }
 
     /**
-     * Callback for when the order of the stacks in the display changes.
-     */
-    interface OnStackOrderChangedListener {
-        void onStackOrderChanged(ActivityStack stack);
-    }
-
-    public void dumpStacks(PrintWriter pw) {
-        for (int i = getStackCount() - 1; i >= 0; --i) {
-            pw.print(getStackAt(i).getRootTaskId());
-            if (i > 0) {
-                pw.print(",");
-            }
-        }
-    }
-
-    /**
      * Similar to {@link RootWindowContainer#isAnyNonToastWindowVisibleForUid(int)}, but
      * used for pid.
      */
@@ -5472,6 +5435,10 @@
         return mDisplayPolicy.getSystemUiContext();
     }
 
+    Point getDisplayPosition() {
+        return mWmService.mDisplayManagerInternal.getDisplayPosition(getDisplayId());
+    }
+
     class RemoteInsetsControlTarget implements InsetsControlTarget {
         private final IDisplayWindowInsetsController mRemoteInsetsController;
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 367151c..e9d3d56 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -696,6 +696,10 @@
         mForceShowSystemBarsFromExternal = forceShowSystemBars;
     }
 
+    boolean getForceShowSystemBars() {
+        return mForceShowSystemBarsFromExternal;
+    }
+
     public boolean hasNavigationBar() {
         return mHasNavigationBar;
     }
@@ -1494,9 +1498,7 @@
         final int behavior = mLastBehavior;
         boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
                 ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
-                : mNavigationBar != null && mNavigationBar.getControllableInsetProvider() != null
-                        && mNavigationBar.getControllableInsetProvider().isClientVisible()
-                        && !mDisplayContent.getInsetsPolicy().isTransient(ITYPE_NAVIGATION_BAR);
+                : isNavigationBarRequestedVisible();
         boolean navTranslucent = (sysui
                 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
         boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0
@@ -1533,6 +1535,14 @@
         mLastNotificationShadeForcesShowingNavigation = notificationShadeForcesShowingNavigation;
     }
 
+    boolean isNavigationBarRequestedVisible() {
+        final InsetsSourceProvider provider =
+                mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR);
+        return provider == null
+                ? InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR)
+                : provider.isClientVisible();
+    }
+
     void updateHideNavInputEventReceiver(boolean navVisible, boolean navAllowedHidden) {
         // When the navigation bar isn't visible, we put up a fake input window to catch all
         // touch events. This way we can detect when the user presses anywhere to bring back the
@@ -2653,8 +2663,8 @@
                     if (mStatusBarController.setBarShowingLw(true)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     }
-                } else if (topIsFullscreen
-                        && !mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
+                } else if (topIsFullscreen && !mDisplayContent.getDefaultTaskDisplayArea()
+                        .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
                     if (mStatusBarController.setBarShowingLw(false)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
@@ -3246,9 +3256,14 @@
                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
         final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
                 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
-        mService.getStackBounds(
-                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
-        final boolean inSplitScreen = !mDockedStackBounds.isEmpty();
+        final boolean inSplitScreen =
+                mService.mRoot.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
+        if (inSplitScreen) {
+            mService.getStackBounds(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
+                    mDockedStackBounds);
+        } else {
+            mDockedStackBounds.setEmpty();
+        }
         mService.getStackBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                         : WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
@@ -3457,10 +3472,10 @@
     }
 
     private Pair<Integer, WindowState> updateSystemBarsLw(WindowState win, int oldVis, int vis) {
-        final boolean dockedStackVisible =
-                mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        final boolean freeformStackVisible =
-                mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM);
+        final boolean dockedStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
+                .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        final boolean freeformStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
+                .isStackVisible(WINDOWING_MODE_FREEFORM);
         final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
 
         // We need to force system bars when the docked stack is visible, when the freeform stack
@@ -3874,10 +3889,10 @@
                 WindowManager.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.MATCH_PARENT);
         lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
-        lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
-                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+        lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+        lp.setFitInsetsTypes(0);
         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
         if (ActivityManager.isHighEndGfx()) {
             lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index af89a05..bef80f0 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -594,7 +594,8 @@
 
         // In the presence of the PINNED stack or System Alert windows we unfortunately can not
         // seamlessly rotate.
-        if (mDisplayContent.hasPinnedTask() || mDisplayContent.hasAlertWindowSurfaces()) {
+        if (mDisplayContent.getDefaultTaskDisplayArea().hasPinnedTask()
+                || mDisplayContent.hasAlertWindowSurfaces()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index a9a9df8..a606668 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -153,10 +153,11 @@
         t.reparent(mInputSurface, wc.getSurfaceControl());
     }
 
-    void disposeChannelsLw() {
+    void disposeChannelsLw(SurfaceControl.Transaction t) {
         mService.mInputManager.unregisterInputChannel(mServerChannel);
         mClientChannel.dispose();
         mServerChannel.dispose();
+        t.remove(mInputSurface);
         unlinkFromDeathRecipient();
     }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 18332b9..8b34b9b 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -112,8 +112,9 @@
         @Override
         public void dispose() {
             synchronized (mService.mGlobalLock) {
-                disposeChannelsLw();
+                disposeChannelsLw(mInputMonitor.mInputTransaction);
                 mInputEventReceiver.dispose();
+                mInputMonitor.updateInputWindowsLw(true /* force */);
             }
         }
     }
@@ -195,8 +196,7 @@
 
     private boolean disposeInputConsumer(InputConsumerImpl consumer) {
         if (consumer != null) {
-            consumer.disposeChannelsLw();
-            consumer.hide(mInputTransaction);
+            consumer.disposeChannelsLw(mInputTransaction);
             return true;
         }
         return false;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 9e954f2..61a199a 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -99,7 +99,7 @@
     }
 
     private void updateHideNavInputEventReceiver() {
-        mPolicy.updateHideNavInputEventReceiver(!isHidden(ITYPE_NAVIGATION_BAR),
+        mPolicy.updateHideNavInputEventReceiver(mPolicy.isNavigationBarRequestedVisible(),
                 mFocusedWin != null
                         && mFocusedWin.mAttrs.insetsFlags.behavior != BEHAVIOR_SHOW_BARS_BY_TOUCH);
     }
@@ -295,16 +295,19 @@
     }
 
     private boolean forceShowsSystemBarsForWindowingMode() {
-        final boolean isDockedStackVisible =
-                mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        final boolean isFreeformStackVisible =
-                mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM);
+        final boolean isDockedStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
+                .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        final boolean isFreeformStackVisible = mDisplayContent.getDefaultTaskDisplayArea()
+                .isStackVisible(WINDOWING_MODE_FREEFORM);
         final boolean isResizing = mDisplayContent.getDockedDividerController().isResizing();
 
         // We need to force system bars when the docked stack is visible, when the freeform stack
         // is visible but also when we are resizing for the transitions when docked stack
         // visibility changes.
-        return isDockedStackVisible || isFreeformStackVisible || isResizing;
+        return isDockedStackVisible
+                || isFreeformStackVisible
+                || isResizing
+                || mPolicy.getForceShowSystemBars();
     }
 
     @VisibleForTesting
@@ -398,7 +401,7 @@
 
             /** Called on SurfaceAnimationThread without global WM lock held. */
             @Override
-            public void scheduleApplyChangeInsets() {
+            public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
                 InsetsState state = getState();
                 if (mAnimationControl.applyChangeInsets(state)) {
                     mAnimationControl.finish(mAnimatingShown);
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 04454a5..ba14d48 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -227,10 +227,19 @@
         for (int i = mProviders.size() - 1; i >= 0; i--) {
             mProviders.valueAt(i).onPostLayout();
         }
+        final ArrayList<WindowState> winInsetsChanged = mDisplayContent.mWinInsetsChanged;
         if (!mLastState.equals(mState)) {
             mLastState.set(mState, true /* copySources */);
             notifyInsetsChanged();
+        } else {
+            // The global insets state has not changed but there might be windows whose conditions
+            // (e.g., z-order) have changed. They can affect the insets states that we dispatch to
+            // the clients.
+            for (int i = winInsetsChanged.size() - 1; i >= 0; i--) {
+                winInsetsChanged.get(i).notifyInsetsChanged();
+            }
         }
+        winInsetsChanged.clear();
     }
 
     void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index a936e74..f672394 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -406,11 +406,12 @@
             // show on top of the lock screen. In this can we want to dismiss the docked
             // stack since it will be complicated/risky to try to put the activity on top
             // of the lock screen in the right fullscreen configuration.
-            final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-            if (!display.mTaskContainers.isSplitScreenModeActivated()) {
+            final TaskDisplayArea taskDisplayArea = mRootWindowContainer
+                    .getDefaultTaskDisplayArea();
+            if (!taskDisplayArea.isSplitScreenModeActivated()) {
                 return;
             }
-            display.mTaskContainers.onSplitScreenModeDismissed();
+            taskDisplayArea.onSplitScreenModeDismissed();
         }
     }
 
@@ -528,11 +529,14 @@
          * occlusion state.
          */
         private ActivityStack getStackForControllingOccluding(DisplayContent display) {
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                if (stack != null && stack.isFocusableAndVisible()
-                        && !stack.inPinnedWindowingMode()) {
-                    return stack;
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    if (stack != null && stack.isFocusableAndVisible()
+                            && !stack.inPinnedWindowingMode()) {
+                        return stack;
+                    }
                 }
             }
             return null;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 66dbfd5..02a2741 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -286,7 +286,8 @@
             }
             try {
                 final Rect animatingBounds = new Rect();
-                final ActivityStack pinnedStack = mDisplayContent.getRootPinnedTask();
+                final ActivityStack pinnedStack = mDisplayContent.getDefaultTaskDisplayArea()
+                        .getRootPinnedTask();
                 if (pinnedStack != null) {
                     pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
                 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 08b0abf..a031fe8 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -52,14 +52,14 @@
  * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
  */
 class RecentsAnimation implements RecentsAnimationCallbacks,
-        DisplayContent.OnStackOrderChangedListener {
+        TaskDisplayArea.OnStackOrderChangedListener {
     private static final String TAG = RecentsAnimation.class.getSimpleName();
 
     private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
     private final ActivityStartController mActivityStartController;
     private final WindowManagerService mWindowManager;
-    private final DisplayContent mDefaultDisplay;
+    private final TaskDisplayArea mDefaultTaskDisplayArea;
     private final Intent mTargetIntent;
     private final ComponentName mRecentsComponent;
     private final @Nullable String mRecentsFeatureId;
@@ -84,7 +84,7 @@
             int recentsUid, @Nullable WindowProcessController caller) {
         mService = atm;
         mStackSupervisor = stackSupervisor;
-        mDefaultDisplay = mService.mRootWindowContainer.getDefaultDisplay();
+        mDefaultTaskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea();
         mActivityStartController = activityStartController;
         mWindowManager = wm;
         mTargetIntent = targetIntent;
@@ -107,7 +107,7 @@
     void preloadRecentsActivity() {
         ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Preload recents with %s",
                 mTargetIntent);
-        ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
+        ActivityStack targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
                 mTargetActivityType);
         ActivityRecord targetActivity = getTargetActivity(targetStack);
         if (targetActivity != null) {
@@ -128,7 +128,8 @@
             // Create the activity record. Because the activity is invisible, this doesn't really
             // start the client.
             startRecentsActivityInBackground("preloadRecents");
-            targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType);
+            targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
+                    mTargetActivityType);
             targetActivity = getTargetActivity(targetStack);
             if (targetActivity == null) {
                 Slog.w(TAG, "Cannot start " + mTargetIntent);
@@ -176,12 +177,11 @@
         }
 
         // If the activity is associated with the recents stack, then try and get that first
-        ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
+        ActivityStack targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
                 mTargetActivityType);
         ActivityRecord targetActivity = getTargetActivity(targetStack);
         final boolean hasExistingActivity = targetActivity != null;
         if (hasExistingActivity) {
-            final TaskDisplayArea taskDisplayArea = targetActivity.getDisplayArea();
             mRestoreTargetBehindStack = getStackAbove(targetStack);
             if (mRestoreTargetBehindStack == null) {
                 notifyAnimationCancelBeforeStart(recentsAnimationRunner);
@@ -209,7 +209,7 @@
         try {
             if (hasExistingActivity) {
                 // Move the recents activity into place for the animation if it is not top most
-                mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(targetStack);
+                mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(targetStack);
                 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
                         targetStack, getStackAbove(targetStack));
 
@@ -225,10 +225,10 @@
                 startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
 
                 // Move the recents activity into place for the animation
-                targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
+                targetStack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
                         mTargetActivityType);
                 targetActivity = getTargetActivity(targetStack);
-                mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(targetStack);
+                mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(targetStack);
                 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
                         targetStack, getStackAbove(targetStack));
 
@@ -251,7 +251,7 @@
             mWindowManager.cancelRecentsAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION,
                     "startRecentsActivity");
             mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
-                    this, mDefaultDisplay.getDisplayId(),
+                    this, mDefaultTaskDisplayArea.getDisplayId(),
                     mStackSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity);
 
             // If we updated the launch-behind state, update the visibility of the activities after
@@ -262,7 +262,7 @@
                     START_TASK_TO_FRONT, targetActivity);
 
             // Register for stack order changes
-            mDefaultDisplay.registerStackOrderChangedListener(this);
+            mDefaultTaskDisplayArea.registerStackOrderChangedListener(this);
         } catch (Exception e) {
             Slog.e(TAG, "Failed to start recents activity", e);
             throw e;
@@ -280,7 +280,7 @@
                             mWindowManager.getRecentsAnimationController(), reorderMode);
 
             // Unregister for stack order changes
-            mDefaultDisplay.unregisterStackOrderChangedListener(this);
+            mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(this);
 
             final RecentsAnimationController controller =
                     mWindowManager.getRecentsAnimationController();
@@ -308,7 +308,7 @@
                 try {
                     mWindowManager.cleanupRecentsAnimation(reorderMode);
 
-                    final ActivityStack targetStack = mDefaultDisplay.getStack(
+                    final ActivityStack targetStack = mDefaultTaskDisplayArea.getStack(
                             WINDOWING_MODE_UNDEFINED, mTargetActivityType);
                     // Prefer to use the original target activity instead of top activity because
                     // we may have moved another task to top (starting 3p launcher).
@@ -422,7 +422,7 @@
     @Override
     public void onStackOrderChanged(ActivityStack stack) {
         ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onStackOrderChanged(): stack=%s", stack);
-        if (mDefaultDisplay.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) {
+        if (mDefaultTaskDisplayArea.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) {
             // The stack is not visible, so ignore this change
             return;
         }
@@ -480,8 +480,8 @@
      * @return The top stack that is not always-on-top.
      */
     private ActivityStack getTopNonAlwaysOnTopStack() {
-        for (int i = mDefaultDisplay.getStackCount() - 1; i >= 0; i--) {
-            final ActivityStack s = mDefaultDisplay.getStackAt(i);
+        for (int i = mDefaultTaskDisplayArea.getStackCount() - 1; i >= 0; i--) {
+            final ActivityStack s = mDefaultTaskDisplayArea.getStackAt(i);
             if (s.getWindowConfiguration().isAlwaysOnTop()) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index a30b70d..6fda117 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -340,9 +340,11 @@
 
         // Make leashes for each of the visible/target tasks and add it to the recents animation to
         // be started
-        final ArrayList<Task> visibleTasks = mDisplayContent.getVisibleTasks();
-        final ActivityStack targetStack = mDisplayContent.getStack(WINDOWING_MODE_UNDEFINED,
-                targetActivityType);
+        // TODO(b/153090560): Support Recents on multiple task display areas
+        final ArrayList<Task> visibleTasks = mDisplayContent.getDefaultTaskDisplayArea()
+                .getVisibleTasks();
+        final ActivityStack targetStack = mDisplayContent.getDefaultTaskDisplayArea()
+                .getStack(WINDOWING_MODE_UNDEFINED, targetActivityType);
         if (targetStack != null) {
             final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
 	            { if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
@@ -385,7 +387,8 @@
         }
 
         // Save the minimized home height
-        mMinimizedHomeBounds = mDisplayContent.getRootHomeTask().getBounds();
+        mMinimizedHomeBounds = mDisplayContent.getDefaultTaskDisplayArea().getRootHomeTask()
+                .getBounds();
 
         mService.mWindowPlacerLocked.performSurfacePlacement();
 
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index 770c088..32de699 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -232,10 +232,11 @@
         }
 
         final ActivityTaskManagerService atmService = mTargetStack.mAtmService;
-        DisplayContent display = mTargetStack.getDisplay();
-        final boolean singleTaskInstanceDisplay = display.isSingleTaskInstance();
+        TaskDisplayArea taskDisplayArea = mTargetStack.getDisplayArea();
+        final boolean singleTaskInstanceDisplay =
+                taskDisplayArea.mDisplayContent.isSingleTaskInstance();
         if (singleTaskInstanceDisplay) {
-            display = atmService.mRootWindowContainer.getDefaultDisplay();
+            taskDisplayArea = atmService.mRootWindowContainer.getDefaultTaskDisplayArea();
         }
 
         final int windowingMode = mTargetStack.getWindowingMode();
@@ -246,7 +247,7 @@
             final boolean alwaysCreateTask = DisplayContent.alwaysCreateStack(windowingMode,
                     activityType);
             final Task task = alwaysCreateTask
-                    ? display.getBottomMostTask() : mTargetStack.getBottomMostTask();
+                    ? taskDisplayArea.getBottomMostTask() : mTargetStack.getBottomMostTask();
             Task targetTask = null;
             if (task != null && r.taskAffinity.equals(task.affinity)) {
                 // If the activity currently at the bottom has the same task affinity as
@@ -257,7 +258,7 @@
             }
             if (targetTask == null) {
                 if (alwaysCreateTask) {
-                    targetTask = display.mTaskContainers.getOrCreateStack(windowingMode,
+                    targetTask = taskDisplayArea.getOrCreateStack(windowingMode,
                             activityType, false /* onTop */);
                 } else {
                     targetTask = mTargetStack.reuseOrCreateTask(r.info, null /*intent*/,
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2764b12..80b8b58 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -178,7 +178,7 @@
 
     private Object mLastWindowFreezeSource = null;
     private Session mHoldScreen = null;
-    private float mScreenBrightness = -1;
+    private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
     private long mUserActivityTimeout = -1;
     private boolean mUpdateRotation = false;
     // Following variables are for debugging screen wakelock only.
@@ -826,7 +826,7 @@
         }
 
         mHoldScreen = null;
-        mScreenBrightness = -1;
+        mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         mUserActivityTimeout = -1;
         mObscureApplicationContentOnSecondaryDisplays = false;
         mSustainedPerformanceModeCurrent = false;
@@ -936,12 +936,14 @@
 
         mWmService.setHoldScreenLocked(mHoldScreen);
         if (!mWmService.mDisplayFrozen) {
-            final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
-                    ? -1 : toBrightnessOverride(mScreenBrightness);
-
+            final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN
+                    || mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX
+                    ? PowerManager.BRIGHTNESS_INVALID_FLOAT : mScreenBrightnessOverride;
+            int brightnessFloatAsIntBits = Float.floatToIntBits(brightnessOverride);
             // Post these on a handler such that we don't call into power manager service while
             // holding the window manager lock to avoid lock contention with power manager lock.
-            mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightness, 0).sendToTarget();
+            mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightnessFloatAsIntBits,
+                    0).sendToTarget();
             mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
         }
 
@@ -1125,8 +1127,9 @@
                                 + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
                         w, Debug.getCallers(10));
             }
-            if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
-                mScreenBrightness = w.mAttrs.screenBrightness;
+            if (!syswin && w.mAttrs.screenBrightness >= 0
+                    && Float.isNaN(mScreenBrightnessOverride)) {
+                mScreenBrightnessOverride = w.mAttrs.screenBrightness;
             }
 
             final int type = attrs.type;
@@ -1190,10 +1193,6 @@
         return doRequest;
     }
 
-    private static int toBrightnessOverride(float value) {
-        return (int)(value * PowerManager.BRIGHTNESS_ON);
-    }
-
     private final class MyHandler extends Handler {
 
         public MyHandler(Looper looper) {
@@ -1205,7 +1204,7 @@
             switch (msg.what) {
                 case SET_SCREEN_BRIGHTNESS_OVERRIDE:
                     mWmService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
-                            msg.arg1);
+                            Float.intBitsToFloat(msg.arg1));
                     break;
                 case SET_USER_ACTIVITY_TIMEOUT:
                     mWmService.mPowerManagerInternal.
@@ -1369,11 +1368,11 @@
         }
         calculateDefaultMinimalSizeOfResizeableTasks();
 
-        final DisplayContent defaultDisplay = getDefaultDisplay();
-
-        defaultDisplay.mTaskContainers.getOrCreateStack(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_HOME, ON_TOP);
-        positionChildAt(POSITION_TOP, defaultDisplay, false /* includingParents */);
+        final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();
+        defaultTaskDisplayArea.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME,
+                ON_TOP);
+        positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent,
+                false /* includingParents */);
     }
 
     // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
@@ -1382,6 +1381,16 @@
     }
 
     /**
+     * Get the default display area on the device dedicated to app windows. This one should be used
+     * only as a fallback location for activity launches when no target display area is specified,
+     * or for cases when multi-instance is not supported yet (like Split-screen, Freeform, PiP or
+     * Recents).
+     */
+    TaskDisplayArea getDefaultTaskDisplayArea() {
+        return mDefaultDisplay.getDefaultTaskDisplayArea();
+    }
+
+    /**
      * Get an existing instance of {@link DisplayContent} that has the given uniqueId. Unique ID is
      * defined in {@link DisplayInfo#uniqueId}.
      *
@@ -1436,12 +1445,8 @@
         return displayContent;
     }
 
-    ActivityRecord getDefaultDisplayHomeActivity() {
-        return getDefaultDisplayHomeActivityForUser(mCurrentUser);
-    }
-
     ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
-        return getDisplayContent(DEFAULT_DISPLAY).mTaskContainers.getHomeActivityForUser(userId);
+        return getDefaultTaskDisplayArea().getHomeActivityForUser(userId);
     }
 
     boolean startHomeOnAllDisplays(int userId, String reason) {
@@ -1637,7 +1642,9 @@
             displayId = DEFAULT_DISPLAY;
         }
 
-        final ActivityRecord r = getDisplayContent(displayId).mTaskContainers.getHomeActivity();
+        // TODO(multi-display-area): Resume home on the right task container
+        final ActivityRecord r = getDisplayContent(displayId).getDefaultTaskDisplayArea()
+                .getHomeActivity();
         final String myReason = reason + " resumeHomeActivity";
 
         // Only resume home activity if isn't finishing.
@@ -1794,19 +1801,23 @@
         final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
         final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
         // Traverse all displays.
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            final DisplayContent display = getChildAt(i);
-            // Traverse all stacks on a display.
-            for (int j = display.getStackCount() - 1; j >= 0; --j) {
-                final ActivityStack stack = display.getStackAt(j);
-                // Get top activity from a visible stack and add it to the list.
-                if (stack.shouldBeVisible(null /* starting */)) {
-                    final ActivityRecord top = stack.getTopNonFinishingActivity();
-                    if (top != null) {
-                        if (stack == topFocusedStack) {
-                            topActivityTokens.add(0, top.appToken);
-                        } else {
-                            topActivityTokens.add(top.appToken);
+        for (int dNdx = getChildCount() - 1; dNdx >= 0; dNdx--) {
+            final DisplayContent display = getChildAt(dNdx);
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea =
+                        display.getTaskDisplayAreaAt(tdaNdx);
+                // Traverse all stacks on a display area.
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    // Get top activity from a visible stack and add it to the list.
+                    if (stack.shouldBeVisible(null /* starting */)) {
+                        final ActivityRecord top = stack.getTopNonFinishingActivity();
+                        if (top != null) {
+                            if (stack == topFocusedStack) {
+                                topActivityTokens.add(0, top.appToken);
+                            } else {
+                                topActivityTokens.add(top.appToken);
+                            }
                         }
                     }
                 }
@@ -1838,10 +1849,13 @@
         // focus order.
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final DisplayContent display = getChildAt(i);
-            final ActivityRecord resumedActivityOnDisplay = display.mTaskContainers
-                    .getResumedActivity();
-            if (resumedActivityOnDisplay != null) {
-                return resumedActivityOnDisplay;
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                final ActivityRecord resumedActivityOnTaskContainer = taskDisplayArea
+                        .getFocusedActivity();
+                if (resumedActivityOnTaskContainer != null) {
+                    return resumedActivityOnTaskContainer;
+                }
             }
         }
         return null;
@@ -1861,16 +1875,19 @@
         WindowProcessController fgApp = null;
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                if (isTopDisplayFocusedStack(stack)) {
-                    final ActivityRecord resumedActivity = stack.getResumedActivity();
-                    if (resumedActivity != null) {
-                        fgApp = resumedActivity.app;
-                    } else if (stack.mPausingActivity != null) {
-                        fgApp = stack.mPausingActivity.app;
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    if (isTopDisplayFocusedStack(stack)) {
+                        final ActivityRecord resumedActivity = stack.getResumedActivity();
+                        if (resumedActivity != null) {
+                            fgApp = resumedActivity.app;
+                        } else if (stack.mPausingActivity != null) {
+                            fgApp = stack.mPausingActivity.app;
+                        }
+                        break;
                     }
-                    break;
                 }
             }
         }
@@ -1972,8 +1989,8 @@
         final int focusStackId = topFocusedStack != null
                 ? topFocusedStack.getRootTaskId() : INVALID_TASK_ID;
         // We dismiss the docked stack whenever we switch users.
-        if (getDefaultDisplay().mTaskContainers.isSplitScreenModeActivated()) {
-            getDefaultDisplay().mTaskContainers.onSplitScreenModeDismissed();
+        if (getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
+            getDefaultTaskDisplayArea().onSplitScreenModeDismissed();
         }
         // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
         // also cause all tasks to be moved to the fullscreen stack at a position that is
@@ -1986,16 +2003,19 @@
         mStackSupervisor.mStartingUsers.add(uss);
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                stack.switchUser(userId);
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    stack.switchUser(userId);
+                }
             }
         }
 
         final int restoreStackId = mUserStackInFront.get(userId);
         ActivityStack stack = getStack(restoreStackId);
         if (stack == null) {
-            stack = getDefaultDisplay().mTaskContainers.getOrCreateRootHomeTask();
+            stack = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
         }
         final boolean homeInFront = stack.isActivityTypeHome();
         if (stack.isOnHomeDisplay()) {
@@ -2018,7 +2038,7 @@
     void updateUserStack(int userId, ActivityStack stack) {
         if (userId != mCurrentUser) {
             if (stack == null) {
-                stack = getDefaultDisplay().mTaskContainers.getOrCreateRootHomeTask();
+                stack = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
             }
 
             mUserStackInFront.put(userId, stack.getRootTaskId());
@@ -2061,7 +2081,7 @@
             return;
         }
 
-        stack.reparent(displayContent.mDisplayContent, onTop);
+        stack.reparent(displayContent.getDefaultTaskDisplayArea(), onTop);
         // TODO(multi-display): resize stacks properly if moved from split-screen.
     }
 
@@ -2155,8 +2175,8 @@
         // Looking up task on preferred display first
         final DisplayContent preferredDisplay = getDisplayContent(preferredDisplayId);
         if (preferredDisplay != null) {
-            preferredDisplay.mTaskContainers.findTaskLocked(r, true /* isPreferredDisplay */,
-                    mTmpFindTaskResult);
+            preferredDisplay.getDefaultTaskDisplayArea().findTaskLocked(r,
+                    true /* isPreferredDisplay */, mTmpFindTaskResult);
             if (mTmpFindTaskResult.mIdealMatch) {
                 return mTmpFindTaskResult.mRecord;
             }
@@ -2168,7 +2188,7 @@
                 continue;
             }
 
-            display.mTaskContainers.findTaskLocked(r, false /* isPreferredDisplay */,
+            display.getDefaultTaskDisplayArea().findTaskLocked(r, false /* isPreferredDisplay */,
                     mTmpFindTaskResult);
             if (mTmpFindTaskResult.mIdealMatch) {
                 return mTmpFindTaskResult.mRecord;
@@ -2190,13 +2210,17 @@
         ActivityStack focusedStack = getTopDisplayFocusedStack();
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            // It is possible that request to finish activity might also remove its task and stack,
-            // so we need to be careful with indexes in the loop and check child count every time.
-            for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                final Task t = stack.finishTopCrashedActivityLocked(app, reason);
-                if (stack == focusedStack || finishedTask == null) {
-                    finishedTask = t;
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                // It is possible that request to finish activity might also remove its task and
+                // stack, so we need to be careful with indexes in the loop and check child count
+                // every time.
+                for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(stackNdx);
+                    final Task t = stack.finishTopCrashedActivityLocked(app, reason);
+                    if (stack == focusedStack || finishedTask == null) {
+                        finishedTask = t;
+                    }
                 }
             }
         }
@@ -2223,26 +2247,29 @@
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             boolean resumedOnDisplay = false;
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                final ActivityRecord topRunningActivity = stack.topRunningActivity();
-                if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
-                    continue;
-                }
-                if (stack == targetStack) {
-                    // Simply update the result for targetStack because the targetStack had
-                    // already resumed in above. We don't want to resume it again, especially in
-                    // some cases, it would cause a second launch failure if app process was dead.
-                    resumedOnDisplay |= result;
-                    continue;
-                }
-                if (display.mTaskContainers.isTopStack(stack)
-                        && topRunningActivity.isState(RESUMED)) {
-                    // Kick off any lingering app transitions form the MoveTaskToFront operation,
-                    // but only consider the top task and stack on that display.
-                    stack.executeAppTransition(targetOptions);
-                } else {
-                    resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    final ActivityRecord topRunningActivity = stack.topRunningActivity();
+                    if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
+                        continue;
+                    }
+                    if (stack == targetStack) {
+                        // Simply update the result for targetStack because the targetStack had
+                        // already resumed in above. We don't want to resume it again, especially in
+                        // some cases, it would cause a second launch failure if app process was
+                        // dead.
+                        resumedOnDisplay |= result;
+                        continue;
+                    }
+                    if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
+                        // Kick off any lingering app transitions form the MoveTaskToFront
+                        // operation, but only consider the top task and stack on that display.
+                        stack.executeAppTransition(targetOptions);
+                    } else {
+                        resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
+                    }
                 }
             }
             if (!resumedOnDisplay) {
@@ -2278,32 +2305,37 @@
             }
 
             // Set the sleeping state of the stacks on the display.
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                if (displayShouldSleep) {
-                    stack.goToSleepIfPossible(false /* shuttingDown */);
-                } else {
-                    // When the display which can only contain one task turns on, start a special
-                    // transition. {@link AppTransitionController#handleAppTransitionReady} later
-                    // picks up the transition, and schedules
-                    // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
-                    // triggered after contents are drawn on the display.
-                    if (display.isSingleTaskInstance()) {
-                        display.mDisplayContent.prepareAppTransition(
-                                TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
-                    }
-                    stack.awakeFromSleepingLocked();
-                    if (display.isSingleTaskInstance()) {
-                        display.executeAppTransition();
-                    }
-                    if (stack.isFocusedStackOnDisplay()
-                            && !mStackSupervisor.getKeyguardController()
-                            .isKeyguardOrAodShowing(display.mDisplayId)) {
-                        // If the keyguard is unlocked - resume immediately.
-                        // It is possible that the display will not be awake at the time we
-                        // process the keyguard going away, which can happen before the sleep token
-                        // is released. As a result, it is important we resume the activity here.
-                        resumeFocusedStacksTopActivities();
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    if (displayShouldSleep) {
+                        stack.goToSleepIfPossible(false /* shuttingDown */);
+                    } else {
+                        // When the display which can only contain one task turns on, start a
+                        // special transition.
+                        // {@link AppTransitionController#handleAppTransitionReady} later picks up
+                        // the transition, and schedules
+                        // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
+                        // triggered after contents are drawn on the display.
+                        if (display.isSingleTaskInstance()) {
+                            display.mDisplayContent.prepareAppTransition(
+                                    TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
+                        }
+                        stack.awakeFromSleepingLocked();
+                        if (display.isSingleTaskInstance()) {
+                            display.executeAppTransition();
+                        }
+                        if (stack.isFocusedStackOnDisplay()
+                                && !mStackSupervisor.getKeyguardController()
+                                .isKeyguardOrAodShowing(display.mDisplayId)) {
+                            // If the keyguard is unlocked - resume immediately.
+                            // It is possible that the display will not be awake at the time we
+                            // process the keyguard going away, which can happen before the sleep
+                            // token is released. As a result, it is important we resume the
+                            // activity here.
+                            resumeFocusedStacksTopActivities();
+                        }
                     }
                 }
             }
@@ -2312,7 +2344,7 @@
 
     protected ActivityStack getStack(int stackId) {
         for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = getChildAt(i).mTaskContainers.getStack(stackId);
+            final ActivityStack stack = getChildAt(i).getStack(stackId);
             if (stack != null) {
                 return stack;
             }
@@ -2408,9 +2440,12 @@
         if (displayId == INVALID_DISPLAY) {
             for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
                 final DisplayContent display = getChildAt(displayNdx);
-                for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                    final ActivityStack stack = display.getStackAt(stackNdx);
-                    list.add(getStackInfo(stack));
+                for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                    final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                    for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                        final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                        list.add(getStackInfo(stack));
+                    }
                 }
             }
             return list;
@@ -2419,9 +2454,12 @@
         if (display == null) {
             return list;
         }
-        for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = display.getStackAt(stackNdx);
-            list.add(getStackInfo(stack));
+        for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                list.add(getStackInfo(stack));
+            }
         }
         return list;
     }
@@ -2640,19 +2678,21 @@
         boolean allSleep = true;
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                // Stacks and activities could be removed while putting activities to sleep if
-                // the app process was gone. This prevents us getting exception by accessing an
-                // invalid stack index.
-                if (stackNdx >= display.getStackCount()) {
-                    continue;
-                }
-
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                if (allowDelay) {
-                    allSleep &= stack.goToSleepIfPossible(shuttingDown);
-                } else {
-                    stack.goToSleep();
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    // Stacks and activities could be removed while putting activities to sleep if
+                    // the app process was gone. This prevents us getting exception by accessing an
+                    // invalid stack index.
+                    if (sNdx >= taskDisplayArea.getStackCount()) {
+                        continue;
+                    }
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    if (allowDelay) {
+                        allSleep &= stack.goToSleepIfPossible(shuttingDown);
+                    } else {
+                        stack.goToSleep();
+                    }
                 }
             }
         }
@@ -2788,8 +2828,10 @@
             }
             final DisplayContent display = getDisplayContentOrCreate(displayId);
             if (display != null) {
-                stack = display.mTaskContainers.getOrCreateStack(r, options, candidateTask,
-                        activityType, onTop);
+                // Falling back to default task container
+                final TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
+                stack = taskDisplayArea.getOrCreateStack(r, options, candidateTask, activityType,
+                        onTop);
                 if (stack != null) {
                     return stack;
                 }
@@ -2835,7 +2877,7 @@
 
         if (container == null
                 || !canLaunchOnDisplay(r, container.mDisplayContent.mDisplayId)) {
-            container = getDefaultDisplay().mTaskContainers;
+            container = getDefaultTaskDisplayArea();
             if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
                 windowingMode = container.resolveWindowingMode(r, options, candidateTask,
                         activityType);
@@ -2887,7 +2929,7 @@
             // it to the target display.
             if (candidateTask.isRootTask()) {
                 final ActivityStack stack = candidateTask.getStack();
-                displayContent.moveStackToDisplay(stack, true /* onTop */);
+                stack.reparent(displayContent.getDefaultTaskDisplayArea(), true /* onTop */);
                 return stack;
             }
         }
@@ -2902,14 +2944,17 @@
             windowingMode = options != null ? options.getLaunchWindowingMode()
                     : r.getWindowingMode();
         }
-        windowingMode = displayContent.mTaskContainers.validateWindowingMode(windowingMode, r,
-                candidateTask, r.getActivityType());
 
         // Return the topmost valid stack on the display.
-        for (int i = displayContent.getStackCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = displayContent.getStackAt(i);
-            if (isValidLaunchStack(stack, r, windowingMode)) {
-                return stack;
+        for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
+            final int validatedWindowingMode = taskDisplayArea
+                    .validateWindowingMode(windowingMode, r, candidateTask, r.getActivityType());
+            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                if (isValidLaunchStack(stack, r, validatedWindowingMode)) {
+                    return stack;
+                }
             }
         }
 
@@ -2918,7 +2963,8 @@
             final int activityType =
                     options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
                             ? options.getLaunchActivityType() : r.getActivityType();
-            return displayContent.createStack(windowingMode, activityType, true /*onTop*/);
+            final TaskDisplayArea taskDisplayArea = displayContent.getDefaultTaskDisplayArea();
+            return taskDisplayArea.createStack(windowingMode, activityType, true /*onTop*/);
         }
 
         return null;
@@ -2989,7 +3035,8 @@
         if (preferredDisplayArea == null) {
             // Stack is currently detached because it is being removed. Use the previous display it
             // was on.
-            preferredDisplayArea = getDisplayContent(currentFocus.mPrevDisplayId).mTaskContainers;
+            preferredDisplayArea = getDisplayContent(currentFocus.mPrevDisplayId)
+                    .getDefaultTaskDisplayArea();
         }
         final ActivityStack preferredFocusableStack = preferredDisplayArea.getNextFocusableStack(
                 currentFocus, ignoreCurrent);
@@ -3010,7 +3057,7 @@
                 // We've already checked this one
                 continue;
             }
-            final ActivityStack nextFocusableStack = display.mTaskContainers
+            final ActivityStack nextFocusableStack = display.getDefaultTaskDisplayArea()
                     .getNextFocusableStack(currentFocus, ignoreCurrent);
             if (nextFocusableStack != null) {
                 return nextFocusableStack;
@@ -3020,38 +3067,16 @@
         return null;
     }
 
-    /**
-     * Get next valid stack for launching provided activity in the system. This will search across
-     * displays and stacks in last-focused order for a focusable and visible stack, except those
-     * that are on a currently focused display.
-     *
-     * @param r The activity that is being launched.
-     * @param currentFocus The display that previously had focus and thus needs to be ignored when
-     *                     searching for the next candidate.
-     * @return Next valid {@link ActivityStack}, null if not found.
-     */
-    ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final DisplayContent display = getChildAt(i);
-            if (display.mDisplayId == currentFocus) {
-                continue;
-            }
-            final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
-                    null /* options */, null /* launchParams */);
-            if (stack != null) {
-                return stack;
-            }
-        }
-        return null;
-    }
-
     boolean handleAppDied(WindowProcessController app) {
         boolean hasVisibleActivities = false;
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                hasVisibleActivities |= stack.handleAppDied(app);
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    hasVisibleActivities |= stack.handleAppDied(app);
+                }
             }
         }
         return hasVisibleActivities;
@@ -3162,10 +3187,14 @@
     void finishVoiceTask(IVoiceInteractionSession session) {
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            final int numStacks = display.getStackCount();
-            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                stack.finishVoiceTask(session);
+            int numTaskContainers = display.getTaskDisplayAreaCount();
+            for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                final int numStacks = display.getStackCount();
+                for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(stackNdx);
+                    stack.finishVoiceTask(session);
+                }
             }
         }
     }
@@ -3229,14 +3258,17 @@
         boolean foundResumed = false;
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                final ActivityRecord r = stack.getResumedActivity();
-                if (r != null) {
-                    if (!r.nowVisible) {
-                        return false;
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    final ActivityRecord r = stack.getResumedActivity();
+                    if (r != null) {
+                        if (!r.nowVisible) {
+                            return false;
+                        }
+                        foundResumed = true;
                     }
-                    foundResumed = true;
                 }
             }
         }
@@ -3247,16 +3279,19 @@
         boolean pausing = true;
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                final ActivityRecord r = stack.mPausingActivity;
-                if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
-                    if (DEBUG_STATES) {
-                        Slog.d(TAG_STATES,
-                                "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
-                        pausing = false;
-                    } else {
-                        return false;
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    final ActivityRecord r = stack.mPausingActivity;
+                    if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
+                        if (DEBUG_STATES) {
+                            Slog.d(TAG_STATES, "allPausedActivitiesComplete: r=" + r
+                                    + " state=" + r.getState());
+                            pausing = false;
+                        } else {
+                            return false;
+                        }
                     }
                 }
             }
@@ -3312,9 +3347,11 @@
     void cancelInitializingActivities() {
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                stack.cancelInitializingActivities();
+            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    taskDisplayArea.getStackAt(sNdx).cancelInitializingActivities();
+                }
             }
         }
     }
@@ -3417,20 +3454,23 @@
         }
 
         if (!sendHint) { // targetActivity != null
-            // Send power hint when the activity's process is different than the current resumed
-            // activity on all displays, or if there are no resumed activities in the system.
+            // Send power hint when the activity's process is different than the current top resumed
+            // activity on all display areas, or if there are no resumed activities in the system.
             boolean noResumedActivities = true;
             boolean allFocusedProcessesDiffer = true;
             for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
-                final DisplayContent displayContent = getChildAt(displayNdx);
-                final ActivityRecord resumedActivity = displayContent.mTaskContainers
-                        .getResumedActivity();
-                final WindowProcessController resumedActivityProcess =
-                        resumedActivity == null ? null : resumedActivity.app;
+                final DisplayContent dc = getChildAt(displayNdx);
+                for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                    final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+                    final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
+                    final WindowProcessController resumedActivityProcess =
+                            resumedActivity == null ? null : resumedActivity.app;
 
-                noResumedActivities &= resumedActivityProcess == null;
-                if (resumedActivityProcess != null) {
-                    allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
+                    noResumedActivities &= resumedActivityProcess == null;
+                    if (resumedActivityProcess != null) {
+                        allFocusedProcessesDiffer &= !resumedActivityProcess.equals(
+                                targetActivity.app);
+                    }
                 }
             }
             sendHint = noResumedActivities || allFocusedProcessesDiffer;
@@ -3477,10 +3517,13 @@
             int numDisplays = getChildCount();
             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
                 final DisplayContent display = getChildAt(displayNdx);
-                for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                    final ActivityStack stack = display.getStackAt(stackNdx);
-                    if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
-                        activities.addAll(stack.getDumpActivitiesLocked(name));
+                for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                    final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+                    for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                        final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                        if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
+                            activities.addAll(stack.getDumpActivitiesLocked(name));
+                        }
                     }
                 }
             }
@@ -3520,14 +3563,21 @@
             DisplayContent displayContent = getChildAt(displayNdx);
             pw.print("Display #"); pw.print(displayContent.mDisplayId);
             pw.println(" (activities from top to bottom):");
-            for (int stackNdx = displayContent.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = displayContent.getStackAt(stackNdx);
-                pw.println();
-                printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
-                needSep = printed;
+            for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
+                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                    pw.println();
+                    printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
+                    needSep = printed;
+                }
             }
-            printThisActivity(pw, displayContent.mTaskContainers.getResumedActivity(), dumpPackage,
-                    needSep, " ResumedActivity:");
+            pw.println(" (resumed activities in task display areas from top to bottom):");
+            for (int tdaNdx = displayContent.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                final TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(tdaNdx);
+                printThisActivity(pw, taskDisplayArea.getFocusedActivity(), dumpPackage, needSep,
+                        "   ResumedActivity:");
+            }
         }
 
         printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, "  ",
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 5f3732a..7d8a56e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -51,6 +51,7 @@
 import android.view.IWindowSession;
 import android.view.IWindowSessionCallback;
 import android.view.InputChannel;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
@@ -158,10 +159,10 @@
             int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
             Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
-            InsetsState outInsetsState) {
+            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
                 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
-                outInsetsState);
+                outInsetsState, outActiveControls);
     }
 
     @Override
@@ -171,7 +172,7 @@
         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                 new Rect() /* outFrame */, outContentInsets, outStableInsets,
                 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
-                outInsetsState);
+                outInsetsState, null);
     }
 
     @Override
@@ -191,7 +192,8 @@
             Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
+            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
+            SurfaceControl outBLASTSurfaceControl) {
         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
@@ -199,8 +201,8 @@
                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                 outFrame, outContentInsets, outVisibleInsets,
                 outStableInsets, outBackdropFrame, cutout,
-                mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize,
-                outBLASTSurfaceControl);
+                mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls,
+                outSurfaceSize, outBLASTSurfaceControl);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index 9732637..701feff 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -16,12 +16,20 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
+import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
+
 import android.annotation.NonNull;
+import android.graphics.Point;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.DisplayInfo;
 import android.view.IWindow;
 import android.view.SurfaceControl;
+import android.view.animation.Animation;
 
 /**
  * Represents a piece of the hierarchy under which a client Shell can manage sub-windows.
@@ -70,5 +78,29 @@
     IWindow getClient() {
         return mClient;
     }
+
+    void startAnimation(Animation anim) {
+        // Only do this for the divider
+        if (mToken.windowType != TYPE_DOCK_DIVIDER) {
+            return;
+        }
+
+        DisplayInfo displayInfo = mToken.getFixedRotationTransformDisplayInfo();
+        if (displayInfo == null) {
+            displayInfo = mDisplayContent.getDisplayInfo();
+        }
+
+        // Mostly copied from WindowState to enable keyguard transition animation
+        anim.initialize(displayInfo.logicalWidth, displayInfo.logicalHeight,
+                displayInfo.appWidth, displayInfo.appHeight);
+        anim.restrictDuration(MAX_ANIMATION_DURATION);
+        anim.scaleCurrentDuration(mDisplayContent.mWmService.getWindowAnimationScaleLocked());
+        final AnimationAdapter adapter = new LocalAnimationAdapter(
+                new WindowAnimationSpec(anim, new Point(0, 0), false /* canSkipFirstFrame */,
+                        0 /* windowCornerRadius */),
+                mDisplayContent.mWmService.mSurfaceAnimationRunner);
+        mToken.startAnimation(mToken.getPendingTransaction(), adapter, false /* hidden */,
+                ANIMATION_TYPE_WINDOW_ANIMATION, null /* animationFinishedCallback */);
+    }
 }
 
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 6358e47..18e32c0 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -202,6 +202,11 @@
         return mAnimation != null;
     }
 
+    @AnimationType
+    int getAnimationType() {
+        return mAnimationType;
+    }
+
     /**
      * @return The current animation spec if we are running an animation, or {@code null} otherwise.
      */
@@ -453,32 +458,38 @@
      * Animation for screen rotation.
      * @hide
      */
-    static final int ANIMATION_TYPE_SCREEN_ROTATION = 2;
+    static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1;
 
     /**
      * Animation for dimming.
      * @hide
      */
-    static final int ANIMATION_TYPE_DIMMER = 3;
+    static final int ANIMATION_TYPE_DIMMER = 1 << 2;
 
     /**
      * Animation for recent apps.
      * @hide
      */
-    static final int ANIMATION_TYPE_RECENTS = 4;
+    static final int ANIMATION_TYPE_RECENTS = 1 << 3;
 
     /**
      * Animation for a {@link WindowState} without animating the activity.
      * @hide
      */
-    static final int ANIMATION_TYPE_WINDOW_ANIMATION = 5;
+    static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4;
 
     /**
      * Animation to control insets. This is actually not an animation, but is used to give the
      * client a leash over the system window causing insets.
      * @hide
      */
-    static final int ANIMATION_TYPE_INSETS_CONTROL = 6;
+    static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
+
+    /**
+     * Bitmask to include all animation types. This is NOT an {@link AnimationType}
+     * @hide
+     */
+    static final int ANIMATION_TYPE_ALL = -1;
 
     /**
      * The type of the animation.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0151b82..d31939d 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2448,7 +2448,8 @@
     Rect updateOverrideConfigurationFromLaunchBounds() {
         // If the task is controlled by another organized task, do not set override
         // configurations and let its parent (organized task) to control it;
-        final Rect bounds = isOrganized() && !isRootTask() ? null : getLaunchBounds();
+        final Task rootTask = getRootTask();
+        final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds();
         setBounds(bounds);
         if (bounds != null && !bounds.isEmpty()) {
             // TODO: Review if we actually want to do this - we are setting the launch bounds
@@ -3347,6 +3348,21 @@
 
     @Override
     Dimmer getDimmer() {
+        // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
+        // bounds match the area the app lives in
+        if (inMultiWindowMode()) {
+            return mDimmer;
+        }
+
+        // If we're not at the root task level, we want to keep traversing through the parents to
+        // find the root.
+        // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
+        // If true, we want to get the Dimmer from the level above since we don't want to animate
+        // the dim with the Task.
+        if (!isRootTask() || isTranslucent(null)) {
+            return super.getDimmer();
+        }
+
         return mDimmer;
     }
 
@@ -4068,21 +4084,7 @@
 
     @Override
     boolean isOrganized() {
-        final Task rootTask = getRootTask();
-        if (rootTask.mTaskOrganizer == null) {
-            // You are obviously not organized...
-            return false;
-        }
-        if (rootTask == this) {
-            // Root tasks can be organized.
-            return true;
-        }
-        if (rootTask.mCreatedByOrganizer && getParent() == rootTask) {
-            // Direct children of tasks added by the organizer can the organized.
-            return true;
-        }
-
-        return false;
+        return mTaskOrganizer != null;
     }
 
     @Override
@@ -4119,24 +4121,23 @@
      * Any time any of these conditions are updated, the updating code should call
      * sendTaskAppeared.
      */
-    private boolean taskAppearedReady() {
+    boolean taskAppearedReady() {
         return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible();
     }
 
     private void sendTaskAppeared() {
-        if (taskAppearedReady() && !mTaskAppearedSent) {
-            mTaskAppearedSent = true;
+        if (mTaskOrganizer != null) {
             mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
         }
     }
 
     private void sendTaskVanished() {
-        if (mTaskOrganizer != null && mTaskAppearedSent) {
-            mTaskAppearedSent = false;
+        if (mTaskOrganizer != null) {
             mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this);
         }
    }
 
+    @VisibleForTesting
     boolean setTaskOrganizer(ITaskOrganizer organizer) {
         if (mTaskOrganizer == organizer) {
             return false;
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 9356ec2..ec3c99b 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -63,6 +63,7 @@
 import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.protolog.common.ProtoLog;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -127,6 +128,18 @@
      * the new stack becomes resumed after which it will be set to current focused stack.
      */
     ActivityStack mLastFocusedStack;
+    /**
+     * All of the stacks on this display. Order matters, topmost stack is in front of all other
+     * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
+     * changing the list should also call {@link #onStackOrderChanged()}.
+     */
+    private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
+
+    /**
+     * The task display area is removed from the system and we are just waiting for all activities
+     * on it to be finished before removing this object.
+     */
+    private boolean mRemoved;
 
     TaskDisplayArea(DisplayContent displayContent, WindowManagerService service) {
         super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
@@ -336,9 +349,9 @@
             // Since a stack could be repositioned while being one of the child, return
             // current index if that's the same stack we are positioning and it is always on
             // top.
-            final boolean sameStack = mDisplayContent.getStacks().get(i) == stack;
+            final boolean sameStack = mChildren.get(i) == stack;
             if ((sameStack && stack.isAlwaysOnTop())
-                    || (!sameStack && !mDisplayContent.getStacks().get(i).isAlwaysOnTop())) {
+                    || (!sameStack && !mChildren.get(i).isAlwaysOnTop())) {
                 belowAlwaysOnTopPosition = i;
                 break;
             }
@@ -352,7 +365,7 @@
         if (stack.isAlwaysOnTop()) {
             if (hasPinnedTask()) {
                 // Always-on-top stacks go below the pinned stack.
-                maxPosition = mDisplayContent.getStacks().indexOf(mRootPinnedTask) - 1;
+                maxPosition = mChildren.indexOf(mRootPinnedTask) - 1;
             }
             // Always-on-top stacks need to be above all other stacks.
             minPosition = belowAlwaysOnTopPosition
@@ -375,7 +388,7 @@
         targetPosition = Math.min(targetPosition, maxPosition);
         targetPosition = Math.max(targetPosition, minPosition);
 
-        int prevPosition = mDisplayContent.getStacks().indexOf(stack);
+        int prevPosition = mChildren.indexOf(stack);
         // The positions we calculated above (maxPosition, minPosition) do not take into
         // consideration the following edge cases.
         // 1) We need to adjust the position depending on the value "adding".
@@ -471,7 +484,7 @@
 
     @Override
     int getOrientation(int candidate) {
-        if (mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
+        if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
             // Apps and their containers are not allowed to specify an orientation while using
             // root tasks...except for the home stack if it is not resizable and currently
             // visible (top of) its root task.
@@ -637,7 +650,7 @@
             mPreferredTopFocusableStack = null;
         }
         mDisplayContent.releaseSelfIfNeeded();
-        mDisplayContent.onStackOrderChanged(stack);
+        onStackOrderChanged(stack);
     }
 
     void positionStackAt(int position, ActivityStack child, boolean includingParents) {
@@ -716,7 +729,7 @@
             }
         }
 
-        mDisplayContent.onStackOrderChanged(stack);
+        onStackOrderChanged(stack);
     }
 
     ActivityStack getStack(int rootTaskId) {
@@ -732,11 +745,11 @@
     /**
      * Returns an existing stack compatible with the windowing mode and activity type or creates one
      * if a compatible stack doesn't exist.
-     * @see #getOrCreateStack(int, int, boolean, Intent, Task, boolean)
+     * @see #getOrCreateStack(int, int, boolean, Intent, Task)
      */
     ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) {
         return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
-                null /* candidateTask */, false /* createdByOrganizer */);
+                null /* candidateTask */);
     }
 
     /**
@@ -748,8 +761,12 @@
      * @see #createStack(int, int, boolean)
      */
     ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop,
-            Intent intent, Task candidateTask, boolean createdByOrganizer) {
-        if (!alwaysCreateStack(windowingMode, activityType)) {
+            Intent intent, Task candidateTask) {
+        // Need to pass in a determined windowing mode to see if a new stack should be created,
+        // so use its parent's windowing mode if it is undefined.
+        if (!alwaysCreateStack(
+                windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(),
+                activityType)) {
             ActivityStack stack = getStack(windowingMode, activityType);
             if (stack != null) {
                 return stack;
@@ -757,19 +774,19 @@
         } else if (candidateTask != null) {
             final ActivityStack stack = (ActivityStack) candidateTask;
             final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
-            if (isSplitScreenModeActivated()) {
-                final Task splitRootSecondary = getTask(t -> t.mCreatedByOrganizer && t.isRootTask()
-                        && t.inSplitScreenSecondaryWindowingMode());
+            Task launchRootTask = updateLaunchRootTask(windowingMode);
+
+            if (launchRootTask != null) {
                 if (stack.getParent() == null) {
-                    splitRootSecondary.addChild(stack, position);
-                } else if (stack.getParent() != splitRootSecondary) {
-                    stack.reparent(splitRootSecondary, position);
+                    launchRootTask.addChild(stack, position);
+                } else if (stack.getParent() != launchRootTask) {
+                    stack.reparent(launchRootTask, position);
                 }
-            } else if (stack.getDisplay() != mDisplayContent || !stack.isRootTask()) {
+            } else if (stack.getDisplayArea() != this || !stack.isRootTask()) {
                 if (stack.getParent() == null) {
                     addStack(stack, position);
                 } else {
-                    stack.reparent(mDisplayContent, onTop);
+                    stack.reparent(this, onTop);
                 }
             }
             // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen.
@@ -779,7 +796,7 @@
             return stack;
         }
         return createStack(windowingMode, activityType, onTop, null /*info*/, intent,
-                createdByOrganizer);
+                false /* createdByOrganizer */);
     }
 
     /**
@@ -798,7 +815,7 @@
         // it's display's windowing mode.
         windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
         return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
-                candidateTask, false /* createdByOrganizer */);
+                candidateTask);
     }
 
     @VisibleForTesting
@@ -832,7 +849,7 @@
             // Create stack on default display instead since this display can only contain 1 stack.
             // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
             // this goes away once ActivityView is no longer using virtual displays.
-            return mRootWindowContainer.getDefaultDisplay().mTaskContainers.createStack(
+            return mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
                     windowingMode, activityType, onTop, info, intent, createdByOrganizer);
         }
 
@@ -919,9 +936,7 @@
             }
         } else {
             addStack(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
-            stack.setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
-                    false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
-                    true /* creating */);
+            stack.setWindowingMode(windowingMode, true /* creating */);
         }
         return stack;
     }
@@ -980,7 +995,7 @@
         return candidate;
     }
 
-    ActivityRecord getResumedActivity() {
+    ActivityRecord getFocusedActivity() {
         final ActivityStack focusedStack = getFocusedStack();
         if (focusedStack == null) {
             return null;
@@ -1131,7 +1146,7 @@
             for (int i = getStackCount() - 1; i >= 0; --i) {
                 final ActivityStack stack = getStackAt(i);
                 // Collect the root tasks that are currently being organized.
-                if (stack.isOrganized()) {
+                if (stack.mCreatedByOrganizer) {
                     for (int k = stack.getChildCount() - 1; k >= 0; --k) {
                         final ActivityStack childStack = (ActivityStack) stack.getChildAt(k);
                         if (childStack.getActivityType() == activityType) {
@@ -1551,11 +1566,139 @@
         return (index < wc.mChildren.size()) ? (ActivityStack) wc.mChildren.get(index) : null;
     }
 
+    /** Returns true if the stack in the windowing mode is visible. */
+    boolean isStackVisible(int windowingMode) {
+        final ActivityStack stack = getTopStackInWindowingMode(windowingMode);
+        return stack != null && stack.isVisible();
+    }
+
+    void removeStack(ActivityStack stack) {
+        removeChild(stack);
+    }
+
     int getDisplayId() {
         return mDisplayContent.getDisplayId();
     }
 
     boolean isRemoved() {
-        return mDisplayContent.isRemoved();
+        return mRemoved;
+    }
+
+    /**
+     * Adds a listener to be notified whenever the stack order in the display changes. Currently
+     * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
+     * current animation when the system state changes.
+     */
+    void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
+        if (!mStackOrderChangedCallbacks.contains(listener)) {
+            mStackOrderChangedCallbacks.add(listener);
+        }
+    }
+
+    /**
+     * Removes a previously registered stack order change listener.
+     */
+    void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
+        mStackOrderChangedCallbacks.remove(listener);
+    }
+
+    /**
+     * Notifies of a stack order change
+     * @param stack The stack which triggered the order change
+     */
+    void onStackOrderChanged(ActivityStack stack) {
+        for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
+            mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
+        }
+    }
+
+    @Override
+    boolean canCreateRemoteAnimationTarget() {
+        return true;
+    }
+
+    /**
+     * Callback for when the order of the stacks in the display changes.
+     */
+    interface OnStackOrderChangedListener {
+        void onStackOrderChanged(ActivityStack stack);
+    }
+
+    void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
+            boolean preserveWindows, boolean notifyClients) {
+        for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getStackAt(stackNdx);
+            stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+                    notifyClients);
+        }
+    }
+
+    void prepareFreezingTaskBounds() {
+        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getChildAt(stackNdx);
+            stack.prepareFreezingTaskBounds();
+        }
+    }
+
+    /**
+     * Removes the stacks in the node applying the content removal node from the display.
+     * @return last reparented stack, or {@code null} if the stacks had to be destroyed.
+     */
+    ActivityStack remove() {
+        mPreferredTopFocusableStack = null;
+        // TODO(b/153090332): Allow setting content removal mode per task display area
+        final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
+        final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        ActivityStack lastReparentedStack = null;
+
+        // Stacks could be reparented from the removed display area to other display area. After
+        // reparenting the last stack of the removed display area, the display area becomes ready to
+        // be released (no more ActivityStack-s). But, we cannot release it at that moment or the
+        // related WindowContainer will also be removed. So, we set display area as removed after
+        // reparenting stack finished.
+        // Keep the order from bottom to top.
+        int numStacks = getStackCount();
+        for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
+            final ActivityStack stack = getStackAt(stackNdx);
+            // Always finish non-standard type stacks.
+            if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
+                stack.finishAllActivitiesImmediately();
+            } else {
+                // If default display is in split-window mode, set windowing mode of the
+                // stack to split-screen secondary. Otherwise, set the windowing mode to
+                // undefined by default to let stack inherited the windowing mode from the
+                // new display.
+                final int windowingMode = toDisplayArea.isSplitScreenModeActivated()
+                        ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                        : WINDOWING_MODE_UNDEFINED;
+                stack.reparent(toDisplayArea, true /* onTop */);
+                stack.setWindowingMode(windowingMode);
+                lastReparentedStack = stack;
+            }
+            // Stacks may be removed from this display. Ensure each stack will be processed
+            // and the loop will end.
+            stackNdx -= numStacks - getStackCount();
+            numStacks = getStackCount();
+        }
+        mRemoved = true;
+
+        return lastReparentedStack;
+    }
+
+
+    @Override
+    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+        pw.println(prefix + "TaskDisplayArea " + getName());
+        if (mPreferredTopFocusableStack != null) {
+            pw.println(prefix + "  mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
+        }
+        if (mLastFocusedStack != null) {
+            pw.println(prefix + "  mLastFocusedStack=" + mLastFocusedStack);
+        }
+        pw.println(prefix + "  Application tokens in top down Z order:");
+        for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+            final ActivityStack stack = getChildAt(stackNdx);
+            stack.dump(pw, prefix + "    ", dumpAll);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index e6757e1..da4401a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -705,14 +705,19 @@
     private void adjustBoundsToAvoidConflictInDisplay(@NonNull DisplayContent display,
             @NonNull Rect inOutBounds) {
         final List<Rect> taskBoundsToCheck = new ArrayList<>();
-        for (int i = 0; i < display.getStackCount(); ++i) {
-            final ActivityStack stack = display.getStackAt(i);
-            if (!stack.inFreeformWindowingMode()) {
-                continue;
-            }
+        int numTaskContainers = display.getTaskDisplayAreaCount();
+        for (int tdaNdx = 0; tdaNdx < numTaskContainers; tdaNdx++) {
+            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+            int numStacks = taskDisplayArea.getStackCount();
+            for (int sNdx = 0; sNdx < numStacks; ++sNdx) {
+                final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                if (!stack.inFreeformWindowingMode()) {
+                    continue;
+                }
 
-            for (int j = 0; j < stack.getChildCount(); ++j) {
-                taskBoundsToCheck.add(stack.getChildAt(j).getBounds());
+                for (int j = 0; j < stack.getChildCount(); ++j) {
+                    taskBoundsToCheck.add(stack.getChildAt(j).getBounds());
+                }
             }
         }
         adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds);
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 872f254..22702dd 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -106,19 +106,29 @@
         }
 
         void addTask(Task t) {
-            mOrganizedTasks.add(t);
-            try {
-                mOrganizer.onTaskAppeared(t.getTaskInfo());
-            } catch (Exception e) {
-                Slog.e(TAG, "Exception sending taskAppeared callback" + e);
+            if (t.mTaskAppearedSent) return;
+
+            if (!mOrganizedTasks.contains(t)) {
+                mOrganizedTasks.add(t);
+            }
+            if (t.taskAppearedReady()) {
+                try {
+                    t.mTaskAppearedSent = true;
+                    mOrganizer.onTaskAppeared(t.getTaskInfo());
+                } catch (Exception e) {
+                    Slog.e(TAG, "Exception sending taskAppeared callback" + e);
+                }
             }
         }
 
         void removeTask(Task t) {
-            try {
-                mOrganizer.onTaskVanished(t.getTaskInfo());
-            } catch (Exception e) {
-                Slog.e(TAG, "Exception sending taskVanished callback" + e);
+            if (t.mTaskAppearedSent) {
+                try {
+                    t.mTaskAppearedSent = false;
+                    mOrganizer.onTaskVanished(t.getTaskInfo());
+                } catch (Exception e) {
+                    Slog.e(TAG, "Exception sending taskVanished callback" + e);
+                }
             }
             mOrganizedTasks.remove(t);
         }
@@ -277,9 +287,9 @@
                     return null;
                 }
 
-                final Task task = display.mTaskContainers.getOrCreateStack(windowingMode,
-                        ACTIVITY_TYPE_UNDEFINED, false /* onTop */, new Intent(),
-                        null /* candidateTask */, true /* createdByOrganizer */);
+                final Task task = display.getDefaultTaskDisplayArea().createStack(windowingMode,
+                        ACTIVITY_TYPE_UNDEFINED, false /* onTop */, null /* info */, new Intent(),
+                        true /* createdByOrganizer */);
                 RunningTaskInfo out = task.getTaskInfo();
                 mLastSentTaskInfos.put(task, out);
                 return out;
@@ -395,26 +405,27 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                TaskDisplayArea taskDisplayArea =
-                        mService.mRootWindowContainer.getDisplayContent(displayId).mTaskContainers;
-                if (taskDisplayArea == null) {
+                TaskDisplayArea defaultTaskDisplayArea = mService.mRootWindowContainer
+                        .getDisplayContent(displayId).getDefaultTaskDisplayArea();
+                if (defaultTaskDisplayArea == null) {
                     return;
                 }
                 Task task = token == null
                         ? null : WindowContainer.fromBinder(token.asBinder()).asTask();
                 if (task == null) {
-                    taskDisplayArea.mLaunchRootTask = null;
+                    defaultTaskDisplayArea.mLaunchRootTask = null;
                     return;
                 }
                 if (!task.mCreatedByOrganizer) {
                     throw new IllegalArgumentException("Attempt to set task not created by "
                             + "organizer as launch root task=" + task);
                 }
-                if (task.getDisplayArea() != taskDisplayArea) {
+                if (task.getDisplayArea() == null
+                        || task.getDisplayArea().getDisplayId() != displayId) {
                     throw new RuntimeException("Can't set launch root for display " + displayId
                             + " to task on display " + task.getDisplayContent().getDisplayId());
                 }
-                taskDisplayArea.mLaunchRootTask = task;
+                task.getDisplayArea().mLaunchRootTask = task;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -475,13 +486,16 @@
                     throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
                 }
                 ArrayList<RunningTaskInfo> out = new ArrayList<>();
-                for (int i = dc.getStackCount() - 1; i >= 0; --i) {
-                    final Task task = dc.getStackAt(i);
-                    if (activityTypes != null
-                            && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
-                        continue;
+                for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                    final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+                    for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                        final Task task = taskDisplayArea.getStackAt(sNdx);
+                        if (activityTypes != null
+                                && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
+                            continue;
+                        }
+                        out.add(task.getTaskInfo());
                     }
-                    out.add(task.getTaskInfo());
                 }
                 return out;
             }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index eb005e0..14e5c6c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -68,6 +68,7 @@
 import android.util.Slog;
 import android.view.DisplayCutout;
 import android.view.IWindowSession;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -164,6 +165,7 @@
         final Rect tmpContentInsets = new Rect();
         final Rect tmpStableInsets = new Rect();
         final InsetsState mTmpInsetsState = new InsetsState();
+        final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
         final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
         final TaskDescription taskDescription = new TaskDescription();
         taskDescription.setBackgroundColor(WHITE);
@@ -231,8 +233,8 @@
         }
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
-                    View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
-                    tmpCutout, null, mTmpInsetsState);
+                    View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect,
+                    tmpRect, tmpCutout, null, mTmpInsetsState, mTempControls);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
                 return null;
@@ -249,7 +251,7 @@
             session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
                     tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect,
                     tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
-                    sTmpSurfaceSize, sTmpSurfaceControl);
+                    mTempControls, sTmpSurfaceSize, sTmpSurfaceControl);
         } catch (RemoteException e) {
             // Local call.
         }
@@ -377,6 +379,7 @@
             frame = null;
             mTmpDstFrame.set(mFrame);
         }
+        mTmpDstFrame.offsetTo(0, 0);
 
         // Scale the mismatch dimensions to fill the task bounds
         mTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 29a2e18..b9b6c08 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -304,7 +304,11 @@
         }
     }
 
-    boolean updateWallpaperOffset(WindowState wallpaperWin, int dw, int dh, boolean sync) {
+    boolean updateWallpaperOffset(WindowState wallpaperWin, boolean sync) {
+        final DisplayInfo displayInfo = wallpaperWin.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
         int xOffset = 0;
         int yOffset = 0;
         boolean rawChanged = false;
@@ -444,10 +448,6 @@
     }
 
     private void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
         WindowState target = mWallpaperTarget;
         if (target != null) {
             if (target.mWallpaperX >= 0) {
@@ -484,7 +484,7 @@
         }
 
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            mWallpaperTokens.get(curTokenNdx).updateWallpaperOffset(dw, dh, sync);
+            mWallpaperTokens.get(curTokenNdx).updateWallpaperOffset(sync);
         }
     }
 
@@ -510,7 +510,7 @@
 
     private void findWallpaperTarget() {
         mFindResults.reset();
-        if (mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM)) {
+        if (mDisplayContent.getDefaultTaskDisplayArea().isStackVisible(WINDOWING_MODE_FREEFORM)) {
             // In freeform mode we set the wallpaper as its own target, so we don't need an
             // additional window to make it visible.
             mFindResults.setUseTopWallpaperAsTarget(true);
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index e29580b..203ca25 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -73,11 +73,11 @@
         }
     }
 
-    void updateWallpaperOffset(int dw, int dh, boolean sync) {
+    void updateWallpaperOffset(boolean sync) {
         final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
             final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
+            if (wallpaperController.updateWallpaperOffset(wallpaper, sync)) {
                 // We only want to be synchronous with one wallpaper.
                 sync = false;
             }
@@ -85,10 +85,6 @@
     }
 
     void updateWallpaperVisibility(boolean visible) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
         if (isVisible() != visible) {
             // Need to do a layout to ensure the wallpaper now has the correct size.
             mDisplayContent.setLayoutNeeded();
@@ -98,7 +94,7 @@
         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
             final WindowState wallpaper = mChildren.get(wallpaperNdx);
             if (visible) {
-                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
+                wallpaperController.updateWallpaperOffset(wallpaper, false /* sync */);
             }
 
             wallpaper.dispatchWallpaperVisibility(visible);
@@ -145,19 +141,11 @@
             }
         }
 
-        DisplayInfo displayInfo = getFixedRotationTransformDisplayInfo();
-        if (displayInfo == null) {
-            displayInfo = mDisplayContent.getDisplayInfo();
-        }
-
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
             final WindowState wallpaper = mChildren.get(wallpaperNdx);
 
             if (visible) {
-                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
+                wallpaperController.updateWallpaperOffset(wallpaper, false /* sync */);
             }
 
             // First, make sure the client has the current visibility state.
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 58119c2..f6e952c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -36,6 +36,7 @@
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
@@ -790,7 +791,7 @@
      * By default this predicate only checks if this container itself is actually running an
      * animation, but you can extend the check target over its relatives, or relax the condition
      * so that this can return {@code true} if an animation starts soon by giving a combination
-     * of {@link #AnimationFlags}.
+     * of {@link AnimationFlags}.
      *
      * Note that you can give a combination of bitmask flags to specify targets and condition for
      * checking animating status.
@@ -800,12 +801,18 @@
      *
      * Note that TRANSITION propagates to parents and children as well.
      *
-     * {@see AnimationFlags#TRANSITION}
-     * {@see AnimationFlags#PARENTS}
-     * {@see AnimationFlags#CHILDREN}
+     * @param flags The combination of bitmask flags to specify targets and condition for
+     *              checking animating status.
+     * @param typesToCheck The combination of bitmask {@link AnimationType} to compare when
+     *                     determining if animating.
+     *
+     * @see AnimationFlags#TRANSITION
+     * @see AnimationFlags#PARENTS
+     * @see AnimationFlags#CHILDREN
      */
-    boolean isAnimating(int flags) {
-        if (mSurfaceAnimator.isAnimating()) {
+    boolean isAnimating(int flags, int typesToCheck) {
+        int animationType = mSurfaceAnimator.getAnimationType();
+        if (mSurfaceAnimator.isAnimating() && (animationType & typesToCheck) > 0) {
             return true;
         }
         if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
@@ -813,14 +820,14 @@
         }
         if ((flags & PARENTS) != 0) {
             final WindowContainer parent = getParent();
-            if (parent != null && parent.isAnimating(flags & ~CHILDREN)) {
+            if (parent != null && parent.isAnimating(flags & ~CHILDREN, typesToCheck)) {
                 return true;
             }
         }
         if ((flags & CHILDREN) != 0) {
             for (int i = 0; i < mChildren.size(); ++i) {
                 final WindowContainer wc = mChildren.get(i);
-                if (wc.isAnimating(flags & ~PARENTS)) {
+                if (wc.isAnimating(flags & ~PARENTS, typesToCheck)) {
                     return true;
                 }
             }
@@ -829,6 +836,26 @@
     }
 
     /**
+     * Similar to {@link #isAnimating(int, int)} except provide a bitmask of
+     * {@link AnimationType} to exclude, rather than include
+     * @param flags The combination of bitmask flags to specify targets and condition for
+     *              checking animating status.
+     * @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when
+     *                     checking if animating.
+     */
+    boolean isAnimatingExcluding(int flags, int typesToExclude) {
+        return isAnimating(flags, ANIMATION_TYPE_ALL & ~typesToExclude);
+    }
+
+    /**
+     * @see #isAnimating(int, int)
+     * TODO (b/152333373): Migrate calls to use isAnimating with specified animation type
+     */
+    boolean isAnimating(int flags) {
+        return isAnimating(flags, ANIMATION_TYPE_ALL);
+    }
+
+    /**
      * @return {@code true} when the container is waiting the app transition start, {@code false}
      *         otherwise.
      */
@@ -2268,6 +2295,10 @@
     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
         mLastLayer = -1;
         reassignLayer(t);
+
+        // Leash is now responsible for position, so set our position to 0.
+        t.setPosition(mSurfaceControl, 0, 0);
+        mLastSurfacePosition.set(0, 0);
     }
 
     @Override
@@ -2275,6 +2306,7 @@
         mLastLayer = -1;
         mSurfaceFreezer.unfreeze(t);
         reassignLayer(t);
+        updateSurfacePosition(t);
     }
 
     /**
@@ -2338,11 +2370,15 @@
         }
     }
 
-    void updateSurfacePosition() {
+    final void updateSurfacePosition() {
+        updateSurfacePosition(getPendingTransaction());
+    }
+
+    void updateSurfacePosition(Transaction t) {
         // Avoid fighting with the organizer over Surface position.
         if (isOrganized()) return;
 
-        if (mSurfaceControl == null) {
+        if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) {
             return;
         }
 
@@ -2351,7 +2387,7 @@
             return;
         }
 
-        getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
+        t.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
         mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
     }
 
@@ -2474,9 +2510,7 @@
             // We need to copy the SurfaceControl instead of returning the original
             // because the Parcel FLAGS PARCELABLE_WRITE_RETURN_VALUE cause SurfaceControls
             // to release themselves.
-            SurfaceControl sc = new SurfaceControl();
-            sc.copyFrom(wc.getSurfaceControl());
-            return sc;
+            return new SurfaceControl(wc.getSurfaceControl());
         }
 
         WindowContainerToken toWindowContainerToken() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8e45752..8d3a4f2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -227,6 +227,7 @@
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputWindowHandle;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.KeyEvent;
 import android.view.MagnificationSpec;
@@ -1356,7 +1357,7 @@
             LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
             Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
-            InsetsState outInsetsState) {
+            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         int[] appOp = new int[1];
         final boolean isRoundedCornerOverlay = (attrs.privateFlags
                 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
@@ -1643,8 +1644,7 @@
                     outStableInsets, outDisplayCutout)) {
                 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
             }
-            outInsetsState.set(win.getInsetsState(),
-                    win.mClient instanceof IWindow.Stub /* copySource */);
+            outInsetsState.set(win.getInsetsState(), win.isClientLocal());
 
             if (mInTouchMode) {
                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -1678,6 +1678,8 @@
             }
             displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
 
+            getInsetsSourceControls(win, outActiveControls);
+
             ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
                     + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));
 
@@ -2080,7 +2082,8 @@
             Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
+            InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
+            SurfaceControl outBLASTSurfaceControl) {
         int result = 0;
         boolean configChanged;
         final int pid = Binder.getCallingPid();
@@ -2332,9 +2335,7 @@
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
 
             if (toBeDisplayed && win.mIsWallpaper) {
-                DisplayInfo displayInfo = displayContent.getDisplayInfo();
-                displayContent.mWallpaperController.updateWallpaperOffset(
-                        win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
+                displayContent.mWallpaperController.updateWallpaperOffset(win, false /* sync */);
             }
             if (win.mActivityRecord != null) {
                 win.mActivityRecord.updateReportedVisibilityLocked();
@@ -2377,8 +2378,8 @@
                     outStableInsets);
             outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
             outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
-            outInsetsState.set(win.getInsetsState(),
-                    win.mClient instanceof IWindow.Stub /* copySource */);
+            outInsetsState.set(win.getInsetsState(), win.isClientLocal());
+            getInsetsSourceControls(win, outActiveControls);
             if (DEBUG) {
                 Slog.v(TAG_WM, "Relayout given client " + client.asBinder()
                         + ", requestedWidth=" + requestedWidth
@@ -2415,6 +2416,21 @@
         return result;
     }
 
+    private void getInsetsSourceControls(WindowState win, InsetsSourceControl[] outControls) {
+        if (outControls != null) {
+            final InsetsSourceControl[] controls =
+                    win.getDisplayContent().getInsetsStateController().getControlsForDispatch(win);
+            Arrays.fill(outControls, null);
+            if (controls != null) {
+                final int length = Math.min(controls.length, outControls.length);
+                for (int i = 0; i < length; i++) {
+                    outControls[i] = win.isClientLocal()
+                            ? new InsetsSourceControl(controls[i]) : controls[i];
+                }
+            }
+        }
+    }
+
     private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
             boolean focusMayChange) {
         // Try starting an animation; if there isn't one, we
@@ -2782,7 +2798,6 @@
                 aspectRatio);
     }
 
-    @Override
     public void getStackBounds(int windowingMode, int activityType, Rect bounds) {
         synchronized (mGlobalLock) {
             final ActivityStack stack = mRoot.getStack(windowingMode, activityType);
@@ -5320,7 +5335,8 @@
                 throw new IllegalArgumentException(
                         "Requested window " + client + " does not exist");
             }
-            ProtoLog.w(WM_ERROR, "Failed looking up window callers=%s", Debug.getCallers(3));
+            ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
+                    Debug.getCallers(3));
             return null;
         }
         if (session != null && win.mSession != session) {
@@ -5328,7 +5344,8 @@
                 throw new IllegalArgumentException("Requested window " + client + " is in session "
                         + win.mSession + ", not " + session);
             }
-            ProtoLog.w(WM_ERROR, "Failed looking up window callers=%s", Debug.getCallers(3));
+            ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
+                    Debug.getCallers(3));
             return null;
         }
 
@@ -6052,11 +6069,21 @@
         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
         mRoot.dumpTopFocusedDisplayId(pw);
         mRoot.forAllDisplays(dc -> {
+            final int displayId = dc.getDisplayId();
             final WindowState inputMethodTarget = dc.mInputMethodTarget;
             if (inputMethodTarget != null) {
-                pw.print("  mInputMethodTarget in display# "); pw.print(dc.getDisplayId());
+                pw.print("  mInputMethodTarget in display# "); pw.print(displayId);
                 pw.print(' '); pw.println(inputMethodTarget);
             }
+            if (mAccessibilityController != null) {
+                final Region magnificationRegion = new Region();
+                mAccessibilityController.getMagnificationRegionLocked(displayId,
+                        magnificationRegion);
+                pw.print("  mMagnificationRegion in display# ");
+                pw.print(displayId);
+                pw.print(' ');
+                pw.println(magnificationRegion);
+            }
         });
         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
         pw.print("  mLastDisplayFreezeDuration=");
@@ -7321,8 +7348,9 @@
 
         @Override
         public boolean isStackVisibleLw(int windowingMode) {
-            final DisplayContent dc = getDefaultDisplayContentLocked();
-            return dc.isStackVisible(windowingMode);
+            // TODO(b/153090332): Support multiple task display areas & displays
+            final TaskDisplayArea tc = mRoot.getDefaultTaskDisplayArea();
+            return tc.isStackVisible(windowingMode);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index a332b69..3e2e9be 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -234,7 +234,7 @@
                 if (task.getParent() != newParent) {
                     if (newParent == null) {
                         // Re-parent task to display as a root task.
-                        dc.moveStackToDisplay(as, hop.getToTop());
+                        as.reparent(dc.getDefaultTaskDisplayArea(), hop.getToTop());
                     } else if (newParent.inMultiWindowMode() && !task.isResizeable()
                             && task.isLeafTask()) {
                         Slog.w(TAG, "Can't support task that doesn't support multi-window mode in"
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7dcf375..5a76bac 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1101,7 +1101,6 @@
                 }
             }
 
-            final ActivityStack stack = getRootTask();
             layoutDisplayFrame = new Rect(windowFrames.mDisplayFrame);
             windowFrames.mDisplayFrame.set(windowFrames.mContainingFrame);
             layoutXDiff = mInsetFrame.left - windowFrames.mContainingFrame.left;
@@ -1205,8 +1204,7 @@
 
         if (mIsWallpaper && (fw != windowFrames.mFrame.width()
                 || fh != windowFrames.mFrame.height())) {
-            dc.mWallpaperController.updateWallpaperOffset(this,
-                    displayInfo.logicalWidth, displayInfo.logicalHeight, false /* sync */);
+            dc.mWallpaperController.updateWallpaperOffset(this, false /* sync */);
         }
 
         // Calculate relative frame
@@ -1518,7 +1516,8 @@
         // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
         // associate them with some stack to enable dimming.
         final DisplayContent dc = getDisplayContent();
-        return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null ? dc.getRootHomeTask() : null;
+        return mAttrs.type >= FIRST_SYSTEM_WINDOW
+                && dc != null ? dc.getDefaultTaskDisplayArea().getRootHomeTask() : null;
     }
 
     /**
@@ -3440,13 +3439,23 @@
         getMergedConfiguration(mLastReportedConfiguration);
         mLastConfigReportedToClient = true;
 
+        final boolean reportOrientation = mReportOrientationChanged;
+        // Always reset these states first, so if {@link IWindow#resized} fails, this
+        // window won't be added to {@link WindowManagerService#mResizingWindows} and set
+        // {@link #mOrientationChanging} to true again by {@link #updateResizingWindowIfNeeded}
+        // that may cause WINDOW_FREEZE_TIMEOUT because resizing the client keeps failing.
+        mReportOrientationChanged = false;
+        mDragResizingChangeReported = true;
+        mWinAnimator.mSurfaceResized = false;
+        mWindowFrames.resetInsetsChanged();
+
         final Rect frame = mWindowFrames.mCompatFrame;
         final Rect contentInsets = mWindowFrames.mLastContentInsets;
         final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
         final Rect stableInsets = mWindowFrames.mLastStableInsets;
         final MergedConfiguration mergedConfiguration = mLastReportedConfiguration;
         final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
-        final boolean forceRelayout = mReportOrientationChanged || isDragResizeChanged();
+        final boolean forceRelayout = reportOrientation || isDragResizeChanged();
         final int displayId = getDisplayId();
         final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout();
 
@@ -3455,29 +3464,25 @@
                     mergedConfiguration, getBackdropFrame(frame), forceRelayout,
                     getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this),
                     displayId, new DisplayCutout.ParcelableWrapper(displayCutout));
-            mDragResizingChangeReported = true;
 
             if (mWmService.mAccessibilityController != null) {
                 mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(displayId);
             }
             updateLocationInParentDisplayIfNeeded();
-
-            mWindowFrames.resetInsetsChanged();
-            mWinAnimator.mSurfaceResized = false;
-            mReportOrientationChanged = false;
         } catch (RemoteException e) {
+            // Cancel orientation change of this window to avoid blocking unfreeze display.
             setOrientationChanging(false);
             mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
                     - mWmService.mDisplayFreezeTime);
-            // We are assuming the hosting process is dead or in a zombie state.
-            Slog.w(TAG, "Failed to report 'resized' to the client of " + this
-                    + ", removing this window.");
-            mWmService.mPendingRemove.add(this);
-            mWmService.mWindowPlacerLocked.requestTraversal();
+            Slog.w(TAG, "Failed to report 'resized' to " + this + " due to " + e);
         }
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
+    boolean isClientLocal() {
+        return mClient instanceof IWindow.Stub;
+    }
+
     void updateLocationInParentDisplayIfNeeded() {
         final int embeddedDisplayContentsSize = mEmbeddedDisplayContents.size();
         // If there is any embedded display which is re-parented to this window, we need to
@@ -4983,7 +4988,7 @@
     }
 
     @Override
-    boolean isAnimating(int flags) {
+    boolean isAnimating(int flags, int typesToCheck) {
 
         // If we are an inset provider, all our animations are driven by the inset client, so we
         // aren't really animating.
@@ -4991,7 +4996,7 @@
         if (mControllableInsetProvider != null) {
             return false;
         }
-        return super.isAnimating(flags);
+        return super.isAnimating(flags, typesToCheck);
     }
 
     void startAnimation(Animation anim) {
@@ -5232,23 +5237,14 @@
     @Override
     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
         super.onAnimationLeashCreated(t, leash);
-
-        // Leash is now responsible for position, so set our position to 0.
-        t.setPosition(mSurfaceControl, 0, 0);
-        mLastSurfacePosition.set(0, 0);
     }
 
     @Override
     public void onAnimationLeashLost(Transaction t) {
         super.onAnimationLeashLost(t);
-        updateSurfacePosition(t);
     }
 
     @Override
-    void updateSurfacePosition() {
-        updateSurfacePosition(getPendingTransaction());
-    }
-
     @VisibleForTesting
     void updateSurfacePosition(Transaction t) {
         if (mSurfaceControl == null) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 563710b..d4470f8 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1066,14 +1066,15 @@
 
 
         if (!w.mSeamlesslyRotated) {
+            // Wallpaper is already updated above when calling setWallpaperPositionAndScale so
+            // we only need to consider the non-wallpaper case here.
             if (!mIsWallpaper) {
                 applyCrop(clipRect, recoveringMemory);
-                mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
+                mSurfaceController.setMatrixInTransaction(
+                        mDsDx * w.mHScale * mExtraHScale,
                         mDtDx * w.mVScale * mExtraVScale,
                         mDtDy * w.mHScale * mExtraHScale,
                         mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
-            } else {
-                setWallpaperPositionAndScale(mXOffset, mYOffset, mWallpaperScale, recoveringMemory);
             }
         }
 
@@ -1152,13 +1153,20 @@
                             mSurfaceController, mShownAlpha, mDsDx, w.mHScale, mDtDx, w.mVScale,
                             mDtDy, w.mHScale, mDsDy, w.mVScale, w);
 
-            boolean prepared =
-                mSurfaceController.prepareToShowInTransaction(mShownAlpha,
+            boolean prepared = true;
+
+            if (mIsWallpaper) {
+                setWallpaperPositionAndScale(
+                        mXOffset, mYOffset, mWallpaperScale, recoveringMemory);
+            } else {
+                prepared =
+                    mSurfaceController.prepareToShowInTransaction(mShownAlpha,
                         mDsDx * w.mHScale * mExtraHScale,
                         mDtDx * w.mVScale * mExtraVScale,
                         mDtDy * w.mHScale * mExtraHScale,
                         mDsDy * w.mVScale * mExtraVScale,
                         recoveringMemory);
+            }
 
             if (prepared && mDrawState == HAS_DRAWN) {
                 if (mLastHidden) {
@@ -1381,7 +1389,8 @@
             return true;
         }
 
-        if (isEntrance && mWin.mAttrs.type == TYPE_INPUT_METHOD) {
+        final boolean isImeWindow = mWin.mAttrs.type == TYPE_INPUT_METHOD;
+        if (isEntrance && isImeWindow) {
             mWin.getDisplayContent().adjustForImeIfNeeded();
             mWin.setDisplayLayoutNeeded();
             mService.mWindowPlacerLocked.requestTraversal();
@@ -1435,11 +1444,11 @@
                 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                 mAnimationIsEntrance = isEntrance;
             }
-        } else {
+        } else if (!isImeWindow) {
             mWin.cancelAnimation();
         }
 
-        if (!isEntrance && mWin.mAttrs.type == TYPE_INPUT_METHOD) {
+        if (!isEntrance && isImeWindow) {
             mWin.getDisplayContent().adjustForImeIfNeeded();
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index d7c97b9..55e6ab7 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -126,7 +126,8 @@
         if (useBLAST) {
             mBLASTSurfaceControl = win.makeSurface()
                 .setParent(mSurfaceControl)
-                .setName("BLAST Adapter Layer")
+                .setName(name + "(BLAST)")
+                .setHidden(false)
                 .setBLASTLayer()
                 .build();
         }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 3c2b6ec..23091a0 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -397,7 +397,8 @@
     void assignLayer(SurfaceControl.Transaction t, int layer) {
         if (windowType == TYPE_DOCK_DIVIDER) {
             // See {@link DisplayContent#mSplitScreenDividerAnchor}
-            super.assignRelativeLayer(t, mDisplayContent.getSplitScreenDividerAnchor(), 1);
+            super.assignRelativeLayer(t,
+                    mDisplayContent.getDefaultTaskDisplayArea().getSplitScreenDividerAnchor(), 1);
         } else if (mRoundedCornerOverlay) {
             super.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
         } else {
@@ -534,8 +535,8 @@
     }
 
     @Override
-    void updateSurfacePosition() {
-        super.updateSurfacePosition();
+    void updateSurfacePosition(SurfaceControl.Transaction t) {
+        super.updateSurfacePosition(t);
         if (isFixedRotationTransforming()) {
             // The window is layouted in a simulated rotated display but the real display hasn't
             // rotated, so here transforms its surface to fit in the real display.
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 74982c6..4c3f73d 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -40,6 +40,7 @@
         "com_android_server_security_VerityUtils.cpp",
         "com_android_server_SerialService.cpp",
         "com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.cpp",
+        "com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp",
         "com_android_server_stats_pull_StatsPullAtomService.cpp",
         "com_android_server_storage_AppFuseBridge.cpp",
         "com_android_server_SystemServer.cpp",
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index e9a5e58..853eba7 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -392,6 +392,7 @@
         mArgs = params.arguments();
         mIfs = ifs;
         mStatusListener = statusListener;
+        mIfs->setParams({.readLogsEnabled = true});
         return true;
     }
     bool onStart() final { return true; }
@@ -438,7 +439,7 @@
             }
 
             const auto fileId = IncFs_FileIdFromMetadata(file.metadata);
-            const auto incfsFd(mIfs->openWrite(fileId));
+            const base::unique_fd incfsFd(mIfs->openForSpecialOps(fileId).release());
             if (incfsFd < 0) {
                 ALOGE("Failed to open an IncFS file for metadata: %.*s, final file name is: %s. "
                       "Error %d",
@@ -716,7 +717,7 @@
 
                 auto& writeFd = writeFds[fileIdx];
                 if (writeFd < 0) {
-                    writeFd.reset(this->mIfs->openWrite(fileId));
+                    writeFd.reset(this->mIfs->openForSpecialOps(fileId).release());
                     if (writeFd < 0) {
                         ALOGE("Failed to open file %d for writing (%d). Aborting.", header.fileIdx,
                               -writeFd);
diff --git a/services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp b/services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp
new file mode 100644
index 0000000..ae6cb18
--- /dev/null
+++ b/services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sstream>
+
+#define LOG_TAG "ExternalCaptureStateTracker"
+
+#include "core_jni_helpers.h"
+#include <log/log.h>
+#include <media/AudioSystem.h>
+
+namespace android {
+namespace {
+
+#define PACKAGE "com/android/server/soundtrigger_middleware"
+#define CLASSNAME PACKAGE "/ExternalCaptureStateTracker"
+
+jclass gExternalCaptureStateTrackerClassId;
+jmethodID gSetCaptureStateMethodId;
+jmethodID gBinderDiedMethodId;
+
+void PopulateIds(JNIEnv* env) {
+    gExternalCaptureStateTrackerClassId =
+        (jclass) env->NewGlobalRef(FindClassOrDie(env, CLASSNAME));
+    gSetCaptureStateMethodId = GetMethodIDOrDie(env,
+                                                gExternalCaptureStateTrackerClassId,
+                                                "setCaptureState",
+                                                "(Z)V");
+    gBinderDiedMethodId = GetMethodIDOrDie(env,
+                                           gExternalCaptureStateTrackerClassId,
+                                           "binderDied",
+                                           "()V");
+}
+
+class Listener : public AudioSystem::CaptureStateListener {
+public:
+    Listener(JNIEnv* env, jobject obj) : mObj(env->NewGlobalRef(obj)) {}
+
+    ~Listener() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->DeleteGlobalRef(mObj);
+    }
+
+    void onStateChanged(bool active) override {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->CallVoidMethod(mObj, gSetCaptureStateMethodId, active);
+    }
+
+    void onServiceDied() override {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->CallVoidMethod(mObj, gBinderDiedMethodId);
+    }
+
+private:
+    jobject mObj;
+};
+
+void connect(JNIEnv* env, jobject obj) {
+    sp<AudioSystem::CaptureStateListener> listener(new Listener(env, obj));
+    status_t status =
+        AudioSystem::registerSoundTriggerCaptureStateListener(listener);
+    LOG_ALWAYS_FATAL_IF(status != NO_ERROR);
+}
+
+const JNINativeMethod gMethods[] = {
+    {"connect", "()V", reinterpret_cast<void*>(connect)},
+};
+
+}  // namespace
+
+int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
+    JNIEnv* env) {
+    PopulateIds(env);
+    return RegisterMethodsOrDie(env,
+                                CLASSNAME,
+                                gMethods,
+                                NELEM(gMethods));
+}
+
+} // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index eb486fe..b988bd4 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -58,6 +58,8 @@
 int register_android_server_am_LowMemDetector(JNIEnv* env);
 int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
         JNIEnv* env);
+int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
+    JNIEnv* env);
 int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
 int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
 int register_android_server_AdbDebuggingManager(JNIEnv* env);
@@ -112,6 +114,8 @@
     register_android_server_am_LowMemDetector(env);
     register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
             env);
+    register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
+        env);
     register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
     register_android_server_stats_pull_StatsPullAtomService(env);
     register_android_server_AdbDebuggingManager(env);
diff --git a/services/core/xsd/vts/Android.bp b/services/core/xsd/vts/Android.bp
index 636d110..a942108 100644
--- a/services/core/xsd/vts/Android.bp
+++ b/services/core/xsd/vts/Android.bp
@@ -36,7 +36,7 @@
     ],
     test_suites: [
         "general-tests",
-        "vts-core"
+        "vts"
     ],
     test_config: "vts_defaultPermissions_validate_test.xml",
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1544ff1..67e83ba 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -87,6 +87,9 @@
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
+import static android.os.UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
+import static android.os.UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
+import static android.os.UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE;
 import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
 import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
 import static android.provider.Telephony.Carriers.DPC_URI;
@@ -284,6 +287,7 @@
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.pm.RestrictionsSet;
 import com.android.server.pm.UserRestrictionsUtils;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.storage.DeviceStorageMonitorInternal;
@@ -322,6 +326,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
+import java.util.function.Predicate;
 
 /**
  * Implementation of the device policy APIs.
@@ -1828,6 +1833,50 @@
             info = deviceAdminInfo;
         }
 
+        Bundle addSyntheticRestrictions(Bundle restrictions) {
+            if (disableCamera) {
+                restrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
+            } else {
+                restrictions.remove(UserManager.DISALLOW_CAMERA);
+            }
+            return restrictions;
+        }
+
+        static Bundle removeDeprecatedRestrictions(Bundle restrictions) {
+            for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) {
+                restrictions.remove(deprecatedRestriction);
+            }
+            return restrictions;
+        }
+
+        static Bundle filterRestrictions(Bundle restrictions, Predicate<String> filter) {
+            Bundle result = new Bundle();
+            for (String key : restrictions.keySet()) {
+                if (!restrictions.getBoolean(key)) {
+                    continue;
+                }
+                if (filter.test(key)) {
+                    result.putBoolean(key, true);
+                }
+            }
+            return result;
+        }
+
+        Bundle getEffectiveRestrictions() {
+            return addSyntheticRestrictions(
+                    removeDeprecatedRestrictions(ensureUserRestrictions()));
+        }
+
+        Bundle getLocalUserRestrictions(int adminType) {
+            return filterRestrictions(getEffectiveRestrictions(),
+                    key -> UserRestrictionsUtils.isLocal(adminType, key));
+        }
+
+        Bundle getGlobalUserRestrictions(int adminType) {
+            return filterRestrictions(getEffectiveRestrictions(),
+                    key -> UserRestrictionsUtils.isGlobal(adminType, key));
+        }
+
         void dump(IndentingPrintWriter pw) {
             pw.print("uid="); pw.println(getUid());
             pw.print("testOnlyAdmin=");
@@ -2772,7 +2821,7 @@
                 Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) != 0) {
             profileOwner.ensureUserRestrictions().putBoolean(
                     UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
-            saveUserRestrictionsLocked(userId, /* parent = */ false);
+            saveUserRestrictionsLocked(userId);
             mInjector.settingsSecurePutIntForUser(
                     Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId);
         }
@@ -2803,7 +2852,7 @@
             }
             admin.defaultEnabledRestrictionsAlreadySet.addAll(restrictionsToSet);
             Slog.i(LOG_TAG, "Enabled the following restrictions by default: " + restrictionsToSet);
-            saveUserRestrictionsLocked(userId, /* parent = */ false);
+            saveUserRestrictionsLocked(userId);
         }
     }
 
@@ -8222,9 +8271,9 @@
             }
         }
         // Tell the user manager that the restrictions have changed.
-        final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
-        pushUserRestrictions(affectedUserId);
+        pushUserRestrictions(userHandle);
 
+        final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
         if (SecurityLog.isLoggingEnabled()) {
             SecurityLog.writeEvent(SecurityLog.TAG_CAMERA_POLICY_SET,
                     who.getPackageName(), userHandle, affectedUserId, disabled ? 1 : 0);
@@ -9119,6 +9168,31 @@
     }
 
     @Override
+    public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(
+            @NonNull UserHandle userHandle) {
+        if (!mHasFeature) {
+            return null;
+        }
+        synchronized (getLockObject()) {
+            final String supervisor = mContext.getResources().getString(
+                    com.android.internal.R.string.config_defaultSupervisionProfileOwnerComponent);
+            if (supervisor == null) {
+                return null;
+            }
+            final ComponentName supervisorComponent = ComponentName.unflattenFromString(supervisor);
+            final ComponentName doComponent = mOwners.getDeviceOwnerComponent();
+            final ComponentName poComponent =
+                    mOwners.getProfileOwnerComponent(userHandle.getIdentifier());
+            if (supervisorComponent.equals(doComponent) || supervisorComponent.equals(
+                    poComponent)) {
+                return supervisorComponent;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    @Override
     public String getProfileOwnerName(int userHandle) {
         if (!mHasFeature) {
             return null;
@@ -10781,10 +10855,14 @@
                             "Cannot use the parent instance in Device Owner mode");
                 }
             } else {
-                if (!(UserRestrictionsUtils.canProfileOwnerChange(key, userHandle) || (
-                        isProfileOwnerOfOrganizationOwnedDevice(activeAdmin) && parent
-                        && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
-                                key)))) {
+                boolean profileOwnerCanChangeOnItself = !parent
+                        && UserRestrictionsUtils.canProfileOwnerChange(key, userHandle);
+                boolean orgOwnedProfileOwnerCanChangesGlobally = parent
+                        && isProfileOwnerOfOrganizationOwnedDevice(activeAdmin)
+                        && UserRestrictionsUtils
+                                .canProfileOwnerOfOrganizationOwnedDeviceChange(key);
+
+                if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangesGlobally) {
                     throw new SecurityException("Profile owner cannot set user restriction " + key);
                 }
             }
@@ -10796,7 +10874,7 @@
             } else {
                 restrictions.remove(key);
             }
-            saveUserRestrictionsLocked(userHandle, parent);
+            saveUserRestrictionsLocked(userHandle);
         }
         final int eventId = enabledFromThisOwner
                 ? DevicePolicyEnums.ADD_USER_RESTRICTION
@@ -10814,91 +10892,65 @@
         }
     }
 
-    private void saveUserRestrictionsLocked(int userId, boolean parent) {
+    private void saveUserRestrictionsLocked(int userId) {
         saveSettingsLocked(userId);
-        pushUserRestrictions(parent ? getProfileParentId(userId) : userId);
+        pushUserRestrictions(userId);
         sendChangedNotification(userId);
     }
 
-    private void pushUserRestrictions(int userId) {
+    /**
+     * Pushes the user restrictions originating from a specific user.
+     *
+     * If called by the profile owner of an organization-owned device, the global and local
+     * user restrictions will be an accumulation of the global user restrictions from the profile
+     * owner active admin and its parent active admin. The key of the local user restrictions set
+     * will be the target user id.
+     */
+    private void pushUserRestrictions(int originatingUserId) {
+        final Bundle global;
+        final RestrictionsSet local = new RestrictionsSet();
+        final boolean isDeviceOwner;
         synchronized (getLockObject()) {
-            final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId);
-            Bundle userRestrictions = null;
-            final int restrictionOwnerType;
-            final int originatingUserId;
-
+            isDeviceOwner = mOwners.isDeviceOwnerUserId(originatingUserId);
             if (isDeviceOwner) {
                 final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
                 if (deviceOwner == null) {
                     return; // Shouldn't happen.
                 }
-                userRestrictions = addOrRemoveDisableCameraRestriction(
-                        deviceOwner.userRestrictions, deviceOwner);
-                restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
-                originatingUserId = deviceOwner.getUserHandle().getIdentifier();
+                global = deviceOwner.getGlobalUserRestrictions(OWNER_TYPE_DEVICE_OWNER);
+                local.updateRestrictions(originatingUserId, deviceOwner.getLocalUserRestrictions(
+                        OWNER_TYPE_DEVICE_OWNER));
             } else {
-                final ActiveAdmin profileOwnerOfOrganizationOwnedDevice =
-                        getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
-
-                // If profile owner of an organization owned device, the restrictions will be
-                // pushed to the parent instance.
-                if (profileOwnerOfOrganizationOwnedDevice != null && !isManagedProfile(userId)) {
-                    restrictionOwnerType =
-                          UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE;
-                    final ActiveAdmin parent = profileOwnerOfOrganizationOwnedDevice
-                            .getParentActiveAdmin();
-                    userRestrictions = parent.userRestrictions;
-                    userRestrictions = addOrRemoveDisableCameraRestriction(userRestrictions,
-                            parent);
-                    originatingUserId =
-                            profileOwnerOfOrganizationOwnedDevice.getUserHandle().getIdentifier();
-                } else {
-                    final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
-
-                    if (profileOwner != null) {
-                        userRestrictions = profileOwner.userRestrictions;
-                        restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
-                        originatingUserId = profileOwner.getUserHandle().getIdentifier();
-                    } else {
-                        restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER;
-                        originatingUserId = userId;
-                    }
-                    userRestrictions = addOrRemoveDisableCameraRestriction(
-                            userRestrictions, userId);
+                final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(originatingUserId);
+                if (profileOwner == null) {
+                    return;
+                }
+                global = profileOwner.getGlobalUserRestrictions(OWNER_TYPE_PROFILE_OWNER);
+                local.updateRestrictions(originatingUserId, profileOwner.getLocalUserRestrictions(
+                        OWNER_TYPE_PROFILE_OWNER));
+                // Global (device-wide) and local user restrictions set by the profile owner of an
+                // organization-owned device are stored in the parent ActiveAdmin instance.
+                if (isProfileOwnerOfOrganizationOwnedDevice(
+                        profileOwner.getUserHandle().getIdentifier())) {
+                    // The global restrictions set on the parent ActiveAdmin instance need to be
+                    // merged with the global restrictions set on the profile owner ActiveAdmin
+                    // instance, since both are to be applied device-wide.
+                    UserRestrictionsUtils.merge(global,
+                            profileOwner.getParentActiveAdmin().getGlobalUserRestrictions(
+                                    OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
+                    // The local restrictions set on the parent ActiveAdmin instance are only to be
+                    // applied to the primary user. They therefore need to be added the local
+                    // restriction set with the primary user id as the key, in this case the
+                    // primary user id is the target user.
+                    local.updateRestrictions(
+                            getProfileParentId(profileOwner.getUserHandle().getIdentifier()),
+                            profileOwner.getParentActiveAdmin().getLocalUserRestrictions(
+                                    OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
                 }
             }
-            // Remove deprecated restrictions.
-            for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) {
-                userRestrictions.remove(deprecatedRestriction);
-            }
-            mUserManagerInternal.setDevicePolicyUserRestrictions(originatingUserId,
-                    userRestrictions, restrictionOwnerType);
         }
-    }
-
-    private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) {
-        if (userRestrictions == null) {
-            userRestrictions = new Bundle();
-        }
-        if (admin.disableCamera) {
-            userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
-        } else {
-            userRestrictions.remove(UserManager.DISALLOW_CAMERA);
-        }
-        return userRestrictions;
-    }
-
-    private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) {
-        if (userRestrictions == null) {
-            userRestrictions = new Bundle();
-        }
-        if (getCameraDisabled(/* who= */ null, userId, /* mergeDeviceOwnerRestriction= */
-                false)) {
-            userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
-        } else {
-            userRestrictions.remove(UserManager.DISALLOW_CAMERA);
-        }
-        return userRestrictions;
+        mUserManagerInternal.setDevicePolicyUserRestrictions(originatingUserId, global, local,
+                isDeviceOwner);
     }
 
     @Override
@@ -11488,6 +11540,18 @@
             throw new SecurityException(
                     "User " + userId + " is not allowed to call setSecondaryLockscreenEnabled");
         }
+        // Only the default supervision app can use this API.
+        final String supervisor = mContext.getResources().getString(
+                com.android.internal.R.string.config_defaultSupervisionProfileOwnerComponent);
+        if (supervisor == null) {
+            throw new SecurityException("Unable to set secondary lockscreen setting, no "
+                    + "default supervision component defined");
+        }
+        final ComponentName supervisorComponent = ComponentName.unflattenFromString(supervisor);
+        if (!who.equals(supervisorComponent)) {
+            throw new SecurityException(
+                    "Admin " + who + " is not the default supervision component");
+        }
     }
 
     @Override
@@ -12395,6 +12459,11 @@
             return DevicePolicyManagerService.this.getAllCrossProfilePackages();
         }
 
+        @Override
+        public List<String> getDefaultCrossProfilePackages() {
+            return DevicePolicyManagerService.this.getDefaultCrossProfilePackages();
+        }
+
         /**
          * Sends the {@code intent} to the packages with cross profile capabilities.
          *
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 25da8fe..d1153e6 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -35,6 +35,7 @@
 #include <uuid/uuid.h>
 #include <zlib.h>
 
+#include <charconv>
 #include <ctime>
 #include <filesystem>
 #include <iterator>
@@ -49,6 +50,9 @@
 using namespace android::content::pm;
 namespace fs = std::filesystem;
 
+constexpr const char* kDataUsageStats = "android.permission.LOADER_USAGE_STATS";
+constexpr const char* kOpUsage = "android:get_usage_stats";
+
 namespace android::incremental {
 
 namespace {
@@ -69,7 +73,7 @@
 };
 
 static const Constants& constants() {
-    static Constants c;
+    static constexpr Constants c;
     return c;
 }
 
@@ -155,6 +159,9 @@
 }
 } // namespace
 
+const bool IncrementalService::sEnablePerfLogging =
+        android::base::GetBoolProperty("incremental.perflogging", false);
+
 IncrementalService::IncFsMount::~IncFsMount() {
     incrementalService.mDataLoaderManager->destroyDataLoader(mountId);
     LOG(INFO) << "Unmounting and cleaning up mount " << mountId << " with root '" << root << '\'';
@@ -231,6 +238,7 @@
       : mVold(sm.getVoldService()),
         mDataLoaderManager(sm.getDataLoaderManager()),
         mIncFs(sm.getIncFs()),
+        mAppOpsManager(sm.getAppOpsManager()),
         mIncrementalDir(rootDir) {
     if (!mVold) {
         LOG(FATAL) << "Vold service is unavailable";
@@ -238,6 +246,9 @@
     if (!mDataLoaderManager) {
         LOG(FATAL) << "DataLoaderManagerService is unavailable";
     }
+    if (!mAppOpsManager) {
+        LOG(FATAL) << "AppOpsManager is unavailable";
+    }
     mountExistingImages();
 }
 
@@ -275,12 +286,12 @@
         const IncFsMount& mnt = *ifs.get();
         dprintf(fd, "\t[%d]:\n", id);
         dprintf(fd, "\t\tmountId: %d\n", mnt.mountId);
+        dprintf(fd, "\t\troot: %s\n", mnt.root.c_str());
         dprintf(fd, "\t\tnextStorageDirNo: %d\n", mnt.nextStorageDirNo.load());
         dprintf(fd, "\t\tdataLoaderStatus: %d\n", mnt.dataLoaderStatus.load());
-        dprintf(fd, "\t\tconnectionLostTime: %s\n", toString(mnt.connectionLostTime));
-        if (mnt.savedDataLoaderParams) {
-            const auto& params = mnt.savedDataLoaderParams.value();
-            dprintf(fd, "\t\tsavedDataLoaderParams:\n");
+        {
+            const auto& params = mnt.dataLoaderParams;
+            dprintf(fd, "\t\tdataLoaderParams:\n");
             dprintf(fd, "\t\t\ttype: %s\n", toString(params.type).c_str());
             dprintf(fd, "\t\t\tpackageName: %s\n", params.packageName.c_str());
             dprintf(fd, "\t\t\tclassName: %s\n", params.className.c_str());
@@ -328,6 +339,7 @@
     }
 
     std::thread([this, mounts = std::move(mounts)]() {
+        /* TODO(b/151241369): restore data loaders on reboot.
         for (auto&& ifs : mounts) {
             if (prepareDataLoader(*ifs)) {
                 LOG(INFO) << "Successfully started data loader for mount " << ifs->mountId;
@@ -336,6 +348,7 @@
                 LOG(WARNING) << "Failed to start data loader for mount " << ifs->mountId;
             }
         }
+        */
         mPrepareDataLoaders.set_value_at_thread_exit();
     }).detach();
     return mPrepareDataLoaders.get_future();
@@ -455,13 +468,15 @@
         return kInvalidStorageId;
     }
 
+    ifs->dataLoaderParams = std::move(dataLoaderParams);
+
     {
         metadata::Mount m;
         m.mutable_storage()->set_id(ifs->mountId);
-        m.mutable_loader()->set_type((int)dataLoaderParams.type);
-        m.mutable_loader()->set_package_name(dataLoaderParams.packageName);
-        m.mutable_loader()->set_class_name(dataLoaderParams.className);
-        m.mutable_loader()->set_arguments(dataLoaderParams.arguments);
+        m.mutable_loader()->set_type((int)ifs->dataLoaderParams.type);
+        m.mutable_loader()->set_package_name(ifs->dataLoaderParams.packageName);
+        m.mutable_loader()->set_class_name(ifs->dataLoaderParams.className);
+        m.mutable_loader()->set_arguments(ifs->dataLoaderParams.arguments);
         const auto metadata = m.SerializeAsString();
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_class_name();
@@ -489,7 +504,7 @@
     // Done here as well, all data structures are in good state.
     secondCleanupOnFailure.release();
 
-    if (!prepareDataLoader(*ifs, &dataLoaderParams, &dataLoaderStatusListener)) {
+    if (!prepareDataLoader(*ifs, &dataLoaderStatusListener)) {
         LOG(ERROR) << "prepareDataLoader() failed";
         deleteStorageLocked(*ifs, std::move(l));
         return kInvalidStorageId;
@@ -563,6 +578,49 @@
     return it->second->second.storage;
 }
 
+int IncrementalService::setStorageParams(StorageId storageId, bool enableReadLogs) {
+    const auto ifs = getIfs(storageId);
+    if (!ifs) {
+        LOG(ERROR) << "setStorageParams failed, invalid storageId: " << storageId;
+        return -EINVAL;
+    }
+
+    if (enableReadLogs) {
+        if (auto status =
+                    mAppOpsManager->checkPermission(kDataUsageStats, kOpUsage,
+                                                    ifs->dataLoaderParams.packageName.c_str());
+            !status.isOk()) {
+            LOG(ERROR) << "checkPermission failed: " << status.toString8();
+            return fromBinderStatus(status);
+        }
+    }
+
+    if (auto status = applyStorageParams(*ifs, enableReadLogs); !status.isOk()) {
+        LOG(ERROR) << "applyStorageParams failed: " << status.toString8();
+        return fromBinderStatus(status);
+    }
+
+    if (enableReadLogs) {
+        registerAppOpsCallback(ifs->dataLoaderParams.packageName);
+    }
+
+    return 0;
+}
+
+binder::Status IncrementalService::applyStorageParams(IncFsMount& ifs, bool enableReadLogs) {
+    using unique_fd = ::android::base::unique_fd;
+    ::android::os::incremental::IncrementalFileSystemControlParcel control;
+    control.cmd.reset(unique_fd(dup(ifs.control.cmd())));
+    control.pendingReads.reset(unique_fd(dup(ifs.control.pendingReads())));
+    auto logsFd = ifs.control.logs();
+    if (logsFd >= 0) {
+        control.log.reset(unique_fd(dup(logsFd)));
+    }
+
+    std::lock_guard l(mMountOperationLock);
+    return mVold->setIncFsMountOptions(control, enableReadLogs);
+}
+
 void IncrementalService::deleteStorage(StorageId storageId) {
     const auto ifs = getIfs(storageId);
     if (!ifs) {
@@ -665,7 +723,10 @@
     if (storageInfo == ifs->storages.end()) {
         return -EINVAL;
     }
-    std::string normSource = normalizePathToStorage(ifs, storage, source);
+    std::string normSource = normalizePathToStorageLocked(storageInfo, source);
+    if (normSource.empty()) {
+        return -EINVAL;
+    }
     l.unlock();
     std::unique_lock l2(mLock, std::defer_lock);
     return addBindMount(*ifs, storage, storageInfo->second.name, std::move(normSource),
@@ -714,22 +775,28 @@
     return 0;
 }
 
-std::string IncrementalService::normalizePathToStorage(const IncrementalService::IfsMountPtr ifs,
+std::string IncrementalService::normalizePathToStorageLocked(
+        IncFsMount::StorageMap::iterator storageIt, std::string_view path) {
+    std::string normPath;
+    if (path::isAbsolute(path)) {
+        normPath = path::normalize(path);
+        if (!path::startsWith(normPath, storageIt->second.name)) {
+            return {};
+        }
+    } else {
+        normPath = path::normalize(path::join(storageIt->second.name, path));
+    }
+    return normPath;
+}
+
+std::string IncrementalService::normalizePathToStorage(const IncrementalService::IfsMountPtr& ifs,
                                                        StorageId storage, std::string_view path) {
+    std::unique_lock l(ifs->lock);
     const auto storageInfo = ifs->storages.find(storage);
     if (storageInfo == ifs->storages.end()) {
         return {};
     }
-    std::string normPath;
-    if (path::isAbsolute(path)) {
-        normPath = path::normalize(path);
-    } else {
-        normPath = path::normalize(path::join(storageInfo->second.name, path));
-    }
-    if (!path::startsWith(normPath, storageInfo->second.name)) {
-        return {};
-    }
-    return normPath;
+    return normalizePathToStorageLocked(storageInfo, path);
 }
 
 int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
@@ -737,16 +804,15 @@
     if (auto ifs = getIfs(storage)) {
         std::string normPath = normalizePathToStorage(ifs, storage, path);
         if (normPath.empty()) {
+            LOG(ERROR) << "Internal error: storageId " << storage
+                       << " failed to normalize: " << path;
             return -EINVAL;
         }
         auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params);
         if (err) {
+            LOG(ERROR) << "Internal error: storageId " << storage << " failed to makeFile: " << err;
             return err;
         }
-        std::vector<uint8_t> metadataBytes;
-        if (params.metadata.data && params.metadata.size > 0) {
-            metadataBytes.assign(params.metadata.data, params.metadata.data + params.metadata.size);
-        }
         return 0;
     }
     return -EINVAL;
@@ -786,8 +852,9 @@
 
 int IncrementalService::link(StorageId sourceStorageId, std::string_view oldPath,
                              StorageId destStorageId, std::string_view newPath) {
-    if (auto ifsSrc = getIfs(sourceStorageId), ifsDest = getIfs(destStorageId);
-        ifsSrc && ifsSrc == ifsDest) {
+    auto ifsSrc = getIfs(sourceStorageId);
+    auto ifsDest = sourceStorageId == destStorageId ? ifsSrc : getIfs(destStorageId);
+    if (ifsSrc && ifsSrc == ifsDest) {
         std::string normOldPath = normalizePathToStorage(ifsSrc, sourceStorageId, oldPath);
         std::string normNewPath = normalizePathToStorage(ifsDest, destStorageId, newPath);
         if (normOldPath.empty() || normNewPath.empty()) {
@@ -955,13 +1022,13 @@
             continue;
         }
         const auto root = path::join(mIncrementalDir, name);
-        if (!mountExistingImage(root, name)) {
+        if (!mountExistingImage(root)) {
             IncFsMount::cleanupFilesystem(path);
         }
     }
 }
 
-bool IncrementalService::mountExistingImage(std::string_view root, std::string_view key) {
+bool IncrementalService::mountExistingImage(std::string_view root) {
     auto mountTarget = path::join(root, constants().mount);
     const auto backing = path::join(root, constants().backing);
 
@@ -979,16 +1046,26 @@
 
     auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
 
-    auto m = parseFromIncfs<metadata::Mount>(mIncFs.get(), ifs->control,
-                                             path::join(mountTarget, constants().infoMdName));
-    if (!m.has_loader() || !m.has_storage()) {
+    auto mount = parseFromIncfs<metadata::Mount>(mIncFs.get(), ifs->control,
+                                                 path::join(mountTarget, constants().infoMdName));
+    if (!mount.has_loader() || !mount.has_storage()) {
         LOG(ERROR) << "Bad mount metadata in mount at " << root;
         return false;
     }
 
-    ifs->mountId = m.storage().id();
+    ifs->mountId = mount.storage().id();
     mNextId = std::max(mNextId, ifs->mountId + 1);
 
+    // DataLoader params
+    {
+        auto& dlp = ifs->dataLoaderParams;
+        const auto& loader = mount.loader();
+        dlp.type = (android::content::pm::DataLoaderType)loader.type();
+        dlp.packageName = loader.package_name();
+        dlp.className = loader.class_name();
+        dlp.arguments = loader.arguments();
+    }
+
     std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
     auto d = openDir(path::c_str(mountTarget));
     while (auto e = ::readdir(d.get())) {
@@ -1012,16 +1089,24 @@
             }
             auto name = std::string_view(e->d_name);
             if (name.starts_with(constants().storagePrefix)) {
-                auto md = parseFromIncfs<metadata::Storage>(mIncFs.get(), ifs->control,
-                                                            path::join(mountTarget, name));
-                auto [_, inserted] = mMounts.try_emplace(md.id(), ifs);
+                int storageId;
+                const auto res = std::from_chars(name.data() + constants().storagePrefix.size() + 1,
+                                                 name.data() + name.size(), storageId);
+                if (res.ec != std::errc{} || *res.ptr != '_') {
+                    LOG(WARNING) << "Ignoring storage with invalid name '" << name << "' for mount "
+                                 << root;
+                    continue;
+                }
+                auto [_, inserted] = mMounts.try_emplace(storageId, ifs);
                 if (!inserted) {
-                    LOG(WARNING) << "Ignoring storage with duplicate id " << md.id()
+                    LOG(WARNING) << "Ignoring storage with duplicate id " << storageId
                                  << " for mount " << root;
                     continue;
                 }
-                ifs->storages.insert_or_assign(md.id(), IncFsMount::Storage{std::string(name)});
-                mNextId = std::max(mNextId, md.id() + 1);
+                ifs->storages.insert_or_assign(storageId,
+                                               IncFsMount::Storage{
+                                                       path::join(root, constants().mount, name)});
+                mNextId = std::max(mNextId, storageId + 1);
             }
         }
     }
@@ -1051,23 +1136,9 @@
 }
 
 bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
-                                           DataLoaderParamsParcel* params,
                                            const DataLoaderStatusListener* externalListener) {
     if (!mSystemReady.load(std::memory_order_relaxed)) {
         std::unique_lock l(ifs.lock);
-        if (params) {
-            if (ifs.savedDataLoaderParams) {
-                LOG(WARNING) << "Trying to pass second set of data loader parameters, ignored it";
-            } else {
-                ifs.savedDataLoaderParams = std::move(*params);
-            }
-        } else {
-            if (!ifs.savedDataLoaderParams) {
-                LOG(ERROR) << "Mount " << ifs.mountId
-                           << " is broken: no data loader params (system is not ready yet)";
-                return false;
-            }
-        }
         return true; // eventually...
     }
 
@@ -1077,38 +1148,45 @@
         return true;
     }
 
-    auto* dlp = params ? params
-                       : ifs.savedDataLoaderParams ? &ifs.savedDataLoaderParams.value() : nullptr;
-    if (!dlp) {
-        LOG(ERROR) << "Mount " << ifs.mountId << " is broken: no data loader params";
-        return false;
-    }
     FileSystemControlParcel fsControlParcel;
     fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
     fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd())));
     fsControlParcel.incremental->pendingReads.reset(
             base::unique_fd(::dup(ifs.control.pendingReads())));
     fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs())));
+    fsControlParcel.service = new IncrementalServiceConnector(*this, ifs.mountId);
     sp<IncrementalDataLoaderListener> listener =
             new IncrementalDataLoaderListener(*this,
                                               externalListener ? *externalListener
                                                                : DataLoaderStatusListener());
     bool created = false;
-    auto status = mDataLoaderManager->initializeDataLoader(ifs.mountId, *dlp, fsControlParcel,
-                                                           listener, &created);
+    auto status = mDataLoaderManager->initializeDataLoader(ifs.mountId, ifs.dataLoaderParams, fsControlParcel, listener, &created);
     if (!status.isOk() || !created) {
         LOG(ERROR) << "Failed to create a data loader for mount " << ifs.mountId;
         return false;
     }
-    ifs.savedDataLoaderParams.reset();
     return true;
 }
 
-// Extract lib filse from zip, create new files in incfs and write data to them
+template <class Duration>
+static long elapsedMcs(Duration start, Duration end) {
+    return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
+}
+
+// Extract lib files from zip, create new files in incfs and write data to them
 bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
                                                  std::string_view libDirRelativePath,
                                                  std::string_view abi) {
+    namespace sc = std::chrono;
+    using Clock = sc::steady_clock;
+    auto start = Clock::now();
+
     const auto ifs = getIfs(storage);
+    if (!ifs) {
+        LOG(ERROR) << "Invalid storage " << storage;
+        return false;
+    }
+
     // First prepare target directories if they don't exist yet
     if (auto res = makeDirs(storage, libDirRelativePath, 0755)) {
         LOG(ERROR) << "Failed to prepare target lib directory " << libDirRelativePath
@@ -1116,112 +1194,196 @@
         return false;
     }
 
-    std::unique_ptr<ZipFileRO> zipFile(ZipFileRO::open(apkFullPath.data()));
+    auto mkDirsTs = Clock::now();
+
+    std::unique_ptr<ZipFileRO> zipFile(ZipFileRO::open(path::c_str(apkFullPath)));
     if (!zipFile) {
         LOG(ERROR) << "Failed to open zip file at " << apkFullPath;
         return false;
     }
     void* cookie = nullptr;
     const auto libFilePrefix = path::join(constants().libDir, abi);
-    if (!zipFile.get()->startIteration(&cookie, libFilePrefix.c_str() /* prefix */,
-                                       constants().libSuffix.data() /* suffix */)) {
+    if (!zipFile->startIteration(&cookie, libFilePrefix.c_str() /* prefix */,
+                                 constants().libSuffix.data() /* suffix */)) {
         LOG(ERROR) << "Failed to start zip iteration for " << apkFullPath;
         return false;
     }
+    auto endIteration = [&zipFile](void* cookie) { zipFile->endIteration(cookie); };
+    auto iterationCleaner = std::unique_ptr<void, decltype(endIteration)>(cookie, endIteration);
+
+    auto openZipTs = Clock::now();
+
+    std::vector<IncFsDataBlock> instructions;
     ZipEntryRO entry = nullptr;
-    bool success = true;
-    while ((entry = zipFile.get()->nextEntry(cookie)) != nullptr) {
+    while ((entry = zipFile->nextEntry(cookie)) != nullptr) {
+        auto startFileTs = Clock::now();
+
         char fileName[PATH_MAX];
-        if (zipFile.get()->getEntryFileName(entry, fileName, sizeof(fileName))) {
+        if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) {
             continue;
         }
         const auto libName = path::basename(fileName);
         const auto targetLibPath = path::join(libDirRelativePath, libName);
         const auto targetLibPathAbsolute = normalizePathToStorage(ifs, storage, targetLibPath);
         // If the extract file already exists, skip
-        struct stat st;
-        if (stat(targetLibPathAbsolute.c_str(), &st) == 0) {
-            LOG(INFO) << "Native lib file already exists: " << targetLibPath
-                      << "; skipping extraction";
+        if (access(targetLibPathAbsolute.c_str(), F_OK) == 0) {
+            if (sEnablePerfLogging) {
+                LOG(INFO) << "incfs: Native lib file already exists: " << targetLibPath
+                          << "; skipping extraction, spent "
+                          << elapsedMcs(startFileTs, Clock::now()) << "mcs";
+            }
             continue;
         }
 
-        uint32_t uncompressedLen;
-        if (!zipFile.get()->getEntryInfo(entry, nullptr, &uncompressedLen, nullptr, nullptr,
-                                         nullptr, nullptr)) {
+        uint32_t uncompressedLen, compressedLen;
+        if (!zipFile->getEntryInfo(entry, nullptr, &uncompressedLen, &compressedLen, nullptr,
+                                   nullptr, nullptr)) {
             LOG(ERROR) << "Failed to read native lib entry: " << fileName;
-            success = false;
-            break;
+            return false;
         }
 
         // Create new lib file without signature info
-        incfs::NewFileParams libFileParams{};
-        libFileParams.size = uncompressedLen;
-        libFileParams.signature = {};
-        // Metadata of the new lib file is its relative path
-        IncFsSpan libFileMetadata;
-        libFileMetadata.data = targetLibPath.c_str();
-        libFileMetadata.size = targetLibPath.size();
-        libFileParams.metadata = libFileMetadata;
+        incfs::NewFileParams libFileParams = {
+                .size = uncompressedLen,
+                .signature = {},
+                // Metadata of the new lib file is its relative path
+                .metadata = {targetLibPath.c_str(), (IncFsSize)targetLibPath.size()},
+        };
         incfs::FileId libFileId = idFromMetadata(targetLibPath);
-        if (auto res = makeFile(storage, targetLibPath, 0777, libFileId, libFileParams)) {
+        if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0777, libFileId,
+                                        libFileParams)) {
             LOG(ERROR) << "Failed to make file for: " << targetLibPath << " errno: " << res;
-            success = false;
             // If one lib file fails to be created, abort others as well
-            break;
+            return false;
         }
+
+        auto makeFileTs = Clock::now();
+
         // If it is a zero-byte file, skip data writing
         if (uncompressedLen == 0) {
+            if (sEnablePerfLogging) {
+                LOG(INFO) << "incfs: Extracted " << libName << "(" << compressedLen << " -> "
+                          << uncompressedLen << " bytes): " << elapsedMcs(startFileTs, makeFileTs)
+                          << "mcs, make: " << elapsedMcs(startFileTs, makeFileTs);
+            }
             continue;
         }
 
         // Write extracted data to new file
-        std::vector<uint8_t> libData(uncompressedLen);
-        if (!zipFile.get()->uncompressEntry(entry, &libData[0], uncompressedLen)) {
+        // NOTE: don't zero-initialize memory, it may take a while
+        auto libData = std::unique_ptr<uint8_t[]>(new uint8_t[uncompressedLen]);
+        if (!zipFile->uncompressEntry(entry, libData.get(), uncompressedLen)) {
             LOG(ERROR) << "Failed to extract native lib zip entry: " << fileName;
-            success = false;
-            break;
+            return false;
         }
-        android::base::unique_fd writeFd(mIncFs->openWrite(ifs->control, libFileId));
-        if (writeFd < 0) {
+
+        auto extractFileTs = Clock::now();
+
+        const auto writeFd = mIncFs->openForSpecialOps(ifs->control, libFileId);
+        if (!writeFd.ok()) {
             LOG(ERROR) << "Failed to open write fd for: " << targetLibPath << " errno: " << writeFd;
-            success = false;
-            break;
+            return false;
         }
-        const int numBlocks = uncompressedLen / constants().blockSize + 1;
-        std::vector<IncFsDataBlock> instructions;
-        auto remainingData = std::span(libData);
-        for (int i = 0; i < numBlocks - 1; i++) {
+
+        auto openFileTs = Clock::now();
+
+        const int numBlocks = (uncompressedLen + constants().blockSize - 1) / constants().blockSize;
+        instructions.clear();
+        instructions.reserve(numBlocks);
+        auto remainingData = std::span(libData.get(), uncompressedLen);
+        for (int i = 0; i < numBlocks; i++) {
+            const auto blockSize = std::min<uint16_t>(constants().blockSize, remainingData.size());
             auto inst = IncFsDataBlock{
-                    .fileFd = writeFd,
+                    .fileFd = writeFd.get(),
                     .pageIndex = static_cast<IncFsBlockIndex>(i),
                     .compression = INCFS_COMPRESSION_KIND_NONE,
                     .kind = INCFS_BLOCK_KIND_DATA,
-                    .dataSize = static_cast<uint16_t>(constants().blockSize),
+                    .dataSize = blockSize,
                     .data = reinterpret_cast<const char*>(remainingData.data()),
             };
             instructions.push_back(inst);
-            remainingData = remainingData.subspan(constants().blockSize);
+            remainingData = remainingData.subspan(blockSize);
         }
-        // Last block
-        auto inst = IncFsDataBlock{
-                .fileFd = writeFd,
-                .pageIndex = static_cast<IncFsBlockIndex>(numBlocks - 1),
-                .compression = INCFS_COMPRESSION_KIND_NONE,
-                .kind = INCFS_BLOCK_KIND_DATA,
-                .dataSize = static_cast<uint16_t>(remainingData.size()),
-                .data = reinterpret_cast<const char*>(remainingData.data()),
-        };
-        instructions.push_back(inst);
+        auto prepareInstsTs = Clock::now();
+
         size_t res = mIncFs->writeBlocks(instructions);
         if (res != instructions.size()) {
             LOG(ERROR) << "Failed to write data into: " << targetLibPath;
-            success = false;
+            return false;
         }
-        instructions.clear();
+
+        if (sEnablePerfLogging) {
+            auto endFileTs = Clock::now();
+            LOG(INFO) << "incfs: Extracted " << libName << "(" << compressedLen << " -> "
+                      << uncompressedLen << " bytes): " << elapsedMcs(startFileTs, endFileTs)
+                      << "mcs, make: " << elapsedMcs(startFileTs, makeFileTs)
+                      << " extract: " << elapsedMcs(makeFileTs, extractFileTs)
+                      << " open: " << elapsedMcs(extractFileTs, openFileTs)
+                      << " prepare: " << elapsedMcs(openFileTs, prepareInstsTs)
+                      << " write:" << elapsedMcs(prepareInstsTs, endFileTs);
+        }
     }
-    zipFile.get()->endIteration(cookie);
-    return success;
+
+    if (sEnablePerfLogging) {
+        auto end = Clock::now();
+        LOG(INFO) << "incfs: configureNativeBinaries complete in " << elapsedMcs(start, end)
+                  << "mcs, make dirs: " << elapsedMcs(start, mkDirsTs)
+                  << " open zip: " << elapsedMcs(mkDirsTs, openZipTs)
+                  << " extract all: " << elapsedMcs(openZipTs, end);
+    }
+
+    return true;
+}
+
+void IncrementalService::registerAppOpsCallback(const std::string& packageName) {
+    sp<IAppOpsCallback> listener;
+    {
+        std::unique_lock lock{mCallbacksLock};
+        auto& cb = mCallbackRegistered[packageName];
+        if (cb) {
+            return;
+        }
+        cb = new AppOpsListener(*this, packageName);
+        listener = cb;
+    }
+
+    mAppOpsManager->startWatchingMode(AppOpsManager::OP_GET_USAGE_STATS, String16(packageName.c_str()), listener);
+}
+
+bool IncrementalService::unregisterAppOpsCallback(const std::string& packageName) {
+    sp<IAppOpsCallback> listener;
+    {
+        std::unique_lock lock{mCallbacksLock};
+        auto found = mCallbackRegistered.find(packageName);
+        if (found == mCallbackRegistered.end()) {
+            return false;
+        }
+        listener = found->second;
+        mCallbackRegistered.erase(found);
+    }
+
+    mAppOpsManager->stopWatchingMode(listener);
+    return true;
+}
+
+void IncrementalService::onAppOpChanged(const std::string& packageName) {
+    if (!unregisterAppOpsCallback(packageName)) {
+        return;
+    }
+
+    std::vector<IfsMountPtr> affected;
+    {
+        std::lock_guard l(mLock);
+        affected.reserve(mMounts.size());
+        for (auto&& [id, ifs] : mMounts) {
+            if (ifs->mountId == id && ifs->dataLoaderParams.packageName == packageName) {
+                affected.push_back(ifs);
+            }
+        }
+    }
+    for (auto&& ifs : affected) {
+        applyStorageParams(*ifs, false);
+    }
 }
 
 binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChanged(MountId mountId,
@@ -1287,4 +1449,14 @@
     return binder::Status::ok();
 }
 
+void IncrementalService::AppOpsListener::opChanged(int32_t, const String16&) {
+    incrementalService.onAppOpChanged(packageName);
+}
+
+binder::Status IncrementalService::IncrementalServiceConnector::setStorageParams(
+        bool enableReadLogs, int32_t* _aidl_return) {
+    *_aidl_return = incrementalService.setStorageParams(storage, enableReadLogs);
+    return binder::Status::ok();
+}
+
 } // namespace android::incremental
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 406b32e..db14a79 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -39,6 +39,7 @@
 
 #include "ServiceWrappers.h"
 #include "android/content/pm/BnDataLoaderStatusListener.h"
+#include "android/os/incremental/BnIncrementalServiceConnector.h"
 #include "incfs.h"
 #include "path.h"
 
@@ -111,6 +112,8 @@
     int unbind(StorageId storage, std::string_view target);
     void deleteStorage(StorageId storage);
 
+    int setStorageParams(StorageId storage, bool enableReadLogs);
+
     int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
                  incfs::NewFileParams params);
     int makeDir(StorageId storage, std::string_view path, int mode = 0755);
@@ -130,20 +133,44 @@
     bool startLoading(StorageId storage) const;
     bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
                                  std::string_view libDirRelativePath, std::string_view abi);
+
     class IncrementalDataLoaderListener : public android::content::pm::BnDataLoaderStatusListener {
     public:
         IncrementalDataLoaderListener(IncrementalService& incrementalService,
                                       DataLoaderStatusListener externalListener)
               : incrementalService(incrementalService), externalListener(externalListener) {}
         // Callbacks interface
-        binder::Status onStatusChanged(MountId mount, int newStatus) override;
+        binder::Status onStatusChanged(MountId mount, int newStatus) final;
 
     private:
         IncrementalService& incrementalService;
         DataLoaderStatusListener externalListener;
     };
 
+    class AppOpsListener : public android::BnAppOpsCallback {
+    public:
+        AppOpsListener(IncrementalService& incrementalService, std::string packageName) : incrementalService(incrementalService), packageName(std::move(packageName)) {}
+        void opChanged(int32_t op, const String16& packageName) final;
+
+    private:
+        IncrementalService& incrementalService;
+        const std::string packageName;
+    };
+
+    class IncrementalServiceConnector : public BnIncrementalServiceConnector {
+    public:
+        IncrementalServiceConnector(IncrementalService& incrementalService, int32_t storage)
+              : incrementalService(incrementalService), storage(storage) {}
+        binder::Status setStorageParams(bool enableReadLogs, int32_t* _aidl_return) final;
+
+    private:
+        IncrementalService& incrementalService;
+        int32_t const storage;
+    };
+
 private:
+    static const bool sEnablePerfLogging;
+
     struct IncFsMount {
         struct Bind {
             StorageId storage;
@@ -167,11 +194,10 @@
         /*const*/ MountId mountId;
         StorageMap storages;
         BindMap bindPoints;
-        std::optional<DataLoaderParamsParcel> savedDataLoaderParams;
+        DataLoaderParamsParcel dataLoaderParams;
         std::atomic<int> nextStorageDirNo{0};
         std::atomic<int> dataLoaderStatus = -1;
         bool dataLoaderStartRequested = false;
-        TimePoint connectionLostTime = TimePoint();
         const IncrementalService& incrementalService;
 
         IncFsMount(std::string root, MountId mountId, Control control,
@@ -194,7 +220,7 @@
     using BindPathMap = std::map<std::string, IncFsMount::BindMap::iterator, path::PathLess>;
 
     void mountExistingImages();
-    bool mountExistingImage(std::string_view root, std::string_view key);
+    bool mountExistingImage(std::string_view root);
 
     IfsMountPtr getIfs(StorageId storage) const;
     const IfsMountPtr& getIfsLocked(StorageId storage) const;
@@ -206,8 +232,7 @@
                            std::string&& source, std::string&& target, BindKind kind,
                            std::unique_lock<std::mutex>& mainLock);
 
-    bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params = nullptr,
-                           const DataLoaderStatusListener* externalListener = nullptr);
+    bool prepareDataLoader(IncFsMount& ifs, const DataLoaderStatusListener* externalListener = nullptr);
     bool startDataLoader(MountId mountId) const;
 
     BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
@@ -216,13 +241,22 @@
     void deleteStorage(IncFsMount& ifs);
     void deleteStorageLocked(IncFsMount& ifs, std::unique_lock<std::mutex>&& ifsLock);
     MountMap::iterator getStorageSlotLocked();
-    std::string normalizePathToStorage(const IfsMountPtr incfs, StorageId storage,
+    std::string normalizePathToStorage(const IfsMountPtr& incfs, StorageId storage,
                                        std::string_view path);
+    std::string normalizePathToStorageLocked(IncFsMount::StorageMap::iterator storageIt,
+                                             std::string_view path);
+
+    binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
+
+    void registerAppOpsCallback(const std::string& packageName);
+    bool unregisterAppOpsCallback(const std::string& packageName);
+    void onAppOpChanged(const std::string& packageName);
 
     // Member variables
-    std::unique_ptr<VoldServiceWrapper> mVold;
-    std::unique_ptr<DataLoaderManagerWrapper> mDataLoaderManager;
-    std::unique_ptr<IncFsWrapper> mIncFs;
+    std::unique_ptr<VoldServiceWrapper> const mVold;
+    std::unique_ptr<DataLoaderManagerWrapper> const mDataLoaderManager;
+    std::unique_ptr<IncFsWrapper> const mIncFs;
+    std::unique_ptr<AppOpsManagerWrapper> const mAppOpsManager;
     const std::string mIncrementalDir;
 
     mutable std::mutex mLock;
@@ -230,6 +264,9 @@
     MountMap mMounts;
     BindPathMap mBindsByPath;
 
+    std::mutex mCallbacksLock;
+    std::map<std::string, sp<AppOpsListener>> mCallbackRegistered;
+
     std::atomic_bool mSystemReady = false;
     StorageId mNextId = 0;
     std::promise<void> mPrepareDataLoaders;
diff --git a/services/incremental/IncrementalServiceValidation.h b/services/incremental/IncrementalServiceValidation.h
new file mode 100644
index 0000000..48894c6
--- /dev/null
+++ b/services/incremental/IncrementalServiceValidation.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/stringprintf.h>
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
+#include <binder/PermissionController.h>
+#include <binder/Status.h>
+
+namespace android::incremental {
+
+inline binder::Status Ok() {
+    return binder::Status::ok();
+}
+
+inline binder::Status Exception(uint32_t code, const std::string& msg) {
+    return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
+}
+
+inline int fromBinderStatus(const binder::Status& status) {
+    return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
+            ? status.serviceSpecificErrorCode() > 0 ? -status.serviceSpecificErrorCode()
+                                                    : status.serviceSpecificErrorCode() == 0
+                            ? -EFAULT
+                            : status.serviceSpecificErrorCode()
+            : -EIO;
+}
+
+inline binder::Status CheckPermissionForDataDelivery(const char* permission, const char* operation,
+                                                     const char* package) {
+    using android::base::StringPrintf;
+
+    int32_t pid;
+    int32_t uid;
+
+    if (!PermissionCache::checkCallingPermission(String16(permission), &pid, &uid)) {
+        return Exception(binder::Status::EX_SECURITY,
+                         StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
+    }
+
+    String16 packageName{package};
+
+    // Caller must also have op granted.
+    PermissionController pc;
+    if (auto packageUid = pc.getPackageUid(packageName, 0); packageUid != uid) {
+        return Exception(binder::Status::EX_SECURITY,
+                         StringPrintf("UID %d / PID %d does not own package %s", uid, pid,
+                                      package));
+    }
+    switch (auto result = pc.noteOp(String16(operation), uid, packageName); result) {
+        case PermissionController::MODE_ALLOWED:
+        case PermissionController::MODE_DEFAULT:
+            return binder::Status::ok();
+        default:
+            return Exception(binder::Status::EX_SECURITY,
+                             StringPrintf("UID %d / PID %d / package %s lacks app-op %s, error %d",
+                                          uid, pid, package, operation, result));
+    }
+}
+
+} // namespace android::incremental
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 2e31ef1..9f4192f 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -59,4 +59,8 @@
     return std::make_unique<RealIncFs>();
 }
 
+std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
+    return std::make_unique<RealAppOpsManager>();
+}
+
 } // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index c70a47d..84bf1ff 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "IncrementalServiceValidation.h"
+
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <android/content/pm/DataLoaderParamsParcel.h>
@@ -24,6 +26,7 @@
 #include <android/content/pm/IDataLoaderManager.h>
 #include <android/content/pm/IDataLoaderStatusListener.h>
 #include <android/os/IVold.h>
+#include <binder/AppOpsManager.h>
 #include <binder/IServiceManager.h>
 #include <incfs.h>
 
@@ -49,6 +52,7 @@
     virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
     virtual binder::Status bindMount(const std::string& sourceDir,
                                      const std::string& targetDir) const = 0;
+    virtual binder::Status setIncFsMountOptions(const ::android::os::incremental::IncrementalFileSystemControlParcel& control, bool enableReadLogs) const = 0;
 };
 
 class DataLoaderManagerWrapper {
@@ -76,16 +80,26 @@
     virtual ErrorCode link(const Control& control, std::string_view from,
                            std::string_view to) const = 0;
     virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
-    virtual base::unique_fd openWrite(const Control& control, FileId id) const = 0;
+    virtual base::unique_fd openForSpecialOps(const Control& control, FileId id) const = 0;
     virtual ErrorCode writeBlocks(Span<const DataBlock> blocks) const = 0;
 };
 
+class AppOpsManagerWrapper {
+public:
+    virtual ~AppOpsManagerWrapper() = default;
+    virtual binder::Status checkPermission(const char* permission, const char* operation,
+                                           const char* package) const = 0;
+    virtual void startWatchingMode(int32_t op, const String16& packageName, const sp<IAppOpsCallback>& callback) = 0;
+    virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
+};
+
 class ServiceManagerWrapper {
 public:
     virtual ~ServiceManagerWrapper() = default;
     virtual std::unique_ptr<VoldServiceWrapper> getVoldService() = 0;
     virtual std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() = 0;
     virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
+    virtual std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() = 0;
 };
 
 // --- Real stuff ---
@@ -96,16 +110,21 @@
     ~RealVoldService() = default;
     binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                               int32_t flags,
-                              IncrementalFileSystemControlParcel* _aidl_return) const override {
+                              IncrementalFileSystemControlParcel* _aidl_return) const final {
         return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
     }
-    binder::Status unmountIncFs(const std::string& dir) const override {
+    binder::Status unmountIncFs(const std::string& dir) const final {
         return mInterface->unmountIncFs(dir);
     }
     binder::Status bindMount(const std::string& sourceDir,
-                             const std::string& targetDir) const override {
+                             const std::string& targetDir) const final {
         return mInterface->bindMount(sourceDir, targetDir);
     }
+    binder::Status setIncFsMountOptions(
+            const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
+            bool enableReadLogs) const final {
+        return mInterface->setIncFsMountOptions(control, enableReadLogs);
+    }
 
 private:
     sp<os::IVold> mInterface;
@@ -119,13 +138,13 @@
     binder::Status initializeDataLoader(MountId mountId, const DataLoaderParamsParcel& params,
                                         const FileSystemControlParcel& control,
                                         const sp<IDataLoaderStatusListener>& listener,
-                                        bool* _aidl_return) const override {
+                                        bool* _aidl_return) const final {
         return mInterface->initializeDataLoader(mountId, params, control, listener, _aidl_return);
     }
-    binder::Status getDataLoader(MountId mountId, sp<IDataLoader>* _aidl_return) const override {
+    binder::Status getDataLoader(MountId mountId, sp<IDataLoader>* _aidl_return) const final {
         return mInterface->getDataLoader(mountId, _aidl_return);
     }
-    binder::Status destroyDataLoader(MountId mountId) const override {
+    binder::Status destroyDataLoader(MountId mountId) const final {
         return mInterface->destroyDataLoader(mountId);
     }
 
@@ -133,13 +152,33 @@
     sp<content::pm::IDataLoaderManager> mInterface;
 };
 
+class RealAppOpsManager : public AppOpsManagerWrapper {
+public:
+    ~RealAppOpsManager() = default;
+    binder::Status checkPermission(const char* permission, const char* operation,
+                                   const char* package) const final {
+        return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
+    }
+    void startWatchingMode(int32_t op, const String16& packageName,
+                           const sp<IAppOpsCallback>& callback) final {
+        mAppOpsManager.startWatchingMode(op, packageName, callback);
+    }
+    void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
+        mAppOpsManager.stopWatchingMode(callback);
+    }
+
+private:
+    android::AppOpsManager mAppOpsManager;
+};
+
 class RealServiceManager : public ServiceManagerWrapper {
 public:
     RealServiceManager(sp<IServiceManager> serviceManager);
     ~RealServiceManager() = default;
-    std::unique_ptr<VoldServiceWrapper> getVoldService() override;
-    std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() override;
-    std::unique_ptr<IncFsWrapper> getIncFs() override;
+    std::unique_ptr<VoldServiceWrapper> getVoldService() final;
+    std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final;
+    std::unique_ptr<IncFsWrapper> getIncFs() final;
+    std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final;
 
 private:
     template <class INTERFACE>
@@ -151,36 +190,35 @@
 public:
     RealIncFs() = default;
     ~RealIncFs() = default;
-    Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const override {
+    Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const final {
         return incfs::createControl(cmd, pendingReads, logs);
     }
     ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
-                       NewFileParams params) const override {
+                       NewFileParams params) const final {
         return incfs::makeFile(control, path, mode, id, params);
     }
-    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const override {
+    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
         return incfs::makeDir(control, path, mode);
     }
-    RawMetadata getMetadata(const Control& control, FileId fileid) const override {
+    RawMetadata getMetadata(const Control& control, FileId fileid) const final {
         return incfs::getMetadata(control, fileid);
     }
-    RawMetadata getMetadata(const Control& control, std::string_view path) const override {
+    RawMetadata getMetadata(const Control& control, std::string_view path) const final {
         return incfs::getMetadata(control, path);
     }
-    FileId getFileId(const Control& control, std::string_view path) const override {
+    FileId getFileId(const Control& control, std::string_view path) const final {
         return incfs::getFileId(control, path);
     }
-    ErrorCode link(const Control& control, std::string_view from,
-                   std::string_view to) const override {
+    ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
         return incfs::link(control, from, to);
     }
-    ErrorCode unlink(const Control& control, std::string_view path) const override {
+    ErrorCode unlink(const Control& control, std::string_view path) const final {
         return incfs::unlink(control, path);
     }
-    base::unique_fd openWrite(const Control& control, FileId id) const override {
-        return base::unique_fd{incfs::openWrite(control, id)};
+    base::unique_fd openForSpecialOps(const Control& control, FileId id) const final {
+        return base::unique_fd{incfs::openForSpecialOps(control, id).release()};
     }
-    ErrorCode writeBlocks(Span<const DataBlock> blocks) const override {
+    ErrorCode writeBlocks(Span<const DataBlock> blocks) const final {
         return incfs::writeBlocks(blocks);
     }
 };
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index c4b4d17..0635ae1 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -52,6 +52,8 @@
     MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
     MOCK_CONST_METHOD2(bindMount,
                        binder::Status(const std::string& sourceDir, const std::string& argetDir));
+    MOCK_CONST_METHOD2(setIncFsMountOptions,
+                       binder::Status(const ::android::os::incremental::IncrementalFileSystemControlParcel&, bool));
 
     void mountIncFsFails() {
         ON_CALL(*this, mountIncFs(_, _, _, _))
@@ -74,6 +76,14 @@
     void bindMountSuccess() {
         ON_CALL(*this, bindMount(_, _)).WillByDefault(Return(binder::Status::ok()));
     }
+    void setIncFsMountOptionsFails() const {
+        ON_CALL(*this, setIncFsMountOptions(_, _))
+                .WillByDefault(
+                        Return(binder::Status::fromExceptionCode(1, String8("failed to set options"))));
+    }
+    void setIncFsMountOptionsSuccess() {
+        ON_CALL(*this, setIncFsMountOptions(_, _)).WillByDefault(Return(binder::Status::ok()));
+    }
     binder::Status getInvalidControlParcel(const std::string& imagePath,
                                            const std::string& targetDir, int32_t flags,
                                            IncrementalFileSystemControlParcel* _aidl_return) {
@@ -175,7 +185,7 @@
     MOCK_CONST_METHOD3(link,
                        ErrorCode(const Control& control, std::string_view from, std::string_view to));
     MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
-    MOCK_CONST_METHOD2(openWrite, base::unique_fd(const Control& control, FileId id));
+    MOCK_CONST_METHOD2(openForSpecialOps, base::unique_fd(const Control& control, FileId id));
     MOCK_CONST_METHOD1(writeBlocks, ErrorCode(Span<const DataBlock> blocks));
 
     void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
@@ -210,24 +220,53 @@
     }
 };
 
+class MockAppOpsManager : public AppOpsManagerWrapper {
+public:
+    MOCK_CONST_METHOD3(checkPermission, binder::Status(const char*, const char*, const char*));
+    MOCK_METHOD3(startWatchingMode, void(int32_t, const String16&, const sp<IAppOpsCallback>&));
+    MOCK_METHOD1(stopWatchingMode, void(const sp<IAppOpsCallback>&));
+
+    void checkPermissionSuccess() {
+        ON_CALL(*this, checkPermission(_, _, _)).WillByDefault(Return(android::incremental::Ok()));
+    }
+    void checkPermissionFails() {
+        ON_CALL(*this, checkPermission(_, _, _))
+                .WillByDefault(
+                        Return(android::incremental::Exception(binder::Status::EX_SECURITY, {})));
+    }
+    void initializeStartWatchingMode() {
+        ON_CALL(*this, startWatchingMode(_, _, _))
+                .WillByDefault(Invoke(this, &MockAppOpsManager::storeCallback));
+    }
+    void storeCallback(int32_t, const String16&, const sp<IAppOpsCallback>& cb) {
+        mStoredCallback = cb;
+    }
+
+    sp<IAppOpsCallback> mStoredCallback;
+};
+
 class MockServiceManager : public ServiceManagerWrapper {
 public:
     MockServiceManager(std::unique_ptr<MockVoldService> vold,
                        std::unique_ptr<MockDataLoaderManager> manager,
-                       std::unique_ptr<MockIncFs> incfs)
+                       std::unique_ptr<MockIncFs> incfs,
+                       std::unique_ptr<MockAppOpsManager> appOpsManager)
           : mVold(std::move(vold)),
             mDataLoaderManager(std::move(manager)),
-            mIncFs(std::move(incfs)) {}
+            mIncFs(std::move(incfs)),
+            mAppOpsManager(std::move(appOpsManager)) {}
     std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
     std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final {
         return std::move(mDataLoaderManager);
     }
     std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
+    std::unique_ptr<AppOpsManagerWrapper> getAppOpsManager() final { return std::move(mAppOpsManager); }
 
 private:
     std::unique_ptr<MockVoldService> mVold;
     std::unique_ptr<MockDataLoaderManager> mDataLoaderManager;
     std::unique_ptr<MockIncFs> mIncFs;
+    std::unique_ptr<MockAppOpsManager> mAppOpsManager;
 };
 
 // --- IncrementalServiceTest ---
@@ -241,11 +280,13 @@
         mDataLoaderManager = dataloaderManager.get();
         auto incFs = std::make_unique<NiceMock<MockIncFs>>();
         mIncFs = incFs.get();
+        auto appOps = std::make_unique<NiceMock<MockAppOpsManager>>();
+        mAppOpsManager = appOps.get();
         mIncrementalService =
                 std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
-                                                                        std::move(
-                                                                                dataloaderManager),
-                                                                        std::move(incFs)),
+                                                                        std::move(dataloaderManager),
+                                                                        std::move(incFs),
+                                                                        std::move(appOps)),
                                                      mRootDir.path);
         mDataLoaderParcel.packageName = "com.test";
         mDataLoaderParcel.arguments = "uri";
@@ -277,6 +318,7 @@
     NiceMock<MockVoldService>* mVold;
     NiceMock<MockIncFs>* mIncFs;
     NiceMock<MockDataLoaderManager>* mDataLoaderManager;
+    NiceMock<MockAppOpsManager>* mAppOpsManager;
     std::unique_ptr<IncrementalService> mIncrementalService;
     TemporaryDir mRootDir;
     DataLoaderParamsParcel mDataLoaderParcel;
@@ -390,6 +432,103 @@
     ASSERT_TRUE(mIncrementalService->startLoading(storageId));
 }
 
+TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccess) {
+    mVold->mountIncFsSuccess();
+    mIncFs->makeFileSuccess();
+    mVold->bindMountSuccess();
+    mVold->setIncFsMountOptionsSuccess();
+    mDataLoaderManager->initializeDataLoaderSuccess();
+    mDataLoaderManager->getDataLoaderSuccess();
+    mAppOpsManager->checkPermissionSuccess();
+    EXPECT_CALL(*mDataLoaderManager, destroyDataLoader(_));
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    // We are calling setIncFsMountOptions(true).
+    EXPECT_CALL(*mVold, setIncFsMountOptions(_, true)).Times(1);
+    // After setIncFsMountOptions succeeded expecting to start watching.
+    EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(1);
+    // Not expecting callback removal.
+    EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
+                                               IncrementalService::CreateOptions::CreateNew);
+    ASSERT_GE(storageId, 0);
+    ASSERT_GE(mIncrementalService->setStorageParams(storageId, true), 0);
+}
+
+TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsSuccessAndPermissionChanged) {
+    mVold->mountIncFsSuccess();
+    mIncFs->makeFileSuccess();
+    mVold->bindMountSuccess();
+    mVold->setIncFsMountOptionsSuccess();
+    mDataLoaderManager->initializeDataLoaderSuccess();
+    mDataLoaderManager->getDataLoaderSuccess();
+    mAppOpsManager->checkPermissionSuccess();
+    mAppOpsManager->initializeStartWatchingMode();
+    EXPECT_CALL(*mDataLoaderManager, destroyDataLoader(_));
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    // We are calling setIncFsMountOptions(true).
+    EXPECT_CALL(*mVold, setIncFsMountOptions(_, true)).Times(1);
+    // setIncFsMountOptions(false) is called on the callback.
+    EXPECT_CALL(*mVold, setIncFsMountOptions(_, false)).Times(1);
+    // After setIncFsMountOptions succeeded expecting to start watching.
+    EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(1);
+    // After callback is called, disable read logs and remove callback.
+    EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(1);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
+                                               IncrementalService::CreateOptions::CreateNew);
+    ASSERT_GE(storageId, 0);
+    ASSERT_GE(mIncrementalService->setStorageParams(storageId, true), 0);
+    ASSERT_NE(nullptr, mAppOpsManager->mStoredCallback.get());
+    mAppOpsManager->mStoredCallback->opChanged(0, {});
+}
+
+TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsCheckPermissionFails) {
+    mVold->mountIncFsSuccess();
+    mIncFs->makeFileSuccess();
+    mVold->bindMountSuccess();
+    mDataLoaderManager->initializeDataLoaderSuccess();
+    mDataLoaderManager->getDataLoaderSuccess();
+    mAppOpsManager->checkPermissionFails();
+    EXPECT_CALL(*mDataLoaderManager, destroyDataLoader(_));
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    // checkPermission fails, no calls to set opitions,  start or stop WatchingMode.
+    EXPECT_CALL(*mVold, setIncFsMountOptions(_, true)).Times(0);
+    EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0);
+    EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
+                                               IncrementalService::CreateOptions::CreateNew);
+    ASSERT_GE(storageId, 0);
+    ASSERT_LT(mIncrementalService->setStorageParams(storageId, true), 0);
+}
+
+TEST_F(IncrementalServiceTest, testSetIncFsMountOptionsFails) {
+    mVold->mountIncFsSuccess();
+    mIncFs->makeFileSuccess();
+    mVold->bindMountSuccess();
+    mVold->setIncFsMountOptionsFails();
+    mDataLoaderManager->initializeDataLoaderSuccess();
+    mDataLoaderManager->getDataLoaderSuccess();
+    mAppOpsManager->checkPermissionSuccess();
+    EXPECT_CALL(*mDataLoaderManager, destroyDataLoader(_));
+    EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+    // We are calling setIncFsMountOptions.
+    EXPECT_CALL(*mVold, setIncFsMountOptions(_, true)).Times(1);
+    // setIncFsMountOptions fails, no calls to start or stop WatchingMode.
+    EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0);
+    EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
+    TemporaryDir tempDir;
+    int storageId =
+            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
+                                               IncrementalService::CreateOptions::CreateNew);
+    ASSERT_GE(storageId, 0);
+    ASSERT_LT(mIncrementalService->setStorageParams(storageId, true), 0);
+}
+
 TEST_F(IncrementalServiceTest, testMakeDirectory) {
     mVold->mountIncFsSuccess();
     mIncFs->makeFileSuccess();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1939313..e2a2473 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -30,6 +30,7 @@
 import android.app.ActivityThread;
 import android.app.AppCompatCallbacks;
 import android.app.INotificationManager;
+import android.app.SystemServiceRegistry;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -135,6 +136,7 @@
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
+import com.android.server.pm.dex.SystemServerDexLoadReporter;
 import com.android.server.policy.PermissionPolicyService;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.policy.role.LegacyRoleResolutionPolicy;
@@ -513,13 +515,13 @@
             Looper.getMainLooper().setSlowLogThresholdMs(
                     SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
 
+            SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
+
             // Initialize native services.
             System.loadLibrary("android_servers");
 
-            // Debug builds - allow heap profiling.
-            if (Build.IS_DEBUGGABLE) {
-                initZygoteChildHeapProfiling();
-            }
+            // Allow heap / perf profiling.
+            initZygoteChildHeapProfiling();
 
             // Debug builds - spawn a thread to monitor for fd leaks.
             if (Build.IS_DEBUGGABLE) {
@@ -836,6 +838,11 @@
             Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
         }
 
+        // Now that the package manager has started, register the dex load reporter to capture any
+        // dex files loaded by system server.
+        // These dex files will be optimized by the BackgroundDexOptService.
+        SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);
+
         mFirstBoot = mPackageManagerService.isFirstBoot();
         mPackageManager = mSystemContext.getPackageManager();
         t.traceEnd();
diff --git a/services/net/java/android/net/ip/IpClientManager.java b/services/net/java/android/net/ip/IpClientManager.java
index 09e333e..db464e7 100644
--- a/services/net/java/android/net/ip/IpClientManager.java
+++ b/services/net/java/android/net/ip/IpClientManager.java
@@ -21,6 +21,7 @@
 import android.net.NattKeepalivePacketData;
 import android.net.ProxyInfo;
 import android.net.TcpKeepalivePacketData;
+import android.net.shared.Layer2Information;
 import android.net.shared.ProvisioningConfiguration;
 import android.net.util.KeepalivePacketDataUtil;
 import android.os.Binder;
@@ -292,4 +293,20 @@
             Binder.restoreCallingIdentity(token);
         }
     }
+
+    /**
+     * Update the bssid, L2 key and group hint layer2 information.
+     */
+    public boolean updateLayer2Information(Layer2Information info) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mIpClient.updateLayer2Information(info.toStableParcelable());
+            return true;
+        } catch (RemoteException e) {
+            log("Error updating layer2 information", e);
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
 }
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 136ee91..c87ece2 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -220,7 +220,7 @@
         String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
         @Event.EventType int eventType = mimeTypeToShareEventType(mimeType);
         EventHistoryImpl eventHistory;
-        if (ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE.equals(event.getLaunchLocation())) {
+        if (ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE.equals(event.getLaunchLocation())) {
             // Direct share event
             if (appTarget.getShortcutInfo() == null) {
                 return;
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 138f982..f8d197a 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -199,6 +199,12 @@
                 CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
         ShadowApplicationPackageManager.setPackageUidAsUser(
                 CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
+        when(mPackageManagerInternal.getPackageUidInternal(
+                CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID))
+                .thenReturn(PERSONAL_PROFILE_UID);
+        when(mPackageManagerInternal.getPackageUidInternal(
+                CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID))
+                .thenReturn(WORK_PROFILE_UID);
     }
 
     @Before
@@ -456,6 +462,19 @@
     }
 
     @Test
+    public void canUserAttemptToConfigureInteractAcrossProfiles_platformSignedAppWithAutomaticPermission_returnsFalse() {
+        mockCrossProfileAppNotWhitelistedByOem();
+        shadowOf(mContext).grantPermissions(
+                Process.myPid(),
+                PERSONAL_PROFILE_UID,
+                Manifest.permission.INTERACT_ACROSS_PROFILES);
+
+        assertThat(mCrossProfileAppsServiceImpl
+                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isFalse();
+    }
+
+    @Test
     public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
         assertThat(mCrossProfileAppsServiceImpl
                 .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
@@ -528,6 +547,11 @@
                 .thenReturn(new ArrayList<>());
     }
 
+    private void mockCrossProfileAppNotWhitelistedByOem() {
+        when(mDevicePolicyManagerInternal.getDefaultCrossProfilePackages())
+                .thenReturn(new ArrayList<>());
+    }
+
     private boolean receivedManifestCanInteractAcrossProfilesChangedBroadcast() {
         final UserHandle userHandle = UserHandle.of(PERSONAL_PROFILE_USER_ID);
         if (!mSentUserBroadcasts.containsKey(userHandle)) {
diff --git a/services/systemcaptions/java/com/android/server/systemcaptions/RemoteSystemCaptionsManagerService.java b/services/systemcaptions/java/com/android/server/systemcaptions/RemoteSystemCaptionsManagerService.java
index 5480b6c..c225d3f 100644
--- a/services/systemcaptions/java/com/android/server/systemcaptions/RemoteSystemCaptionsManagerService.java
+++ b/services/systemcaptions/java/com/android/server/systemcaptions/RemoteSystemCaptionsManagerService.java
@@ -108,7 +108,8 @@
             }
             mBinding = true;
 
-            int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
+            int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+                    | Context.BIND_INCLUDE_CAPABILITIES;
             boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags,
                     mHandler, new UserHandle(mUserId));
             if (!willBind) {
diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp
new file mode 100644
index 0000000..a2668a1
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// NOTE: This test is separate from service tests since it relies on same vs different calling UID,
+// and this is more representative of a real caller. It also uses Mockito extended, and this
+// prevents converting the entire services test module.
+android_test {
+    name: "PackageManagerComponentOverrideTests",
+    srcs: [
+        "src/**/*.kt"
+    ],
+    static_libs: [
+        "androidx.test.runner",
+        "mockito-target-extended-minus-junit4",
+        "services.core",
+        "servicestests-utils-mockito-extended",
+        "testng", // TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
+        "truth-prebuilt",
+    ],
+
+    jni_libs: [
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
+    test_suites: ["device-tests"],
+    platform_apis: true,
+}
diff --git a/services/tests/PackageManagerComponentOverrideTests/AndroidManifest.xml b/services/tests/PackageManagerComponentOverrideTests/AndroidManifest.xml
new file mode 100644
index 0000000..c25e112
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.pm.test.override">
+
+    <uses-sdk
+        android:minSdkVersion="1"
+        android:targetSdkVersion="28" />
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.mock" android:required="true" />
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="PackageManagerComponentOverrideTests"
+        android:targetPackage="com.android.server.pm.test.override" />
+
+</manifest>
diff --git a/services/tests/PackageManagerComponentOverrideTests/AndroidTest.xml b/services/tests/PackageManagerComponentOverrideTests/AndroidTest.xml
new file mode 100644
index 0000000..b83b1a8
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration description="Test module config for PackageManagerComponentOverrideTests">
+    <option name="test-tag" value="PackageManagerComponentOverrideTests" />
+
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="PackageManagerComponentOverrideTests.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.server.pm.test.override" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/services/tests/PackageManagerComponentOverrideTests/res/drawable/black16x16.png b/services/tests/PackageManagerComponentOverrideTests/res/drawable/black16x16.png
new file mode 100644
index 0000000..86b12fc
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/res/drawable/black16x16.png
Binary files differ
diff --git a/services/tests/PackageManagerComponentOverrideTests/res/drawable/white16x16.png b/services/tests/PackageManagerComponentOverrideTests/res/drawable/white16x16.png
new file mode 100644
index 0000000..49dbb4f
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/res/drawable/white16x16.png
Binary files differ
diff --git a/core/tests/ResourceLoaderTests/resources/framework/res/values/values.xml b/services/tests/PackageManagerComponentOverrideTests/res/values/values.xml
similarity index 84%
rename from core/tests/ResourceLoaderTests/resources/framework/res/values/values.xml
rename to services/tests/PackageManagerComponentOverrideTests/res/values/values.xml
index 5f6e90c..73d1128 100644
--- a/core/tests/ResourceLoaderTests/resources/framework/res/values/values.xml
+++ b/services/tests/PackageManagerComponentOverrideTests/res/values/values.xml
@@ -16,5 +16,6 @@
   -->
 
 <resources>
-    <string name="cancel">SomeRidiculouslyUnlikelyString</string>
+    <public name="black16x16" type="drawable" id="0x7f080001"/>
+    <public name="white16x16" type="drawable" id="0x7f080002"/>
 </resources>
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
new file mode 100644
index 0000000..ecdb30f
--- /dev/null
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.pm.test.override
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.parsing.component.ParsedActivity
+import android.os.Binder
+import android.os.UserHandle
+import android.util.ArrayMap
+import com.android.server.pm.AppsFilter
+import com.android.server.pm.ComponentResolver
+import com.android.server.pm.PackageManagerService
+import com.android.server.pm.PackageSetting
+import com.android.server.pm.Settings
+import com.android.server.pm.UserManagerService
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.server.pm.parsing.pkg.ParsedPackage
+import com.android.server.pm.permission.PermissionManagerServiceInternal
+import com.android.server.pm.test.override.PackageManagerComponentLabelIconOverrideTest.Companion.Params.AppType
+import com.android.server.pm.test.override.R
+import com.android.server.testutils.TestHandler
+import com.android.server.testutils.mock
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.spy
+import com.android.server.testutils.whenever
+import com.android.server.wm.ActivityTaskManagerInternal
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.intThat
+import org.mockito.Mockito.never
+import org.mockito.Mockito.same
+import org.mockito.Mockito.verify
+import org.testng.Assert.assertThrows
+import java.io.File
+
+@RunWith(Parameterized::class)
+class PackageManagerComponentLabelIconOverrideTest {
+
+    companion object {
+        private const val VALID_PKG = "com.android.server.pm.test.override"
+        private const val SHARED_PKG = "com.android.server.pm.test.override.shared"
+        private const val INVALID_PKG = "com.android.server.pm.test.override.invalid"
+
+        private const val SEND_PENDING_BROADCAST = 1 // PackageManagerService.SEND_PENDING_BROADCAST
+
+        private const val DEFAULT_LABEL = "DefaultLabel"
+        private const val TEST_LABEL = "TestLabel"
+
+        private const val DEFAULT_ICON = R.drawable.black16x16
+        private const val TEST_ICON = R.drawable.white16x16
+
+        private const val COMPONENT_CLASS_NAME = ".TestComponent"
+
+        sealed class Result {
+            // Component label/icon changed, message sent to send broadcast
+            object Changed : Result()
+
+            // Component label/icon changed, message was pending, not re-sent
+            object ChangedWithoutNotify : Result()
+
+            // Component label/icon did not changed, was already equivalent
+            object NotChanged : Result()
+
+            // Updating label/icon encountered a specific exception
+            data class Exception(val type: Class<out java.lang.Exception>) : Result()
+        }
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun parameters() = arrayOf(
+                // Start with an array of the simplest known inputs and expected outputs
+                Params(VALID_PKG, AppType.SYSTEM_APP, Result.Changed),
+                Params(SHARED_PKG, AppType.SYSTEM_APP, Result.Changed),
+                Params(INVALID_PKG, AppType.SYSTEM_APP, SecurityException::class.java)
+        )
+                .flatMap { param ->
+                    mutableListOf(param).apply {
+                        if (param.result is Result.Changed) {
+                            // For each param that would've succeeded, also verify that if a change
+                            // happened, but a message was pending, another is not re-queued/reset
+                            this += param.copy(result = Result.ChangedWithoutNotify)
+                            // Also verify that when the component is already configured, no change
+                            // is propagated
+                            this += param.copy(result = Result.NotChanged)
+                        }
+                        // For all params, verify that an invalid component will cause an
+                        // IllegalArgumentException, instead of result initially specified
+                        this += param.copy(componentName = null,
+                                result = Result.Exception(IllegalArgumentException::class.java))
+                        // Also verify an updated system app variant, which should have the same
+                        // result as a vanilla system app
+                        this += param.copy(appType = AppType.UPDATED_SYSTEM_APP)
+                        // Also verify a non-system app will cause a failure, since normal apps
+                        // are not allowed to edit their label/icon
+                        this += param.copy(appType = AppType.NORMAL_APP,
+                                result = Result.Exception(SecurityException::class.java))
+                    }
+                }
+
+        data class Params(
+            val pkgName: String,
+            private val appType: AppType,
+            val result: Result,
+            val componentName: ComponentName? = ComponentName(pkgName, COMPONENT_CLASS_NAME)
+        ) {
+            constructor(pkgName: String, appType: AppType, exception: Class<out Exception>)
+                    : this(pkgName, appType, Result.Exception(exception))
+
+            val expectedLabel = when (result) {
+                Result.Changed, Result.ChangedWithoutNotify, Result.NotChanged -> TEST_LABEL
+                is Result.Exception -> DEFAULT_LABEL
+            }
+
+            val expectedIcon = when (result) {
+                Result.Changed, Result.ChangedWithoutNotify, Result.NotChanged -> TEST_ICON
+                is Result.Exception -> DEFAULT_ICON
+            }
+
+            val isUpdatedSystemApp = appType == AppType.UPDATED_SYSTEM_APP
+            val isSystem = appType == AppType.SYSTEM_APP || isUpdatedSystemApp
+
+            override fun toString(): String {
+                val resultString = when (result) {
+                    Result.Changed -> "Changed"
+                    Result.ChangedWithoutNotify -> "ChangedWithoutNotify"
+                    Result.NotChanged -> "NotChanged"
+                    is Result.Exception -> result.type.simpleName
+                }
+
+                // Nicer formatting for the test method suffix
+                return "pkg=$pkgName, type=$appType, component=$componentName, result=$resultString"
+            }
+
+            enum class AppType { SYSTEM_APP, UPDATED_SYSTEM_APP, NORMAL_APP }
+        }
+    }
+
+    @Parameterized.Parameter(0)
+    lateinit var params: Params
+
+    private lateinit var testHandler: TestHandler
+    private lateinit var mockPendingBroadcasts: PackageManagerService.PendingPackageBroadcasts
+    private lateinit var mockPkg: AndroidPackage
+    private lateinit var mockPkgSetting: PackageSetting
+    private lateinit var service: PackageManagerService
+
+    private val userId = UserHandle.getCallingUserId()
+    private val userIdDifferent = userId + 1
+
+    @Before
+    fun setUpMocks() {
+        makeTestData()
+
+        testHandler = TestHandler(null)
+        if (params.result is Result.ChangedWithoutNotify) {
+            // Case where the handler already has a message and so another should not be sent.
+            // This case will verify that only 1 message exists, which is the one added here.
+            testHandler.sendEmptyMessage(SEND_PENDING_BROADCAST)
+        }
+
+        mockPendingBroadcasts = PackageManagerService.PendingPackageBroadcasts()
+
+        service = mockService()
+    }
+
+    @Test
+    fun updateComponentLabelIcon() {
+        fun runUpdate() {
+            service.updateComponentLabelIcon(params.componentName, TEST_LABEL, TEST_ICON, userId)
+        }
+
+        when (val result = params.result) {
+            Result.Changed, Result.ChangedWithoutNotify, Result.NotChanged -> {
+                runUpdate()
+                verify(mockPkgSetting).overrideNonLocalizedLabelAndIcon(params.componentName!!,
+                        TEST_LABEL, TEST_ICON, userId)
+            }
+            is Result.Exception -> {
+                assertThrows(result.type) { runUpdate() }
+                verify(mockPkgSetting, never()).overrideNonLocalizedLabelAndIcon(
+                        any<ComponentName>(), any(), anyInt(), anyInt())
+            }
+        }
+    }
+
+    @After
+    fun verifyExpectedResult() {
+        if (params.componentName != null) {
+            val activityInfo = service.getActivityInfo(params.componentName, 0, userId)
+            assertThat(activityInfo.nonLocalizedLabel).isEqualTo(params.expectedLabel)
+            assertThat(activityInfo.icon).isEqualTo(params.expectedIcon)
+        }
+    }
+
+    @After
+    fun verifyDifferentUserUnchanged() {
+        when (params.result) {
+            Result.Changed, Result.ChangedWithoutNotify -> {
+                val activityInfo = service.getActivityInfo(params.componentName, 0, userIdDifferent)
+                assertThat(activityInfo.nonLocalizedLabel).isEqualTo(DEFAULT_LABEL)
+                assertThat(activityInfo.icon).isEqualTo(DEFAULT_ICON)
+            }
+            Result.NotChanged, is Result.Exception -> {}
+        }.run { /*exhaust*/ }
+    }
+
+    @After
+    fun verifyHandlerHasMessage() {
+        when (params.result) {
+            is Result.Changed, is Result.ChangedWithoutNotify -> {
+                assertThat(testHandler.pendingMessages).hasSize(1)
+                assertThat(testHandler.pendingMessages.first().message.what)
+                        .isEqualTo(SEND_PENDING_BROADCAST)
+            }
+            is Result.NotChanged, is Result.Exception -> {
+                assertThat(testHandler.pendingMessages).hasSize(0)
+            }
+        }.run { /*exhaust*/ }
+    }
+
+    @After
+    fun verifyPendingBroadcast() {
+        when (params.result) {
+            is Result.Changed, Result.ChangedWithoutNotify -> {
+                assertThat(mockPendingBroadcasts.get(userId, params.pkgName))
+                        .containsExactly(params.componentName!!.className)
+                        .inOrder()
+            }
+            is Result.NotChanged, is Result.Exception -> {
+                assertThat(mockPendingBroadcasts.get(userId, params.pkgName)).isNull()
+            }
+        }.run { /*exhaust*/ }
+    }
+
+    private fun makePkg(pkgName: String, block: ParsedPackage.() -> Unit = {}) =
+            PackageImpl.forTesting(pkgName)
+                    .setEnabled(true)
+                    .let { it.hideAsParsed() as ParsedPackage }
+                    .setSystem(params.isSystem)
+                    .apply(block)
+                    .hideAsFinal()
+
+    private fun makePkgSetting(pkgName: String) = spy(PackageSetting(pkgName, null, File("/test"),
+            File("/test"), null, null, null, null, 0, 0, 0, 0, null, null, null)) {
+        this.pkgState.isUpdatedSystemApp = params.isUpdatedSystemApp
+    }
+
+    private fun makeTestData() {
+        mockPkg = makePkg(params.pkgName)
+        mockPkgSetting = makePkgSetting(params.pkgName)
+
+        if (params.result is Result.NotChanged) {
+            // If verifying no-op behavior, set the current setting to the test values
+            mockPkgSetting.overrideNonLocalizedLabelAndIcon(params.componentName!!, TEST_LABEL,
+                    TEST_ICON, userId)
+            // Then clear the mock because the line above just incremented it
+            clearInvocations(mockPkgSetting)
+        }
+    }
+
+    private fun mockService(): PackageManagerService {
+        val mockedPkgs = mapOf(
+                // Must use the test app's UID so that PMS can match them when querying, since
+                // the static Binder.getCallingUid can't mocked as it's marked final
+                VALID_PKG to makePkg(VALID_PKG) { uid = Binder.getCallingUid() },
+                SHARED_PKG to makePkg(SHARED_PKG) { uid = Binder.getCallingUid() },
+                INVALID_PKG to makePkg(INVALID_PKG) { uid = Binder.getCallingUid() + 1 }
+        )
+        val mockedPkgSettings = mapOf(
+                VALID_PKG to makePkgSetting(VALID_PKG),
+                SHARED_PKG to makePkgSetting(SHARED_PKG),
+                INVALID_PKG to makePkgSetting(INVALID_PKG)
+        )
+                // Add pkgSetting under test so its attributes override the defaults added above
+                .plus(params.pkgName to mockPkgSetting)
+
+        val mockActivity: ParsedActivity = mock {
+            whenever(this.packageName) { params.pkgName }
+            whenever(this.nonLocalizedLabel) { DEFAULT_LABEL }
+            whenever(this.icon) { DEFAULT_ICON }
+            whenever(this.componentName) { params.componentName }
+            whenever(this.name) { params.componentName?.className }
+            whenever(this.isEnabled) { true }
+            whenever(this.isDirectBootAware) { params.isSystem }
+        }
+
+        val mockSettings = Settings(mockedPkgSettings)
+        val mockComponentResolver: ComponentResolver = mockThrowOnUnmocked {
+            params.componentName?.let {
+                whenever(this.componentExists(same(it))) { true }
+                whenever(this.getActivity(same(it))) { mockActivity }
+            }
+        }
+        val mockUserManagerService: UserManagerService = mockThrowOnUnmocked {
+            val matcher: (Int) -> Boolean = { it == userId || it == userIdDifferent }
+            whenever(this.exists(intThat(matcher))) { true }
+            whenever(this.isUserUnlockingOrUnlocked(intThat(matcher))) { true }
+        }
+        val mockPermissionManagerService: PermissionManagerServiceInternal = mockThrowOnUnmocked {
+            whenever(this.enforceCrossUserPermission(anyInt(), anyInt(), anyBoolean(), anyBoolean(),
+                    anyString())) { }
+        }
+        val mockActivityTaskManager: ActivityTaskManagerInternal = mockThrowOnUnmocked {
+            whenever(this.isCallerRecents(anyInt())) { false }
+        }
+        val mockAppsFilter: AppsFilter = mockThrowOnUnmocked {
+            whenever(this.shouldFilterApplication(anyInt(), any<PackageSetting>(),
+                    any<PackageSetting>(), anyInt())) { false }
+        }
+        val mockContext: Context = mockThrowOnUnmocked {
+            whenever(this.getString(
+                    com.android.internal.R.string.config_overrideComponentUiPackage)) { VALID_PKG }
+        }
+        val mockInjector: PackageManagerService.Injector = mock {
+            whenever(this.lock) { Object() }
+            whenever(this.componentResolver) { mockComponentResolver }
+            whenever(this.userManagerService) { mockUserManagerService }
+            whenever(this.permissionManagerServiceInternal) { mockPermissionManagerService }
+            whenever(this.settings) { mockSettings }
+            whenever(this.activityTaskManagerInternal) { mockActivityTaskManager }
+            whenever(this.appsFilter) { mockAppsFilter }
+            whenever(this.context) { mockContext }
+        }
+        val testParams = PackageManagerService.TestParams().apply {
+            this.handler = testHandler
+            this.pendingPackageBroadcasts = mockPendingBroadcasts
+            this.resolveComponentName = ComponentName("android", ".Test")
+            this.packages = ArrayMap<String, AndroidPackage>().apply { putAll(mockedPkgs) }
+        }
+
+        return PackageManagerService(mockInjector, testParams)
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 5c82200..736a7be 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -79,7 +79,8 @@
     private static final String CALLING_PACKAGE2 = "com.package.name2";
     private static final String NAMESPACE1 = "namespace1";
     private static final String NAMESPACE2 = "namespace2";
-    private static final String DISABLE_RESCUE_PARTY_FLAG = "disable_rescue_party";
+    private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
+            "persist.device_config.configuration.disable_rescue_party";
 
     private MockitoSession mSession;
     private HashMap<String, String> mSystemSettingsMap;
@@ -172,6 +173,7 @@
                 Integer.toString(RescueParty.LEVEL_NONE));
         SystemProperties.set(RescueParty.PROP_RESCUE_BOOT_COUNT, Integer.toString(0));
         SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
+        SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false));
     }
 
     @After
@@ -317,13 +319,6 @@
 
     @Test
     public void testExplicitlyEnablingAndDisablingRescue() {
-        // mock the DeviceConfig get call to avoid hitting
-        // android.permission.READ_DEVICE_CONFIG when calling real DeviceConfig.
-        doReturn(true)
-                .when(() -> DeviceConfig.getBoolean(
-                    eq(DeviceConfig.NAMESPACE_CONFIGURATION),
-                    eq(DISABLE_RESCUE_PARTY_FLAG),
-                    eq(false)));
         SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(false));
         SystemProperties.set(PROP_DISABLE_RESCUE, Boolean.toString(true));
         assertEquals(RescuePartyObserver.getInstance(mMockContext).execute(sFailingPackage,
@@ -336,18 +331,15 @@
 
     @Test
     public void testDisablingRescueByDeviceConfigFlag() {
-        doReturn(true)
-                .when(() -> DeviceConfig.getBoolean(
-                    eq(DeviceConfig.NAMESPACE_CONFIGURATION),
-                    eq(DISABLE_RESCUE_PARTY_FLAG),
-                    eq(false)));
         SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(false));
+        SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(true));
 
         assertEquals(RescuePartyObserver.getInstance(mMockContext).execute(sFailingPackage,
                 PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING), false);
 
         // Restore the property value initalized in SetUp()
         SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
+        SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false));
     }
 
     @Test
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index e58e911..b457856 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -107,6 +107,8 @@
     name: "servicestests-utils",
     srcs: [
         "utils/**/*.java",
+        "utils/**/*.kt",
+        "utils-mockito/**/*.kt",
     ],
     static_libs: [
         "junit",
@@ -117,6 +119,22 @@
     ],
 }
 
+java_library {
+    name: "servicestests-utils-mockito-extended",
+    srcs: [
+        "utils/**/*.java",
+        "utils/**/*.kt",
+        "utils-mockito/**/*.kt",
+    ],
+    static_libs: [
+        "junit",
+        "mockito-target-extended-minus-junit4",
+    ],
+    libs: [
+        "android.test.runner",
+    ],
+}
+
 filegroup {
     name: "servicestests-SuspendTestApp-files",
     srcs: [
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 7bf1d98..0445bff 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -16,7 +16,10 @@
 
 package com.android.server.accessibility;
 
+import static android.accessibilityservice.AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY;
+import static android.accessibilityservice.AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS;
 import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_HOME;
+import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS;
 import static android.accessibilityservice.AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION;
 import static android.accessibilityservice.AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES;
 import static android.accessibilityservice.AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS;
@@ -69,6 +72,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.Region;
+import android.hardware.display.DisplayManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -93,6 +97,7 @@
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
@@ -162,6 +167,7 @@
     @Mock private IAccessibilityInteractionConnectionCallback mMockCallback;
     @Mock private FingerprintGestureDispatcher mMockFingerprintGestureDispatcher;
     @Mock private MagnificationController mMockMagnificationController;
+    @Mock private RemoteCallback.OnResultListener mMockListener;
 
     @Before
     public void setup() {
@@ -705,6 +711,38 @@
         }));
     }
 
+    @Test
+    public void takeScreenshot_NoA11yAccess_returnErrorCode() throws InterruptedException {
+        // no checkAccessibilityAccess, should return error code.
+        when(mMockSecurityPolicy.canTakeScreenshotLocked(mServiceConnection)).thenReturn(true);
+        when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(false);
+
+        mServiceConnection.takeScreenshot(Display.DEFAULT_DISPLAY,
+                new RemoteCallback(mMockListener));
+        mHandler.sendLastMessage();
+
+        verify(mMockListener).onResult(Mockito.argThat(
+                bundle -> ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS
+                        == bundle.getInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS)));
+    }
+
+    @Test
+    public void takeScreenshot_invalidDisplay_returnErrorCode() throws InterruptedException {
+        when(mMockSecurityPolicy.canTakeScreenshotLocked(mServiceConnection)).thenReturn(true);
+        when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(true);
+
+        final DisplayManager displayManager = new DisplayManager(mMockContext);
+        when(mMockContext.getSystemService(Context.DISPLAY_SERVICE)).thenReturn(displayManager);
+
+        mServiceConnection.takeScreenshot(Display.DEFAULT_DISPLAY + 1,
+                new RemoteCallback(mMockListener));
+        mHandler.sendLastMessage();
+
+        verify(mMockListener).onResult(Mockito.argThat(
+                bundle -> ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY
+                        == bundle.getInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS)));
+    }
+
     private void updateServiceInfo(AccessibilityServiceInfo serviceInfo, int eventType,
             int feedbackType, int flags, String[] packageNames, int notificationTimeout) {
         serviceInfo.eventTypes = eventType;
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceBaseTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceBaseTest.java
new file mode 100644
index 0000000..4fe9458
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceBaseTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.biometrics;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.biometrics.BiometricAuthenticator;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+@SmallTest
+public class BiometricServiceBaseTest {
+    private static class TestableBiometricServiceBase extends BiometricServiceBase {
+        TestableBiometricServiceBase(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected String getTag() {
+            return null;
+        }
+
+        @Override
+        protected DaemonWrapper getDaemonWrapper() {
+            return null;
+        }
+
+        @Override
+        protected BiometricUtils getBiometricUtils() {
+            return null;
+        }
+
+        @Override
+        protected Constants getConstants() {
+            return null;
+        }
+
+        @Override
+        protected boolean hasReachedEnrollmentLimit(int userId) {
+            return false;
+        }
+
+        @Override
+        protected void updateActiveGroup(int userId, String clientPackage) {
+        }
+
+        @Override
+        protected String getLockoutResetIntent() {
+            return null;
+        }
+
+        @Override
+        protected String getLockoutBroadcastPermission() {
+            return null;
+        }
+
+        @Override
+        protected long getHalDeviceId() {
+            return 0;
+        }
+
+        @Override
+        protected boolean hasEnrolledBiometrics(int userId) {
+            return false;
+        }
+
+        @Override
+        protected String getManageBiometricPermission() {
+            return null;
+        }
+
+        @Override
+        protected void checkUseBiometricPermission() {
+        }
+
+        @Override
+        protected boolean checkAppOps(int uid, String opPackageName) {
+            return false;
+        }
+
+        @Override
+        protected List<? extends BiometricAuthenticator.Identifier> getEnrolledTemplates(
+                int userId) {
+            return null;
+        }
+
+        @Override
+        protected int statsModality() {
+            return 0;
+        }
+
+        @Override
+        protected int getLockoutMode() {
+            return 0;
+        }
+    }
+
+    private static final int CLIENT_COOKIE = 0xc00c1e;
+
+    private BiometricServiceBase mBiometricServiceBase;
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private Resources mResources;
+    @Mock
+    private BiometricAuthenticator.Identifier mIdentifier;
+    @Mock
+    private ClientMonitor mClient;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getString(anyInt())).thenReturn("");
+        when(mClient.getCookie()).thenReturn(CLIENT_COOKIE);
+
+        mBiometricServiceBase = new TestableBiometricServiceBase(mContext);
+    }
+
+    @Test
+    public void testHandleEnumerate_doesNotCrash_withNullClient() {
+        mBiometricServiceBase.handleEnumerate(mIdentifier, 0 /* remaining */);
+    }
+
+    @Test
+    public void testStartClient_sendsErrorAndRemovesClient_onNonzeroErrorCode() {
+        when(mClient.start()).thenReturn(1);
+
+        mBiometricServiceBase.startClient(mClient, false /* initiatedByClient */);
+
+        verify(mClient).onError(anyLong(), anyInt(), anyInt());
+        verify(mClient).destroy();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index baf551e..d780370 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -83,7 +83,6 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.UserManagerInternal;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.security.KeyChain;
@@ -1170,7 +1169,6 @@
                 () -> dpm.clearDeviceOwnerApp(admin1.getPackageName()));
 
         when(getServices().userManager.isUserUnlocked(anyInt())).thenReturn(true);
-        reset(getServices().userManagerInternal);
         dpm.clearDeviceOwnerApp(admin1.getPackageName());
 
         // Now DO shouldn't be set.
@@ -1181,9 +1179,8 @@
                 MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
 
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
-                eq(UserHandle.USER_SYSTEM),
-                MockUtils.checkUserRestrictions(),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                eq(UserHandle.USER_SYSTEM), MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
 
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, UserHandle.USER_SYSTEM);
@@ -1745,15 +1742,16 @@
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(UserHandle.USER_SYSTEM),
                 MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
         reset(getServices().userManagerInternal);
 
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(UserHandle.USER_SYSTEM),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS,
-                        UserManager.DISALLOW_ADD_USER),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER),
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM,
+                        UserManager.DISALLOW_OUTGOING_CALLS),
+                eq(true));
         reset(getServices().userManagerInternal);
 
         DpmTestUtils.assertRestrictions(
@@ -1770,8 +1768,10 @@
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(UserHandle.USER_SYSTEM),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM,
+                        UserManager.DISALLOW_OUTGOING_CALLS),
+                eq(true));
         reset(getServices().userManagerInternal);
 
         DpmTestUtils.assertRestrictions(
@@ -1787,7 +1787,7 @@
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(UserHandle.USER_SYSTEM),
                 MockUtils.checkUserRestrictions(),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
         reset(getServices().userManagerInternal);
 
         assertNoDeviceOwnerRestrictions();
@@ -1801,7 +1801,7 @@
                 eq(UserHandle.USER_SYSTEM),
                 MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME,
                         UserManager.DISALLOW_UNMUTE_MICROPHONE),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
         reset(getServices().userManagerInternal);
 
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADJUST_VOLUME);
@@ -1813,7 +1813,7 @@
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(UserHandle.USER_SYSTEM),
                 MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
         reset(getServices().userManagerInternal);
 
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_FUN);
@@ -1821,7 +1821,7 @@
                 eq(UserHandle.USER_SYSTEM),
                 MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN,
                         UserManager.DISALLOW_ADD_USER),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
         reset(getServices().userManagerInternal);
 
         dpm.setCameraDisabled(admin1, true);
@@ -1830,7 +1830,7 @@
                 // DISALLOW_CAMERA will be applied globally.
                 MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN,
                         UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_CAMERA),
-                eq(UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM), eq(true));
         reset(getServices().userManagerInternal);
     }
 
@@ -1887,17 +1887,19 @@
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER));
-        reset(getServices().userManagerInternal);
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES),
+                eq(false));
 
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE,
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
                         UserManager.DISALLOW_OUTGOING_CALLS),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER));
-        reset(getServices().userManagerInternal);
+                eq(false));
 
         DpmTestUtils.assertRestrictions(
                 DpmTestUtils.newRestrictions(
@@ -1918,9 +1920,10 @@
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER));
-        reset(getServices().userManagerInternal);
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE,
+                        UserManager.DISALLOW_OUTGOING_CALLS),
+                eq(false));
 
         DpmTestUtils.assertRestrictions(
                 DpmTestUtils.newRestrictions(
@@ -1940,8 +1943,7 @@
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
                 MockUtils.checkUserRestrictions(),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER));
-        reset(getServices().userManagerInternal);
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE), eq(false));
 
         DpmTestUtils.assertRestrictions(
                 DpmTestUtils.newRestrictions(),
@@ -1956,21 +1958,25 @@
         // DISALLOW_ADJUST_VOLUME and DISALLOW_UNMUTE_MICROPHONE can be set by PO too, even
         // though when DO sets them they'll be applied globally.
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADJUST_VOLUME);
-        reset(getServices().userManagerInternal);
+
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_UNMUTE_MICROPHONE);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME,
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE,
+                        UserManager.DISALLOW_ADJUST_VOLUME,
                         UserManager.DISALLOW_UNMUTE_MICROPHONE),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER));
-        reset(getServices().userManagerInternal);
+                eq(false));
 
         dpm.setCameraDisabled(admin1, true);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME,
-                        UserManager.DISALLOW_UNMUTE_MICROPHONE, UserManager.DISALLOW_CAMERA),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER));
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE,
+                        UserManager.DISALLOW_ADJUST_VOLUME,
+                        UserManager.DISALLOW_UNMUTE_MICROPHONE,
+                        UserManager.DISALLOW_CAMERA),
+                eq(false));
         reset(getServices().userManagerInternal);
 
         // TODO Make sure restrictions are written to the file.
@@ -2004,15 +2010,14 @@
             );
 
     public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception {
-        final int MANAGED_PROFILE_USER_ID = DpmMockContext.CALLER_USER_HANDLE;
         final int MANAGED_PROFILE_ADMIN_UID =
-                UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
+                UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID);
         mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
 
         addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
         configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
 
-        when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID))
+        when(getServices().userManager.getProfileParent(DpmMockContext.CALLER_USER_HANDLE))
                 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
 
         for (String restriction : PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS) {
@@ -2021,16 +2026,20 @@
 
         parentDpm.setCameraDisabled(admin1, true);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
-                eq(MANAGED_PROFILE_USER_ID),
+                eq(DpmMockContext.CALLER_USER_HANDLE),
                 MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
-        reset(getServices().userManagerInternal);
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE),
+                eq(false));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(UserManager.DISALLOW_CAMERA),
+                parentDpm.getUserRestrictions(admin1)
+        );
 
         parentDpm.setCameraDisabled(admin1, false);
-        verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
-                eq(MANAGED_PROFILE_USER_ID),
-                MockUtils.checkUserRestrictions(),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(),
+                parentDpm.getUserRestrictions(admin1)
+        );
         reset(getServices().userManagerInternal);
     }
 
@@ -2039,13 +2048,13 @@
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(DpmMockContext.CALLER_USER_HANDLE),
                 MockUtils.checkUserRestrictions(restriction),
-                eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
+                MockUtils.checkUserRestrictions(DpmMockContext.CALLER_USER_HANDLE),
+                eq(false));
         parentDpm.clearUserRestriction(admin1, restriction);
         DpmTestUtils.assertRestrictions(
                 DpmTestUtils.newRestrictions(),
                 parentDpm.getUserRestrictions(admin1)
         );
-        reset(getServices().userManagerInternal);
     }
 
     public void testNoDefaultEnabledUserRestrictions() throws Exception {
@@ -4274,6 +4283,9 @@
 
         // Profile owner can set enabled state.
         setAsProfileOwner(admin1);
+        when(mServiceContext.resources
+                .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
+                .thenReturn(admin1.flattenToString());
         dpm.setSecondaryLockscreenEnabled(admin1, true);
         assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
                 DpmMockContext.CALLER_USER_HANDLE)));
@@ -4297,6 +4309,9 @@
 
         // Device owners can set enabled state.
         setupDeviceOwner();
+        when(mServiceContext.resources
+                .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
+                .thenReturn(admin1.flattenToString());
         dpm.setSecondaryLockscreenEnabled(admin1, true);
         assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)));
     }
@@ -4309,12 +4324,39 @@
                 DpmMockContext.CALLER_USER_HANDLE)));
 
         // Non-DO/PO cannot set enabled state.
+        when(mServiceContext.resources
+                .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
+                .thenReturn(admin1.flattenToString());
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
                 () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
         assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
                 DpmMockContext.CALLER_USER_HANDLE)));
     }
 
+    public void testSecondaryLockscreen_nonSupervisionApp() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+
+        // Initial state is disabled.
+        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+                DpmMockContext.CALLER_USER_HANDLE)));
+
+        // Caller is Profile Owner, but no supervision app is configured.
+        setAsProfileOwner(admin1);
+        assertExpectException(SecurityException.class, "no default supervision component defined",
+                () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
+        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+                DpmMockContext.CALLER_USER_HANDLE)));
+
+        // Caller is Profile Owner, but is not the default configured supervision app.
+        when(mServiceContext.resources
+                .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
+                .thenReturn(admin2.flattenToString());
+        assertExpectException(SecurityException.class, "is not the default supervision component",
+                () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
+        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+                DpmMockContext.CALLER_USER_HANDLE)));
+    }
+
     public void testIsDeviceManaged() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 09a6819..15f3ed1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -15,10 +15,6 @@
  */
 package com.android.server.devicepolicy;
 
-import com.google.common.base.Objects;
-
-import com.android.server.pm.UserRestrictionsUtils;
-
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.BaseBundle;
@@ -26,6 +22,11 @@
 import android.os.UserHandle;
 import android.util.ArraySet;
 
+import com.android.server.pm.RestrictionsSet;
+import com.android.server.pm.UserRestrictionsUtils;
+
+import com.google.common.base.Objects;
+
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
@@ -106,11 +107,14 @@
     }
 
     public static Bundle checkUserRestrictions(String... keys) {
-        final Bundle expected = DpmTestUtils.newRestrictions(java.util.Objects.requireNonNull(keys));
+        final Bundle expected = DpmTestUtils.newRestrictions(
+                java.util.Objects.requireNonNull(keys));
         final Matcher<Bundle> m = new BaseMatcher<Bundle>() {
             @Override
             public boolean matches(Object item) {
-                if (item == null) return false;
+                if (item == null) {
+                    return false;
+                }
                 return UserRestrictionsUtils.areEqual((Bundle) item, expected);
             }
 
@@ -122,6 +126,26 @@
         return MockitoHamcrest.argThat(m);
     }
 
+    public static RestrictionsSet checkUserRestrictions(int userId, String... keys) {
+        final RestrictionsSet expected = DpmTestUtils.newRestrictions(userId,
+                java.util.Objects.requireNonNull(keys));
+        final Matcher<RestrictionsSet> m = new BaseMatcher<RestrictionsSet>() {
+            @Override
+            public boolean matches(Object item) {
+                if (item == null) return false;
+                RestrictionsSet actual = (RestrictionsSet) item;
+                return UserRestrictionsUtils.areEqual(expected.getRestrictions(userId),
+                        actual.getRestrictions(userId));
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("User restrictions=" + getRestrictionsAsString(expected));
+            }
+        };
+        return MockitoHamcrest.argThat(m);
+    }
+
     public static Set<String> checkApps(String... adminApps) {
         final Matcher<Set<String>> m = new BaseMatcher<Set<String>>() {
             @Override
@@ -146,6 +170,23 @@
         return MockitoHamcrest.argThat(m);
     }
 
+    private static String getRestrictionsAsString(RestrictionsSet r) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("{");
+
+        if (r != null) {
+            String sep = "";
+            for (int i = 0; i < r.size(); i++) {
+                sb.append(sep);
+                sep = ",";
+                sb.append(
+                        String.format("%s= %s", r.keyAt(i), getRestrictionsAsString(r.valueAt(i))));
+            }
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
     private static String getRestrictionsAsString(Bundle b) {
         final StringBuilder sb = new StringBuilder();
         sb.append("[");
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 234c987..7b3417a 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -60,6 +60,7 @@
     @Mock HysteresisLevels mAmbientBrightnessThresholds;
     @Mock HysteresisLevels mScreenBrightnessThresholds;
     @Mock Handler mNoopHandler;
+    @Mock DisplayDeviceConfig mDisplayDeviceConfig;
 
     private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
     @Before
@@ -82,7 +83,8 @@
                 BRIGHTNESS_MAX_FLOAT, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE,
                 INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
                 DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
-                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mContext);
+                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mContext,
+                mDisplayDeviceConfig);
         controller.setLoggingEnabled(true);
 
         // Configure the brightness controller and grab an instance of the sensor listener,
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 7027185..7ad39b4 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -34,14 +34,17 @@
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
 import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
 import android.hardware.input.InputManagerInternal;
 import android.os.Handler;
 import android.os.IBinder;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.Surface;
 import android.view.SurfaceControl;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -67,6 +70,8 @@
 public class DisplayManagerServiceTest {
     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
     private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
+    private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
+    private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
 
     private Context mContext;
 
@@ -97,6 +102,7 @@
 
     @Mock InputManagerInternal mMockInputManagerInternal;
     @Mock IVirtualDisplayCallback.Stub mMockAppToken;
+    @Mock IVirtualDisplayCallback.Stub mMockAppToken2;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
     @Mock LightsManager mMockLightsManager;
     @Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
@@ -135,10 +141,12 @@
         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
 
         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
-        int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
-                null /* projection */, "com.android.frameworks.servicestests",
-                "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
-                uniqueId);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, width, height, dpi);
+        builder.setUniqueId(uniqueId);
+        builder.setFlags(flags);
+        int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+                null /* projection */, PACKAGE_NAME);
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -241,10 +249,12 @@
         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
 
         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
-        int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
-                null /* projection */, "com.android.frameworks.servicestests",
-                "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
-                uniqueId);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, width, height, dpi);
+        builder.setFlags(flags);
+        builder.setUniqueId(uniqueId);
+        int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+                null /* projection */, PACKAGE_NAME);
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -409,6 +419,87 @@
         assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
     }
 
+    /**
+     * Tests that the virtual display is created with
+     * {@link VirtualDisplayConfig.Builder#setDisplayIdToMirror(int)}
+     */
+    @Test
+    @FlakyTest(bugId = 127687569)
+    public void testCreateVirtualDisplay_displayIdToMirror() throws Exception {
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+
+        // This is effectively the DisplayManager service published to ServiceManager.
+        DisplayManagerService.BinderService binderService = displayManager.new BinderService();
+
+        final String uniqueId = "uniqueId --- displayIdToMirrorTest";
+        final int width = 600;
+        final int height = 800;
+        final int dpi = 320;
+
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, width, height, dpi);
+        builder.setUniqueId(uniqueId);
+        final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
+                mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+
+        // The second virtual display requests to mirror the first virtual display.
+        final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
+        when(mMockAppToken2.asBinder()).thenReturn(mMockAppToken2);
+        final VirtualDisplayConfig.Builder builder2 = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, width, height, dpi).setUniqueId(uniqueId2);
+        builder2.setUniqueId(uniqueId2);
+        builder2.setDisplayIdToMirror(firstDisplayId);
+        final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
+                mMockAppToken2 /* callback */, null /* projection */, PACKAGE_NAME);
+        displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+
+        // flush the handler
+        displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+
+        // The displayId to mirror should be a default display if there is none initially.
+        assertEquals(displayManager.getDisplayIdToMirrorInternal(firstDisplayId),
+                Display.DEFAULT_DISPLAY);
+        assertEquals(displayManager.getDisplayIdToMirrorInternal(secondDisplayId),
+                firstDisplayId);
+    }
+
+    /**
+     * Tests that the virtual display is created with
+     * {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
+     */
+    @Test
+    @FlakyTest(bugId = 127687569)
+    public void testCreateVirtualDisplay_setSurface() throws Exception {
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+
+        // This is effectively the DisplayManager service published to ServiceManager.
+        DisplayManagerService.BinderService binderService = displayManager.new BinderService();
+
+        final String uniqueId = "uniqueId --- setSurface";
+        final int width = 600;
+        final int height = 800;
+        final int dpi = 320;
+        final Surface surface = new Surface();
+
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, width, height, dpi);
+        builder.setSurface(surface);
+        builder.setUniqueId(uniqueId);
+        final int displayId = binderService.createVirtualDisplay(builder.build(),
+                mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+
+        displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+
+        // flush the handler
+        displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+
+        assertEquals(displayManager.getVirtualDisplaySurfaceInternal(mMockAppToken), surface);
+    }
+
     private void registerDefaultDisplays(DisplayManagerService displayManager) {
         Handler handler = displayManager.getDisplayHandler();
         // Would prefer to call displayManager.onStart() directly here but it performs binderService
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
new file mode 100644
index 0000000..301a9fe
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.display;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Point;
+import android.view.DisplayInfo;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+public class LogicalDisplayTest {
+    private static final int DISPLAY_ID = 0;
+    private static final int LAYER_STACK = 0;
+    private static final int DISPLAY_WIDTH = 100;
+    private static final int DISPLAY_HEIGHT = 200;
+
+    private LogicalDisplay mLogicalDisplay;
+    private DisplayDevice mDisplayDevice;
+
+    @Before
+    public void setUp() {
+        // Share classloader to allow package private access.
+        System.setProperty("dexmaker.share_classloader", "true");
+        mDisplayDevice = mock(DisplayDevice.class);
+        DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
+        displayDeviceInfo.width = DISPLAY_WIDTH;
+        displayDeviceInfo.height = DISPLAY_HEIGHT;
+        displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
+        mLogicalDisplay = new LogicalDisplay(DISPLAY_ID, LAYER_STACK, mDisplayDevice);
+        when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(displayDeviceInfo);
+
+        ArrayList<DisplayDevice> displayDevices = new ArrayList<>();
+        displayDevices.add(mDisplayDevice);
+        mLogicalDisplay.updateLocked(displayDevices);
+    }
+
+    @Test
+    public void testGetDisplayPosition() {
+        Point expectedPosition = new Point();
+
+        SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+        mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+        assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition());
+
+        expectedPosition.set(20, 40);
+        mLogicalDisplay.setDisplayOffsetsLocked(20, 40);
+        mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+        assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition());
+
+        expectedPosition.set(40, -20);
+        DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.logicalWidth = DISPLAY_HEIGHT;
+        displayInfo.logicalHeight = DISPLAY_WIDTH;
+        displayInfo.rotation = Surface.ROTATION_90;
+        mLogicalDisplay.setDisplayInfoOverrideFromWindowManagerLocked(displayInfo);
+        mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
+        assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
index 063cd5da..78c7080 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
@@ -18,6 +18,8 @@
 
 import android.net.Uri
 import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 5199604..728e149 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -299,7 +299,7 @@
                 .build();
         AppTargetEvent appTargetEvent =
                 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
-                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
+                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
                         .build();
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
         mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
@@ -319,7 +319,7 @@
                 .build();
         AppTargetEvent appTargetEvent =
                 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
-                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
+                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
                         .build();
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
 
@@ -667,7 +667,7 @@
                 .build();
         AppTargetEvent appTargetEvent =
                 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
-                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
+                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
                         .build();
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 5109de5..b60e993 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -17,7 +17,9 @@
 package com.android.server.pm;
 
 
-import static org.hamcrest.Matchers.arrayContaining;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.empty;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -48,7 +50,6 @@
 import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.parsing.pkg.ParsedPackage;
 
-import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -58,7 +59,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.security.cert.CertificateException;
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -650,32 +651,32 @@
         final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
         final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
         PackageSetting system = simulateAddPackage(appsFilter, pkg("some.system.pkg"), systemAppId);
-        PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("some.system.pkg"),
+        PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("com.some.package"),
                 seesNothingAppId);
         PackageSetting hasProvider = simulateAddPackage(appsFilter,
-                pkgWithProvider("com.some.package", "com.some.authority"), hasProviderAppId);
+                pkgWithProvider("com.some.other.package", "com.some.authority"), hasProviderAppId);
         PackageSetting queriesProvider = simulateAddPackage(appsFilter,
-                pkgQueriesProvider("com.some.other.package", "com.some.authority"),
+                pkgQueriesProvider("com.yet.some.other.package", "com.some.authority"),
                 queriesProviderAppId);
 
         final int[] systemFilter =
                 appsFilter.getVisibilityWhitelist(system, new int[]{0}, mExisting).get(0);
-        assertThat(Arrays.asList(systemFilter), arrayContaining(systemAppId));
+        assertThat(toList(systemFilter), empty());
 
         final int[] seesNothingFilter =
                 appsFilter.getVisibilityWhitelist(seesNothing, new int[]{0}, mExisting).get(0);
-        assertThat(Arrays.asList(seesNothingFilter),
-                arrayContaining(systemAppId, seesNothingAppId));
+        assertThat(toList(seesNothingFilter),
+                contains(seesNothingAppId));
 
         final int[] hasProviderFilter =
                 appsFilter.getVisibilityWhitelist(hasProvider, new int[]{0}, mExisting).get(0);
-        assertThat(Arrays.asList(hasProviderFilter),
-                arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
+        assertThat(toList(hasProviderFilter),
+                contains(hasProviderAppId, queriesProviderAppId));
 
         int[] queriesProviderFilter =
                 appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
-        assertThat(Arrays.asList(queriesProviderFilter),
-                arrayContaining(systemAppId, queriesProviderAppId));
+        assertThat(toList(queriesProviderFilter),
+                contains(queriesProviderAppId));
 
         // provider read
         appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
@@ -683,11 +684,16 @@
         // ensure implicit access is included in the filter
         queriesProviderFilter =
                 appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
-        assertThat(Arrays.asList(queriesProviderFilter),
-                arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
+        assertThat(toList(queriesProviderFilter),
+                contains(hasProviderAppId, queriesProviderAppId));
     }
 
-    private void assertThat(List<int[]> asList, Matcher<Integer[]> arrayContainingInAnyOrder) {
+    private List<Integer> toList(int[] array) {
+        ArrayList<Integer> ret = new ArrayList<>(array.length);
+        for (int i = 0; i < array.length; i++) {
+            ret.add(i, array[i]);
+        }
+        return ret;
     }
 
     private interface WithSettingBuilder {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 2cbb6d5..06b344b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -8595,6 +8595,56 @@
         }
     }
 
+    public void testIsSharingShortcut() throws IntentFilter.MalformedMimeTypeException {
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_share_targets);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        setCaller(CALLING_PACKAGE_1, USER_0);
+
+        final ShortcutInfo s1 = makeShortcutWithCategory("s1",
+                set("com.test.category.CATEGORY1", "com.test.category.CATEGORY2"));
+        final ShortcutInfo s2 = makeShortcutWithCategory("s2",
+                set("com.test.category.CATEGORY5", "com.test.category.CATEGORY6"));
+        final ShortcutInfo s3 = makeShortcut("s3");
+
+        assertTrue(mManager.setDynamicShortcuts(list(s1, s2, s3)));
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
+                "s1", "s2", "s3");
+
+        IntentFilter filter_cat1 = new IntentFilter();
+        filter_cat1.addDataType("text/plain");
+        IntentFilter filter_cat5 = new IntentFilter();
+        filter_cat5.addDataType("video/*");
+        IntentFilter filter_any = new IntentFilter();
+        filter_any.addDataType("*/*");
+
+        setCaller(LAUNCHER_1, USER_0);
+        mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS);
+
+        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+                filter_cat1));
+        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+                filter_cat5));
+        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+                filter_any));
+
+        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+                filter_cat1));
+        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+                filter_cat5));
+        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+                filter_any));
+
+        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_0,
+                filter_any));
+        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s4", USER_0,
+                filter_any));
+    }
+
     private Uri getFileUriFromResource(String fileName, int resId) throws IOException {
         File file = new File(getTestContext().getFilesDir(), fileName);
         // Make sure we are not leaving phantom files behind.
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index 1c2313e..dc181a9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -22,7 +22,6 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.UserManagerInternal;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.SparseArray;
@@ -118,135 +117,6 @@
                 UserManager.DISALLOW_ADJUST_VOLUME, user));
     }
 
-    public void testSortToGlobalAndLocal() {
-        final Bundle local = new Bundle();
-        final Bundle global = new Bundle();
-
-        UserRestrictionsUtils.sortToGlobalAndLocal(null,
-                UserManagerInternal.OWNER_TYPE_PROFILE_OWNER,
-                global, local);
-        assertEquals(0, global.size());
-        assertEquals(0, local.size());
-
-        UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY,
-                UserManagerInternal.OWNER_TYPE_PROFILE_OWNER,
-                global, local);
-        assertEquals(0, global.size());
-        assertEquals(0, local.size());
-
-        // Restrictions set by DO.
-        UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(
-                UserManager.DISALLOW_ADJUST_VOLUME,
-                UserManager.DISALLOW_UNMUTE_MICROPHONE,
-                UserManager.DISALLOW_USB_FILE_TRANSFER,
-                UserManager.DISALLOW_CONFIG_TETHERING,
-                UserManager.DISALLOW_OUTGOING_BEAM,
-                UserManager.DISALLOW_APPS_CONTROL,
-                UserManager.ENSURE_VERIFY_APPS,
-                UserManager.DISALLOW_CAMERA
-                ), UserManagerInternal.OWNER_TYPE_DEVICE_OWNER,
-                global, local);
-
-
-        assertRestrictions(newRestrictions(
-                // This one is global no matter who sets it.
-                UserManager.ENSURE_VERIFY_APPS,
-
-                // These can be set by PO too, but when DO sets them, they're global.
-                UserManager.DISALLOW_ADJUST_VOLUME,
-                UserManager.DISALLOW_UNMUTE_MICROPHONE,
-
-                // These can only be set by DO.
-                UserManager.DISALLOW_USB_FILE_TRANSFER,
-                UserManager.DISALLOW_CONFIG_TETHERING,
-
-                // This can be set by DO or PO of organisation owned device
-                UserManager.DISALLOW_CAMERA
-        ), global);
-
-        assertRestrictions(newRestrictions(
-                // They can be set by both DO/PO.
-                UserManager.DISALLOW_OUTGOING_BEAM,
-                UserManager.DISALLOW_APPS_CONTROL
-        ), local);
-
-        local.clear();
-        global.clear();
-
-        // Restrictions set by PO.
-        UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(
-                UserManager.DISALLOW_ADJUST_VOLUME,
-                UserManager.DISALLOW_UNMUTE_MICROPHONE,
-                UserManager.DISALLOW_USB_FILE_TRANSFER,
-                UserManager.DISALLOW_CONFIG_TETHERING,
-                UserManager.DISALLOW_OUTGOING_BEAM,
-                UserManager.DISALLOW_APPS_CONTROL,
-                UserManager.ENSURE_VERIFY_APPS,
-                UserManager.DISALLOW_CAMERA
-                ), UserManagerInternal.OWNER_TYPE_PROFILE_OWNER,
-                global, local);
-
-        assertRestrictions(newRestrictions(
-                // This one is global no matter who sets it.
-                UserManager.ENSURE_VERIFY_APPS
-        ), global);
-
-        assertRestrictions(newRestrictions(
-                // These can be set by PO too, but when PO sets them, they're local.
-                UserManager.DISALLOW_ADJUST_VOLUME,
-                UserManager.DISALLOW_UNMUTE_MICROPHONE,
-
-                // They can be set by both DO/PO.
-                UserManager.DISALLOW_OUTGOING_BEAM,
-                UserManager.DISALLOW_APPS_CONTROL,
-
-                // These can only be set by DO.
-                UserManager.DISALLOW_USB_FILE_TRANSFER,
-                UserManager.DISALLOW_CONFIG_TETHERING,
-
-                // This can be set by DO or PO of organisation owned device
-                UserManager.DISALLOW_CAMERA
-        ), local);
-
-        local.clear();
-        global.clear();
-
-        // Restrictions set by PO of organisation owned device
-        UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(
-                UserManager.DISALLOW_CONFIG_DATE_TIME
-                ), UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE,
-                global, local);
-
-        assertRestrictions(newRestrictions(
-                // This user restriction is global when set by PO of org owned device
-                UserManager.DISALLOW_CONFIG_DATE_TIME
-        ), global);
-        assertEquals(0, local.size());
-    }
-
-    public void testSortToLocalAndGlobalWithCameraDisabled() {
-        final Bundle local = new Bundle();
-        final Bundle global = new Bundle();
-
-        UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(UserManager.DISALLOW_CAMERA),
-                UserManagerInternal.OWNER_TYPE_DEVICE_OWNER, global, local);
-        assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), global);
-        assertEquals(0, local.size());
-        global.clear();
-
-        UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(UserManager.DISALLOW_CAMERA),
-                UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE, global,
-                local);
-        assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), global);
-        assertEquals(0, local.size());
-        global.clear();
-
-        UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(UserManager.DISALLOW_CAMERA),
-                UserManagerInternal.OWNER_TYPE_PROFILE_OWNER, global, local);
-        assertEquals(0, global.size());
-        assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), local);
-    }
-
     public void testMoveRestriction() {
         SparseArray<RestrictionsSet> localRestrictions = new SparseArray<>();
         RestrictionsSet globalRestrictions = new RestrictionsSet();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index d69e1b8..8398585 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -85,6 +85,9 @@
     private TestData mBarUser0UnsupportedClassLoader;
     private TestData mBarUser0DelegateLastClassLoader;
 
+    private TestData mSystemServerJar;
+    private TestData mSystemServerJarInvalid;
+
     private int mUser0;
     private int mUser1;
 
@@ -108,6 +111,9 @@
         mBarUser0DelegateLastClassLoader = new TestData(bar, isa, mUser0,
                 DELEGATE_LAST_CLASS_LOADER_NAME);
 
+        mSystemServerJar = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME);
+        mSystemServerJarInvalid = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME);
+
         mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null,
                 mInstaller, mInstallLock);
 
@@ -587,6 +593,25 @@
         assertHasDclInfo(mFooUser0, mFooUser0, fooSecondaries);
     }
 
+
+    @Test
+    public void testNotifySystemServerUse() {
+        List<String> dexFiles = new ArrayList<String>();
+        dexFiles.add("/system/framework/foo");
+        notifyDexLoad(mSystemServerJar, dexFiles, mUser0);
+        PackageUseInfo pui = getPackageUseInfo(mSystemServerJar);
+        assertIsUsedByOtherApps(mSystemServerJar, pui, false);
+    }
+
+    @Test
+    public void testNotifySystemServerInvalidUse() {
+        List<String> dexFiles = new ArrayList<String>();
+        dexFiles.add("/data/foo");
+        notifyDexLoad(mSystemServerJarInvalid, dexFiles, mUser0);
+        assertNoUseInfo(mSystemServerJarInvalid);
+        assertNoDclInfo(mSystemServerJarInvalid);
+    }
+
     private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
             List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId,
             String[] expectedContexts) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 5df4509..adf4551 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -77,25 +77,25 @@
         String fooDataDir = "/data/user/0/com.google.foo/";
 
         mFooBaseUser0 = new TestData(fooPackageName,
-                fooCodeDir + "base.apk", 0, ISA, false, true, fooPackageName);
+                fooCodeDir + "base.apk", 0, ISA, true, fooPackageName);
 
         mFooSplit1User0 = new TestData(fooPackageName,
-                fooCodeDir + "split-1.apk", 0, ISA, false, true, fooPackageName);
+                fooCodeDir + "split-1.apk", 0, ISA, true, fooPackageName);
 
         mFooSplit2UsedByOtherApps0 = new TestData(fooPackageName,
-                fooCodeDir + "split-2.apk", 0, ISA, true, true, "used.by.other.com");
+                fooCodeDir + "split-2.apk", 0, ISA, true, "used.by.other.com");
 
         mFooSecondary1User0 = new TestData(fooPackageName,
-                fooDataDir + "sec-1.dex", 0, ISA, false, false, fooPackageName);
+                fooDataDir + "sec-1.dex", 0, ISA, false, fooPackageName);
 
         mFooSecondary1User1 = new TestData(fooPackageName,
-                fooDataDir + "sec-1.dex", 1, ISA, false, false, fooPackageName);
+                fooDataDir + "sec-1.dex", 1, ISA, false, fooPackageName);
 
         mFooSecondary2UsedByOtherApps0 = new TestData(fooPackageName,
-                fooDataDir + "sec-2.dex", 0, ISA, true, false, "used.by.other.com");
+                fooDataDir + "sec-2.dex", 0, ISA, false, "used.by.other.com");
 
         mInvalidIsa = new TestData(fooPackageName,
-                fooCodeDir + "base.apk", 0, "INVALID_ISA", false, true, "INALID_USER");
+                fooCodeDir + "base.apk", 0, "INVALID_ISA", true, "INALID_USER");
 
         String barPackageName = "com.google.bar";
         String barCodeDir = "/data/app/com.google.bar/";
@@ -103,11 +103,11 @@
         String barDataDir1 = "/data/user/1/com.google.bar/";
 
         mBarBaseUser0 = new TestData(barPackageName,
-                barCodeDir + "base.apk", 0, ISA, false, true, barPackageName);
+                barCodeDir + "base.apk", 0, ISA, true, barPackageName);
         mBarSecondary1User0 = new TestData(barPackageName,
-                barDataDir + "sec-1.dex", 0, ISA, false, false, barPackageName);
+                barDataDir + "sec-1.dex", 0, ISA, false, barPackageName);
         mBarSecondary2User1 = new TestData(barPackageName,
-                barDataDir1 + "sec-2.dex", 1, ISA, false, false, barPackageName);
+                barDataDir1 + "sec-2.dex", 1, ISA, false, barPackageName);
     }
 
     @Test
@@ -134,7 +134,9 @@
     public void testRecordSplitPrimarySequence() {
         // Assert new information.
         assertTrue(record(mFooBaseUser0));
-        // Assert no new information.
+        assertTrue(record(mFooSplit1User0));
+        // Assert no new information if we add again
+        assertFalse(record(mFooBaseUser0));
         assertFalse(record(mFooSplit1User0));
 
         assertPackageDexUsage(mFooBaseUser0);
@@ -192,7 +194,7 @@
         for (int i = 1; i <= tooManyFiles; i++) {
             String fooPackageName = "com.google.foo";
             TestData testData = new TestData(fooPackageName,
-                    "/data/user/0/" + fooPackageName + "/sec-" + i + "1.dex", 0, ISA, false, false,
+                    "/data/user/0/" + fooPackageName + "/sec-" + i + "1.dex", 0, ISA, false,
                     fooPackageName);
             if (i < tooManyFiles) {
                 assertTrue("Adding " + testData.mDexFile, record(testData));
@@ -200,7 +202,11 @@
             } else {
                 assertFalse("Adding " + testData.mDexFile, record(testData));
             }
-            assertPackageDexUsage(mPackageDexUsage, null, null, expectedSecondaries);
+            assertPackageDexUsage(
+                    mPackageDexUsage,
+                    /* usdeBy=*/ (Set<String>) null,
+                    /* primaryDex= */ null,
+                    expectedSecondaries);
         }
     }
 
@@ -276,7 +282,7 @@
         Map<String, Set<String>> packageToCodePaths = new HashMap<>();
         packageToCodePaths.put(mBarBaseUser0.mPackageName,
                 new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
-        mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
+        mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths, new ArrayList<String>());
 
         // Assert that only user 1 files are there.
         assertPackageDexUsage(mBarBaseUser0, mBarSecondary2User1);
@@ -284,6 +290,41 @@
     }
 
     @Test
+    public void testSyncDataKeepPackages() {
+        PackageDexUsage packageDexUsage = new PackageDexUsage();
+        // Write the record we want to keep and which won't be keep by default.
+        Set<String> fooUsers = new HashSet<>(Arrays.asList(
+                new String[] {mFooBaseUser0.mPackageName}));
+        assertTrue(record(packageDexUsage, mFooBaseUser0, fooUsers));
+        // Write a record that would be kept by default.
+        Set<String> barUsers = new HashSet<>(Arrays.asList(
+                new String[] {"another.package", mFooBaseUser0.mPackageName}));
+        assertTrue(record(packageDexUsage, mBarBaseUser0, barUsers));
+
+        // Construct the user packages and their code paths (things that will be
+        // kept by default during sync).
+        Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
+        packageToUsersMap.put(mBarBaseUser0.mPackageName,
+                new HashSet<>(Arrays.asList(mBarBaseUser0.mOwnerUserId)));
+        Map<String, Set<String>> packageToCodePaths = new HashMap<>();
+        packageToCodePaths.put(mBarBaseUser0.mPackageName,
+                new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
+
+        // Sync data.
+        List<String> keepData = new ArrayList<String>();
+        keepData.add(mFooBaseUser0.mPackageName);
+        packageDexUsage.syncData(packageToUsersMap, packageToCodePaths, keepData);
+
+        // Assert that both packages are kept
+        assertPackageDexUsage(packageDexUsage, fooUsers, mFooBaseUser0);
+        // "another.package" should not be in the loading packages after sync.
+        Set<String> expectedBarUsers = new HashSet<>(Arrays.asList(
+                new String[] {mFooBaseUser0.mPackageName}));
+        assertPackageDexUsage(packageDexUsage, expectedBarUsers,
+                mBarBaseUser0.updateUsedBy(mFooBaseUser0.mPackageName));
+    }
+
+    @Test
     public void testRemovePackage() {
         // Record Bar secondaries for two different users.
         assertTrue(record(mBarSecondary1User0));
@@ -345,9 +386,8 @@
             mFooSplit2UsedByOtherApps0.mDexFile,
             mFooSplit2UsedByOtherApps0.mOwnerUserId,
             mFooSplit2UsedByOtherApps0.mLoaderIsa,
-            /*mIsUsedByOtherApps*/false,
             mFooSplit2UsedByOtherApps0.mPrimaryOrSplit,
-            mFooSplit2UsedByOtherApps0.mUsedBy);
+            /*usedBy=*/ null);
         assertPackageDexUsage(noLongerUsedByOtherApps);
     }
 
@@ -371,19 +411,19 @@
         assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, users));
         assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, usersExtra));
 
-        assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, users));
-        assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, usersExtra));
+        assertTrue(record(packageDexUsageRecordUsers, mFooSecondary2UsedByOtherApps0, users));
+        assertTrue(record(packageDexUsageRecordUsers, mFooSecondary2UsedByOtherApps0, usersExtra));
 
         packageDexUsageRecordUsers = writeAndReadBack(packageDexUsageRecordUsers);
         // Verify that the users were recorded.
         Set<String> userAll = new HashSet<>(users);
         userAll.addAll(usersExtra);
         assertPackageDexUsage(packageDexUsageRecordUsers, userAll, mFooSplit2UsedByOtherApps0,
-                mFooSecondary1User0);
+                mFooSecondary2UsedByOtherApps0);
     }
 
     @Test
-    public void testRecordDexFileUsersNotTheOwningPackage() {
+    public void testRecordDexFileUsersAndTheOwningPackage() {
         PackageDexUsage packageDexUsageRecordUsers = new PackageDexUsage();
         Set<String> users = new HashSet<>(Arrays.asList(
                 new String[] {mFooSplit2UsedByOtherApps0.mPackageName}));
@@ -393,13 +433,13 @@
         assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, users));
         assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, usersExtra));
 
-        assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, users));
-        assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, usersExtra));
-
         packageDexUsageRecordUsers = writeAndReadBack(packageDexUsageRecordUsers);
-        // Verify that only the non owning packages were recorded.
-        assertPackageDexUsage(packageDexUsageRecordUsers, usersExtra, mFooSplit2UsedByOtherApps0,
-                mFooSecondary1User0);
+
+        Set<String> expectedUsers = new HashSet<>(users);
+        expectedUsers.addAll(usersExtra);
+        // Verify that all loading packages were recorded.
+        assertPackageDexUsage(
+                packageDexUsageRecordUsers, expectedUsers, mFooSplit2UsedByOtherApps0);
     }
 
     @Test
@@ -421,44 +461,97 @@
     }
 
     @Test
-    public void testRecordClassLoaderContextTransitionFromUnknown() {
-        // Record a secondary dex file.
-        TestData unknownContext = mFooSecondary1User0.updateClassLoaderContext(
-                PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT);
-        assertTrue(record(unknownContext));
-
-        assertPackageDexUsage(null, unknownContext);
-        writeAndReadBack();
-        assertPackageDexUsage(null, unknownContext);
-
-        // Now update the secondary dex record with a class loader context. This simulates the
-        // version 2 to version 3 upgrade.
-
-        assertTrue(record(mFooSecondary1User0));
-
-        assertPackageDexUsage(null, mFooSecondary1User0);
-        writeAndReadBack();
-        assertPackageDexUsage(null, mFooSecondary1User0);
-    }
-
-    @Test
     public void testDexUsageClassLoaderContext() {
         final boolean isUsedByOtherApps = false;
         final int userId = 0;
         PackageDexUsage.DexUseInfo validContext = new DexUseInfo(isUsedByOtherApps, userId,
                 "valid_context", "arm");
-        assertFalse(validContext.isUnknownClassLoaderContext());
+        assertFalse(validContext.isUnsupportedClassLoaderContext());
         assertFalse(validContext.isVariableClassLoaderContext());
 
         PackageDexUsage.DexUseInfo variableContext = new DexUseInfo(isUsedByOtherApps, userId,
                 PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT, "arm");
-        assertFalse(variableContext.isUnknownClassLoaderContext());
+        assertFalse(variableContext.isUnsupportedClassLoaderContext());
         assertTrue(variableContext.isVariableClassLoaderContext());
+    }
 
-        PackageDexUsage.DexUseInfo unknownContext = new DexUseInfo(isUsedByOtherApps, userId,
-                PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT, "arm");
-        assertTrue(unknownContext.isUnknownClassLoaderContext());
-        assertFalse(unknownContext.isVariableClassLoaderContext());
+    @Test
+    public void testRead() {
+        String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+        // Equivalent to
+        //   record(mFooSplit2UsedByOtherApps0);
+        //   record(mFooSecondary1User0);
+        //   record(mFooSecondary2UsedByOtherApps0);
+        //   record(mBarBaseUser0);
+        //   record(mBarSecondary1User0);
+        String content = "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__2\n"
+                + "com.google.foo\n"
+                + "+/data/app/com.google.foo/split-2.apk\n"
+                + "@used.by.other.com\n"
+                + "#/data/user/0/com.google.foo/sec-2.dex\n"
+                + "0,1," + ISA + "\n"
+                + "@used.by.other.com\n"
+                + "PCL[/data/user/0/com.google.foo/sec-2.dex]\n"
+                + "#/data/user/0/com.google.foo/sec-1.dex\n"
+                + "0,0," + ISA + "\n"
+                + "@\n"
+                + "PCL[/data/user/0/com.google.foo/sec-1.dex]\n"
+                + "com.google.bar\n"
+                + "+/data/app/com.google.bar/base.apk\n"
+                + "@com.google.bar\n"
+                + "#/data/user/0/com.google.bar/sec-1.dex\n"
+                + "0,0," + ISA + "\n"
+                + "@\n"
+                + "PCL[/data/user/0/com.google.bar/sec-1.dex]";
+
+        PackageDexUsage packageDexUsage = new PackageDexUsage();
+        try {
+            packageDexUsage.read(new StringReader(content));
+        } catch (IOException e) {
+            fail();
+        }
+
+        // After the read we must sync the data to fill the missing information on the code paths.
+        Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
+        Map<String, Set<String>> packageToCodePaths = new HashMap<>();
+
+        // Handle foo package.
+        packageToUsersMap.put(
+                mFooSplit2UsedByOtherApps0.mPackageName,
+                new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mOwnerUserId)));
+        packageToCodePaths.put(
+                mFooSplit2UsedByOtherApps0.mPackageName,
+                new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mDexFile,
+                        mFooSplit1User0.mDexFile, mFooBaseUser0.mDexFile)));
+        // Handle bar package.
+        packageToUsersMap.put(
+                mBarBaseUser0.mPackageName,
+                new HashSet<>(Arrays.asList(mBarBaseUser0.mOwnerUserId)));
+        packageToCodePaths.put(
+                mBarBaseUser0.mPackageName,
+                new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
+        // Handle the loading package.
+        packageToUsersMap.put(
+                mFooSplit2UsedByOtherApps0.mUsedBy,
+                new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mOwnerUserId)));
+
+        // Sync the data.
+        packageDexUsage.syncData(packageToUsersMap, packageToCodePaths, new ArrayList<>());
+
+        // Assert foo code paths.
+        assertPackageDexUsage(
+                packageDexUsage,
+                /*nonDefaultUsers=*/ null,
+                mFooSplit2UsedByOtherApps0,
+                mFooSecondary2UsedByOtherApps0,
+                mFooSecondary1User0);
+
+        // Assert bar code paths.
+        assertPackageDexUsage(
+                packageDexUsage,
+                /*nonDefaultUsers=*/ null,
+                mBarBaseUser0,
+                mBarSecondary1User0);
     }
 
     @Test
@@ -483,77 +576,19 @@
     }
 
     @Test
-    public void testReadVersion1() {
+    public void testEnsureLoadingPackagesCanBeExtended() {
         String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
-        // Equivalent to
-        //   record(mFooSplit2UsedByOtherApps0);
-        //   record(mFooSecondary1User0);
-        //   record(mFooSecondary2UsedByOtherApps0);
-        //   record(mBarBaseUser0);
-        //   record(mBarSecondary1User0);
-        String content = "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__1\n"
-                + "com.google.foo,1\n"
-                + "#/data/user/0/com.google.foo/sec-1.dex\n"
-                + "0,0," + isa + "\n"
-                + "#/data/user/0/com.google.foo/sec-2.dex\n"
-                + "0,1," + isa + "\n"
-                + "com.google.bar,0\n"
-                + "#/data/user/0/com.google.bar/sec-1.dex\n"
-                + "0,0," + isa + "\n";
-
+        String content = "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__2\n"
+                + "com.google.foo\n"
+                + "+/data/app/com.google.foo/split-2.apk\n"
+                + "@\n";
         PackageDexUsage packageDexUsage = new PackageDexUsage();
         try {
             packageDexUsage.read(new StringReader(content));
         } catch (IOException e) {
             fail();
         }
-
-        // After the read we must sync the data to fill the missing information on the code paths.
-        Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
-        Map<String, Set<String>> packageToCodePaths = new HashMap<>();
-
-        // Handle foo package.
-        packageToUsersMap.put(mFooSplit2UsedByOtherApps0.mPackageName,
-            new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mOwnerUserId)));
-        packageToCodePaths.put(mFooSplit2UsedByOtherApps0.mPackageName,
-            new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mDexFile,
-                mFooSplit1User0.mDexFile, mFooBaseUser0.mDexFile)));
-        // Handle bar package.
-        packageToUsersMap.put(mBarBaseUser0.mPackageName,
-            new HashSet<>(Arrays.asList(mBarBaseUser0.mOwnerUserId)));
-        packageToCodePaths.put(mBarBaseUser0.mPackageName,
-            new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile)));
-
-        // Sync the data.
-        packageDexUsage.syncData(packageToUsersMap, packageToCodePaths);
-
-        // Update the class loaders to unknown before asserting if needed. Before version 2 we
-        // didn't have any.
-        String unknown = PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT;
-        TestData fooBaseUser0 = mFooBaseUser0.updateClassLoaderContext(unknown);
-        TestData fooSplit1User0 = mFooSplit1User0.updateClassLoaderContext(unknown);
-        TestData fooSplit2UsedByOtherApps0 =
-            mFooSplit2UsedByOtherApps0.updateClassLoaderContext(unknown);
-        TestData fooSecondary1User0 = mFooSecondary1User0.updateClassLoaderContext(unknown);
-        TestData fooSecondary2UsedByOtherApps0 =
-            mFooSecondary2UsedByOtherApps0.updateClassLoaderContext(unknown);
-        TestData barBaseUser0 = mBarBaseUser0.updateClassLoaderContext(unknown);
-        TestData barSecondary1User0 = mBarSecondary1User0.updateClassLoaderContext(unknown);
-
-        // Assert foo code paths. Note that we ignore the users during upgrade.
-        final Set<String> ignoredUsers = null;
-        assertPackageDexUsage(packageDexUsage, ignoredUsers,
-            fooSplit2UsedByOtherApps0, fooSecondary1User0, fooSecondary2UsedByOtherApps0);
-        // Because fooSplit2UsedByOtherApps0 is used by others, all the other code paths must
-        // share the same data.
-        assertPackageDexUsage(packageDexUsage, ignoredUsers,
-            fooSplit1User0.updateUseByOthers(true),
-            fooSecondary1User0, fooSecondary2UsedByOtherApps0);
-        assertPackageDexUsage(packageDexUsage, ignoredUsers, fooBaseUser0.updateUseByOthers(true),
-            fooSecondary1User0, fooSecondary2UsedByOtherApps0);
-
-        // Assert bar code paths. Note that we ignore the users during upgrade.
-        assertPackageDexUsage(packageDexUsage, ignoredUsers, barBaseUser0, barSecondary1User0);
+        record(packageDexUsage, mFooSplit2UsedByOtherApps0, mFooSplit2UsedByOtherApps0.getUsedBy());
     }
 
     private void assertPackageDexUsage(TestData primary, TestData... secondaries) {
@@ -570,16 +605,18 @@
         String packageName = primary == null
                 ? secondaries.get(0).mPackageName
                 : primary.mPackageName;
-        boolean primaryUsedByOtherApps = primary != null && primary.mUsedByOtherApps;
+        boolean primaryUsedByOtherApps = primary != null && primary.isUsedByOtherApps();
         PackageUseInfo pInfo = packageDexUsage.getPackageUseInfo(packageName);
 
         // Check package use info
         assertNotNull(pInfo);
         if (primary != null) {
-            assertEquals(primaryUsedByOtherApps, pInfo.isUsedByOtherApps(primary.mDexFile));
             if (users != null) {
                 assertEquals(pInfo.getLoadingPackages(primary.mDexFile), users);
+            } else if (pInfo.getLoadingPackages(primary.mDexFile) != null) {
+                assertEquals(pInfo.getLoadingPackages(primary.mDexFile), primary.getUsedBy());
             }
+            assertEquals(primaryUsedByOtherApps, pInfo.isUsedByOtherApps(primary.mDexFile));
         }
 
         Map<String, DexUseInfo> dexUseInfoMap = pInfo.getDexUseInfoMap();
@@ -589,13 +626,15 @@
         for (TestData testData : secondaries) {
             DexUseInfo dInfo = dexUseInfoMap.get(testData.mDexFile);
             assertNotNull(dInfo);
-            assertEquals(testData.mUsedByOtherApps, dInfo.isUsedByOtherApps());
+            if (users != null) {
+                assertEquals(testData.mDexFile, dInfo.getLoadingPackages(), users);
+            } else {
+                assertEquals(testData.mDexFile, dInfo.getLoadingPackages(), testData.getUsedBy());
+            }
+            assertEquals(testData.isUsedByOtherApps(), dInfo.isUsedByOtherApps());
             assertEquals(testData.mOwnerUserId, dInfo.getOwnerUserId());
             assertEquals(1, dInfo.getLoaderIsas().size());
             assertTrue(dInfo.getLoaderIsas().contains(testData.mLoaderIsa));
-            if (users != null) {
-                 assertEquals(dInfo.getLoadingPackages(), users);
-            }
 
             assertEquals(testData.mClassLoaderContext, dInfo.getClassLoaderContext());
         }
@@ -603,7 +642,7 @@
 
     private boolean record(TestData testData) {
         return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile,
-               testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps,
+               testData.mOwnerUserId, testData.mLoaderIsa,
                testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext);
     }
 
@@ -611,7 +650,7 @@
         boolean result = true;
         for (String user : users) {
             result = result && packageDexUsage.record(testData.mPackageName, testData.mDexFile,
-                    testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps,
+                    testData.mOwnerUserId, testData.mLoaderIsa,
                     testData.mPrimaryOrSplit, user, testData.mClassLoaderContext);
         }
         return result;
@@ -640,37 +679,49 @@
         private final String mDexFile;
         private final int mOwnerUserId;
         private final String mLoaderIsa;
-        private final boolean mUsedByOtherApps;
         private final boolean mPrimaryOrSplit;
         private final String mUsedBy;
         private final String mClassLoaderContext;
 
         private TestData(String packageName, String dexFile, int ownerUserId,
-                String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit, String usedBy) {
-            this(packageName, dexFile, ownerUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit,
-                    usedBy, "DefaultClassLoaderContextFor_" + dexFile);
+                String loaderIsa, boolean primaryOrSplit, String usedBy) {
+            this(packageName, dexFile, ownerUserId, loaderIsa, primaryOrSplit,
+                    usedBy, "PCL[" + dexFile + "]");
         }
         private TestData(String packageName, String dexFile, int ownerUserId,
-                String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit, String usedBy,
+                String loaderIsa, boolean primaryOrSplit, String usedBy,
                 String classLoaderContext) {
             mPackageName = packageName;
             mDexFile = dexFile;
             mOwnerUserId = ownerUserId;
             mLoaderIsa = loaderIsa;
-            mUsedByOtherApps = isUsedByOtherApps;
             mPrimaryOrSplit = primaryOrSplit;
             mUsedBy = usedBy;
             mClassLoaderContext = classLoaderContext;
         }
 
         private TestData updateClassLoaderContext(String newContext) {
-            return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa, mUsedByOtherApps,
+            return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
                     mPrimaryOrSplit, mUsedBy, newContext);
         }
 
-        private TestData updateUseByOthers(boolean newUsedByOthers) {
-            return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa, newUsedByOthers,
-                mPrimaryOrSplit, mUsedBy, mClassLoaderContext);
+        private TestData updateUsedBy(String newUsedBy) {
+            return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
+                mPrimaryOrSplit, newUsedBy, mClassLoaderContext);
+        }
+
+        private boolean isUsedByOtherApps() {
+            return mUsedBy != null && !mPackageName.equals(mUsedBy);
+        }
+
+        private Set<String> getUsedBy() {
+            Set<String> users = new HashSet<>();
+            if ((mUsedBy != null) && (mPrimaryOrSplit || isUsedByOtherApps())) {
+                // We do not store the loading package for secondary dex files
+                // which are not used by others.
+                users.add(mUsedBy);
+            }
+            return users;
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
index 191c038..5412bb5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
@@ -18,7 +18,9 @@
 
 import android.content.pm.PackageManager
 import android.platform.test.annotations.Presubmit
+import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Rule
 import org.junit.Test
 
 /**
@@ -28,6 +30,9 @@
 @Presubmit
 class AndroidPackageParsingEquivalenceTest : AndroidPackageParsingTestBase() {
 
+    @get:Rule
+    val expect = Expect.create()
+
     @Test
     fun applicationInfoEquality() {
         val flags = PackageManager.GET_META_DATA or PackageManager.GET_SHARED_LIBRARY_FILES
@@ -41,7 +46,8 @@
             } else {
                 "$firstName | $secondName"
             }
-            assertWithMessage(packageName).that(it.first?.dumpToString())
+            expect.withMessage("${it.first?.sourceDir} $packageName")
+                    .that(it.first?.dumpToString())
                     .isEqualTo(it.second?.dumpToString())
         }
     }
@@ -71,7 +77,8 @@
             } else {
                 "$firstName | $secondName"
             }
-            assertWithMessage(packageName).that(it.first?.dumpToString())
+            expect.withMessage("${it.first?.applicationInfo?.sourceDir} $packageName")
+                    .that(it.first?.dumpToString())
                     .isEqualTo(it.second?.dumpToString())
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index f532dd8..7b1b2d2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -29,14 +29,17 @@
 import android.content.pm.ProviderInfo
 import android.os.Debug
 import android.os.Environment
+import android.os.ServiceManager
 import android.util.SparseArray
 import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.om.mockThrowOnUnmocked
-import com.android.server.om.whenever
+import com.android.internal.compat.IPlatformCompat
 import com.android.server.pm.PackageManagerService
 import com.android.server.pm.PackageSetting
 import com.android.server.pm.parsing.pkg.AndroidPackage
 import com.android.server.pm.pkg.PackageStateUnserialized
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
+import org.junit.After
 import org.junit.BeforeClass
 import org.mockito.Mockito
 import org.mockito.Mockito.anyInt
@@ -59,7 +62,27 @@
             setCallback { false /* hasFeature */ }
         }
 
-        protected val packageParser2 = TestPackageParser2()
+        private val platformCompat = IPlatformCompat.Stub
+                .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE))
+
+        protected val packageParser2 = PackageParser2(null /* separateProcesses */,
+                false /* onlyCoreApps */, context.resources.displayMetrics, null /* cacheDir */,
+                object : PackageParser2.Callback() {
+                    override fun isChangeEnabled(
+                        changeId: Long,
+                        appInfo: ApplicationInfo
+                    ): Boolean {
+                        // This test queries PlatformCompat because prebuilts in the tree
+                        // may not be updated to be compliant with the latest enforcement checks.
+                        return platformCompat.isChangeEnabled(changeId, appInfo)
+                    }
+
+                    // Assume the device doesn't support anything. This will affect permission
+                    // parsing and will force <uses-permission/> declarations to include all
+                    // requiredNotFeature permissions and exclude all requiredFeature permissions.
+                    // This mirrors the old behavior.
+                    override fun hasFeature(feature: String) = false
+                })
 
         /**
          * It would be difficult to mock all possibilities, so just use the APKs on device.
@@ -91,22 +114,29 @@
 
         lateinit var newPackages: List<AndroidPackage>
 
+        private val thrownInSetUp = mutableListOf<Throwable>()
+
         @Suppress("ConstantConditionIf")
         @JvmStatic
         @BeforeClass
         fun setUpPackages() {
-            this.oldPackages = apks.map {
-                packageParser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+            this.oldPackages = apks.mapNotNull {
+                tryOrNull {
+                    packageParser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+                }
             }
 
-            this.newPackages = apks.map {
-                packageParser2.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+            this.newPackages = apks.mapNotNull {
+                tryOrNull {
+                    packageParser2.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+                }
             }
 
             if (DUMP_HPROF_TO_EXTERNAL) {
                 System.gc()
                 Environment.getExternalStorageDirectory()
-                        .resolve("${AndroidPackageParsingTestBase::class.java.simpleName}.hprof")
+                        .resolve(
+                                "${AndroidPackageParsingTestBase::class.java.simpleName}.hprof")
                         .absolutePath
                         .run(Debug::dumpHprofData)
             }
@@ -135,6 +165,36 @@
             this.pkg = aPkg
             whenever(pkgState) { PackageStateUnserialized() }
         }
+
+        private fun <T> tryOrNull(block: () -> T) = try {
+            block()
+        } catch (t: Throwable) {
+            thrownInSetUp.add(t)
+            null
+        }
+    }
+
+    @After
+    fun verifySetUpPackages() {
+        if (thrownInSetUp.isEmpty()) return
+        val exception = AssertionError("setUpPackages failed with ${thrownInSetUp.size} errors:\n" +
+                thrownInSetUp.joinToString(separator = "\n") { it.message.orEmpty() })
+
+        /*
+            Testing infrastructure doesn't currently support errors thrown in @AfterClass,
+            so instead it's thrown here. But to avoid throwing a massive repeated stack for every
+            test method, only throw on the first method run in the class, clearing the list so that
+            subsequent methods can run without failing. Doing this in @After lets true method
+            failures propagate, as those should throw before this does.
+
+            This will cause the failure to be attached to a different method depending on run order,
+            which could make comparisons difficult. So if a failure points here, it's worth
+            checking failures for all methods in all subclasses.
+
+            TODO: When infrastructure supports @AfterClass errors, move this
+        */
+        thrownInSetUp.clear()
+        throw exception
     }
 
     // The following methods dump an exact set of fields from the object to compare, because
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
new file mode 100644
index 0000000..404f29c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.pm.parsing.library;
+
+import android.os.Build;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link ComGoogleAndroidMapsUpdater}
+ */
+@Presubmit
+@SmallTest
+@RunWith(JUnit4.class)
+public class ComGoogleAndroidMapsUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+    @Test
+    public void otherUsesLibraries() {
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.O)
+                .addUsesLibrary("other")
+                .addUsesOptionalLibrary("optional")
+                .addUsesLibrary("com.google.android.maps")
+                .hideAsParsed());
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.O)
+                .addUsesLibrary("other")
+                .addUsesOptionalLibrary("optional")
+                .hideAsParsed())
+                .hideAsFinal();
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void in_usesLibraries() {
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .addUsesLibrary("com.google.android.maps")
+                .hideAsParsed());
+
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .hideAsParsed())
+                .hideAsFinal();
+
+        // No change is required because the package explicitly requests org.apache.http.legacy
+        // and is targeted at the current version so does not need backwards compatibility.
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void in_usesOptionalLibraries() {
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .addUsesOptionalLibrary("com.google.android.maps")
+                .hideAsParsed());
+
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .hideAsParsed())
+                .hideAsFinal();
+
+        // No change is required because the package explicitly requests org.apache.http.legacy
+        // and is targeted at the current version so does not need backwards compatibility.
+        checkBackwardsCompatibility(before, after);
+    }
+
+    private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
+        checkBackwardsCompatibility(before, after, ComGoogleAndroidMapsUpdater::new);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
index ca38860..09c8142 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -148,6 +148,23 @@
         checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal());
     }
 
+    /**
+     * Ensures that the {@link PackageBackwardCompatibility} uses a
+     * {@link ComGoogleAndroidMapsUpdater}.
+     */
+    @Test
+    public void com_google_android_maps_in_usesLibraries() {
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .addUsesLibrary("com.google.android.maps")
+                .hideAsParsed());
+
+        ParsingPackage after = PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT);
+
+        checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal());
+    }
+
     private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
         checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance);
     }
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
index 06b5fe4..ebcf10d 100644
--- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
@@ -1106,7 +1106,7 @@
     public void testAbortRecognition() throws Exception {
         // Make sure the HAL doesn't support concurrent capture.
         initService(false);
-        mService.setExternalCaptureState(false);
+        mService.setCaptureState(false);
 
         ISoundTriggerCallback callback = createCallbackMock();
         ISoundTriggerModule module = mService.attach(0, callback);
@@ -1120,7 +1120,7 @@
         startRecognition(module, handle, hwHandle);
 
         // Abort.
-        mService.setExternalCaptureState(true);
+        mService.setCaptureState(true);
 
         ArgumentCaptor<RecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
                 RecognitionEvent.class);
@@ -1142,7 +1142,7 @@
         verifyNotStartRecognition();
 
         // Now enable it and make sure we are notified.
-        mService.setExternalCaptureState(false);
+        mService.setCaptureState(false);
         verify(callback).onRecognitionAvailabilityChange(true);
 
         // Unload the model.
@@ -1154,7 +1154,7 @@
     public void testAbortPhraseRecognition() throws Exception {
         // Make sure the HAL doesn't support concurrent capture.
         initService(false);
-        mService.setExternalCaptureState(false);
+        mService.setCaptureState(false);
 
         ISoundTriggerCallback callback = createCallbackMock();
         ISoundTriggerModule module = mService.attach(0, callback);
@@ -1168,7 +1168,7 @@
         startRecognition(module, handle, hwHandle);
 
         // Abort.
-        mService.setExternalCaptureState(true);
+        mService.setCaptureState(true);
 
         ArgumentCaptor<PhraseRecognitionEvent> eventCaptor = ArgumentCaptor.forClass(
                 PhraseRecognitionEvent.class);
@@ -1190,7 +1190,7 @@
         verifyNotStartRecognition();
 
         // Now enable it and make sure we are notified.
-        mService.setExternalCaptureState(false);
+        mService.setCaptureState(false);
         verify(callback).onRecognitionAvailabilityChange(true);
 
         // Unload the model.
@@ -1216,7 +1216,7 @@
         startRecognition(module, handle, hwHandle);
 
         // Signal concurrent capture. Shouldn't abort.
-        mService.setExternalCaptureState(true);
+        mService.setCaptureState(true);
         verify(callback, never()).onRecognition(anyInt(), any());
         verify(callback, never()).onRecognitionAvailabilityChange(anyBoolean());
 
@@ -1252,7 +1252,7 @@
         startRecognition(module, handle, hwHandle);
 
         // Signal concurrent capture. Shouldn't abort.
-        mService.setExternalCaptureState(true);
+        mService.setCaptureState(true);
         verify(callback, never()).onPhraseRecognition(anyInt(), any());
         verify(callback, never()).onRecognitionAvailabilityChange(anyBoolean());
 
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index eef9012..10981ab 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.systemconfig;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
@@ -164,7 +166,7 @@
 
         mSysConfig.readPermissions(folder, /* No permission needed anyway */ 0);
 
-        final ArrayMap<String, Boolean>  packageOneExpected = new ArrayMap<>();
+        final ArrayMap<String, Boolean> packageOneExpected = new ArrayMap<>();
         packageOneExpected.put("com.android.package1.Full", true);
         packageOneExpected.put("com.android.package1.Relative", false);
 
@@ -181,7 +183,47 @@
     }
 
     /**
+     * Tests that readPermissions works correctly with {@link SystemConfig#ALLOW_APP_CONFIGS}
+     * permission flag for the tag: whitelisted-staged-installer.
+     */
+    @Test
+    public void readPermissions_allowAppConfigs_parsesStagedInstallerWhitelist()
+            throws IOException {
+        final String contents =
+                "<config>\n"
+                + "    <whitelisted-staged-installer package=\"com.android.package1\" />\n"
+                + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "staged-installer-whitelist.xml", contents);
+
+        mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(mSysConfig.getWhitelistedStagedInstallers())
+                .containsExactly("com.android.package1");
+    }
+
+    /**
+     * Tests that readPermissions works correctly without {@link SystemConfig#ALLOW_APP_CONFIGS}
+     * permission flag for the tag: whitelisted-staged-installer.
+     */
+    @Test
+    public void readPermissions_notAllowAppConfigs_wontParseStagedInstallerWhitelist()
+            throws IOException {
+        final String contents =
+                "<config>\n"
+                + "    <whitelisted-staged-installer package=\"com.android.package1\" />\n"
+                + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "staged-installer-whitelist.xml", contents);
+
+        mSysConfig.readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
+
+        assertThat(mSysConfig.getWhitelistedStagedInstallers()).isEmpty();
+    }
+
+    /**
      * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
+     *
      * @param folderName subdirectory of mTemporaryFolder to put the file, creating if needed
      * @return the folder
      */
@@ -194,7 +236,8 @@
 
     /**
      * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
-     * @param folder pre-existing subdirectory of mTemporaryFolder to put the file
+     *
+     * @param folder   pre-existing subdirectory of mTemporaryFolder to put the file
      * @param fileName name of the file (e.g. filename.xml) to create
      * @param contents contents to write to the file
      * @return the folder containing the newly created file (not the file itself!)
diff --git a/services/tests/servicestests/src/com/android/server/om/MockitoUtils.kt b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
similarity index 74%
rename from services/tests/servicestests/src/com/android/server/om/MockitoUtils.kt
rename to services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
index 0f915db..056fa88 100644
--- a/services/tests/servicestests/src/com/android/server/om/MockitoUtils.kt
+++ b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open 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,7 @@
  * limitations under the License.
  */
 
-package com.android.server.om
+package com.android.server.testutils
 
 import org.mockito.Answers
 import org.mockito.Mockito
@@ -31,6 +31,13 @@
             else -> {
                 val arguments = it.arguments
                         ?.takeUnless { it.isEmpty() }
+                        ?.mapIndexed { index, arg ->
+                            try {
+                                arg?.toString()
+                            } catch (e: Exception) {
+                                "toString[$index] threw ${e.message}"
+                            }
+                        }
                         ?.joinToString()
                         ?.let {
                             "with $it"
@@ -46,6 +53,8 @@
 
 inline fun <reified T> mock(block: T.() -> Unit = {}) = Mockito.mock(T::class.java).apply(block)
 
+fun <T> spy(value: T, block: T.() -> Unit = {}) = Mockito.spy(value).apply(block)
+
 fun <Type> Stubber.whenever(mock: Type) = Mockito.`when`(mock)
 fun <Type : Any?> whenever(mock: Type) = Mockito.`when`(mock)
 
@@ -55,7 +64,7 @@
 
 fun whenever(mock: Unit) = Mockito.`when`(mock).thenAnswer { }
 
-inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit): T {
+inline fun <reified T> spyThrowOnUnmocked(value: T?, block: T.() -> Unit): T {
     val swappingAnswer = object : Answer<Any?> {
         var delegate: Answer<*> = Answers.RETURNS_DEFAULTS
 
@@ -64,9 +73,12 @@
         }
     }
 
-    return Mockito.mock(T::class.java, swappingAnswer).apply(block)
+    return Mockito.mock(T::class.java, Mockito.withSettings().spiedInstance(value)
+            .defaultAnswer(swappingAnswer)).apply(block)
             .also {
                 // To allow when() usage inside block, only swap to throwing afterwards
                 swappingAnswer.delegate = MockitoUtils.ANSWER_THROWS
             }
 }
+
+inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit) = spyThrowOnUnmocked<T>(null, block)
diff --git a/services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java b/services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
index 69db384..355e7f3 100644
--- a/services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
+++ b/services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
@@ -139,7 +139,7 @@
         }
     }
 
-    private class MsgInfo implements Comparable<MsgInfo> {
+    public class MsgInfo implements Comparable<MsgInfo> {
         public final Message message;
         public final long sendTime;
         public final RuntimeException postPoint;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java
index 47ad831..a23ade6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelExtractorTest.java
@@ -18,7 +18,6 @@
 
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.util.FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
@@ -77,8 +76,8 @@
 
     @Test
     public void testInvalidShortcutFlagEnabled_looksUpCorrectChannel() {
-        Settings.Global.putString(
-                mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0);
 
         NotificationChannelExtractor extractor = new NotificationChannelExtractor();
         extractor.setConfig(mConfig);
@@ -97,7 +96,8 @@
         NotificationChannel updatedChannel =
                 new NotificationChannel("a", "", IMPORTANCE_HIGH);
         when(mConfig.getConversationNotificationChannel(
-                any(), anyInt(), eq("a"), eq(r.getSbn().getShortcutId(mContext)), eq(true), eq(false)))
+                any(), anyInt(), eq("a"), eq(r.getSbn().getShortcutId(mContext)),
+                eq(true), eq(false)))
                 .thenReturn(updatedChannel);
 
         assertNull(extractor.process(r));
@@ -106,8 +106,8 @@
 
     @Test
     public void testInvalidShortcutFlagDisabled_looksUpCorrectChannel() {
-        Settings.Global.putString(
-                mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 1);
 
         NotificationChannelExtractor extractor = new NotificationChannelExtractor();
         extractor.setConfig(mConfig);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
index 3991d8d..80b474f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
@@ -146,7 +146,29 @@
         assertThat(mDataBase.mHistoryFiles).containsExactlyElementsIn(expectedFiles);
 
         verify(mAlarmManager, times(6)).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+    }
 
+    @Test
+    public void testPrune_badFileName() {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.setTimeInMillis(10);
+        int retainDays = 1;
+
+        List<AtomicFile> expectedFiles = new ArrayList<>();
+
+        // add 5 files with a creation date of "today", but the file names are bad
+        for (long i = cal.getTimeInMillis(); i >= 5; i--) {
+            File file = mock(File.class);
+            when(file.getName()).thenReturn(i + ".txt");
+            AtomicFile af = new AtomicFile(file);
+            mDataBase.mHistoryFiles.addLast(af);
+        }
+
+        // trim everything a day+ old
+        cal.add(Calendar.DATE, 1 * retainDays);
+        mDataBase.prune(retainDays, cal.getTimeInMillis());
+
+        assertThat(mDataBase.mHistoryFiles).containsExactlyElementsIn(expectedFiles);
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index f083f0e..15220e1 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4791,7 +4791,7 @@
         // enqueue toast -> no toasts enqueued
         ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
                 "Text", 2000, 0, null);
-        verify(mStatusBar).showToast(any(), any(), any(), any(), anyInt(), any());
+        verify(mStatusBar).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
     }
 
     @Test
@@ -6504,4 +6504,19 @@
         assertNull(conversations.get(0).getShortcutInfo());
         assertNull(conversations.get(1).getShortcutInfo());
     }
+
+    @Test
+    public void testShortcutHelperNull_doesntCrashEnqueue() throws RemoteException {
+        mService.setShortcutHelper(null);
+        NotificationRecord nr =
+                generateMessageBubbleNotifRecord(mTestNotificationChannel,
+                        "testShortcutHelperNull_doesntCrashEnqueue");
+        try {
+            mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+                    nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+            waitForIdle();
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 00b9273..3139bfa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -63,7 +63,6 @@
 import android.provider.Settings;
 import android.service.notification.Adjustment;
 import android.service.notification.StatusBarNotification;
-import android.util.FeatureFlagUtils;
 import android.widget.RemoteViews;
 
 import androidx.test.filters.SmallTest;
@@ -124,8 +123,8 @@
         when(mMockContext.getResources()).thenReturn(getContext().getResources());
         when(mMockContext.getPackageManager()).thenReturn(mPm);
         when(mMockContext.getContentResolver()).thenReturn(mContentResolver);
-        Settings.Global.putString(mContentResolver,
-                FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 1);
         ApplicationInfo appInfo = new ApplicationInfo();
         appInfo.targetSdkVersion = Build.VERSION_CODES.O;
         when(mMockContext.getApplicationInfo()).thenReturn(appInfo);
@@ -1138,8 +1137,8 @@
 
     @Test
     public void testIsConversation_bypassShortcutFlagEnabled() {
-        Settings.Global.putString(mContentResolver,
-                FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0);
         StatusBarNotification sbn = getMessagingStyleNotification();
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         record.setShortcutInfo(null);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index af60511..ed5ec6a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -22,7 +22,6 @@
 import static android.app.NotificationManager.IMPORTANCE_MAX;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-import static android.util.FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ;
 
 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
 
@@ -2922,9 +2921,10 @@
     }
 
     @Test
-    public void testPlaceholderConversationId_flagOn() throws Exception {
-        Settings.Global.putString(
-                mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
+    public void testPlaceholderConversationId_shortcutNotRequired() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 0);
+
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -2942,9 +2942,9 @@
     }
 
     @Test
-    public void testPlaceholderConversationId_flagOff() throws Exception {
-        Settings.Global.putString(
-                mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
+    public void testPlaceholderConversationId_shortcutRequired() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 1);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -2962,9 +2962,9 @@
     }
 
     @Test
-    public void testNormalConversationId_flagOff() throws Exception {
-        Settings.Global.putString(
-                mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
+    public void testNormalConversationId_shortcutRequired() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 1);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
 
         final String xml = "<ranking version=\"1\">\n"
@@ -2982,9 +2982,9 @@
     }
 
     @Test
-    public void testNoConversationId_flagOff() throws Exception {
-        Settings.Global.putString(
-                mContext.getContentResolver(), NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
+    public void testNoConversationId_shortcutRequired() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.REQUIRE_SHORTCUTS_FOR_CONVERSATIONS, 1);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mLogger);
 
         final String xml = "<ranking version=\"1\">\n"
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
index 551e186..5a527a2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
@@ -3,8 +3,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 
+import android.app.Application;
 import android.content.Intent;
 import android.net.Uri;
 import android.service.notification.Condition;
@@ -45,7 +47,7 @@
                 null,               // ActivityThread not actually used in Service
                 ScheduleConditionProvider.class.getName(),
                 null,               // token not needed when not talking with the activity manager
-                null,
+                mock(Application.class),
                 null                // mocked services don't talk with the activity manager
                 );
         service.onCreate();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 05604b2..1debd8c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -61,19 +61,20 @@
     @Test
     public void testLastFocusedStackIsUpdatedWhenMovingStack() {
         // Create a stack at bottom.
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
+        final TaskDisplayArea taskDisplayAreas =
+                mRootWindowContainer.getDefaultDisplay().getDefaultTaskDisplayArea();
         final ActivityStack stack =
                 new StackBuilder(mRootWindowContainer).setOnTop(!ON_TOP).build();
-        final ActivityStack prevFocusedStack = display.getFocusedStack();
+        final ActivityStack prevFocusedStack = taskDisplayAreas.getFocusedStack();
 
         stack.moveToFront("moveStackToFront");
         // After moving the stack to front, the previous focused should be the last focused.
         assertTrue(stack.isFocusedStackOnDisplay());
-        assertEquals(prevFocusedStack, display.mTaskContainers.getLastFocusedStack());
+        assertEquals(prevFocusedStack, taskDisplayAreas.getLastFocusedStack());
 
         stack.moveToBack("moveStackToBack", null /* task */);
         // After moving the stack to back, the stack should be the last focused.
-        assertEquals(stack, display.mTaskContainers.getLastFocusedStack());
+        assertEquals(stack, taskDisplayAreas.getLastFocusedStack());
     }
 
     /**
@@ -83,8 +84,8 @@
     @Test
     public void testFullscreenStackCanBeFocusedWhenFocusablePinnedStackExists() {
         // Create a pinned stack and move to front.
-        final ActivityStack pinnedStack = mRootWindowContainer.getDefaultDisplay().createStack(
-                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
+        final ActivityStack pinnedStack = mRootWindowContainer.getDefaultTaskDisplayArea()
+                .createStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
         final Task pinnedTask = new TaskBuilder(mService.mStackSupervisor)
                 .setStack(pinnedStack).build();
         new ActivityBuilder(mService).setActivityFlags(FLAG_ALWAYS_FOCUSABLE)
@@ -104,8 +105,8 @@
     }
 
     /**
-     * Test {@link DisplayContent#mPreferredTopFocusableStack} will be cleared when the stack is
-     * removed or moved to back, and the focused stack will be according to z-order.
+     * Test {@link TaskDisplayArea#mPreferredTopFocusableStack} will be cleared when
+     * the stack is removed or moved to back, and the focused stack will be according to z-order.
      */
     @Test
     public void testStackShouldNotBeFocusedAfterMovingToBackOrRemoving() {
@@ -124,7 +125,7 @@
         assertTrue(stack1.isFocusedStackOnDisplay());
 
         // Stack2 should be focused after removing stack1.
-        display.removeStack(stack1);
+        stack1.getDisplayArea().removeStack(stack1);
         assertTrue(stack2.isFocusedStackOnDisplay());
     }
 
@@ -156,7 +157,7 @@
     }
 
     private ActivityStack createFullscreenStackWithSimpleActivityAt(DisplayContent display) {
-        final ActivityStack fullscreenStack = display.createStack(
+        final ActivityStack fullscreenStack = display.getDefaultTaskDisplayArea().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP);
         final Task fullscreenTask = new TaskBuilder(mService.mStackSupervisor)
                 .setStack(fullscreenStack).build();
@@ -219,58 +220,56 @@
      */
     @Test
     public void testAlwaysOnTopStackLocation() {
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final ActivityStack alwaysOnTopStack = display.createStack(WINDOWING_MODE_FREEFORM,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final ActivityStack alwaysOnTopStack = taskDisplayArea.createStack(WINDOWING_MODE_FREEFORM,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(alwaysOnTopStack).build();
         alwaysOnTopStack.setAlwaysOnTop(true);
-        display.mTaskContainers.positionStackAtTop(alwaysOnTopStack, false /* includingParents */);
+        taskDisplayArea.positionStackAtTop(alwaysOnTopStack, false /* includingParents */);
         assertTrue(alwaysOnTopStack.isAlwaysOnTop());
         // Ensure always on top state is synced to the children of the stack.
         assertTrue(alwaysOnTopStack.getTopNonFinishingActivity().isAlwaysOnTop());
-        assertEquals(alwaysOnTopStack, display.getTopStack());
+        assertEquals(alwaysOnTopStack, taskDisplayArea.getTopStack());
 
-        final ActivityStack pinnedStack = display.createStack(
+        final ActivityStack pinnedStack = taskDisplayArea.createStack(
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        assertEquals(pinnedStack, display.getRootPinnedTask());
-        assertEquals(pinnedStack, display.getTopStack());
+        assertEquals(pinnedStack, taskDisplayArea.getRootPinnedTask());
+        assertEquals(pinnedStack, taskDisplayArea.getTopStack());
 
-        final ActivityStack anotherAlwaysOnTopStack = display.createStack(
+        final ActivityStack anotherAlwaysOnTopStack = taskDisplayArea.createStack(
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
-        display.mTaskContainers.positionStackAtTop(anotherAlwaysOnTopStack,
-                false /* includingParents */);
+        taskDisplayArea.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        int topPosition = display.getStackCount() - 1;
+        int topPosition = taskDisplayArea.getStackCount() - 1;
         // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
         // existing alwaysOnTop stack.
-        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 1));
+        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getStackAt(topPosition - 1));
 
-        final ActivityStack nonAlwaysOnTopStack = display.createStack(
+        final ActivityStack nonAlwaysOnTopStack = taskDisplayArea.createStack(
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        assertEquals(display, nonAlwaysOnTopStack.getDisplay());
-        topPosition = display.getStackCount() - 1;
+        assertEquals(taskDisplayArea, nonAlwaysOnTopStack.getDisplayArea());
+        topPosition = taskDisplayArea.getStackCount() - 1;
         // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
         // existing other non-alwaysOnTop stacks.
-        assertEquals(nonAlwaysOnTopStack, display.getStackAt(topPosition - 3));
+        assertEquals(nonAlwaysOnTopStack, taskDisplayArea.getStackAt(topPosition - 3));
 
         anotherAlwaysOnTopStack.setAlwaysOnTop(false);
-        display.mTaskContainers.positionStackAtTop(anotherAlwaysOnTopStack,
-                false /* includingParents */);
+        taskDisplayArea.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
-        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 2));
+        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getStackAt(topPosition - 2));
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
 
         // Ensure always on top state changes properly when windowing mode changes.
         anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 2));
+        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getStackAt(topPosition - 2));
         anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 1));
+        assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getStackAt(topPosition - 1));
     }
 
     @Test
@@ -286,14 +285,14 @@
     }
 
     private void removeStackTests(Runnable runnable) {
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final ActivityStack stack1 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final ActivityStack stack1 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, ON_TOP);
-        final ActivityStack stack2 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final ActivityStack stack2 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, ON_TOP);
-        final ActivityStack stack3 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final ActivityStack stack3 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, ON_TOP);
-        final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final ActivityStack stack4 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, ON_TOP);
         final Task task1 = new TaskBuilder(mService.mStackSupervisor).setStack(stack1).build();
         final Task task2 = new TaskBuilder(mService.mStackSupervisor).setStack(stack2).build();
@@ -302,13 +301,13 @@
 
         // Reordering stacks while removing stacks.
         doAnswer(invocation -> {
-            display.mTaskContainers.positionStackAtTop(stack3, false);
+            taskDisplayArea.positionStackAtTop(stack3, false);
             return true;
         }).when(mSupervisor).removeTask(eq(task4), anyBoolean(), anyBoolean(), any());
 
         // Removing stacks from the display while removing stacks.
         doAnswer(invocation -> {
-            display.removeStack(stack2);
+            taskDisplayArea.removeStack(stack2);
             return true;
         }).when(mSupervisor).removeTask(eq(task2), anyBoolean(), anyBoolean(), any());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 747ae94..08f6409 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -82,6 +82,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.MergedConfiguration;
 import android.util.MutableBoolean;
+import android.view.DisplayInfo;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner.Stub;
 import android.view.RemoteAnimationAdapter;
@@ -399,6 +400,16 @@
         mStack.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
         final Rect stableRect = new Rect();
         mStack.getDisplay().mDisplayContent.getStableRect(stableRect);
+
+        // Carve out non-decor insets from stableRect
+        final Rect insets = new Rect();
+        final DisplayInfo displayInfo = mStack.getDisplay().getDisplayInfo();
+        final DisplayPolicy policy = mStack.getDisplay().getDisplayPolicy();
+        policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
+                displayInfo.logicalHeight, displayInfo.displayCutout, insets);
+        policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation);
+        Task.intersectWithInsetsIfFits(stableRect, stableRect, insets);
+
         final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
         final Rect bounds = new Rect(stableRect);
         if (isScreenPortrait) {
@@ -427,7 +438,17 @@
     public void ignoreRequestedOrientationInSplitWindows() {
         mStack.setWindowingMode(WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         final Rect stableRect = new Rect();
-        mStack.getDisplay().mDisplayContent.getStableRect(stableRect);
+        mStack.getDisplay().getStableRect(stableRect);
+
+        // Carve out non-decor insets from stableRect
+        final Rect insets = new Rect();
+        final DisplayInfo displayInfo = mStack.getDisplay().getDisplayInfo();
+        final DisplayPolicy policy = mStack.getDisplay().getDisplayPolicy();
+        policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
+                displayInfo.logicalHeight, displayInfo.displayCutout, insets);
+        policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation);
+        Task.intersectWithInsetsIfFits(stableRect, stableRect, insets);
+
         final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
         final Rect bounds = new Rect(stableRect);
         if (isScreenPortrait) {
@@ -1379,8 +1400,8 @@
             display = new TestDisplayContent.Builder(mService, 2000, 1000).setDensityDpi(300)
                     .setPosition(DisplayContent.POSITION_TOP).build();
         }
-        final ActivityStack stack = display.createStack(WINDOWING_MODE_UNDEFINED,
-                ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack stack = display.getDefaultTaskDisplayArea()
+                .createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
         return new ActivityBuilder(mService).setTask(task).setUseProcess(process).build();
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index e8c0362..22d7fcb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -60,7 +60,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mFullscreenStack = mRootWindowContainer.getDefaultDisplay().createStack(
+        mFullscreenStack = mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index af5afff..3d15401 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -82,15 +82,15 @@
 @Presubmit
 @RunWith(WindowTestRunner.class)
 public class ActivityStackTests extends ActivityTestsBase {
-    private DisplayContent mDefaultDisplay;
+    private TaskDisplayArea mDefaultTaskDisplayArea;
     private ActivityStack mStack;
     private Task mTask;
 
     @Before
     public void setUp() throws Exception {
-        mDefaultDisplay = mRootWindowContainer.getDefaultDisplay();
-        mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
-                true /* onTop */);
+        mDefaultTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        mStack = mDefaultTaskDisplayArea.createStack(WINDOWING_MODE_UNDEFINED,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
         spyOn(mStack);
         mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
     }
@@ -112,7 +112,7 @@
         r.setState(RESUMED, "testResumedActivityFromTaskReparenting");
         assertEquals(r, mStack.getResumedActivity());
 
-        final ActivityStack destStack = mRootWindowContainer.getDefaultDisplay().createStack(
+        final ActivityStack destStack = mDefaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         mTask.reparent(destStack, true /* toTop */, Task.REPARENT_KEEP_STACK_AT_FRONT,
@@ -130,7 +130,7 @@
         r.setState(RESUMED, "testResumedActivityFromActivityReparenting");
         assertEquals(r, mStack.getResumedActivity());
 
-        final ActivityStack destStack = mRootWindowContainer.getDefaultDisplay().createStack(
+        final ActivityStack destStack = mDefaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         mTask.reparent(destStack, true /*toTop*/, REPARENT_MOVE_STACK_TO_FRONT, false, false,
                 "testResumedActivityFromActivityReparenting");
@@ -143,7 +143,7 @@
     public void testPrimarySplitScreenRestoresWhenMovedToBack() {
         // Create primary splitscreen stack. This will create secondary stacks and places the
         // existing fullscreen stack on the bottom.
-        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+        final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Assert windowing mode.
@@ -154,7 +154,7 @@
                 null /* task */);
 
         // Assert that stack is at the bottom.
-        assertEquals(0, mDefaultDisplay.getIndexOf(primarySplitScreen));
+        assertEquals(0, mDefaultTaskDisplayArea.getIndexOf(primarySplitScreen));
 
         // Ensure no longer in splitscreen.
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
@@ -167,7 +167,7 @@
     @Test
     public void testPrimarySplitScreenRestoresPreviousWhenMovedToBack() {
         // This time, start with a fullscreen activitystack
-        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+        final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         primarySplitScreen.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -180,7 +180,7 @@
                 null /* task */);
 
         // Assert that stack is at the bottom.
-        assertEquals(0, mDefaultDisplay.getIndexOf(primarySplitScreen));
+        assertEquals(0, mDefaultTaskDisplayArea.getIndexOf(primarySplitScreen));
 
         // Ensure that the override mode is restored to what it was (fullscreen)
         assertEquals(WINDOWING_MODE_FULLSCREEN,
@@ -189,14 +189,14 @@
 
     @Test
     public void testStackInheritsDisplayWindowingMode() {
-        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+        final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
         assertEquals(WINDOWING_MODE_UNDEFINED,
                 primarySplitScreen.getRequestedOverrideWindowingMode());
 
-        mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        mDefaultTaskDisplayArea.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(WINDOWING_MODE_FREEFORM, primarySplitScreen.getWindowingMode());
         assertEquals(WINDOWING_MODE_UNDEFINED,
                 primarySplitScreen.getRequestedOverrideWindowingMode());
@@ -204,7 +204,7 @@
 
     @Test
     public void testStackOverridesDisplayWindowingMode() {
-        final ActivityStack primarySplitScreen = mDefaultDisplay.createStack(
+        final ActivityStack primarySplitScreen = mDefaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
@@ -216,7 +216,7 @@
         assertEquals(WINDOWING_MODE_FULLSCREEN,
                 primarySplitScreen.getRequestedOverrideWindowingMode());
 
-        mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        mDefaultTaskDisplayArea.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
     }
 
@@ -283,10 +283,11 @@
 
     @Test
     public void testMoveStackToBackIncludingParent() {
-        final DisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
-        final ActivityStack stack1 = createStackForShouldBeVisibleTest(display,
+        final TaskDisplayArea taskDisplayArea = addNewDisplayContentAt(DisplayContent.POSITION_TOP)
+                .getDefaultTaskDisplayArea();
+        final ActivityStack stack1 = createStackForShouldBeVisibleTest(taskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final ActivityStack stack2 = createStackForShouldBeVisibleTest(display,
+        final ActivityStack stack2 = createStackForShouldBeVisibleTest(taskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Do not move display to back because there is still another stack.
@@ -294,16 +295,16 @@
         verify(stack2).positionChildAtBottom(any(), eq(false) /* includingParents */);
 
         // Also move display to back because there is only one stack left.
-        display.removeStack(stack1);
+        taskDisplayArea.removeStack(stack1);
         stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.getTopMostTask());
         verify(stack2).positionChildAtBottom(any(), eq(true) /* includingParents */);
     }
 
     @Test
     public void testShouldBeVisible_Fullscreen() {
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         // Add an activity to the pinned stack so it isn't considered empty for visibility check.
         final ActivityRecord pinnedActivity = new ActivityBuilder(mService)
@@ -314,8 +315,9 @@
         assertTrue(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(pinnedStack.shouldBeVisible(null /* starting */));
 
-        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                true /* onTop */);
         // Home stack shouldn't be visible behind an opaque fullscreen stack, but pinned stack
         // should be visible since it is always on-top.
         doReturn(false).when(fullscreenStack).isTranslucent(any());
@@ -331,15 +333,15 @@
 
     @Test
     public void testShouldBeVisible_SplitScreen() {
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         // Home stack should always be fullscreen for this test.
         doReturn(false).when(homeStack).supportsSplitScreenWindowingMode();
         final ActivityStack splitScreenPrimary =
-                createStackForShouldBeVisibleTest(mDefaultDisplay,
+                createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityStack splitScreenSecondary =
-                createStackForShouldBeVisibleTest(mDefaultDisplay,
+                createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Home stack shouldn't be visible if both halves of split-screen are opaque.
@@ -367,7 +369,7 @@
                 splitScreenSecondary.getVisibility(null /* starting */));
 
         final ActivityStack splitScreenSecondary2 =
-                createStackForShouldBeVisibleTest(mDefaultDisplay,
+                createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         // First split-screen secondary shouldn't be visible behind another opaque split-split
         // secondary.
@@ -389,8 +391,9 @@
         assertEquals(STACK_VISIBILITY_VISIBLE,
                 splitScreenSecondary2.getVisibility(null /* starting */));
 
-        final ActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
+        final ActivityStack assistantStack = createStackForShouldBeVisibleTest(
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT,
+                true /* onTop */);
 
         // Split-screen stacks shouldn't be visible behind an opaque fullscreen stack.
         doReturn(false).when(assistantStack).isTranslucent(any());
@@ -530,7 +533,7 @@
         final ActivityStack translucentStack =
                 createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
                         true /* translucent */);
-        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
@@ -547,7 +550,7 @@
 
     @Test
     public void testShouldBeVisible_Finishing() {
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         ActivityRecord topRunningHomeActivity = homeStack.topRunningActivity();
         if (topRunningHomeActivity == null) {
@@ -558,7 +561,7 @@
         }
 
         final ActivityStack translucentStack = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         doReturn(true).when(translucentStack).isTranslucent(any());
 
@@ -580,7 +583,7 @@
 
     @Test
     public void testShouldBeVisible_FullscreenBehindTranslucentInHomeStack() {
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
         final ActivityRecord firstActivity = new ActivityBuilder(mService)
@@ -601,74 +604,77 @@
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                true /* onTop */);
 
         doReturn(false).when(homeStack).isTranslucent(any());
         doReturn(false).when(fullscreenStack).isTranslucent(any());
 
         // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
-        int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
         assertEquals(fullscreenStack, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
-        assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
+        mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
     }
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindTranslucent() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
+                mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         doReturn(false).when(homeStack).isTranslucent(any());
         doReturn(true).when(fullscreenStack).isTranslucent(any());
 
         // Ensure that we don't move the home stack if it is already behind the top fullscreen stack
-        int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
         assertEquals(fullscreenStack, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
-        assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
+        mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
     }
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeOnTop() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
-        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack fullscreenStack = createStackForShouldBeVisibleTest(
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                true /* onTop */);
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
         doReturn(false).when(homeStack).isTranslucent(any());
         doReturn(false).when(fullscreenStack).isTranslucent(any());
 
         // Ensure we don't move the home stack if it is already on top
-        int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
+        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
         assertNull(getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
-        assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
+        mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
     }
 
     @Test
     public void testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreen() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         doReturn(false).when(homeStack).isTranslucent(any());
@@ -678,22 +684,22 @@
         // Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the
         // pinned stack
         assertEquals(fullscreenStack1, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
+        mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
         assertEquals(fullscreenStack2, getStackAbove(homeStack));
     }
 
     @Test
     public void
             testMoveHomeStackBehindBottomMostVisibleStack_MoveHomeBehindFullscreenAndTranslucent() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
 
         doReturn(false).when(homeStack).isTranslucent(any());
@@ -703,21 +709,21 @@
         // Ensure that we move the home stack behind the bottom most non-translucent fullscreen
         // stack
         assertEquals(fullscreenStack1, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
+        mDefaultTaskDisplayArea.moveStackBehindBottomMostVisibleStack(homeStack);
         assertEquals(fullscreenStack1, getStackAbove(homeStack));
     }
 
     @Test
     public void testMoveHomeStackBehindStack_BehindHomeStack() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
         final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
         doReturn(false).when(homeStack).isTranslucent(any());
@@ -725,50 +731,50 @@
         doReturn(false).when(fullscreenStack2).isTranslucent(any());
 
         // Ensure we don't move the home stack behind itself
-        int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
-        mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, homeStack);
-        assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
+        int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+        mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, homeStack);
+        assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
     }
 
     @Test
     public void testMoveHomeStackBehindStack() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
         final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack fullscreenStack3 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         final ActivityStack fullscreenStack4 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
-        mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack1);
+        mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack1);
         assertEquals(fullscreenStack1, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack2);
+        mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack2);
         assertEquals(fullscreenStack2, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack4);
+        mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack4);
         assertEquals(fullscreenStack4, getStackAbove(homeStack));
-        mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack2);
+        mDefaultTaskDisplayArea.moveStackBehindStack(homeStack, fullscreenStack2);
         assertEquals(fullscreenStack2, getStackAbove(homeStack));
     }
 
     @Test
     public void testSetAlwaysOnTop() {
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
-        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         assertEquals(pinnedStack, getStackAbove(homeStack));
 
         final ActivityStack alwaysOnTopStack = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         alwaysOnTopStack.setAlwaysOnTop(true);
         assertTrue(alwaysOnTopStack.isAlwaysOnTop());
@@ -776,13 +782,13 @@
         assertEquals(pinnedStack, getStackAbove(alwaysOnTopStack));
 
         final ActivityStack nonAlwaysOnTopStack = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         // Ensure non always on top stack is put below always on top stacks.
         assertEquals(alwaysOnTopStack, getStackAbove(nonAlwaysOnTopStack));
 
         final ActivityStack alwaysOnTopStack2 = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         alwaysOnTopStack2.setAlwaysOnTop(true);
         assertTrue(alwaysOnTopStack2.isAlwaysOnTop());
@@ -807,13 +813,14 @@
     @Test
     public void testSplitScreenMoveToFront() {
         final ActivityStack splitScreenPrimary = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
-                true /* onTop */);
+                mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityStack splitScreenSecondary = createStackForShouldBeVisibleTest(
-                mDefaultDisplay, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
+                mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack assistantStack = createStackForShouldBeVisibleTest(
+                mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT,
                 true /* onTop */);
-        final ActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
 
         doReturn(false).when(splitScreenPrimary).isTranslucent(any());
         doReturn(false).when(splitScreenSecondary).isTranslucent(any());
@@ -832,7 +839,7 @@
 
     private ActivityStack createStandardStackForVisibilityTest(int windowingMode,
             boolean translucent) {
-        final ActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack stack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         doReturn(translucent).when(stack).isTranslucent(any());
         return stack;
@@ -840,20 +847,20 @@
 
     @SuppressWarnings("TypeParameterUnusedInFormals")
     private ActivityStack createStackForShouldBeVisibleTest(
-            DisplayContent display, int windowingMode, int activityType, boolean onTop) {
+            TaskDisplayArea taskDisplayArea, int windowingMode, int activityType, boolean onTop) {
         final ActivityStack stack;
         if (activityType == ACTIVITY_TYPE_HOME) {
             // Home stack and activity are created in ActivityTestsBase#setupActivityManagerService
-            stack = mDefaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
+            stack = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
             if (onTop) {
-                mDefaultDisplay.mTaskContainers.positionStackAtTop(stack,
+                mDefaultTaskDisplayArea.positionStackAtTop(stack,
                         false /* includingParents */);
             } else {
-                mDefaultDisplay.mTaskContainers.positionStackAtBottom(stack);
+                mDefaultTaskDisplayArea.positionStackAtBottom(stack);
             }
         } else {
             stack = new StackBuilder(mRootWindowContainer)
-                    .setDisplay(display)
+                    .setTaskDisplayArea(taskDisplayArea)
                     .setWindowingMode(windowingMode)
                     .setActivityType(activityType)
                     .setOnTop(onTop)
@@ -1005,7 +1012,7 @@
 
     @Test
     public void testWontFinishHomeStackImmediately() {
-        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultTaskDisplayArea,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
 
         ActivityRecord activity = homeStack.topRunningActivity();
@@ -1025,9 +1032,11 @@
     public void testFinishCurrentActivity() {
         // Create 2 activities on a new display.
         final DisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
-        final ActivityStack stack1 = createStackForShouldBeVisibleTest(display,
+        final ActivityStack stack1 = createStackForShouldBeVisibleTest(
+                display.getDefaultTaskDisplayArea(),
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final ActivityStack stack2 = createStackForShouldBeVisibleTest(display,
+        final ActivityStack stack2 = createStackForShouldBeVisibleTest(
+                display.getDefaultTaskDisplayArea(),
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // There is still an activity1 in stack1 so the activity2 should be added to finishing list
@@ -1075,26 +1084,26 @@
     @Test
     public void testStackOrderChangedOnRemoveStack() {
         StackOrderChangedListener listener = new StackOrderChangedListener();
-        mDefaultDisplay.registerStackOrderChangedListener(listener);
+        mDefaultTaskDisplayArea.registerStackOrderChangedListener(listener);
         try {
-            mDefaultDisplay.removeStack(mStack);
+            mDefaultTaskDisplayArea.removeStack(mStack);
         } finally {
-            mDefaultDisplay.unregisterStackOrderChangedListener(listener);
+            mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(listener);
         }
         assertTrue(listener.mChanged);
     }
 
     @Test
     public void testStackOrderChangedOnAddPositionStack() {
-        mDefaultDisplay.removeStack(mStack);
+        mDefaultTaskDisplayArea.removeStack(mStack);
 
         StackOrderChangedListener listener = new StackOrderChangedListener();
-        mDefaultDisplay.registerStackOrderChangedListener(listener);
+        mDefaultTaskDisplayArea.registerStackOrderChangedListener(listener);
         try {
             mStack.mReparenting = true;
-            mDefaultDisplay.mTaskContainers.addStack(mStack, 0);
+            mDefaultTaskDisplayArea.addStack(mStack, 0);
         } finally {
-            mDefaultDisplay.unregisterStackOrderChangedListener(listener);
+            mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(listener);
         }
         assertTrue(listener.mChanged);
     }
@@ -1104,12 +1113,12 @@
         StackOrderChangedListener listener = new StackOrderChangedListener();
         try {
             final ActivityStack fullscreenStack1 = createStackForShouldBeVisibleTest(
-                    mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                    mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                     true /* onTop */);
-            mDefaultDisplay.registerStackOrderChangedListener(listener);
-            mDefaultDisplay.mTaskContainers.positionStackAtBottom(fullscreenStack1);
+            mDefaultTaskDisplayArea.registerStackOrderChangedListener(listener);
+            mDefaultTaskDisplayArea.positionStackAtBottom(fullscreenStack1);
         } finally {
-            mDefaultDisplay.unregisterStackOrderChangedListener(listener);
+            mDefaultTaskDisplayArea.unregisterStackOrderChangedListener(listener);
         }
         assertTrue(listener.mChanged);
     }
@@ -1189,7 +1198,7 @@
     @Test
     public void testClearUnknownAppVisibilityBehindFullscreenActivity() {
         final UnknownAppVisibilityController unknownAppVisibilityController =
-                mDefaultDisplay.mDisplayContent.mUnknownAppVisibilityController;
+                mDefaultTaskDisplayArea.mDisplayContent.mUnknownAppVisibilityController;
         final KeyguardController keyguardController = mSupervisor.getKeyguardController();
         doReturn(true).when(keyguardController).isKeyguardLocked();
 
@@ -1254,7 +1263,7 @@
     }
 
     private static class StackOrderChangedListener
-            implements DisplayContent.OnStackOrderChangedListener {
+            implements TaskDisplayArea.OnStackOrderChangedListener {
         public boolean mChanged = false;
 
         @Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 76a761c..27782f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -77,8 +77,8 @@
                 .setCreateTask(true)
                 .build();
         final int startFlags = random.nextInt();
-        final ActivityStack stack = mService.mRootWindowContainer.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack stack = mService.mRootWindowContainer.getDefaultTaskDisplayArea()
+                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final WindowProcessController wpc = new WindowProcessController(mService,
                 mService.mContext.getApplicationInfo(), "name", 12345,
                 UserHandle.getUserId(12345), mock(Object.class),
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 1d952bf..bdba4b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -326,8 +326,9 @@
 
         if (mockGetLaunchStack) {
             // Instrument the stack and task used.
-            final ActivityStack stack = mRootWindowContainer.getDefaultDisplay().createStack(
-                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+            final ActivityStack stack = mRootWindowContainer.getDefaultTaskDisplayArea()
+                    .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                            true /* onTop */);
 
             // Direct starter to use spy stack.
             doReturn(stack).when(mRootWindowContainer)
@@ -494,9 +495,12 @@
     }
 
     private void assertNoTasks(DisplayContent display) {
-        for (int i = display.getStackCount() - 1; i >= 0; --i) {
-            final ActivityStack stack = display.getStackAt(i);
-            assertFalse(stack.hasChild());
+        for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
+            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                assertFalse(stack.hasChild());
+            }
         }
     }
 
@@ -742,7 +746,7 @@
         final TestDisplayContent secondaryDisplay =
                 new TestDisplayContent.Builder(mService, 1000, 1500)
                         .setPosition(POSITION_BOTTOM).build();
-        final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.mTaskContainers;
+        final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.getDefaultTaskDisplayArea();
         final ActivityStack stack = secondaryTaskContainer.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
@@ -783,7 +787,7 @@
                 new TestDisplayContent.Builder(mService, 1000, 1500).build();
         mRootWindowContainer.positionChildAt(POSITION_TOP, secondaryDisplay,
                 false /* includingParents */);
-        final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.mTaskContainers;
+        final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.getDefaultTaskDisplayArea();
         final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
                 secondaryTaskContainer.createStack(WINDOWING_MODE_FULLSCREEN,
                         ACTIVITY_TYPE_STANDARD, false /* onTop */));
@@ -835,7 +839,7 @@
 
         // Create a secondary display at bottom.
         final TestDisplayContent secondaryDisplay = addNewDisplayContentAt(POSITION_BOTTOM);
-        final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.mTaskContainers;
+        final TaskDisplayArea secondaryTaskContainer = secondaryDisplay.getDefaultTaskDisplayArea();
         secondaryTaskContainer.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
 
@@ -951,7 +955,7 @@
         final ActivityStarter starter = prepareStarter(0 /* flags */);
         starter.mStartActivity = new ActivityBuilder(mService).build();
         final Task task = new TaskBuilder(mService.mStackSupervisor)
-                .setStack(mService.mRootWindowContainer.getDefaultDisplay().createStack(
+                .setStack(mService.mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
                         WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */))
                 .setUserId(10)
                 .build();
@@ -1041,10 +1045,14 @@
                     // move everything to secondary because test expects this but usually sysui
                     // does it.
                     DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
-                    for (int i = dc.getStackCount() - 1; i >= 0; --i) {
-                        if (!WindowConfiguration.isSplitScreenWindowingMode(
-                                dc.getStackAt(i).getWindowingMode())) {
-                            dc.getStackAt(i).reparent(mSecondary, POSITION_BOTTOM);
+                    for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+                        final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+                        for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                            final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
+                            if (!WindowConfiguration.isSplitScreenWindowingMode(
+                                    stack.getWindowingMode())) {
+                                stack.reparent(mSecondary, POSITION_BOTTOM);
+                            }
                         }
                     }
                 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 9240b22..67d4769 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -372,7 +372,7 @@
 
         Task build() {
             if (mStack == null && mCreateStack) {
-                mStack = mSupervisor.mRootWindowContainer.getDefaultDisplay().createStack(
+                mStack = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
                         WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
                 spyOn(mStack);
             }
@@ -408,6 +408,7 @@
     static class StackBuilder {
         private final RootWindowContainer mRootWindowContainer;
         private DisplayContent mDisplay;
+        private TaskDisplayArea mTaskDisplayArea;
         private int mStackId = -1;
         private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
         private int mActivityType = ACTIVITY_TYPE_STANDARD;
@@ -419,6 +420,7 @@
         StackBuilder(RootWindowContainer root) {
             mRootWindowContainer = root;
             mDisplay = mRootWindowContainer.getDefaultDisplay();
+            mTaskDisplayArea = mDisplay.getDefaultTaskDisplayArea();
         }
 
         StackBuilder setWindowingMode(int windowingMode) {
@@ -436,8 +438,20 @@
             return this;
         }
 
+        /**
+         * Set the parent {@link DisplayContent} and use the default task display area. Overrides
+         * the task display area, if was set before.
+         */
         StackBuilder setDisplay(DisplayContent display) {
             mDisplay = display;
+            mTaskDisplayArea = mDisplay.getDefaultTaskDisplayArea();
+            return this;
+        }
+
+        /** Set the parent {@link TaskDisplayArea}. Overrides the display, if was set before. */
+        StackBuilder setTaskDisplayArea(TaskDisplayArea taskDisplayArea) {
+            mTaskDisplayArea = taskDisplayArea;
+            mDisplay = mTaskDisplayArea.mDisplayContent;
             return this;
         }
 
@@ -462,9 +476,8 @@
         }
 
         ActivityStack build() {
-            final int stackId = mStackId >= 0 ? mStackId
-                    : mDisplay.mTaskContainers.getNextStackId();
-            final ActivityStack stack = mDisplay.mTaskContainers.createStackUnchecked(
+            final int stackId = mStackId >= 0 ? mStackId : mTaskDisplayArea.getNextStackId();
+            final ActivityStack stack = mTaskDisplayArea.createStackUnchecked(
                     mWindowingMode, mActivityType, stackId, mOnTop, mInfo, mIntent,
                     false /* createdByOrganizer */);
             final ActivityStackSupervisor supervisor = mRootWindowContainer.mStackSupervisor;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 4cb50c7..9b7ffd6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -147,7 +147,7 @@
         // Reparenting to a display with different windowing mode may trigger
         // a change transition internally, but it should be cleaned-up once
         // the display change is complete.
-        mStack.reparent(mDisplayContent, true);
+        mStack.reparent(mDisplayContent.getDefaultTaskDisplayArea(), true);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, mTask.getWindowingMode());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 08e492a..8c8fd05 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -73,7 +73,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testKeyguardOverride() {
         mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
         mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
@@ -81,7 +80,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testKeyguardKeep() {
         mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
         mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
@@ -89,7 +87,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testForceOverride() {
         mWm.prepareAppTransition(TRANSIT_KEYGUARD_UNOCCLUDE, false /* alwaysKeepCurrent */);
         mDc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
@@ -105,7 +102,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testKeepKeyguard_withCrashing() {
         mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
         mWm.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
@@ -113,7 +109,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testAppTransitionStateForMultiDisplay() {
         // Create 2 displays & presume both display the state is ON for ready to display & animate.
         final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
@@ -174,7 +169,7 @@
         assertTrue(dc1.mOpeningApps.size() > 0);
 
         // Move stack to another display.
-        stack1.reparent(dc2, true);
+        stack1.reparent(dc2.getDefaultTaskDisplayArea(), true);
 
         // Verify if token are cleared from both pending transition list in former display.
         assertFalse(dc1.mOpeningApps.contains(activity1));
@@ -182,7 +177,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testLoadAnimationSafely() {
         DisplayContent dc = createNewDisplay(Display.STATE_ON);
         assertNull(dc.mAppTransition.loadAnimationSafely(
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 6e78a27..b93a8fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -67,7 +67,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void clipAfterAnim_boundsLayerIsCreated() {
         mActivity.mNeedsAnimationBoundsLayer = true;
 
@@ -91,7 +90,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void clipAfterAnim_boundsLayerIsDestroyed() {
         mActivity.mNeedsAnimationBoundsLayer = true;
         mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */,
@@ -126,7 +124,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void clipNoneAnim_boundsLayerIsNotCreated() {
         mActivity.mNeedsAnimationBoundsLayer = false;
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 9cfee34..a901d1e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -281,7 +281,7 @@
         assertEquals(dc, activity.getDisplayContent());
 
         // Move stack to first display.
-        mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
+        stack.reparent(mDisplayContent.getDefaultTaskDisplayArea(), true /* onTop */);
         assertEquals(mDisplayContent.getDisplayId(), stack.getDisplayContent().getDisplayId());
         assertEquals(mDisplayContent, stack.getDisplayContent());
         assertEquals(mDisplayContent, task.getDisplayContent());
@@ -753,7 +753,7 @@
         doReturn(true).when(freeformStack).isVisible();
         freeformStack.getTopChild().setBounds(100, 100, 300, 400);
 
-        assertTrue(dc.isStackVisible(WINDOWING_MODE_FREEFORM));
+        assertTrue(dc.getDefaultTaskDisplayArea().isStackVisible(WINDOWING_MODE_FREEFORM));
 
         freeformStack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
         stack.getTopNonFinishingActivity().setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -1039,6 +1039,13 @@
         assertEquals(config90.orientation, app.getConfiguration().orientation);
         assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
 
+        // Force the negative offset to verify it can be updated.
+        mWallpaperWindow.mWinAnimator.mXOffset = mWallpaperWindow.mWinAnimator.mYOffset = -1;
+        assertTrue(mDisplayContent.mWallpaperController.updateWallpaperOffset(mWallpaperWindow,
+                false /* sync */));
+        assertThat(mWallpaperWindow.mWinAnimator.mXOffset).isGreaterThan(-1);
+        assertThat(mWallpaperWindow.mWinAnimator.mYOffset).isGreaterThan(-1);
+
         mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
 
         // The animation in old rotation should be cancelled.
@@ -1089,8 +1096,7 @@
 
     @Test
     public void testGetOrCreateRootHomeTask_defaultDisplay() {
-        DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
-        TaskDisplayArea defaultTaskDisplayArea = defaultDisplay.mTaskContainers;
+        TaskDisplayArea defaultTaskDisplayArea = mWm.mRoot.getDefaultTaskDisplayArea();
 
         // Remove the current home stack if it exists so a new one can be created below.
         ActivityStack homeTask = defaultTaskDisplayArea.getRootHomeTask();
@@ -1109,7 +1115,7 @@
         doReturn(false).when(display).isUntrustedVirtualDisplay();
 
         // Remove the current home stack if it exists so a new one can be created below.
-        TaskDisplayArea taskDisplayArea = display.mTaskContainers;
+        TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
         ActivityStack homeTask = taskDisplayArea.getRootHomeTask();
         if (homeTask != null) {
             taskDisplayArea.removeChild(homeTask);
@@ -1122,7 +1128,7 @@
     @Test
     public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
         DisplayContent display = createNewDisplay();
-        TaskDisplayArea taskDisplayArea = display.mTaskContainers;
+        TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
         doReturn(false).when(display).supportsSystemDecorations();
 
         assertNull(taskDisplayArea.getRootHomeTask());
@@ -1132,7 +1138,7 @@
     @Test
     public void testGetOrCreateRootHomeTask_untrustedVirtualDisplay() {
         DisplayContent display = createNewDisplay();
-        TaskDisplayArea taskDisplayArea = display.mTaskContainers;
+        TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
         doReturn(true).when(display).isUntrustedVirtualDisplay();
 
         assertNull(taskDisplayArea.getRootHomeTask());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 7928e76..28ae36a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -677,7 +677,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 149760800)
     public void layoutWindowLw_withLongEdgeDisplayCutout() {
         addLongEdgeDisplayCutout();
 
@@ -698,7 +697,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 149760800)
     public void layoutWindowLw_withLongEdgeDisplayCutout_never() {
         addLongEdgeDisplayCutout();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index c370d6c..d0fd50d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -277,7 +277,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testOverlappingWithNavBar() {
         final WindowState targetWin = createApplicationWindow();
         final WindowFrames winFrame = targetWin.getWindowFrames();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index cf7411e..9b2a2db 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -860,6 +860,8 @@
             mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
             when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt()))
                     .thenReturn(WmDisplayCutout.NO_CUTOUT);
+            when(mMockDisplayContent.getDefaultTaskDisplayArea())
+                    .thenReturn(mock(TaskDisplayArea.class));
 
             mMockDisplayPolicy = mock(DisplayPolicy.class);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 956c200..0eee3ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -147,19 +147,16 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testDragFlow() {
         dragFlow(0, ClipData.newPlainText("label", "Test"), 0, 0);
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testPerformDrag_NullDataWithGrantUri() {
         dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testPerformDrag_NullDataToOtherUser() {
         final WindowState otherUsersWindow =
                 createDropTargetWindow("Other user's window", 1 * UserHandle.PER_USER_RANGE);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index b21ea79..b6eb901 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -30,7 +30,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 
-import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -41,7 +40,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
 
 import android.platform.test.annotations.Presubmit;
 import android.util.IntArray;
@@ -49,7 +47,6 @@
 import android.view.InsetsState;
 import android.view.test.InsetsModeSession;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.AfterClass;
@@ -58,7 +55,6 @@
 import org.junit.runner.RunWith;
 
 @SmallTest
-@FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
 @Presubmit
 @RunWith(WindowTestRunner.class)
 public class InsetsPolicyTest extends WindowTestsBase {
@@ -169,6 +165,18 @@
     }
 
     @Test
+    public void testControlsForDispatch_forceShowSystemBarsFromExternal_appHasNoControl() {
+        mDisplayContent.getDisplayPolicy().setForceShowSystemBars(true);
+        addWindow(TYPE_STATUS_BAR, "statusBar");
+        addWindow(TYPE_NAVIGATION_BAR, "navBar");
+
+        final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
+
+        // The focused app window cannot control system bars.
+        assertNull(controls);
+    }
+
+    @Test
     public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
         addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
                 .getControllableInsetProvider().getSource().setVisible(false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index db7bce4..61b74b0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -32,6 +32,10 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
@@ -49,7 +53,6 @@
 import org.junit.runner.RunWith;
 
 @SmallTest
-@FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
 @Presubmit
 @RunWith(WindowTestRunner.class)
 public class InsetsStateControllerTest extends WindowTestsBase {
@@ -68,7 +71,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testStripForDispatch_notOwn() {
         final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
@@ -102,7 +104,8 @@
         getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
         getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
         getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
-        assertEquals(0, getController().getInsetsForDispatch(navBar).getSourcesCount());
+        assertNull(getController().getInsetsForDispatch(navBar).peekSource(ITYPE_IME));
+        assertNull(getController().getInsetsForDispatch(navBar).peekSource(ITYPE_STATUS_BAR));
     }
 
     @Test
@@ -169,6 +172,45 @@
     }
 
     @Test
+    public void testStripForDispatch_imeOrderChanged() {
+        getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
+
+        // This window can be the IME target while app cannot be the IME target.
+        createWindow(null, TYPE_APPLICATION, "base");
+
+        // Send our spy window (app) into the system so that we can detect the invocation.
+        final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
+        final WindowToken parent = win.mToken;
+        parent.removeChild(win);
+        final WindowState app = spy(win);
+        parent.addWindow(app);
+
+        // Adding FLAG_NOT_FOCUSABLE makes app above IME.
+        app.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+        mDisplayContent.computeImeTarget(true);
+        mDisplayContent.setLayoutNeeded();
+        mDisplayContent.applySurfaceChangesTransaction();
+
+        // app won't get IME insets while above IME.
+        assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
+
+        // Reset invocation counter.
+        clearInvocations(app);
+
+        // Removing FLAG_NOT_FOCUSABLE makes app below IME.
+        app.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
+        mDisplayContent.computeImeTarget(true);
+        mDisplayContent.setLayoutNeeded();
+        mDisplayContent.applySurfaceChangesTransaction();
+
+        // Make sure app got notified.
+        verify(app, atLeast(1)).notifyInsetsChanged();
+
+        // app will get IME insets while below IME.
+        assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
+    }
+
+    @Test
     public void testStripForDispatch_childWindow_altFocusable() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
@@ -247,7 +289,6 @@
         assertNull(getController().getControlsForDispatch(app));
     }
 
-    @FlakyTest(bugId = 124088319)
     @Test
     public void testControlRevoked_animation() {
         final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index ae467c0..6a71a7d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -114,8 +114,8 @@
         when(mRootWindowContainer.getDisplayContent(eq(mDisplayUniqueId)))
                 .thenReturn(mTestDisplay);
 
-        ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
-                ACTIVITY_TYPE_STANDARD, /* onTop */ true);
+        ActivityStack stack = mTestDisplay.getDefaultTaskDisplayArea()
+                .createStack(TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true);
         mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).setStack(stack)
                 .build();
         mTestTask.mUserId = TEST_USER_ID;
@@ -337,8 +337,8 @@
     public void testClearsRecordsOfTheUserOnUserCleanUp() {
         mTarget.saveTask(mTestTask);
 
-        ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
-                ACTIVITY_TYPE_STANDARD, /* onTop */ true);
+        ActivityStack stack = mTestDisplay.getDefaultTaskDisplayArea().createStack(
+                TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true);
         final Task anotherTaskOfTheSameUser = new TaskBuilder(mSupervisor)
                 .setComponent(ALTERNATIVE_COMPONENT)
                 .setUserId(TEST_USER_ID)
@@ -349,7 +349,7 @@
         anotherTaskOfTheSameUser.setHasBeenVisible(true);
         mTarget.saveTask(anotherTaskOfTheSameUser);
 
-        stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
+        stack = mTestDisplay.getDefaultTaskDisplayArea().createStack(TEST_WINDOWING_MODE,
                 ACTIVITY_TYPE_STANDARD, /* onTop */ true);
         final Task anotherTaskOfDifferentUser = new TaskBuilder(mSupervisor)
                 .setComponent(TEST_COMPONENT)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 071386f..ea933df 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -28,7 +28,6 @@
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -119,7 +118,7 @@
     public void setUp() throws Exception {
         mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
         spyOn(mTaskPersister);
-        mTaskContainer = mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY).mTaskContainers;
+        mTaskContainer = mRootWindowContainer.getDefaultTaskDisplayArea();
 
         // Set the recent tasks we should use for testing in this class.
         mRecentTasks = new TestRecentTasks(mService, mTaskPersister);
@@ -687,8 +686,8 @@
         mRecentTasks.setOnlyTestVisibleRange();
         mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
 
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final Task alwaysOnTopTask = display.createStack(WINDOWING_MODE_MULTI_WINDOW,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final Task alwaysOnTopTask = taskDisplayArea.createStack(WINDOWING_MODE_MULTI_WINDOW,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
         alwaysOnTopTask.setAlwaysOnTop(true);
 
@@ -863,8 +862,8 @@
 
         final ActivityStack homeStack = mTaskContainer.getRootHomeTask();
         final DisplayContent otherDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
-        final ActivityStack otherDisplayStack = otherDisplay.createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack otherDisplayStack = otherDisplay.getDefaultTaskDisplayArea()
+                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Add a number of tasks (beyond the max) on each display, ensure that the tasks are not
         // removed
@@ -1125,8 +1124,6 @@
             }
         });
         assertSecurityException(expectCallable,
-                () -> mService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
-        assertSecurityException(expectCallable,
                 () -> mService.startActivityFromRecents(0, new Bundle()));
         assertSecurityException(expectCallable, () -> mService.getTaskSnapshot(0, true));
         assertSecurityException(expectCallable, () -> mService.registerTaskStackListener(null));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index da07bac..f19550c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -23,7 +23,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -105,7 +104,7 @@
         mDefaultDisplay = mWm.mRoot.getDefaultDisplay();
         mController = spy(new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
                 DEFAULT_DISPLAY));
-        mRootHomeTask = mDefaultDisplay.getRootHomeTask();
+        mRootHomeTask = mDefaultDisplay.getDefaultTaskDisplayArea().getRootHomeTask();
         assertNotNull(mRootHomeTask);
     }
 
@@ -318,7 +317,7 @@
         // Assume activity transition should animate when no
         // IRecentsAnimationController#setDeferCancelUntilNextTransition called.
         assertFalse(mController.shouldDeferCancelWithScreenshot());
-        assertTrue(activity.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
+        assertTrue(activity.shouldAnimate());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 6810f64..881561f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -88,7 +88,7 @@
 
     @Test
     public void testRecentsActivityVisiblility() {
-        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultDisplay().mTaskContainers;
+        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         ActivityStack recentsStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_RECENTS, true /* onTop */);
         ActivityRecord recentActivity = new ActivityBuilder(mService)
@@ -116,8 +116,7 @@
 
     @Test
     public void testPreloadRecentsActivity() {
-        TaskDisplayArea defaultTaskDisplayArea = mRootWindowContainer.getDefaultDisplay()
-                .mTaskContainers;
+        TaskDisplayArea defaultTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         final ActivityStack homeStack =
                 defaultTaskDisplayArea.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
         defaultTaskDisplayArea.positionStackAtTop(homeStack, false /* includingParents */);
@@ -178,8 +177,7 @@
     @Test
     public void testRestartRecentsActivity() throws Exception {
         // Have a recents activity that is not attached to its process (ActivityRecord.app = null).
-        TaskDisplayArea defaultTaskDisplayArea = mRootWindowContainer.getDefaultDisplay()
-                .mTaskContainers;
+        TaskDisplayArea defaultTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         ActivityStack recentsStack = defaultTaskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_RECENTS, true /* onTop */);
         ActivityRecord recentActivity = new ActivityBuilder(mService).setComponent(
@@ -208,7 +206,7 @@
 
     @Test
     public void testSetLaunchTaskBehindOfTargetActivity() {
-        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultDisplay().mTaskContainers;
+        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         ActivityStack homeStack = taskDisplayArea.getRootHomeTask();
         // Assume the home activity support recents.
         ActivityRecord targetActivity = homeStack.getTopNonFinishingActivity();
@@ -253,7 +251,7 @@
 
     @Test
     public void testCancelAnimationOnVisibleStackOrderChange() {
-        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultDisplay().mTaskContainers;
+        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         ActivityStack fullscreenStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
         new ActivityBuilder(mService)
@@ -298,7 +296,7 @@
 
     @Test
     public void testKeepAnimationOnHiddenStackOrderChange() {
-        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultDisplay().mTaskContainers;
+        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         ActivityStack fullscreenStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
         new ActivityBuilder(mService)
@@ -334,7 +332,8 @@
 
     @Test
     public void testMultipleUserHomeActivity_findUserHomeTask() {
-        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultDisplay().mTaskContainers;
+        TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultDisplay()
+                .getDefaultTaskDisplayArea();
         ActivityStack homeStack = taskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
                 ACTIVITY_TYPE_HOME);
         ActivityRecord otherUserHomeActivity = new ActivityBuilder(mService)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 34ac835..67aab7e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -146,7 +146,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 133372977)
     public void testTimeout() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 83631049..b648346 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -89,7 +89,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mFullscreenStack = mRootWindowContainer.getDefaultDisplay().createStack(
+        mFullscreenStack = mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         doNothing().when(mService).updateSleepIfNeededLocked();
     }
@@ -129,8 +129,8 @@
         mRootWindowContainer.moveActivityToPinnedStack(firstActivity, sourceBounds,
                 0f /*aspectRatio*/, "initialMove");
 
-        final DisplayContent display = mFullscreenStack.getDisplay();
-        ActivityStack pinnedStack = display.getRootPinnedTask();
+        final TaskDisplayArea taskDisplayArea = mFullscreenStack.getDisplayArea();
+        ActivityStack pinnedStack = taskDisplayArea.getRootPinnedTask();
         // Ensure a task has moved over.
         ensureStackPlacement(pinnedStack, firstActivity);
         ensureStackPlacement(mFullscreenStack, secondActivity);
@@ -140,8 +140,9 @@
                 0f /*aspectRatio*/, "secondMove");
 
         // Need to get stacks again as a new instance might have been created.
-        pinnedStack = display.getRootPinnedTask();
-        mFullscreenStack = display.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        pinnedStack = taskDisplayArea.getRootPinnedTask();
+        mFullscreenStack = taskDisplayArea.getStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD);
         // Ensure stacks have swapped tasks.
         ensureStackPlacement(pinnedStack, secondActivity);
         ensureStackPlacement(mFullscreenStack, firstActivity);
@@ -215,6 +216,8 @@
 
         doReturn(isFocusedStack).when(stack).isFocusedStackOnDisplay();
         doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack();
+        TaskDisplayArea defaultTaskDisplayArea = display.getDefaultTaskDisplayArea();
+        doReturn(isFocusedStack ? stack : null).when(defaultTaskDisplayArea).getFocusedStack();
         mRootWindowContainer.applySleepTokens(true);
         verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked();
         verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked(
@@ -226,26 +229,29 @@
      */
     @Test
     public void testRemovingStackOnAppCrash() {
-        final DisplayContent defaultDisplay = mRootWindowContainer.getDefaultDisplay();
-        final int originalStackCount = defaultDisplay.getStackCount();
-        final ActivityStack stack = mRootWindowContainer.getDefaultDisplay().createStack(
+        final TaskDisplayArea defaultTaskDisplayArea = mRootWindowContainer
+                .getDefaultTaskDisplayArea();
+        final int originalStackCount = defaultTaskDisplayArea.getStackCount();
+        final ActivityStack stack = defaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
         final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(stack).build();
 
-        assertEquals(originalStackCount + 1, defaultDisplay.getStackCount());
+        assertEquals(originalStackCount + 1, defaultTaskDisplayArea.getStackCount());
 
         // Let's pretend that the app has crashed.
         firstActivity.app.setThread(null);
         mRootWindowContainer.finishTopCrashedActivities(firstActivity.app, "test");
 
         // Verify that the stack was removed.
-        assertEquals(originalStackCount, defaultDisplay.getStackCount());
+        assertEquals(originalStackCount, defaultTaskDisplayArea.getStackCount());
     }
 
     @Test
     public void testFocusability() {
-        final ActivityStack stack = mRootWindowContainer.getDefaultDisplay().createStack(
+        final TaskDisplayArea defaultTaskDisplayArea = mRootWindowContainer
+                .getDefaultTaskDisplayArea();
+        final ActivityStack stack = defaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(stack).build();
@@ -259,7 +265,7 @@
         assertFalse(stack.isTopActivityFocusable());
         assertFalse(activity.isFocusable());
 
-        final ActivityStack pinnedStack = mRootWindowContainer.getDefaultDisplay().createStack(
+        final ActivityStack pinnedStack = defaultTaskDisplayArea.createStack(
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true)
                 .setStack(pinnedStack).build();
@@ -288,7 +294,7 @@
     @Test
     public void testSplitScreenPrimaryChosenWhenTopActivityLaunchedToSecondary() {
         // Create primary split-screen stack with a task and an activity.
-        final ActivityStack primaryStack = mRootWindowContainer.getDefaultDisplay()
+        final ActivityStack primaryStack = mRootWindowContainer.getDefaultTaskDisplayArea()
                 .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
                         true /* onTop */);
         final Task task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
@@ -311,7 +317,6 @@
     @Test
     public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
         // Create stack/task on default display.
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
         final ActivityStack targetStack = new StackBuilder(mRootWindowContainer)
                 .setOnTop(false)
                 .build();
@@ -325,7 +330,7 @@
         mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
                 false);
 
-        final TaskDisplayArea taskDisplayArea = display.mTaskContainers;
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         verify(taskDisplayArea).moveHomeStackToFront(contains(reason));
     }
 
@@ -336,16 +341,16 @@
     @Test
     public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() {
         // Create stack/task on default display.
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final ActivityStack targetStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */);
         final Task targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
 
         // Create Recents on secondary display.
         final TestDisplayContent secondDisplay = addNewDisplayContentAt(
                 DisplayContent.POSITION_TOP);
-        final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_RECENTS, true /* onTop */);
+        final ActivityStack stack = secondDisplay.getDefaultTaskDisplayArea()
+                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
         final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
         new ActivityBuilder(mService).setTask(task).build();
 
@@ -353,7 +358,6 @@
         mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
                 false);
 
-        final TaskDisplayArea taskDisplayArea = display.mTaskContainers;
         verify(taskDisplayArea, never()).moveHomeStackToFront(contains(reason));
     }
 
@@ -364,12 +368,12 @@
     @Test
     public void testResumeActivityWhenNonTopmostStackIsTopFocused() {
         // Create a stack at bottom.
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final ActivityStack targetStack = spy(taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
         final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
         final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
-        display.mTaskContainers.positionStackAtBottom(targetStack);
+        taskDisplayArea.positionStackAtBottom(targetStack);
 
         // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
         // is the current top focused stack.
@@ -392,10 +396,9 @@
     @Test
     public void testResumeFocusedStacksStartsHomeActivity_NoActivities() {
         mFullscreenStack.removeIfPossible();
-        mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY).getRootHomeTask()
-                .removeIfPossible();
-        mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY)
-                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        taskDisplayArea.getRootHomeTask().removeIfPossible();
+        taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
 
         doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), anyInt());
 
@@ -415,16 +418,15 @@
     @Test
     public void testResumeFocusedStacksStartsHomeActivity_ActivityOnSecondaryScreen() {
         mFullscreenStack.removeIfPossible();
-        mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY).getRootHomeTask()
-                .removeIfPossible();
-        mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY)
-                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        taskDisplayArea.getRootHomeTask().removeIfPossible();
+        taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
 
         // Create an activity on secondary display.
         final TestDisplayContent secondDisplay = addNewDisplayContentAt(
                 DisplayContent.POSITION_TOP);
-        final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final ActivityStack stack = secondDisplay.getDefaultTaskDisplayArea()
+                .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
         new ActivityBuilder(mService).setTask(task).build();
 
@@ -446,8 +448,8 @@
     @Test
     public void testResumeActivityLingeringTransition() {
         // Create a stack at top.
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final ActivityStack targetStack = spy(taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
         final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
         final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
@@ -466,13 +468,13 @@
     @Test
     public void testResumeActivityLingeringTransition_notExecuted() {
         // Create a stack at bottom.
-        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
-        final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        final ActivityStack targetStack = spy(taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
         final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
         final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
         activity.setState(ActivityState.RESUMED, "test");
-        display.mTaskContainers.positionStackAtBottom(targetStack);
+        taskDisplayArea.positionStackAtBottom(targetStack);
 
         // Assume the stack is at the topmost position
         assertFalse(targetStack.isTopStackInDisplayArea());
@@ -809,20 +811,20 @@
     public void testSwitchUser_missingHomeRootTask() {
         doReturn(mFullscreenStack).when(mRootWindowContainer).getTopDisplayFocusedStack();
 
-        DisplayContent defaultDisplay = mRootWindowContainer.getDefaultDisplay();
-        ActivityStack homeStack = defaultDisplay.getRootHomeTask();
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        ActivityStack homeStack = taskDisplayArea.getRootHomeTask();
         if (homeStack != null) {
             homeStack.removeImmediately();
         }
-        assertNull(defaultDisplay.getRootHomeTask());
+        assertNull(taskDisplayArea.getRootHomeTask());
 
         int currentUser = mRootWindowContainer.mCurrentUser;
         int otherUser = currentUser + 1;
 
         mRootWindowContainer.switchUser(otherUser, null);
 
-        assertNotNull(defaultDisplay.getRootHomeTask());
-        assertEquals(defaultDisplay.getTopStack(), defaultDisplay.getRootHomeTask());
+        assertNotNull(taskDisplayArea.getRootHomeTask());
+        assertEquals(taskDisplayArea.getTopStack(), taskDisplayArea.getRootHomeTask());
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index d6a67ab..3d3a0f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -72,7 +72,8 @@
         final int numTasks = 10;
         int activeTime = 0;
         for (int i = 0; i < numTasks; i++) {
-            createTask(display.getStackAt(i % numStacks), ".Task" + i, i, activeTime++, null);
+            createTask(display.getDefaultTaskDisplayArea().getStackAt(i % numStacks),
+                    ".Task" + i, i, activeTime++, null);
         }
 
         // Ensure that the latest tasks were returned in order of decreasing last active time,
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 893a145..6734694 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -189,7 +189,7 @@
         final int originalDpi = mActivity.getConfiguration().densityDpi;
 
         // Move the non-resizable activity to the new display.
-        mStack.reparent(newDisplay.mDisplayContent, true /* onTop */);
+        mStack.reparent(newDisplay.getDefaultTaskDisplayArea(), true /* onTop */);
 
         assertEquals(originalBounds.width(), mActivity.getBounds().width());
         assertEquals(originalBounds.height(), mActivity.getBounds().height());
@@ -257,7 +257,7 @@
                 .setCanRotate(false).setNotch(notchHeight).build();
 
         // Move the non-resizable activity to the new display.
-        mStack.reparent(newDisplay, true /* onTop */);
+        mStack.reparent(newDisplay.getDefaultTaskDisplayArea(), true /* onTop */);
         // The configuration bounds should keep the same.
         assertEquals(origWidth, configBounds.width());
         assertEquals(origHeight, configBounds.height());
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index af76e7f..af3ec38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -316,7 +316,7 @@
         // that the default display is in fullscreen mode.
         display.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN);
         spyOn(display);
-        final TaskDisplayArea taskDisplayArea = display.mTaskContainers;
+        final TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
         spyOn(taskDisplayArea);
         final ActivityStack homeStack = taskDisplayArea.getStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 19824bf7..9625ffd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -16,8 +16,18 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -27,6 +37,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 
 import android.platform.test.annotations.Presubmit;
 
@@ -134,4 +147,48 @@
         assertEquals("The testing DisplayContent should be moved to top with task",
                 mWm.mRoot.getChildCount() - 1, indexOfDisplayWithPinnedStack);
     }
+
+    @Test
+    public void testReuseTaskAsStack() {
+        final Task candidateTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        final Task newStack = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        doReturn(newStack).when(mDisplayContent.mTaskContainers).createStack(anyInt(),
+                anyInt(), anyBoolean(), any(), any(), anyBoolean());
+
+        final int type = ACTIVITY_TYPE_STANDARD;
+        assertGetOrCreateStack(WINDOWING_MODE_FULLSCREEN, type, candidateTask,
+                true /* reuseCandidate */);
+        assertGetOrCreateStack(WINDOWING_MODE_UNDEFINED, type, candidateTask,
+                true /* reuseCandidate */);
+        assertGetOrCreateStack(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, type, candidateTask,
+                true /* reuseCandidate */);
+        assertGetOrCreateStack(WINDOWING_MODE_FREEFORM, type, candidateTask,
+                true /* reuseCandidate */);
+        assertGetOrCreateStack(WINDOWING_MODE_MULTI_WINDOW, type, candidateTask,
+                true /* reuseCandidate */);
+        assertGetOrCreateStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, type, candidateTask,
+                false /* reuseCandidate */);
+        assertGetOrCreateStack(WINDOWING_MODE_PINNED, type, candidateTask,
+                false /* reuseCandidate */);
+
+        final int windowingMode = WINDOWING_MODE_FULLSCREEN;
+        assertGetOrCreateStack(windowingMode, ACTIVITY_TYPE_HOME, candidateTask,
+                false /* reuseCandidate */);
+        assertGetOrCreateStack(windowingMode, ACTIVITY_TYPE_RECENTS, candidateTask,
+                false /* reuseCandidate */);
+        assertGetOrCreateStack(windowingMode, ACTIVITY_TYPE_ASSISTANT, candidateTask,
+                false /* reuseCandidate */);
+        assertGetOrCreateStack(windowingMode, ACTIVITY_TYPE_DREAM, candidateTask,
+                false /* reuseCandidate */);
+    }
+
+    private void assertGetOrCreateStack(int windowingMode, int activityType, Task candidateTask,
+            boolean reuseCandidate) {
+        final TaskDisplayArea taskDisplayArea = (TaskDisplayArea) candidateTask.getParent();
+        final ActivityStack stack = taskDisplayArea.getOrCreateStack(windowingMode, activityType,
+                false /* onTop */, null /* intent */, candidateTask /* candidateTask */);
+        assertEquals(reuseCandidate, stack == candidateTask);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index a3446d1..1a38ff2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -1312,14 +1312,14 @@
     }
 
     private ActivityRecord createSourceActivity(TestDisplayContent display) {
-        final ActivityStack stack = display.createStack(display.getWindowingMode(),
-                ACTIVITY_TYPE_STANDARD, true);
+        final ActivityStack stack = display.getDefaultTaskDisplayArea()
+                .createStack(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true);
         return new ActivityBuilder(mService).setStack(stack).setCreateTask(true).build();
     }
 
     private void addFreeformTaskTo(TestDisplayContent display, Rect bounds) {
-        final ActivityStack stack = display.createStack(display.getWindowingMode(),
-                ACTIVITY_TYPE_STANDARD, true);
+        final ActivityStack stack = display.getDefaultTaskDisplayArea()
+                .createStack(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true);
         stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
         final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
         // Just work around the unnecessary adjustments for bounds.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 6ef714e..06ca6c1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -192,6 +192,21 @@
     }
 
     @Test
+    public void testTaskNoDraw() throws RemoteException {
+        final ActivityStack stack = createStack();
+        final Task task = createTask(stack, false /* fakeDraw */);
+        final ITaskOrganizer organizer = registerMockOrganizer();
+
+        stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+        verify(organizer, never()).onTaskAppeared(any());
+        assertTrue(stack.isOrganized());
+
+        mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
+        verify(organizer, never()).onTaskVanished(any());
+        assertFalse(stack.isOrganized());
+    }
+
+    @Test
     public void testClearOrganizer() throws RemoteException {
         final ActivityStack stack = createStack();
         final Task task = createTask(stack);
@@ -618,9 +633,12 @@
 
     private List<Task> getTasksCreatedByOrganizer(DisplayContent dc) {
         ArrayList<Task> out = new ArrayList<>();
-        for (int i = dc.getStackCount() - 1; i >= 0; --i) {
-            final Task t = dc.getStackAt(i);
-            if (t.mCreatedByOrganizer) out.add(t);
+        for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
+            final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
+            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
+                final Task t = taskDisplayArea.getStackAt(sNdx);
+                if (t.mCreatedByOrganizer) out.add(t);
+            }
         }
         return out;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java
index 9fc1602..12ed3c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPersisterTest.java
@@ -74,7 +74,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 131005232)
     public void testTaskIdsPersistence() {
         SparseBooleanArray taskIdsOnFile = new SparseBooleanArray();
         for (int i = 0; i < 100; i++) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index ea52d7d..93dcc91 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -518,7 +518,6 @@
         assertEquals(expected, actual);
     }
 
-    @FlakyTest(bugId = 129492888)
     @Test
     public void testFinishingMovingWhenBinderDied() {
         spyOn(mWm.mTaskPositioningController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index ca84932..75226b7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -90,7 +90,6 @@
         assertNull(mTarget.getDragWindowHandleLocked());
     }
 
-    @FlakyTest(bugId = 129507487)
     @Test
     public void testFinishPositioningWhenAppRequested() {
         assertFalse(mTarget.isPositioningLocked());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 31d68a4..519ac78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -184,7 +184,6 @@
 
     /** Ensures that bounds on freeform stacks are not clipped. */
     @Test
-    @FlakyTest(bugId = 137879065)
     public void testAppBounds_FreeFormBounds() {
         final Rect freeFormBounds = new Rect(mParentBounds);
         freeFormBounds.offset(10, 10);
@@ -194,7 +193,6 @@
 
     /** Ensures that fully contained bounds are not clipped. */
     @Test
-    @FlakyTest(bugId = 137879065)
     public void testAppBounds_ContainedBounds() {
         final Rect insetBounds = new Rect(mParentBounds);
         insetBounds.inset(5, 5, 5, 5);
@@ -203,12 +201,11 @@
     }
 
     @Test
-    @FlakyTest(bugId = 137879065)
     public void testFitWithinBounds() {
         final Rect parentBounds = new Rect(10, 10, 200, 200);
-        DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
-        ActivityStack stack = display.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
-                true /* onTop */);
+        TaskDisplayArea taskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea();
+        ActivityStack stack = taskDisplayArea.createStack(WINDOWING_MODE_FREEFORM,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
         Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
         final Configuration parentConfig = stack.getConfiguration();
         parentConfig.windowConfiguration.setBounds(parentBounds);
@@ -243,7 +240,6 @@
 
     /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
     @Test
-    @FlakyTest(bugId = 137879065)
     public void testBoundsOnModeChangeFreeformToFullscreen() {
         DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
         ActivityStack stack = new StackBuilder(mRootWindowContainer).setDisplay(display)
@@ -358,7 +354,7 @@
         spyOn(parentWindowContainer);
         parentWindowContainer.setBounds(fullScreenBounds);
         doReturn(parentWindowContainer).when(task).getParent();
-        doReturn(display.mTaskContainers).when(task).getDisplayArea();
+        doReturn(display.getDefaultTaskDisplayArea()).when(task).getDisplayArea();
         doReturn(stack).when(task).getStack();
         doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();
 
@@ -442,9 +438,9 @@
 
     @Test
     public void testInsetDisregardedWhenFreeformOverlapsNavBar() {
-        DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
-        ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
-                true /* onTop */);
+        TaskDisplayArea taskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea();
+        ActivityStack stack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
         DisplayInfo displayInfo = new DisplayInfo();
         mService.mContext.getDisplay().getDisplayInfo(displayInfo);
         final int displayHeight = displayInfo.logicalHeight;
@@ -963,8 +959,8 @@
     private void testStackBoundsConfiguration(int windowingMode, Rect parentBounds, Rect bounds,
             Rect expectedConfigBounds) {
 
-        DisplayContent display = mService.mRootWindowContainer.getDefaultDisplay();
-        ActivityStack stack = display.createStack(windowingMode, ACTIVITY_TYPE_STANDARD,
+        TaskDisplayArea taskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea();
+        ActivityStack stack = taskDisplayArea.createStack(windowingMode, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 6387a3b..413ae13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -33,6 +33,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 
 import android.app.WindowConfiguration;
@@ -144,7 +146,7 @@
 
         // Stack removal is deferred if one of its child is animating.
         doReturn(true).when(stack).hasWindowsAlive();
-        doReturn(true).when(task).isAnimating(TRANSITION | CHILDREN);
+        doReturn(true).when(task).isAnimating(eq(TRANSITION | CHILDREN), anyInt());
 
         stack.removeIfPossible();
         // For the case of deferred removal the task controller will still be connected to the its
@@ -171,7 +173,7 @@
 
         // Reparent
         clearInvocations(task1); // reset the number of onDisplayChanged for task.
-        stack1.reparent(dc, true /* onTop */);
+        stack1.reparent(dc.getDefaultTaskDisplayArea(), true /* onTop */);
         assertEquals(dc, stack1.getDisplayContent());
         final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
         final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 900f014..a4f1487 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -254,7 +254,7 @@
 
     private WindowState createWallpaperTargetWindow(DisplayContent dc) {
         final ActivityRecord homeActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
-                .setStack(dc.getRootHomeTask())
+                .setStack(dc.getDefaultTaskDisplayArea().getRootHomeTask())
                 .setCreateTask(true)
                 .build();
         homeActivity.setVisibility(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 27ea37d..353c781 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -21,6 +21,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -35,6 +36,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -423,6 +425,35 @@
     }
 
     @Test
+    public void testIsAnimating_typesToCheck() {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
+        final TestWindowContainer window = builder.setIsAnimating(true).setLayer(0).build();
+
+        assertTrue(window.isAnimating());
+        assertFalse(window.isAnimating(0, ANIMATION_TYPE_SCREEN_ROTATION));
+        assertTrue(window.isAnimating(0, ANIMATION_TYPE_APP_TRANSITION));
+        assertFalse(window.isAnimatingExcluding(0, ANIMATION_TYPE_APP_TRANSITION));
+
+        final TestWindowContainer child = window.addChildWindow();
+        assertFalse(child.isAnimating());
+        assertTrue(child.isAnimating(PARENTS));
+        assertTrue(child.isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
+        assertFalse(child.isAnimating(PARENTS, ANIMATION_TYPE_SCREEN_ROTATION));
+
+        final WindowState windowState = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
+                mDisplayContent, "TestWindowState");
+        WindowContainer parent = windowState.getParent();
+        spyOn(windowState.mSurfaceAnimator);
+        doReturn(true).when(windowState.mSurfaceAnimator).isAnimating();
+        doReturn(ANIMATION_TYPE_APP_TRANSITION).when(
+                windowState.mSurfaceAnimator).getAnimationType();
+        assertTrue(parent.isAnimating(CHILDREN));
+
+        windowState.setControllableInsetProvider(mock(InsetsSourceProvider.class));
+        assertFalse(parent.isAnimating(CHILDREN));
+    }
+
+    @Test
     public void testIsVisible() {
         final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
         final TestWindowContainer root = builder.setLayer(0).build();
@@ -780,8 +811,8 @@
                 WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
 
         final DisplayContent newDc = createNewDisplay();
-        mDisplayContent.removeStack(stack);
-        newDc.mTaskContainers.addChild(stack, POSITION_TOP);
+        stack.getDisplayArea().removeStack(stack);
+        newDc.getDefaultTaskDisplayArea().addChild(stack, POSITION_TOP);
 
         verify(stack).onDisplayChanged(newDc);
         verify(task).onDisplayChanged(newDc);
@@ -895,6 +926,7 @@
             mWaitForTransitStart = waitTransitStart;
             spyOn(mSurfaceAnimator);
             doReturn(mIsAnimating).when(mSurfaceAnimator).isAnimating();
+            doReturn(ANIMATION_TYPE_APP_TRANSITION).when(mSurfaceAnimator).getAnimationType();
         }
 
         TestWindowContainer getParentWindow() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index e95ccab..71b35b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -40,6 +40,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
@@ -47,6 +48,8 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
@@ -55,6 +58,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -65,6 +69,7 @@
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.util.Size;
 import android.view.DisplayCutout;
@@ -449,7 +454,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 74078662)
     public void testLayoutSeqResetOnReparent() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         app.mLayoutSeq = 1;
@@ -508,7 +512,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 74078662)
     public void testDisplayCutoutIsCalculatedRelativeToFrame() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         WindowFrames wf = app.getWindowFrames();
@@ -570,6 +573,36 @@
     }
 
     @Test
+    public void testReportResizedWithRemoteException() {
+        final WindowState win = mChildAppWindowAbove;
+        makeWindowVisible(win, win.getParentWindow());
+        win.mLayoutSeq = win.getDisplayContent().mLayoutSeq;
+        win.updateResizingWindowIfNeeded();
+
+        assertThat(mWm.mResizingWindows).contains(win);
+        assertTrue(win.getOrientationChanging());
+
+        mWm.mResizingWindows.remove(win);
+        spyOn(win.mClient);
+        try {
+            doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frame */,
+                    any() /* contentInsets */, any() /* visibleInsets */, any() /* stableInsets */,
+                    anyBoolean() /* reportDraw */, any() /* mergedConfig */,
+                    any() /* backDropFrame */, anyBoolean() /* forceLayout */,
+                    anyBoolean() /* alwaysConsumeSystemBars */, anyInt() /* displayId */,
+                    any() /* displayCutout */);
+        } catch (RemoteException ignored) {
+        }
+        win.reportResized();
+        win.updateResizingWindowIfNeeded();
+
+        // Even "resized" throws remote exception, it is still considered as reported. So the window
+        // shouldn't be resized again (which may block unfreeze in real case).
+        assertThat(mWm.mResizingWindows).doesNotContain(win);
+        assertFalse(win.getOrientationChanging());
+    }
+
+    @Test
     public void testGetTransformationMatrix() {
         final int PARENT_WINDOW_OFFSET = 1;
         final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 1ca2e318..397f73c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -134,6 +134,7 @@
                 mChildAppWindowBelow = createCommonWindow(mAppWindow,
                         TYPE_APPLICATION_MEDIA_OVERLAY,
                         "mChildAppWindowBelow");
+                mDisplayContent.getDisplayPolicy().setForceShowSystemBars(false);
             }
 
             // Adding a display will cause freezing the display. Make sure to wait until it's
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 6c0f2b0..edbdd4e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -40,6 +40,9 @@
 import android.hardware.soundtrigger.SoundTriggerModule;
 import android.os.Binder;
 import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.RemoteException;
@@ -113,6 +116,13 @@
 
     private PowerSaveModeListener mPowerSaveModeListener;
 
+    // Handler to process call state changes will delay to allow time for the audio
+    // and sound trigger HALs to process the end of call notifications
+    // before we re enable pending recognition requests.
+    private final Handler mHandler;
+    private static final int MSG_CALL_STATE_CHANGED = 0;
+    private static final int CALL_INACTIVE_MSG_DELAY_MS = 1000;
+
     SoundTriggerHelper(Context context) {
         ArrayList <ModuleProperties> modules = new ArrayList<>();
         int status = SoundTrigger.listModules(modules);
@@ -130,6 +140,31 @@
             // TODO: Figure out how to determine which module corresponds to the DSP hardware.
             mModuleProperties = modules.get(0);
         }
+
+        Looper looper = Looper.myLooper();
+        if (looper == null) {
+            looper = Looper.getMainLooper();
+        }
+        if (looper != null) {
+            mHandler = new Handler(looper) {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case MSG_CALL_STATE_CHANGED:
+                            synchronized (mLock) {
+                                onCallStateChangedLocked(
+                                        TelephonyManager.CALL_STATE_OFFHOOK == msg.arg1);
+                            }
+                            break;
+                        default:
+                            Slog.e(TAG, "unknown message in handler:" + msg.what);
+                            break;
+                    }
+                }
+            };
+        } else {
+            mHandler = null;
+        }
     }
 
     /**
@@ -227,6 +262,37 @@
         return status;
     }
 
+    private int prepareForRecognition(ModelData modelData) {
+        if (mModule == null) {
+            mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null);
+            if (mModule == null) {
+                Slog.w(TAG, "prepareForRecognition: cannot attach to sound trigger module");
+                return STATUS_ERROR;
+            }
+        }
+        // Load the model if it is not loaded.
+        if (!modelData.isModelLoaded()) {
+            // Before we try and load this model, we should first make sure that any other
+            // models that don't have an active recognition/dead callback are unloaded. Since
+            // there is a finite limit on the number of models that the hardware may be able to
+            // have loaded, we want to make sure there's room for our model.
+            stopAndUnloadDeadModelsLocked();
+            int[] handle = new int[] { 0 };
+            int status = mModule.loadSoundModel(modelData.getSoundModel(), handle);
+            if (status != SoundTrigger.STATUS_OK) {
+                Slog.w(TAG, "prepareForRecognition: loadSoundModel failed with status: " + status);
+                return status;
+            }
+            modelData.setHandle(handle[0]);
+            modelData.setLoaded();
+            if (DBG) {
+                Slog.d(TAG, "prepareForRecognition: Sound model loaded with handle:" + handle[0]);
+            }
+        }
+        return STATUS_OK;
+    }
+
+
     /**
      * Starts recognition for the given sound model. A single routine for both keyphrase and
      * generic sound models.
@@ -248,12 +314,17 @@
                 Slog.w(TAG, "Attempting startRecognition without the capability");
                 return STATUS_ERROR;
             }
-            if (mModule == null) {
-                mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null);
-                if (mModule == null) {
-                    Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
-                    return STATUS_ERROR;
+
+            IRecognitionStatusCallback oldCallback = modelData.getCallback();
+            if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) {
+                Slog.w(TAG, "Canceling previous recognition for model id: "
+                        + modelData.getModelId());
+                try {
+                    oldCallback.onError(STATUS_ERROR);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "RemoteException in onDetectionStopped", e);
                 }
+                modelData.clearCallback();
             }
 
             // If the existing SoundModel is different (for the same UUID for Generic and same
@@ -287,48 +358,25 @@
                 }
             }
 
-            IRecognitionStatusCallback oldCallback = modelData.getCallback();
-            if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) {
-                Slog.w(TAG, "Canceling previous recognition for model id: " +
-                        modelData.getModelId());
-                try {
-                    oldCallback.onError(STATUS_ERROR);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "RemoteException in onDetectionStopped", e);
-                }
-                modelData.clearCallback();
-            }
-
-            // Load the model if it is not loaded.
-            if (!modelData.isModelLoaded()) {
-                // Before we try and load this model, we should first make sure that any other
-                // models that don't have an active recognition/dead callback are unloaded. Since
-                // there is a finite limit on the number of models that the hardware may be able to
-                // have loaded, we want to make sure there's room for our model.
-                stopAndUnloadDeadModelsLocked();
-                int[] handle = new int[] { INVALID_VALUE };
-                int status = mModule.loadSoundModel(soundModel, handle);
-                if (status != SoundTrigger.STATUS_OK) {
-                    Slog.w(TAG, "loadSoundModel call failed with " + status);
-                    return status;
-                }
-                if (handle[0] == INVALID_VALUE) {
-                    Slog.w(TAG, "loadSoundModel call returned invalid sound model handle");
-                    return STATUS_ERROR;
-                }
-                modelData.setHandle(handle[0]);
-                modelData.setLoaded();
-                Slog.d(TAG, "Sound model loaded with handle:" + handle[0]);
-            }
             modelData.setCallback(callback);
             modelData.setRequested(true);
             modelData.setRecognitionConfig(recognitionConfig);
             modelData.setSoundModel(soundModel);
 
-            int status = startRecognitionLocked(modelData,
+            if (!isRecognitionAllowed()) {
+                initializeTelephonyAndPowerStateListeners();
+                return STATUS_OK;
+            }
+
+            int status = prepareForRecognition(modelData);
+            if (status != STATUS_OK) {
+                Slog.w(TAG, "startRecognition failed to prepare model for recognition");
+                return status;
+            }
+            status = startRecognitionLocked(modelData,
                     false /* Don't notify for synchronous calls */);
 
-                                // Initialize power save, call active state monitoring logic.
+            // Initialize power save, call active state monitoring logic.
             if (status == STATUS_OK) {
                 initializeTelephonyAndPowerStateListeners();
             }
@@ -398,7 +446,8 @@
             if (DBG) {
                 Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId + ", callback =" +
                         callback.asBinder());
-                Slog.d(TAG, "current callback=" + (modelData == null ? "null" :
+                Slog.d(TAG, "current callback="
+                        + ((modelData == null || modelData.getCallback() == null) ? "null" :
                             modelData.getCallback().asBinder()));
             }
             int status = stopRecognition(modelData, callback);
@@ -507,8 +556,8 @@
         synchronized (mLock) {
             MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1);
             ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
-            if (mModule == null || modelData == null || modelData.getHandle() == INVALID_VALUE ||
-                    !modelData.isKeyphraseModel()) {
+            if (mModule == null || modelData == null || !modelData.isModelLoaded()
+                    || !modelData.isKeyphraseModel()) {
                 return STATUS_ERROR;
             }
 
@@ -943,6 +992,10 @@
             return STATUS_OK;
         }
         if (start) {
+            int status = prepareForRecognition(model);
+            if (status != STATUS_OK) {
+                return status;
+            }
             return startRecognitionLocked(model, notify);
         } else {
             return stopRecognitionLocked(model, notify);
@@ -992,8 +1045,15 @@
         @Override
         public void onCallStateChanged(int state, String arg1) {
             if (DBG) Slog.d(TAG, "onCallStateChanged: " + state);
-            synchronized (mLock) {
-                onCallStateChangedLocked(TelephonyManager.CALL_STATE_OFFHOOK == state);
+
+            if (mHandler != null) {
+                synchronized (mLock) {
+                    mHandler.removeMessages(MSG_CALL_STATE_CHANGED);
+                    Message msg = mHandler.obtainMessage(MSG_CALL_STATE_CHANGED, state, 0);
+                    mHandler.sendMessageDelayed(
+                            msg, (TelephonyManager.CALL_STATE_OFFHOOK == state) ? 0
+                                    : CALL_INACTIVE_MSG_DELAY_MS);
+                }
             }
         }
     }
@@ -1216,9 +1276,8 @@
     // models.
     private int startRecognitionLocked(ModelData modelData, boolean notify) {
         IRecognitionStatusCallback callback = modelData.getCallback();
-        int handle = modelData.getHandle();
         RecognitionConfig config = modelData.getRecognitionConfig();
-        if (callback == null || handle == INVALID_VALUE || config == null) {
+        if (callback == null || !modelData.isModelLoaded() || config == null) {
             // Nothing to do here.
             Slog.w(TAG, "startRecognition: Bad data passed in.");
             MetricsLogger.count(mContext, "sth_start_recognition_error", 1);
@@ -1235,7 +1294,7 @@
         if (mModule == null) {
             return STATUS_ERROR;
         }
-        int status = mModule.startRecognition(handle, config);
+        int status = mModule.startRecognition(modelData.getHandle(), config);
         if (status != SoundTrigger.STATUS_OK) {
             Slog.w(TAG, "startRecognition failed with " + status);
             MetricsLogger.count(mContext, "sth_start_recognition_error", 1);
@@ -1376,7 +1435,7 @@
 
         // Model handle is an integer used by the HAL as an identifier for sound
         // models.
-        private int mModelHandle = INVALID_VALUE;
+        private int mModelHandle;
 
         // The SoundModel instance, one of KeyphraseSoundModel or GenericSoundModel.
         private SoundModel mSoundModel = null;
@@ -1436,7 +1495,6 @@
 
         synchronized void clearState() {
             mModelState = MODEL_NOTLOADED;
-            mModelHandle = INVALID_VALUE;
             mRecognitionConfig = null;
             mRequested = false;
             mCallback = null;
diff --git a/startop/iorap/functional_tests/Android.bp b/startop/iorap/functional_tests/Android.bp
index ce9dc32..ad85f14 100644
--- a/startop/iorap/functional_tests/Android.bp
+++ b/startop/iorap/functional_tests/Android.bp
@@ -15,6 +15,7 @@
 android_test {
     name: "iorap-functional-tests",
     srcs: ["src/**/*.java"],
+    data: ["test_data/*"],
     static_libs: [
         // Non-test dependencies
         // library under test
diff --git a/startop/iorap/functional_tests/AndroidTest.xml b/startop/iorap/functional_tests/AndroidTest.xml
index 3d5a229..31d4f6c 100644
--- a/startop/iorap/functional_tests/AndroidTest.xml
+++ b/startop/iorap/functional_tests/AndroidTest.xml
@@ -45,6 +45,20 @@
         <option name="run-command" value="sleep 1" />
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="abort-on-push-failure" value="true" />
+        <option name="push-file"
+          key="iorap_test_app_v1.apk"
+          value="/data/misc/iorapd/iorap_test_app_v1.apk" />
+        <option name="push-file"
+          key="iorap_test_app_v2.apk"
+          value="/data/misc/iorapd/iorap_test_app_v2.apk" />
+        <option name="push-file"
+          key="iorap_test_app_v3.apk"
+          value="/data/misc/iorapd/iorap_test_app_v3.apk" />
+    </target_preparer>
+
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.google.android.startop.iorap.tests" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java b/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
index 9abbcd7..c35dd3b 100644
--- a/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
+++ b/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
@@ -37,45 +37,46 @@
 import androidx.test.uiautomator.UiDevice;
 import androidx.test.uiautomator.Until;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
+import java.util.Date;
 import java.util.function.BooleanSupplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.List;
-
+import java.text.SimpleDateFormat;
 
 /**
  * Test for the work flow of iorap.
  *
- * <p> This test tests the function of iorap from perfetto collection -> compilation ->
- * prefetching.
- * </p>
+ * <p> This test tests the function of iorap from:
+ * perfetto collection -> compilation ->  prefetching -> version update -> perfetto collection.
  */
 @RunWith(AndroidJUnit4.class)
 public class IorapWorkFlowTest {
-
   private static final String TAG = "IorapWorkFlowTest";
 
-  private static final String TEST_PACKAGE_NAME = "com.android.settings";
-  private static final String TEST_ACTIVITY_NAME = "com.android.settings.Settings";
+  private static final String TEST_APP_VERSION_ONE_PATH = "/data/misc/iorapd/iorap_test_app_v1.apk";
+  private static final String TEST_APP_VERSION_TWO_PATH = "/data/misc/iorapd/iorap_test_app_v2.apk";
+  private static final String TEST_APP_VERSION_THREE_PATH = "/data/misc/iorapd/iorap_test_app_v3.apk";
 
   private static final String DB_PATH = "/data/misc/iorapd/sqlite.db";
   private static final Duration TIMEOUT = Duration.ofSeconds(300L);
 
-  private static final String READAHEAD_INDICATOR =
-      "Description = /data/misc/iorapd/com.android.settings/-?\\d+/com.android.settings.Settings/compiled_traces/compiled_trace.pb";
-
   private UiDevice mDevice;
 
   @Before
-  public void startMainActivityFromHomeScreen() throws Exception {
+  public void setUp() throws Exception {
     // Initialize UiDevice instance
     mDevice = UiDevice.getInstance(getInstrumentation());
 
@@ -88,21 +89,81 @@
     mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), TIMEOUT.getSeconds());
   }
 
+  @After
+  public void tearDown() throws Exception {
+    String packageName = "com.example.ioraptestapp";
+    uninstallApk(packageName);
+  }
+
   @Test (timeout = 300000)
-  public void testApp() throws Exception {
+  public void testNormalWorkFlow() throws Exception {
     assertThat(mDevice, notNullValue());
 
+    // Install test app version one
+    installApk(TEST_APP_VERSION_ONE_PATH);
+    String packageName = "com.example.ioraptestapp";
+    String activityName = "com.example.ioraptestapp.MainActivity";
+
     // Perfetto trace collection phase.
-    assertTrue(startAppForPerfettoTrace(/*expectPerfettoTraceCount=*/1));
-    assertTrue(startAppForPerfettoTrace(/*expectPerfettoTraceCount=*/2));
-    assertTrue(startAppForPerfettoTrace(/*expectPerfettoTraceCount=*/3));
-    assertTrue(checkPerfettoTracesExistence(TIMEOUT, 3));
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/1L));
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/1L));
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/1L));
 
     // Trigger maintenance service for compilation.
-    assertTrue(compile(TIMEOUT));
+    TimeUnit.SECONDS.sleep(5L);
+    assertTrue(compile(packageName, activityName, /*version=*/1L));
 
-    // Check if prefetching works.
-    assertTrue(waitForPrefetchingFromLogcat(/*expectPerfettoTraceCount=*/3));
+    // Run app with prefetching
+    assertTrue(startAppWithCompiledTrace(
+        packageName, activityName, /*version=*/1L));
+  }
+
+  @Test (timeout = 300000)
+  public void testUpdateApp() throws Exception {
+    assertThat(mDevice, notNullValue());
+
+    // Install test app version two,
+    String packageName = "com.example.ioraptestapp";
+    String activityName = "com.example.ioraptestapp.MainActivity";
+    installApk(TEST_APP_VERSION_TWO_PATH);
+
+    // Perfetto trace collection phase.
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/2L));
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/2L));
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/2L));
+
+    // Trigger maintenance service for compilation.
+    TimeUnit.SECONDS.sleep(5L);
+    assertTrue(compile(packageName, activityName, /*version=*/2L));
+
+    // Run app with prefetching
+    assertTrue(startAppWithCompiledTrace(
+        packageName, activityName, /*version=*/2L));
+
+    // Update test app to version 3
+    installApk(TEST_APP_VERSION_THREE_PATH);
+
+    // Rerun app, should do pefetto tracing.
+    assertTrue(startAppForPerfettoTrace(
+        packageName, activityName, /*version=*/3L));
+  }
+
+  private static void installApk(String apkPath) throws Exception {
+    // Disable the selinux to allow pm install apk in the dir.
+    executeShellCommand("setenforce 0");
+    executeShellCommand("pm install -r -d " + apkPath);
+    executeShellCommand("setenforce 1");
+
+  }
+
+  private static void uninstallApk(String apkPath) throws Exception {
+    executeShellCommand("pm uninstall " + apkPath);
   }
 
   /**
@@ -110,43 +171,81 @@
    *
    * @param expectPerfettoTraceCount is the expected count of perfetto traces.
    */
-  private boolean startAppForPerfettoTrace(long expectPerfettoTraceCount)
+  private boolean startAppForPerfettoTrace(
+      String packageName, String activityName, long version)
       throws Exception {
-    // Close the specified app if it's open
-    closeApp();
-    // Launch the specified app
-    startApp();
-    // Wait for the app to appear
-    mDevice.wait(Until.hasObject(By.pkg(TEST_PACKAGE_NAME).depth(0)), TIMEOUT.getSeconds());
+    LogcatTimestamp timestamp = runAppOnce(packageName, activityName);
+    return waitForPerfettoTraceSavedFromLogcat(
+        packageName, activityName, version, timestamp);
+  }
 
-    String sql = "SELECT COUNT(*) FROM activities "
-        + "JOIN app_launch_histories ON activities.id = app_launch_histories.activity_id "
-        + "JOIN raw_traces ON raw_traces.history_id = app_launch_histories.id "
-        + "WHERE activities.name = ?";
-    return checkAndWaitEntriesNum(sql, new String[]{TEST_ACTIVITY_NAME}, expectPerfettoTraceCount,
-        TIMEOUT);
+  private boolean startAppWithCompiledTrace(
+      String packageName, String activityName, long version)
+      throws Exception {
+    LogcatTimestamp timestamp = runAppOnce(packageName, activityName);
+    return waitForPrefetchingFromLogcat(
+        packageName, activityName, version, timestamp);
+  }
+
+  private LogcatTimestamp runAppOnce(String packageName, String activityName) throws Exception {
+    // Close the specified app if it's open
+    closeApp(packageName);
+    LogcatTimestamp timestamp = new LogcatTimestamp();
+    // Launch the specified app
+    startApp(packageName, activityName);
+    // Wait for the app to appear
+    mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), TIMEOUT.getSeconds());
+    return timestamp;
   }
 
   // Invokes the maintenance to compile the perfetto traces to compiled trace.
-  private boolean compile(Duration timeout) throws Exception {
+  private boolean compile(
+      String packageName, String activityName, long version) throws Exception {
     // The job id (283673059) is defined in class IorapForwardingService.
-    executeShellCommand("cmd jobscheduler run -f android 283673059");
+    executeShellCommandViaTmpFile("cmd jobscheduler run -f android 283673059");
+    return waitForFileExistence(getCompiledTracePath(packageName, activityName, version));
+  }
 
-    // Wait for the compilation.
-    String sql = "SELECT COUNT(*) FROM activities JOIN prefetch_files ON "
-        + "activities.id = prefetch_files.activity_id "
-        + "WHERE activities.name = ?";
-    boolean result = checkAndWaitEntriesNum(sql, new String[]{TEST_ACTIVITY_NAME}, /*count=*/1,
-        timeout);
-    if (!result) {
-      return false;
+  private String getCompiledTracePath(
+      String packageName, String activityName, long version) {
+    return String.format(
+        "/data/misc/iorapd/%s/%d/%s/compiled_traces/compiled_trace.pb",
+        packageName, version, activityName);
+  }
+
+  /**
+   * Starts the testing app.
+   */
+  private void startApp(String packageName, String activityName) throws Exception {
+    executeShellCommandViaTmpFile(
+        String.format("am start %s/%s", packageName, activityName));
+  }
+
+  /**
+   * Closes the testing app.
+   * <p> Keep trying to kill the process of the app until no process of the app package
+   * appears.</p>
+   */
+  private void closeApp(String packageName) throws Exception {
+    while (true) {
+      String pid = executeShellCommand("pidof " + packageName);
+      if (pid.isEmpty()) {
+        Log.i(TAG, "Closed app " + packageName);
+        return;
+      }
+      executeShellCommand("kill -9 " + pid);
+      TimeUnit.SECONDS.sleep(1L);
     }
+  }
 
-    return retryWithTimeout(timeout, () -> {
+  /** Waits for a file to appear. */
+  private boolean waitForFileExistence(String fileName) throws Exception {
+    return retryWithTimeout(TIMEOUT, () -> {
       try {
-        String compiledTrace = getCompiledTraceFilePath();
-        File compiledTraceLocal = copyFileToLocal(compiledTrace, "compiled_trace.tmp");
-        return compiledTraceLocal.exists();
+        String fileExists = executeShellCommandViaTmpFile(
+            String.format("test -f %s; echo $?", fileName));
+        Log.i(TAG, fileName + " existence is " +  fileExists);
+        return fileExists.trim().equals("0");
       } catch (Exception e) {
         Log.i(TAG, e.getMessage());
         return false;
@@ -154,92 +253,96 @@
     });
   }
 
-  /**
-   * Check if all the perfetto traces in the db exist.
-   */
-  private boolean checkPerfettoTracesExistence(Duration timeout, int expectPerfettoTraceCount)
+  /** Waits for the perfetto trace saved message from logcat. */
+  private boolean waitForPerfettoTraceSavedFromLogcat(
+      String packageName, String activityName, long version, LogcatTimestamp timestamp)
       throws Exception {
-    return retryWithTimeout(timeout, () -> {
-      try {
-        File dbFile = getIorapDb();
-        List<String> traces = getPerfettoTracePaths(dbFile);
-        assertEquals(traces.size(), expectPerfettoTraceCount);
+    Pattern p = Pattern.compile(".*"
+        + getPerfettoTraceSavedIndicator(packageName, activityName, version)
+        + "(.*[.]perfetto_trace[.]pb)\n.*", Pattern.DOTALL);
 
-        int count = 0;
-        for (String trace : traces) {
-          File tmp = copyFileToLocal(trace, "perfetto_trace.tmp" + count);
-          ++count;
-          Log.i(TAG, "Check perfetto trace: " + trace);
-          if (!tmp.exists()) {
-            Log.i(TAG, "Perfetto trace does not exist: " + trace);
-            return false;
-          }
+    return retryWithTimeout(TIMEOUT, () -> {
+      try {
+        String log = timestamp.getLogcatAfter();
+        Matcher m = p.matcher(log);
+        Log.d(TAG, "Tries to find perfetto trace...");
+        if (!m.matches()) {
+          Log.i(TAG, "Cannot find perfetto trace saved in log.");
+          return false;
         }
+        String filePath = m.group(1);
+        Log.i(TAG, "Perfetto trace is saved to " + filePath);
         return true;
-      } catch (Exception e) {
-        Log.i(TAG, e.getMessage());
+      } catch(Exception e) {
+        Log.e(TAG, e.getMessage());
         return false;
       }
-    });
+   });
+  }
+
+  private String getPerfettoTraceSavedIndicator(
+      String packageName, String activityName, long version) {
+    return String.format(
+        "Perfetto TraceBuffer saved to file: /data/misc/iorapd/%s/%d/%s/raw_traces/",
+        packageName, version, activityName);
   }
 
   /**
-   * Gets the perfetto traces file path from the db.
-   */
-  private List<String> getPerfettoTracePaths(File dbFile) throws Exception {
-    String sql = "SELECT raw_traces.file_path FROM activities "
-        + "JOIN app_launch_histories ON activities.id = app_launch_histories.activity_id "
-        + "JOIN raw_traces ON raw_traces.history_id = app_launch_histories.id "
-        + "WHERE activities.name = ?";
-
-    List<String> perfettoTraces = new ArrayList<>();
-    try (SQLiteDatabase db = SQLiteDatabase
-        .openDatabase(dbFile.getPath(), null, SQLiteDatabase.OPEN_READONLY)) {
-      Cursor cursor = db.rawQuery(sql, new String[]{TEST_ACTIVITY_NAME});
-      while (cursor.moveToNext()) {
-        perfettoTraces.add(cursor.getString(0));
-      }
-    }
-    return perfettoTraces;
-  }
-
-  private String getCompiledTraceFilePath() throws Exception {
-    File dbFile = getIorapDb();
-    try (SQLiteDatabase db = SQLiteDatabase
-        .openDatabase(dbFile.getPath(), null, SQLiteDatabase.OPEN_READONLY)) {
-      String sql = "SELECT prefetch_files.file_path FROM activities JOIN prefetch_files ON "
-              + "activities.id = prefetch_files.activity_id "
-              + "WHERE activities.name = ?";
-      return DatabaseUtils.stringForQuery(db, sql, new String[]{TEST_ACTIVITY_NAME});
-    }
-  }
-
-  /**
-   * Checks the number of entries in the database table.
+   * Waits for the prefetching log in the logcat.
    *
-   * <p> Keep checking until the timeout.
+   * <p> When prefetching works, the perfetto traces should not be collected. </p>
    */
-  private boolean checkAndWaitEntriesNum(String sql, String[] selectionArgs, long count,
-      Duration timeout)
+  private boolean waitForPrefetchingFromLogcat(
+      String packageName, String activityName, long version, LogcatTimestamp timestamp)
       throws Exception {
-    return retryWithTimeout(timeout, () -> {
+    Pattern p = Pattern.compile(
+    ".*" + getReadaheadIndicator(packageName, activityName, version) +
+    ".*Total File Paths=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
+        + ".*Total Entries=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
+        + ".*Total Bytes=(\\d+) \\(good: (\\d+[.]?\\d*)%\\).*",
+    Pattern.DOTALL);
+
+    return retryWithTimeout(TIMEOUT, () -> {
       try {
-        File db = getIorapDb();
-        long curCount = getEntriesNum(db, selectionArgs, sql);
-        Log.i(TAG, String
-            .format("For %s, current count is %d, expected count is :%d.", sql, curCount,
-                count));
-        return curCount == count;
-      } catch (Exception e) {
-        Log.i(TAG, e.getMessage());
+        String log = timestamp.getLogcatAfter();
+        Matcher m = p.matcher(log);
+        if (!m.matches()) {
+          Log.i(TAG, "Cannot find readahead log.");
+          return false;
+        }
+
+        int totalFilePath = Integer.parseInt(m.group(1));
+        float totalFilePathGoodRate = Float.parseFloat(m.group(2)) / 100;
+        int totalEntries = Integer.parseInt(m.group(3));
+        float totalEntriesGoodRate = Float.parseFloat(m.group(4)) / 100;
+        int totalBytes = Integer.parseInt(m.group(5));
+        float totalBytesGoodRate = Float.parseFloat(m.group(6)) / 100;
+
+        Log.i(TAG, String.format(
+            "totalFilePath: %d (good %.2f) totalEntries: %d (good %.2f) totalBytes: %d (good %.2f)",
+            totalFilePath, totalFilePathGoodRate, totalEntries, totalEntriesGoodRate, totalBytes,
+            totalBytesGoodRate));
+
+        return totalFilePath > 0 &&
+          totalEntries > 0 &&
+          totalBytes > 0 &&
+          totalFilePathGoodRate > 0.5 &&
+          totalEntriesGoodRate > 0.5 &&
+          totalBytesGoodRate > 0.5;
+      } catch(Exception e) {
         return false;
       }
-    });
+   });
   }
 
-  /**
-   * Retry until timeout.
-   */
+  private static String getReadaheadIndicator(
+      String packageName, String activityName, long version) {
+    return String.format(
+        "Description = /data/misc/iorapd/%s/%d/%s/compiled_traces/compiled_trace.pb",
+        packageName, version, activityName);
+  }
+
+  /** Retry until timeout. */
   private boolean retryWithTimeout(Duration timeout, BooleanSupplier supplier) throws Exception {
     long totalSleepTimeSeconds = 0L;
     long sleepIntervalSeconds = 2L;
@@ -256,113 +359,28 @@
   }
 
   /**
-   * Gets the number of entries in the query of sql.
-   */
-  private long getEntriesNum(File dbFile, String[] selectionArgs, String sql) throws Exception {
-    try (SQLiteDatabase db = SQLiteDatabase
-        .openDatabase(dbFile.getPath(), null, SQLiteDatabase.OPEN_READONLY)) {
-      return DatabaseUtils.longForQuery(db, sql, selectionArgs);
-    }
-  }
-
-  /**
-   * Gets the iorapd sqlite db file.
+   * Executes command in adb shell via a tmp file.
    *
-   * <p> The test cannot access the db file directly under "/data/misc/iorapd".
-   * Copy it to the local directory and change the mode.
+   * <p> This should be run as root.</p>
    */
-  private File getIorapDb() throws Exception {
-    File tmpDb = copyFileToLocal("/data/misc/iorapd/sqlite.db", "tmp.db");
-    // Change the mode of the file to allow the access from test.
-    executeShellCommand("chmod 777 " + tmpDb.getPath());
-    return tmpDb;
-  }
-
-  /**
-   * Copys a file to local directory.
-   */
-  private File copyFileToLocal(String src, String tgtFileName) throws Exception {
-    File localDir = getApplicationContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE);
-    File localFile = new File(localDir, tgtFileName);
-    executeShellCommand(String.format("cp %s %s", src, localFile.getPath()));
-    return localFile;
-  }
-
-  /**
-   * Starts the testing app.
-   */
-  private void startApp() throws Exception {
-    Context context = getApplicationContext();
-    final Intent intent = context.getPackageManager()
-        .getLaunchIntentForPackage(TEST_PACKAGE_NAME);
-    context.startActivity(intent);
-    Log.i(TAG, "Started app " + TEST_PACKAGE_NAME);
-  }
-
-  /**
-   * Closes the testing app.
-   * <p> Keep trying to kill the process of the app until no process of the app package
-   * appears.</p>
-   */
-  private void closeApp() throws Exception {
-    while (true) {
-      String pid = executeShellCommand("pidof " + TEST_PACKAGE_NAME);
-      if (pid.isEmpty()) {
-        Log.i(TAG, "Closed app " + TEST_PACKAGE_NAME);
-        return;
+  private static String executeShellCommandViaTmpFile(String cmd) throws Exception {
+    Log.i(TAG, "Execute via tmp file: " + cmd);
+    Path tmp = null;
+    try {
+      tmp = Files.createTempFile(/*prefix=*/null, /*suffix=*/".sh");
+      Files.write(tmp, cmd.getBytes(StandardCharsets.UTF_8));
+      tmp.toFile().setExecutable(true);
+      return UiDevice.getInstance(
+          InstrumentationRegistry.getInstrumentation()).
+          executeShellCommand(tmp.toString());
+    } finally {
+      if (tmp != null) {
+        Files.delete(tmp);
       }
-      executeShellCommand("kill -9 " + pid);
-      TimeUnit.SECONDS.sleep(1L);
     }
   }
 
   /**
-   * Waits for the prefetching log in the logcat.
-   *
-   * <p> When prefetching works, the perfetto traces should not be collected. </p>
-   */
-  private boolean waitForPrefetchingFromLogcat(long expectPerfettoTraceCount) throws Exception {
-    if (!startAppForPerfettoTrace(expectPerfettoTraceCount)) {
-      return false;
-    }
-
-    String log = executeShellCommand("logcat -d");
-
-    Pattern p = Pattern.compile(
-    ".*" + READAHEAD_INDICATOR
-        + ".*Total File Paths=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
-        + ".*Total Entries=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
-        + ".*Total Bytes=(\\d+) \\(good: (\\d+[.]?\\d*)%\\).*",
-    Pattern.DOTALL);
-    Matcher m = p.matcher(log);
-
-    if (!m.matches()) {
-      Log.i(TAG, "Cannot find readahead log.");
-      return false;
-    }
-
-    int totalFilePath = Integer.parseInt(m.group(1));
-    float totalFilePathGoodRate = Float.parseFloat(m.group(2)) / 100;
-    int totalEntries = Integer.parseInt(m.group(3));
-    float totalEntriesGoodRate = Float.parseFloat(m.group(4)) / 100;
-    int totalBytes = Integer.parseInt(m.group(5));
-    float totalBytesGoodRate = Float.parseFloat(m.group(6)) / 100;
-
-    Log.i(TAG, String.format(
-        "totalFilePath: %d (good %.2f) totalEntries: %d (good %.2f) totalBytes: %d (good %.2f)",
-        totalFilePath, totalFilePathGoodRate, totalEntries, totalEntriesGoodRate, totalBytes,
-        totalBytesGoodRate));
-
-    return totalFilePath > 0 &&
-        totalEntries > 0 &&
-        totalBytes > 100000 &&
-        totalFilePathGoodRate > 0.5 &&
-        totalEntriesGoodRate > 0.5 &&
-        totalBytesGoodRate > 0.5;
-  }
-
-
-  /**
    * Executes command in adb shell.
    *
    * <p> This should be run as root.</p>
@@ -372,6 +390,27 @@
     return UiDevice.getInstance(
         InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
   }
-}
 
+  static class LogcatTimestamp {
+    private String epochTime;
+
+    public LogcatTimestamp() throws Exception{
+      long currentTimeMillis = System.currentTimeMillis();
+      epochTime = String.format(
+          "%d.%d", currentTimeMillis/1000, currentTimeMillis%1000);
+      Log.i(TAG, "Current logcat timestamp is " + epochTime);
+    }
+
+    // For example, 1585264100.000
+    public String getEpochTime() {
+      return epochTime;
+    }
+
+    // Gets the logcat after this epoch time.
+    public String getLogcatAfter() throws Exception {
+      return executeShellCommandViaTmpFile(
+          "logcat -v epoch -t '" + epochTime + "'");
+    }
+  }
+}
 
diff --git a/startop/iorap/functional_tests/test_data/iorap_test_app_v1.apk b/startop/iorap/functional_tests/test_data/iorap_test_app_v1.apk
new file mode 120000
index 0000000..1c1a437
--- /dev/null
+++ b/startop/iorap/functional_tests/test_data/iorap_test_app_v1.apk
@@ -0,0 +1 @@
+../../../../../../packages/modules/ArtPrebuilt/iorap/test/iorap_test_app_v1.apk
\ No newline at end of file
diff --git a/startop/iorap/functional_tests/test_data/iorap_test_app_v2.apk b/startop/iorap/functional_tests/test_data/iorap_test_app_v2.apk
new file mode 120000
index 0000000..7cd41c4
--- /dev/null
+++ b/startop/iorap/functional_tests/test_data/iorap_test_app_v2.apk
@@ -0,0 +1 @@
+../../../../../../packages/modules/ArtPrebuilt/iorap/test/iorap_test_app_v2.apk
\ No newline at end of file
diff --git a/startop/iorap/functional_tests/test_data/iorap_test_app_v3.apk b/startop/iorap/functional_tests/test_data/iorap_test_app_v3.apk
new file mode 120000
index 0000000..7f4e996
--- /dev/null
+++ b/startop/iorap/functional_tests/test_data/iorap_test_app_v3.apk
@@ -0,0 +1 @@
+../../../../../../packages/modules/ArtPrebuilt/iorap/test/iorap_test_app_v3.apk
\ No newline at end of file
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index f3e9de0..3048ad7 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -311,7 +311,7 @@
         }
         // If the user or profile is current, permission is granted.
         // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
-        return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context, uid, pid);
+        return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context, pid, uid);
     }
 
     private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b0570a1..1a4b9d7 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -52,6 +52,14 @@
     public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
 
     /**
+     * Extra included in {@link #ACTION_CARRIER_CONFIG_CHANGED} to indicate whether this is a
+     * rebroadcast on unlock. Defaults to {@code false} if not specified.
+     * @hide
+     */
+    public static final String EXTRA_REBROADCAST_ON_UNLOCK =
+            "android.telephony.extra.REBROADCAST_ON_UNLOCK";
+
+    /**
      * Optional extra included in {@link #ACTION_CARRIER_CONFIG_CHANGED} to indicate the
      * subscription index that the broadcast is for, if a valid one is available.
      */
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index c37735c..13a8273 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -153,8 +153,10 @@
                 cid.bands.stream().mapToInt(Integer::intValue).toArray(), cid.base.bandwidth,
                 cid.base.base.mcc, cid.base.base.mnc, cid.base.operatorNames.alphaLong,
                 cid.base.operatorNames.alphaShort, cid.additionalPlmns,
-                cid.optionalCsgInfo.csgInfo() != null
-                        ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null);
+                cid.optionalCsgInfo.getDiscriminator()
+                        == android.hardware.radio.V1_5.OptionalCsgInfo.hidl_discriminator.csgInfo
+                                ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo())
+                                        : null);
     }
 
     private CellIdentityLte(@NonNull CellIdentityLte cid) {
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 3f95596..6dffe92 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -128,8 +128,11 @@
         this(cid.base.base.mcc, cid.base.base.mnc, cid.base.base.lac, cid.base.base.cid,
                 cid.base.base.cpid, cid.base.uarfcn, cid.base.operatorNames.alphaLong,
                 cid.base.operatorNames.alphaShort,
-                cid.additionalPlmns, cid.optionalCsgInfo.csgInfo() != null
-                        ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null);
+                cid.additionalPlmns,
+                cid.optionalCsgInfo.getDiscriminator()
+                        == android.hardware.radio.V1_5.OptionalCsgInfo.hidl_discriminator.csgInfo
+                                ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo())
+                                        : null);
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 38c4ed4..eab174a 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -123,8 +123,10 @@
         this(cid.base.base.lac, cid.base.base.cid, cid.base.base.psc, cid.base.base.uarfcn,
                 cid.base.base.mcc, cid.base.base.mnc, cid.base.operatorNames.alphaLong,
                 cid.base.operatorNames.alphaShort, cid.additionalPlmns,
-                cid.optionalCsgInfo.csgInfo() != null
-                        ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null);
+                cid.optionalCsgInfo.getDiscriminator()
+                        == android.hardware.radio.V1_5.OptionalCsgInfo.hidl_discriminator.csgInfo
+                                ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo())
+                                        : null);
     }
 
     private CellIdentityWcdma(@NonNull CellIdentityWcdma cid) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4e5be5c..d6cdaa6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11776,6 +11776,7 @@
      * subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
      * as the list of {@link EmergencyNumber}; empty Map if this information is not available;
      * or throw a SecurityException if the caller does not have the permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     @NonNull
@@ -11823,6 +11824,7 @@
      * @param number - the number to look up
      * @return {@code true} if the given number is an emergency number based on current locale,
      * SIM card(s), Android database, modem, network or defaults; {@code false} otherwise.
+     * @throws IllegalStateException if the Telephony process is not currently available.
      */
     public boolean isEmergencyNumber(@NonNull String number) {
         try {
@@ -11858,7 +11860,7 @@
      * the same digits of any current emergency number based on current locale, sim, modem and
      * network; {@code false} if it is not; or throw an SecurityException if the caller does not
      * have the required permission/privileges
-     *
+     * @throws IllegalStateException if the Telephony process is not currently available.
      * @hide
      */
     @SystemApi
@@ -12344,6 +12346,9 @@
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     @IsMultiSimSupportedResult
     public int isMultiSimSupported() {
+        if (getSupportedModemCount() < 2) {
+            return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
+        }
         try {
             ITelephony service = getITelephony();
             if (service != null) {
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 2b1d9e5..18e2592 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -113,6 +113,7 @@
     public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
     public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
     public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55;
+    public static final int EVENT_SIM_STATE_UPDATED = BASE + 56;
 
     /***** Constants *****/
 
diff --git a/tests/ApkVerityTest/Android.bp b/tests/ApkVerityTest/Android.bp
index 2482068..02c75ed 100644
--- a/tests/ApkVerityTest/Android.bp
+++ b/tests/ApkVerityTest/Android.bp
@@ -16,7 +16,7 @@
     name: "ApkVerityTest",
     srcs: ["src/**/*.java"],
     libs: ["tradefed", "compatibility-tradefed", "compatibility-host-util"],
-    test_suites: ["general-tests", "vts-core"],
+    test_suites: ["general-tests", "vts"],
     target_required: [
         "block_device_writer_module",
     ],
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp
index 2760fe8..37fbc29 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/ApkVerityTest/block_device_writer/Android.bp
@@ -48,6 +48,6 @@
     },
 
     auto_gen_config: false,
-    test_suites: ["general-tests", "pts", "vts-core"],
+    test_suites: ["general-tests", "pts", "vts"],
     gtest: false,
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index a616c61..6c9ffe2 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -477,4 +477,12 @@
         StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
         assertThat(sm.isCheckpointSupported()).isTrue();
     }
+
+    @Test
+    public void hasMainlineModule() throws Exception {
+        String pkgName = getModuleMetadataPackageName();
+        boolean existed =  InstrumentationRegistry.getInstrumentation().getContext()
+                .getPackageManager().getModuleInfo(pkgName, 0) != null;
+        assertThat(existed).isTrue();
+    }
 }
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 282f012..78775be 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -243,6 +243,7 @@
      */
     @Test
     public void testRollbackWhitelistedApp() throws Exception {
+        assumeTrue(hasMainlineModule());
         runPhase("testRollbackWhitelistedApp_Phase1");
         getDevice().reboot();
         runPhase("testRollbackWhitelistedApp_Phase2");
@@ -460,4 +461,16 @@
             return false;
         }
     }
+
+    /**
+     * True if this build has mainline modules installed.
+     */
+    private boolean hasMainlineModule() throws Exception {
+        try {
+            runPhase("hasMainlineModule");
+            return true;
+        } catch (AssertionError ignore) {
+            return false;
+        }
+    }
 }
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
index 548af0c..498cb7c 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
@@ -18,7 +18,6 @@
 
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
-
 import static java.lang.Math.max;
 import static java.lang.Math.min;
 
@@ -31,6 +30,7 @@
 import android.graphics.Insets;
 import android.os.Bundle;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
@@ -44,11 +44,11 @@
 import android.view.animation.LinearInterpolator;
 import android.widget.LinearLayout;
 
-import androidx.appcompat.app.AppCompatActivity;
-
 import java.util.ArrayList;
 import java.util.List;
 
+import androidx.appcompat.app.AppCompatActivity;
+
 public class WindowInsetsActivity extends AppCompatActivity {
 
     private View mRoot;
@@ -191,6 +191,40 @@
                 mTransitions.forEach(it -> it.onFinish(animation));
             }
         });
+
+        findViewById(R.id.floating_action_button).setOnClickListener(
+                v -> v.getWindowInsetsController().controlWindowInsetsAnimation(ime(), -1,
+                new LinearInterpolator(), null /* cancellationSignal */,
+                new WindowInsetsAnimationControlListener() {
+                    @Override
+                    public void onReady(
+                            WindowInsetsAnimationController controller,
+                            int types) {
+                        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+                        anim.setDuration(1500);
+                        anim.addUpdateListener(animation
+                                -> controller.setInsetsAndAlpha(
+                                controller.getShownStateInsets(),
+                                (float) animation.getAnimatedValue(),
+                                anim.getAnimatedFraction()));
+                        anim.addListener(new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                super.onAnimationEnd(animation);
+                                controller.finish(true);
+                            }
+                        });
+                        anim.start();
+                    }
+
+                    @Override
+                    public void onCancelled(WindowInsetsAnimationController controller) {
+                    }
+
+                    @Override
+                    public void onFinished(WindowInsetsAnimationController controller) {
+                    }
+                }));
     }
 
     @Override
@@ -200,57 +234,6 @@
         getWindow().getDecorView().post(() -> getWindow().setDecorFitsSystemWindows(false));
     }
 
-    @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        getWindow().getInsetsController().addOnControllableInsetsChangedListener(
-                new OnControllableInsetsChangedListener() {
-
-                    boolean hasControl = false;
-                    @Override
-                    public void onControllableInsetsChanged(WindowInsetsController controller,
-                            int types) {
-                        if ((types & ime()) != 0 && !hasControl) {
-                            hasControl = true;
-                            controller.controlWindowInsetsAnimation(ime(), -1,
-                                    new LinearInterpolator(), null /* cancellationSignal */,
-                                    new WindowInsetsAnimationControlListener() {
-                                        @Override
-                                        public void onReady(
-                                                WindowInsetsAnimationController controller,
-                                                int types) {
-                                            ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
-                                            anim.setDuration(1500);
-                                            anim.addUpdateListener(animation
-                                                    -> controller.setInsetsAndAlpha(
-                                                    controller.getShownStateInsets(),
-                                                    (float) animation.getAnimatedValue(),
-                                                    anim.getAnimatedFraction()));
-                                            anim.addListener(new AnimatorListenerAdapter() {
-                                                @Override
-                                                public void onAnimationEnd(Animator animation) {
-                                                    super.onAnimationEnd(animation);
-                                                    controller.finish(true);
-                                                }
-                                            });
-                                            anim.start();
-                                        }
-
-                                        @Override
-                                        public void onFinished(
-                                                WindowInsetsAnimationController controller) {
-                                        }
-
-                                        @Override
-                                        public void onCancelled(
-                                                WindowInsetsAnimationController controller) {
-                                        }
-                                    });
-                        }
-                    }
-                });
-    }
-
     static class Transition {
         private int mEndBottom;
         private int mStartBottom;
diff --git a/tests/net/common/java/android/net/DependenciesTest.java b/tests/net/common/java/android/net/DependenciesTest.java
new file mode 100644
index 0000000..ac1c28a
--- /dev/null
+++ b/tests/net/common/java/android/net/DependenciesTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A simple class that tests dependencies to java standard tools from the
+ * Network stack. These tests are not meant to be comprehensive tests of
+ * the relevant APIs : such tests belong in the relevant test suite for
+ * these dependencies. Instead, this just makes sure coverage is present
+ * by calling the methods in the exact way (or a representative way of how)
+ * they are called in the network stack.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DependenciesTest {
+    // Used to in ipmemorystore's RegularMaintenanceJobService to convert
+    // 24 hours into seconds
+    @Test
+    public void testTimeUnit() {
+        final int hours = 24;
+        final long inSeconds = TimeUnit.HOURS.toMillis(hours);
+        assertEquals(inSeconds, hours * 60 * 60 * 1000);
+    }
+
+    private byte[] makeTrivialArray(final int size) {
+        final byte[] src = new byte[size];
+        for (int i = 0; i < size; ++i) {
+            src[i] = (byte) i;
+        }
+        return src;
+    }
+
+    // Used in ApfFilter to find an IP address from a byte array
+    @Test
+    public void testArrays() {
+        final int size = 128;
+        final byte[] src = makeTrivialArray(size);
+
+        // Test copy
+        final int copySize = 16;
+        final int offset = 24;
+        final byte[] expected = new byte[copySize];
+        for (int i = 0; i < copySize; ++i) {
+            expected[i] = (byte) (offset + i);
+        }
+
+        final byte[] copy = Arrays.copyOfRange(src, offset, offset + copySize);
+        assertArrayEquals(expected, copy);
+        assertArrayEquals(new byte[0], Arrays.copyOfRange(src, size, size));
+    }
+
+    // Used mainly in the Dhcp code
+    @Test
+    public void testCopyOf() {
+        final byte[] src = makeTrivialArray(128);
+        final byte[] copy = Arrays.copyOf(src, src.length);
+        assertArrayEquals(src, copy);
+        assertFalse(src == copy);
+
+        assertArrayEquals(new byte[0], Arrays.copyOf(src, 0));
+
+        final int excess = 16;
+        final byte[] biggerCopy = Arrays.copyOf(src, src.length + excess);
+        for (int i = src.length; i < src.length + excess; ++i) {
+            assertEquals(0, biggerCopy[i]);
+        }
+        for (int i = src.length - 1; i >= 0; --i) {
+            assertEquals(src[i], biggerCopy[i]);
+        }
+    }
+
+    // Used mainly in DnsUtils but also various other places
+    @Test
+    public void testAsList() {
+        final int size = 24;
+        final Object[] src = new Object[size];
+        final ArrayList<Object> expected = new ArrayList<>(size);
+        for (int i = 0; i < size; ++i) {
+            final Object o = new Object();
+            src[i] = o;
+            expected.add(o);
+        }
+        assertEquals(expected, Arrays.asList(src));
+    }
+}
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 2b5720a..0fc9be3 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static android.net.RouteInfo.RTN_UNREACHABLE;
+
 import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
 import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
 import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip;
@@ -46,6 +48,7 @@
 import org.junit.runner.RunWith;
 
 import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -445,14 +448,20 @@
         // Check comparisons work.
         LinkProperties lp2 = new LinkProperties(lp);
         assertAllRoutesHaveInterface("wlan0", lp2);
-        assertEquals(0, lp.compareAllRoutes(lp2).added.size());
-        assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
+        // LinkProperties#compareAllRoutes exists both in R and before R, but the return type
+        // changed in R, so a test compiled with the R version of LinkProperties cannot run on Q.
+        if (isAtLeastR()) {
+            assertEquals(0, lp.compareAllRoutes(lp2).added.size());
+            assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
+        }
 
         lp2.setInterfaceName("p2p0");
         assertAllRoutesHaveInterface("p2p0", lp2);
         assertAllRoutesNotHaveInterface("wlan0", lp2);
-        assertEquals(3, lp.compareAllRoutes(lp2).added.size());
-        assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
+        if (isAtLeastR()) {
+            assertEquals(3, lp.compareAllRoutes(lp2).added.size());
+            assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
+        }
 
         // Remove route with incorrect interface, no route removed.
         lp.removeRoute(new RouteInfo(prefix2, null, null));
@@ -480,6 +489,8 @@
         assertEquals(1, rmnet0.getLinkAddresses().size());
         assertEquals(1, rmnet0.getAllAddresses().size());
         assertEquals(1, rmnet0.getAllLinkAddresses().size());
+        assertEquals(1, rmnet0.getAllInterfaceNames().size());
+        assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
 
         rmnet0.addStackedLink(clat4);
         assertEquals(1, rmnet0.getStackedLinks().size());
@@ -487,6 +498,9 @@
         assertEquals(1, rmnet0.getLinkAddresses().size());
         assertEquals(2, rmnet0.getAllAddresses().size());
         assertEquals(2, rmnet0.getAllLinkAddresses().size());
+        assertEquals(2, rmnet0.getAllInterfaceNames().size());
+        assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
+        assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1));
 
         rmnet0.addStackedLink(clat4);
         assertEquals(1, rmnet0.getStackedLinks().size());
@@ -494,6 +508,9 @@
         assertEquals(1, rmnet0.getLinkAddresses().size());
         assertEquals(2, rmnet0.getAllAddresses().size());
         assertEquals(2, rmnet0.getAllLinkAddresses().size());
+        assertEquals(2, rmnet0.getAllInterfaceNames().size());
+        assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
+        assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1));
 
         assertEquals(0, clat4.getStackedLinks().size());
 
@@ -513,6 +530,8 @@
         assertEquals(1, rmnet0.getLinkAddresses().size());
         assertEquals(1, rmnet0.getAllAddresses().size());
         assertEquals(1, rmnet0.getAllLinkAddresses().size());
+        assertEquals(1, rmnet0.getAllInterfaceNames().size());
+        assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
 
         assertFalse(rmnet0.removeStackedLink("clat4"));
     }
@@ -936,7 +955,7 @@
 
     }
 
-    @Test
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testCompareResult() {
         // Either adding or removing items
         compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
@@ -1197,4 +1216,70 @@
         lp.clear();
         assertNull(lp.getCaptivePortalData());
     }
+
+    private LinkProperties makeIpv4LinkProperties() {
+        final LinkProperties linkProperties = new LinkProperties();
+        linkProperties.setInterfaceName(NAME);
+        linkProperties.addLinkAddress(LINKADDRV4);
+        linkProperties.addDnsServer(DNS1);
+        linkProperties.addRoute(new RouteInfo(GATEWAY1));
+        linkProperties.addRoute(new RouteInfo(GATEWAY2));
+        return linkProperties;
+    }
+
+    private LinkProperties makeIpv6LinkProperties() {
+        final LinkProperties linkProperties = new LinkProperties();
+        linkProperties.setInterfaceName(NAME);
+        linkProperties.addLinkAddress(LINKADDRV6);
+        linkProperties.addDnsServer(DNS6);
+        linkProperties.addRoute(new RouteInfo(GATEWAY61));
+        linkProperties.addRoute(new RouteInfo(GATEWAY62));
+        return linkProperties;
+    }
+
+    @Test
+    public void testHasIpv4DefaultRoute() {
+        final LinkProperties Ipv4 = makeIpv4LinkProperties();
+        assertTrue(Ipv4.hasIpv4DefaultRoute());
+        final LinkProperties Ipv6 = makeIpv6LinkProperties();
+        assertFalse(Ipv6.hasIpv4DefaultRoute());
+    }
+
+    @Test
+    public void testHasIpv4DnsServer() {
+        final LinkProperties Ipv4 = makeIpv4LinkProperties();
+        assertTrue(Ipv4.hasIpv4DnsServer());
+        final LinkProperties Ipv6 = makeIpv6LinkProperties();
+        assertFalse(Ipv6.hasIpv4DnsServer());
+    }
+
+    @Test
+    public void testHasIpv6DnsServer() {
+        final LinkProperties Ipv4 = makeIpv4LinkProperties();
+        assertFalse(Ipv4.hasIpv6DnsServer());
+        final LinkProperties Ipv6 = makeIpv6LinkProperties();
+        assertTrue(Ipv6.hasIpv6DnsServer());
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testHasIpv4UnreachableDefaultRoute() {
+        final LinkProperties lp = makeTestObject();
+        assertFalse(lp.hasIpv4UnreachableDefaultRoute());
+        assertFalse(lp.hasIpv6UnreachableDefaultRoute());
+
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
+        assertTrue(lp.hasIpv4UnreachableDefaultRoute());
+        assertFalse(lp.hasIpv6UnreachableDefaultRoute());
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testHasIpv6UnreachableDefaultRoute() {
+        final LinkProperties lp = makeTestObject();
+        assertFalse(lp.hasIpv6UnreachableDefaultRoute());
+        assertFalse(lp.hasIpv4UnreachableDefaultRoute());
+
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
+        assertTrue(lp.hasIpv6UnreachableDefaultRoute());
+        assertFalse(lp.hasIpv4UnreachableDefaultRoute());
+    }
 }
diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt
new file mode 100644
index 0000000..ef15b66
--- /dev/null
+++ b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.wifi.aware.DiscoverySession
+import android.net.wifi.aware.PeerHandle
+import android.net.wifi.aware.WifiAwareNetworkSpecifier
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+
+import com.android.testutils.assertParcelSane
+
+import java.lang.IllegalStateException
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class MatchAllNetworkSpecifierTest {
+    @Test
+    fun testParcel() {
+        assertParcelSane(MatchAllNetworkSpecifier(), 0)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun testSatisfiedBy() {
+        val specifier = MatchAllNetworkSpecifier()
+        val discoverySession = Mockito.mock(DiscoverySession::class.java)
+        val peerHandle = Mockito.mock(PeerHandle::class.java)
+        val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession,
+                peerHandle).build()
+        specifier.satisfiedBy(wifiAwareNetworkSpecifier)
+    }
+}
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 316a83a..3f8261d 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -17,6 +17,8 @@
 package android.net;
 
 import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+import static android.net.NetworkCapabilities.MAX_TRANSPORT;
+import static android.net.NetworkCapabilities.MIN_TRANSPORT;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
@@ -32,10 +34,12 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
 import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
+import static android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
 import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
 
 import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
@@ -45,18 +49,28 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.net.wifi.aware.DiscoverySession;
+import android.net.wifi.aware.PeerHandle;
+import android.net.wifi.aware.WifiAwareNetworkSpecifier;
 import android.os.Build;
+import android.os.Process;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
 
 import androidx.core.os.BuildCompat;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 
 import java.util.Arrays;
 import java.util.Set;
@@ -67,6 +81,12 @@
     private static final String TEST_SSID = "TEST_SSID";
     private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID";
 
+    @Rule
+    public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
+
+    private DiscoverySession mDiscoverySession = Mockito.mock(DiscoverySession.class);
+    private PeerHandle mPeerHandle = Mockito.mock(PeerHandle.class);
+
     private boolean isAtLeastR() {
         // BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R.
         // Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after
@@ -441,7 +461,7 @@
         return range;
     }
 
-    @Test
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testSetAdministratorUids() {
         NetworkCapabilities nc =
                 new NetworkCapabilities().setAdministratorUids(new int[] {2, 1, 3});
@@ -449,7 +469,7 @@
         assertArrayEquals(new int[] {1, 2, 3}, nc.getAdministratorUids());
     }
 
-    @Test
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testSetAdministratorUidsWithDuplicates() {
         try {
             new NetworkCapabilities().setAdministratorUids(new int[] {1, 1});
@@ -510,6 +530,12 @@
         assertFalse(nc2.appliesToUid(12));
         assertTrue(nc1.appliesToUid(22));
         assertTrue(nc2.appliesToUid(22));
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testCombineCapabilities_AdministratorUids() {
+        final NetworkCapabilities nc1 = new NetworkCapabilities();
+        final NetworkCapabilities nc2 = new NetworkCapabilities();
 
         final int[] adminUids = {3, 6, 12};
         nc1.setAdministratorUids(adminUids);
@@ -518,7 +544,7 @@
         assertArrayEquals(nc2.getAdministratorUids(), adminUids);
 
         final int[] adminUidsOtherOrder = {3, 12, 6};
-        nc1.setAdministratorUids(adminUids);
+        nc1.setAdministratorUids(adminUidsOtherOrder);
         assertTrue(nc2.equalsAdministratorUids(nc1));
 
         final int[] adminUids2 = {11, 1, 12, 3, 6};
@@ -672,4 +698,238 @@
         assertEquals(TRANSPORT_VPN, transportTypes[2]);
         assertEquals(TRANSPORT_TEST, transportTypes[3]);
     }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testTelephonyNetworkSpecifier() {
+        final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1);
+        final NetworkCapabilities nc1 = new NetworkCapabilities.Builder()
+                .addTransportType(TRANSPORT_WIFI)
+                .setNetworkSpecifier(specifier)
+                .build();
+        assertEquals(specifier, nc1.getNetworkSpecifier());
+        try {
+            final NetworkCapabilities nc2 = new NetworkCapabilities.Builder()
+                    .setNetworkSpecifier(specifier)
+                    .build();
+            fail("Must have a single transport type. Without transport type or multiple transport"
+                    + " types is invalid.");
+        } catch (IllegalStateException expected) { }
+    }
+
+    @Test
+    public void testWifiAwareNetworkSpecifier() {
+        final NetworkCapabilities nc = new NetworkCapabilities()
+                .addTransportType(TRANSPORT_WIFI_AWARE);
+        // If NetworkSpecifier is not set, the default value is null.
+        assertNull(nc.getNetworkSpecifier());
+        final WifiAwareNetworkSpecifier specifier = new WifiAwareNetworkSpecifier.Builder(
+                mDiscoverySession, mPeerHandle).build();
+        nc.setNetworkSpecifier(specifier);
+        assertEquals(specifier, nc.getNetworkSpecifier());
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testAdministratorUidsAndOwnerUid() {
+        // Test default owner uid.
+        // If the owner uid is not set, the default value should be Process.INVALID_UID.
+        final NetworkCapabilities nc1 = new NetworkCapabilities.Builder().build();
+        assertEquals(Process.INVALID_UID, nc1.getOwnerUid());
+        // Test setAdministratorUids and getAdministratorUids.
+        final int[] administratorUids = {1001, 10001};
+        final NetworkCapabilities nc2 = new NetworkCapabilities.Builder()
+                .setAdministratorUids(administratorUids)
+                .build();
+        assertTrue(Arrays.equals(administratorUids, nc2.getAdministratorUids()));
+        // Test setOwnerUid and getOwnerUid.
+        // The owner UID must be included in administrator UIDs, or throw IllegalStateException.
+        try {
+            final NetworkCapabilities nc3 = new NetworkCapabilities.Builder()
+                    .setOwnerUid(1001)
+                    .build();
+            fail("The owner UID must be included in administrator UIDs.");
+        } catch (IllegalStateException expected) { }
+        final NetworkCapabilities nc4 = new NetworkCapabilities.Builder()
+                .setAdministratorUids(administratorUids)
+                .setOwnerUid(1001)
+                .build();
+        assertEquals(1001, nc4.getOwnerUid());
+        try {
+            final NetworkCapabilities nc5 = new NetworkCapabilities.Builder()
+                    .setAdministratorUids(null)
+                    .build();
+            fail("Should not set null into setAdministratorUids");
+        } catch (NullPointerException expected) { }
+    }
+
+    @Test
+    public void testLinkBandwidthKbps() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        // The default value of LinkDown/UpstreamBandwidthKbps should be LINK_BANDWIDTH_UNSPECIFIED.
+        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, nc.getLinkDownstreamBandwidthKbps());
+        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, nc.getLinkUpstreamBandwidthKbps());
+        nc.setLinkDownstreamBandwidthKbps(512);
+        nc.setLinkUpstreamBandwidthKbps(128);
+        assertEquals(512, nc.getLinkDownstreamBandwidthKbps());
+        assertNotEquals(128, nc.getLinkDownstreamBandwidthKbps());
+        assertEquals(128, nc.getLinkUpstreamBandwidthKbps());
+        assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps());
+    }
+
+    @Test
+    public void testSignalStrength() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        // The default value of signal strength should be SIGNAL_STRENGTH_UNSPECIFIED.
+        assertEquals(SIGNAL_STRENGTH_UNSPECIFIED, nc.getSignalStrength());
+        nc.setSignalStrength(-80);
+        assertEquals(-80, nc.getSignalStrength());
+        assertNotEquals(-50, nc.getSignalStrength());
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testDeduceRestrictedCapability() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        // Default capabilities don't have restricted capability.
+        assertFalse(nc.deduceRestrictedCapability());
+        // If there is a force restricted capability, then the network capabilities is restricted.
+        nc.addCapability(NET_CAPABILITY_OEM_PAID);
+        nc.addCapability(NET_CAPABILITY_INTERNET);
+        assertTrue(nc.deduceRestrictedCapability());
+        // Except for the force restricted capability, if there is any unrestricted capability in
+        // capabilities, then the network capabilities is not restricted.
+        nc.removeCapability(NET_CAPABILITY_OEM_PAID);
+        nc.addCapability(NET_CAPABILITY_CBS);
+        assertFalse(nc.deduceRestrictedCapability());
+        // Except for the force restricted capability, the network capabilities will only be treated
+        // as restricted when there is no any unrestricted capability.
+        nc.removeCapability(NET_CAPABILITY_INTERNET);
+        assertTrue(nc.deduceRestrictedCapability());
+    }
+
+    private void assertNoTransport(NetworkCapabilities nc) {
+        for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
+            assertFalse(nc.hasTransport(i));
+        }
+    }
+
+    // Checks that all transport types from MIN_TRANSPORT to maxTransportType are set and all
+    // transport types from maxTransportType + 1 to MAX_TRANSPORT are not set when positiveSequence
+    // is true. If positiveSequence is false, then the check sequence is opposite.
+    private void checkCurrentTransportTypes(NetworkCapabilities nc, int maxTransportType,
+            boolean positiveSequence) {
+        for (int i = MIN_TRANSPORT; i <= maxTransportType; i++) {
+            if (positiveSequence) {
+                assertTrue(nc.hasTransport(i));
+            } else {
+                assertFalse(nc.hasTransport(i));
+            }
+        }
+        for (int i = MAX_TRANSPORT; i > maxTransportType; i--) {
+            if (positiveSequence) {
+                assertFalse(nc.hasTransport(i));
+            } else {
+                assertTrue(nc.hasTransport(i));
+            }
+        }
+    }
+
+    @Test
+    public void testMultipleTransportTypes() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        assertNoTransport(nc);
+        // Test adding multiple transport types.
+        for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
+            nc.addTransportType(i);
+            checkCurrentTransportTypes(nc, i, true /* positiveSequence */);
+        }
+        // Test removing multiple transport types.
+        for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
+            nc.removeTransportType(i);
+            checkCurrentTransportTypes(nc, i, false /* positiveSequence */);
+        }
+        assertNoTransport(nc);
+        nc.addTransportType(TRANSPORT_WIFI);
+        assertTrue(nc.hasTransport(TRANSPORT_WIFI));
+        assertFalse(nc.hasTransport(TRANSPORT_VPN));
+        nc.addTransportType(TRANSPORT_VPN);
+        assertTrue(nc.hasTransport(TRANSPORT_WIFI));
+        assertTrue(nc.hasTransport(TRANSPORT_VPN));
+        nc.removeTransportType(TRANSPORT_WIFI);
+        assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+        assertTrue(nc.hasTransport(TRANSPORT_VPN));
+        nc.removeTransportType(TRANSPORT_VPN);
+        assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+        assertFalse(nc.hasTransport(TRANSPORT_VPN));
+        assertNoTransport(nc);
+    }
+
+    @Test
+    public void testAddAndRemoveTransportType() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        try {
+            nc.addTransportType(-1);
+            fail("Should not set invalid transport type into addTransportType");
+        } catch (IllegalArgumentException expected) { }
+        try {
+            nc.removeTransportType(-1);
+            fail("Should not set invalid transport type into removeTransportType");
+        } catch (IllegalArgumentException e) { }
+    }
+
+    private class TestTransportInfo implements TransportInfo {
+        TestTransportInfo() {
+        }
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testBuilder() {
+        final int ownerUid = 1001;
+        final int signalStrength = -80;
+        final int requestUid = 10100;
+        final int[] administratorUids = {ownerUid, 10001};
+        final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1);
+        final TestTransportInfo transportInfo = new TestTransportInfo();
+        final String ssid = "TEST_SSID";
+        final String packageName = "com.google.test.networkcapabilities";
+        final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+                .addTransportType(TRANSPORT_WIFI)
+                .addTransportType(TRANSPORT_CELLULAR)
+                .removeTransportType(TRANSPORT_CELLULAR)
+                .addCapability(NET_CAPABILITY_EIMS)
+                .addCapability(NET_CAPABILITY_CBS)
+                .removeCapability(NET_CAPABILITY_CBS)
+                .setAdministratorUids(administratorUids)
+                .setOwnerUid(ownerUid)
+                .setLinkDownstreamBandwidthKbps(512)
+                .setLinkUpstreamBandwidthKbps(128)
+                .setNetworkSpecifier(specifier)
+                .setTransportInfo(transportInfo)
+                .setSignalStrength(signalStrength)
+                .setSsid(ssid)
+                .setRequestorUid(requestUid)
+                .setRequestorPackageName(packageName)
+                .build();
+        assertEquals(1, nc.getTransportTypes().length);
+        assertEquals(TRANSPORT_WIFI, nc.getTransportTypes()[0]);
+        assertTrue(nc.hasCapability(NET_CAPABILITY_EIMS));
+        assertFalse(nc.hasCapability(NET_CAPABILITY_CBS));
+        assertTrue(Arrays.equals(administratorUids, nc.getAdministratorUids()));
+        assertEquals(ownerUid, nc.getOwnerUid());
+        assertEquals(512, nc.getLinkDownstreamBandwidthKbps());
+        assertNotEquals(128, nc.getLinkDownstreamBandwidthKbps());
+        assertEquals(128, nc.getLinkUpstreamBandwidthKbps());
+        assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps());
+        assertEquals(specifier, nc.getNetworkSpecifier());
+        assertEquals(transportInfo, nc.getTransportInfo());
+        assertEquals(signalStrength, nc.getSignalStrength());
+        assertNotEquals(-50, nc.getSignalStrength());
+        assertEquals(ssid, nc.getSsid());
+        assertEquals(requestUid, nc.getRequestorUid());
+        assertEquals(packageName, nc.getRequestorPackageName());
+        // Cannot assign null into NetworkCapabilities.Builder
+        try {
+            final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(null);
+            fail("Should not set null into NetworkCapabilities.Builder");
+        } catch (NullPointerException expected) { }
+        assertEquals(nc, new NetworkCapabilities.Builder(nc).build());
+    }
 }
diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java
index 1658262..8204b49 100644
--- a/tests/net/common/java/android/net/RouteInfoTest.java
+++ b/tests/net/common/java/android/net/RouteInfoTest.java
@@ -31,6 +31,7 @@
 
 import android.os.Build;
 
+import androidx.core.os.BuildCompat;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -62,6 +63,11 @@
         return new IpPrefix(prefix);
     }
 
+    private static boolean isAtLeastR() {
+        // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R)
+        return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR();
+    }
+
     @Test
     public void testConstructor() {
         RouteInfo r;
@@ -195,78 +201,130 @@
         assertTrue(r.isDefaultRoute());
         assertTrue(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("::/0"), Address("::"), "wlan0");
         assertFalse(r.isHostRoute());
         assertTrue(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertTrue(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0");
         assertFalse(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("2001:db8::/48"), null, "wlan0");
         assertFalse(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("192.0.2.0/32"), Address("0.0.0.0"), "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("2001:db8::/128"), Address("::"), "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("192.0.2.0/32"), null, "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("2001:db8::/128"), null, "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("::/128"), Address("fe80::"), "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0");
         assertTrue(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE);
         assertFalse(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertTrue(r.isIPv4UnreachableDefault());
+            assertFalse(r.isIPv6UnreachableDefault());
+        }
 
         r = new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE);
         assertFalse(r.isHostRoute());
         assertFalse(r.isDefaultRoute());
         assertFalse(r.isIPv4Default());
         assertFalse(r.isIPv6Default());
+        if (isAtLeastR()) {
+            assertFalse(r.isIPv4UnreachableDefault());
+            assertTrue(r.isIPv6UnreachableDefault());
+        }
     }
 
     @Test
diff --git a/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt b/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt
new file mode 100644
index 0000000..7b22e45
--- /dev/null
+++ b/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.netstats
+
+import android.net.NetworkStats
+import android.net.NetworkStats.DEFAULT_NETWORK_NO
+import android.net.NetworkStats.DEFAULT_NETWORK_YES
+import android.net.NetworkStats.Entry
+import android.net.NetworkStats.IFACE_VT
+import android.net.NetworkStats.METERED_NO
+import android.net.NetworkStats.METERED_YES
+import android.net.NetworkStats.ROAMING_NO
+import android.net.NetworkStats.ROAMING_YES
+import android.net.NetworkStats.SET_DEFAULT
+import android.net.NetworkStats.SET_FOREGROUND
+import android.net.NetworkStats.TAG_NONE
+import android.os.Build
+import androidx.test.filters.SmallTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.assertFieldCountEquals
+import com.android.testutils.assertNetworkStatsEquals
+import com.android.testutils.assertParcelingIsLossless
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.test.assertEquals
+
+@RunWith(JUnit4::class)
+@SmallTest
+class NetworkStatsApiTest {
+    @Rule
+    @JvmField
+    val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q)
+
+    private val testStatsEmpty = NetworkStats(0L, 0)
+
+    // Note that these variables need to be initialized outside of constructor, initialize
+    // here with methods that don't exist in Q devices will result in crash.
+
+    // stats1 and stats2 will have some entries with common keys, which are expected to
+    // be merged if performing add on these 2 stats.
+    private lateinit var testStats1: NetworkStats
+    private lateinit var testStats2: NetworkStats
+
+    // This is a result of adding stats1 and stats2, while the merging of common key items is
+    // subject to test later, this should not be initialized with for a loop to add stats1
+    // and stats2 above.
+    private lateinit var testStats3: NetworkStats
+
+    companion object {
+        private const val TEST_IFACE = "test0"
+        private const val TEST_UID1 = 1001
+        private const val TEST_UID2 = 1002
+    }
+
+    @Before
+    fun setUp() {
+        testStats1 = NetworkStats(0L, 0)
+                // Entries which only appear in set1.
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 37, 52, 1, 10, 4))
+                // Entries which are common for set1 and set2.
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 17, 2, 11, 1, 0))
+                .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 40, 1, 0, 0, 8))
+                .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 1, 6, 2, 0))
+        assertEquals(8, testStats1.size())
+
+        testStats2 = NetworkStats(0L, 0)
+                // Entries which are common for set1 and set2.
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45))
+                .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7))
+                .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0))
+                // Entry which only appears in set2.
+                .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0))
+        assertEquals(5, testStats2.size())
+
+        testStats3 = NetworkStats(0L, 9)
+                // Entries which are unique either in stats1 or stats2.
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2))
+                .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0))
+                // Entries which are common for stats1 and stats2 are being merged.
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 20, 17, 13, 32, 1))
+                .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 50, 113, 11, 11, 49))
+                .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51, 3, 3, 4, 15))
+                .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 7, 4, 8, 3, 0))
+        assertEquals(9, testStats3.size())
+    }
+
+    @Test
+    fun testAddEntry() {
+        val expectedEntriesInStats2 = arrayOf(
+                Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1),
+                Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45),
+                Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7),
+                Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0),
+                Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0))
+
+        // While testStats* are already initialized with addEntry, verify content added
+        // matches expectation.
+        for (i in expectedEntriesInStats2.indices) {
+            val entry = testStats2.getValues(i, null)
+            assertEquals(expectedEntriesInStats2[i], entry)
+        }
+
+        // Verify entry updated with addEntry.
+        val stats = testStats2.addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12, -5, 7, 0, 9))
+        assertEquals(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE,
+                METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 16, -2, 9, 1, 9),
+                stats.getValues(3, null))
+    }
+
+    @Test
+    fun testAdd() {
+        var stats = NetworkStats(0L, 0)
+        assertNetworkStatsEquals(testStatsEmpty, stats)
+        stats = stats.add(testStats2)
+        assertNetworkStatsEquals(testStats2, stats)
+        stats = stats.add(testStats1)
+        // EMPTY + STATS2 + STATS1 = STATS3
+        assertNetworkStatsEquals(testStats3, stats)
+    }
+
+    @Test
+    fun testParcelUnparcel() {
+        assertParcelingIsLossless(testStatsEmpty)
+        assertParcelingIsLossless(testStats1)
+        assertParcelingIsLossless(testStats2)
+        assertFieldCountEquals(15, NetworkStats::class.java)
+    }
+
+    @Test
+    fun testDescribeContents() {
+        assertEquals(0, testStatsEmpty.describeContents())
+        assertEquals(0, testStats1.describeContents())
+        assertEquals(0, testStats2.describeContents())
+        assertEquals(0, testStats3.describeContents())
+    }
+
+    @Test
+    fun testSubtract() {
+        // STATS3 - STATS2 = STATS1
+        assertNetworkStatsEquals(testStats1, testStats3.subtract(testStats2))
+        // STATS3 - STATS1 = STATS2
+        assertNetworkStatsEquals(testStats2, testStats3.subtract(testStats1))
+    }
+
+    @Test
+    fun testMethodsDontModifyReceiver() {
+        listOf(testStatsEmpty, testStats1, testStats2, testStats3).forEach {
+            val origStats = it.clone()
+            it.addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE,
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45))
+            it.add(testStats3)
+            it.subtract(testStats1)
+            assertNetworkStatsEquals(origStats, it)
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index e71d599..98f705f 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -503,6 +503,53 @@
     }
 
     @Test
+    public void testRemoveEmptyEntries() throws Exception {
+        // Test empty stats.
+        final NetworkStats statsEmpty = new NetworkStats(TEST_START, 3);
+        assertEquals(0, statsEmpty.removeEmptyEntries().size());
+
+        // Test stats with non-zero entry.
+        final NetworkStats statsNonZero = new NetworkStats(TEST_START, 1)
+                .insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO,
+                        ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L);
+        assertEquals(1, statsNonZero.size());
+        final NetworkStats expectedNonZero = statsNonZero.removeEmptyEntries();
+        assertEquals(1, expectedNonZero.size());
+        assertValues(expectedNonZero, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L);
+
+        // Test stats with empty entry.
+        final NetworkStats statsZero = new NetworkStats(TEST_START, 1)
+                .insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO,
+                        ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
+        assertEquals(1, statsZero.size());
+        final NetworkStats expectedZero = statsZero.removeEmptyEntries();
+        assertEquals(1, statsZero.size()); // Assert immutable.
+        assertEquals(0, expectedZero.size());
+
+        // Test stats with multiple entries.
+        final NetworkStats statsMultiple = new NetworkStats(TEST_START, 0)
+                .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
+                .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
+                .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 0L)
+                .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 0L)
+                .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
+                .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 0L, 8L, 0L, 0L, 0L)
+                .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 4L, 0L, 0L)
+                .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 2L, 0L)
+                .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 1L);
+        assertEquals(9, statsMultiple.size());
+        final NetworkStats expectedMultiple = statsMultiple.removeEmptyEntries();
+        assertEquals(9, statsMultiple.size()); // Assert immutable.
+        assertEquals(7, expectedMultiple.size());
+        assertValues(expectedMultiple.getTotalIncludingTags(null), 14L, 104L, 4L, 4L, 21L);
+
+        // Test stats with multiple empty entries.
+        assertEquals(statsMultiple.size(), statsMultiple.subtract(statsMultiple).size());
+        assertEquals(0, statsMultiple.subtract(statsMultiple).removeEmptyEntries().size());
+    }
+
+    @Test
     public void testClone() throws Exception {
         final NetworkStats original = new NetworkStats(TEST_START, 5)
                 .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b02398d..912a27f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -6336,6 +6336,7 @@
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
         // The uid range needs to cover the test app so the network is visible to it.
         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
@@ -6361,6 +6362,7 @@
     public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
@@ -6392,6 +6394,7 @@
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
         final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
         final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange);
@@ -6428,6 +6431,7 @@
         reset(mMockNetd);
         lp = new LinkProperties();
         lp.setInterfaceName("tun1");
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         vpnNetworkAgent.sendLinkProperties(lp);
         waitForIdle();
@@ -6440,6 +6444,7 @@
     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
+        lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
         final UidRange vpnRange = UidRange.createForUser(VPN_USER);
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index 9b24887..d0ebb52 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -181,7 +181,7 @@
         Nat464Xlat nat = makeNat464Xlat();
         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
 
-        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+        nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX));
 
         // Start clat.
         nat.start();
@@ -222,7 +222,7 @@
         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
         InOrder inOrder = inOrder(mNetd, mConnectivity);
 
-        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+        nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX));
 
         nat.start();
 
@@ -309,7 +309,7 @@
         Nat464Xlat nat = makeNat464Xlat();
         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
 
-        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+        nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX));
 
         nat.start();
 
@@ -348,7 +348,7 @@
     public void testStopBeforeClatdStarts() throws Exception {
         Nat464Xlat nat = makeNat464Xlat();
 
-        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+        nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX));
 
         nat.start();
 
@@ -380,7 +380,7 @@
     public void testStopAndClatdNeverStarts() throws Exception {
         Nat464Xlat nat = makeNat464Xlat();
 
-        nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX));
+        nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX));
 
         nat.start();
 
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 1387bb5..526876f 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -50,7 +50,7 @@
       primaryFields(that.primaryFields),
       exclusiveField(that.exclusiveField),
       defaultState(that.defaultState),
-      resetState(that.resetState),
+      triggerStateReset(that.triggerStateReset),
       nested(that.nested),
       uidField(that.uidField),
       whitelisted(that.whitelisted),
@@ -153,7 +153,8 @@
 }
 
 static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
-                                    const int annotationId, const AnnotationType annotationType,
+                                    const AnnotationId annotationId,
+                                    const AnnotationType annotationType,
                                     const AnnotationValue annotationValue) {
     if (dbg) {
         printf("   Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
@@ -168,23 +169,35 @@
     int errorCount = 0;
 
     if (field->options().HasExtension(os::statsd::state_field_option)) {
-        const int option = field->options().GetExtension(os::statsd::state_field_option).option();
-        if (option != STATE_OPTION_UNSET) {
-            addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_OPTION,
-                                    ANNOTATION_TYPE_INT, AnnotationValue(option));
+        const os::statsd::StateAtomFieldOption& stateFieldOption =
+                field->options().GetExtension(os::statsd::state_field_option);
+        const bool primaryField = stateFieldOption.primary_field();
+        const bool exclusiveState = stateFieldOption.exclusive_state();
+        const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid();
+
+        // Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid.
+        if (primaryField + primaryFieldFirstUid + exclusiveState > 1) {
+            print_error(field,
+                        "Field can be max 1 of primary_field, exclusive_state, "
+                        "or primary_field_first_uid: '%s'\n",
+                        atomDecl->message.c_str());
+            errorCount++;
         }
 
-        if (option == STATE_OPTION_PRIMARY) {
+        if (primaryField) {
             if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
                 javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
                 print_error(field, "Invalid primary state field: '%s'\n",
                             atomDecl->message.c_str());
                 errorCount++;
+            } else {
+                atomDecl->primaryFields.push_back(fieldNumber);
+                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD,
+                                        ANNOTATION_TYPE_BOOL, AnnotationValue(true));
             }
-            atomDecl->primaryFields.push_back(fieldNumber);
         }
 
-        if (option == STATE_OPTION_PRIMARY_FIELD_FIRST_UID) {
+        if (primaryFieldFirstUid) {
             if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
                 print_error(field,
                             "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
@@ -193,10 +206,13 @@
                 errorCount++;
             } else {
                 atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
+                addAnnotationToAtomDecl(atomDecl, fieldNumber,
+                                        ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL,
+                                        AnnotationValue(true));
             }
         }
 
-        if (option == STATE_OPTION_EXCLUSIVE) {
+        if (exclusiveState) {
             if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
                 javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
                 print_error(field, "Invalid exclusive state field: '%s'\n",
@@ -204,43 +220,36 @@
                 errorCount++;
             }
 
-            if (atomDecl->exclusiveField == 0) {
-                atomDecl->exclusiveField = fieldNumber;
-            } else {
+            if (atomDecl->exclusiveField != 0) {
                 print_error(field,
                             "Cannot have more than one exclusive state field in an "
                             "atom: '%s'\n",
                             atomDecl->message.c_str());
                 errorCount++;
+            } else {
+                atomDecl->exclusiveField = fieldNumber;
+                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE,
+                                        ANNOTATION_TYPE_BOOL, AnnotationValue(true));
             }
 
-            if (field->options()
-                        .GetExtension(os::statsd::state_field_option)
-                        .has_default_state_value()) {
-                const int defaultState = field->options()
-                                                 .GetExtension(os::statsd::state_field_option)
-                                                 .default_state_value();
+            if (stateFieldOption.has_default_state_value()) {
+                const int defaultState = stateFieldOption.default_state_value();
                 atomDecl->defaultState = defaultState;
 
                 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
                                         ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
             }
 
-            if (field->options()
-                        .GetExtension(os::statsd::state_field_option)
-                        .has_reset_state_value()) {
-                const int resetState = field->options()
-                                               .GetExtension(os::statsd::state_field_option)
-                                               .reset_state_value();
+            if (stateFieldOption.has_trigger_state_reset_value()) {
+                const int triggerStateReset = stateFieldOption.trigger_state_reset_value();
 
-                atomDecl->resetState = resetState;
-                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_RESET_STATE,
-                                        ANNOTATION_TYPE_INT, AnnotationValue(resetState));
+                atomDecl->triggerStateReset = triggerStateReset;
+                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET,
+                                        ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset));
             }
 
-            if (field->options().GetExtension(os::statsd::state_field_option).has_nested()) {
-                const bool nested =
-                        field->options().GetExtension(os::statsd::state_field_option).nested();
+            if (stateFieldOption.has_nested()) {
+                const bool nested = stateFieldOption.nested();
                 atomDecl->nested = nested;
 
                 addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index b1cf134..b513463e 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -18,6 +18,7 @@
 #define ANDROID_STATS_LOG_API_GEN_COLLATION_H
 
 #include <google/protobuf/descriptor.h>
+#include <stdint.h>
 
 #include <map>
 #include <set>
@@ -40,17 +41,16 @@
 
 const int FIRST_UID_IN_CHAIN_ID = 0;
 
-const unsigned char ANNOTATION_ID_IS_UID = 1;
-const unsigned char ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
-const unsigned char ANNOTATION_ID_STATE_OPTION = 3;
-const unsigned char ANNOTATION_ID_DEFAULT_STATE = 4;
-const unsigned char ANNOTATION_ID_RESET_STATE = 5;
-const unsigned char ANNOTATION_ID_STATE_NESTED = 6;
-
-const int STATE_OPTION_UNSET = os::statsd::StateField::STATE_FIELD_UNSET;
-const int STATE_OPTION_EXCLUSIVE = os::statsd::StateField::EXCLUSIVE_STATE;
-const int STATE_OPTION_PRIMARY_FIELD_FIRST_UID = os::statsd::StateField::PRIMARY_FIELD_FIRST_UID;
-const int STATE_OPTION_PRIMARY = os::statsd::StateField::PRIMARY_FIELD;
+enum AnnotationId : uint8_t {
+    ANNOTATION_ID_IS_UID = 1,
+    ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2,
+    ANNOTATION_ID_PRIMARY_FIELD = 3,
+    ANNOTATION_ID_EXCLUSIVE_STATE = 4,
+    ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5,
+    ANNOTATION_ID_DEFAULT_STATE = 6,
+    ANNOTATION_ID_TRIGGER_STATE_RESET = 7,
+    ANNOTATION_ID_STATE_NESTED = 8,
+};
 
 const int ATOM_ID_FIELD_NUMBER = -1;
 
@@ -93,12 +93,12 @@
 };
 
 struct Annotation {
-    const unsigned char annotationId;
+    const AnnotationId annotationId;
     const int atomId;
     AnnotationType type;
     AnnotationValue value;
 
-    inline Annotation(unsigned char annotationId, int atomId, AnnotationType type,
+    inline Annotation(AnnotationId annotationId, int atomId, AnnotationType type,
                       AnnotationValue value)
         : annotationId(annotationId), atomId(atomId), type(type), value(value) {
     }
@@ -159,8 +159,8 @@
     vector<int> primaryFields;
     int exclusiveField = 0;
     int defaultState = INT_MAX;
-    int resetState = INT_MAX;
-    bool nested;
+    int triggerStateReset = INT_MAX;
+    bool nested = true;
 
     int uidField = 0;
 
diff --git a/tools/stats_log_api_gen/atoms_info_writer.cpp b/tools/stats_log_api_gen/atoms_info_writer.cpp
index 862fed4..23a0f72 100644
--- a/tools/stats_log_api_gen/atoms_info_writer.cpp
+++ b/tools/stats_log_api_gen/atoms_info_writer.cpp
@@ -151,8 +151,8 @@
             fprintf(out, "    opt->defaultState = UNSET_VALUE;\n");
         }
 
-        if ((*atomIt)->resetState != INT_MAX) {
-            fprintf(out, "    opt->resetState = %d;\n", (*atomIt)->resetState);
+        if ((*atomIt)->triggerStateReset != INT_MAX) {
+            fprintf(out, "    opt->resetState = %d;\n", (*atomIt)->triggerStateReset);
         } else {
             fprintf(out, "    opt->resetState = UNSET_VALUE;\n");
         }
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 3eabb14..556cf5e 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -39,6 +39,15 @@
     return 0;
 }
 
+static void write_java_annotation_constants(FILE* out) {
+    fprintf(out, "    // Annotation constants.\n");
+
+    for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
+        fprintf(out, "    public static final byte %s = %hhu;\n", name.c_str(), id);
+    }
+    fprintf(out, "\n");
+}
+
 static void write_annotations(FILE* out, int argIndex,
                               const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet) {
     FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
@@ -48,32 +57,27 @@
     }
     const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
     for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
-        fprintf(out, "        if (code == %d) {\n", atomDecl->code);
+        const string atomConstant = make_constant_name(atomDecl->name);
+        fprintf(out, "        if (%s == code) {\n", atomConstant.c_str());
         const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
         int resetState = -1;
         int defaultState = -1;
         for (const shared_ptr<Annotation>& annotation : annotations) {
-            // TODO(b/151786433): Write atom constant name instead of atom id literal.
+            const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
             switch (annotation->type) {
-                // TODO(b/151776731): Check for reset state annotation and only include
-                // reset state when field value == default state annotation value.
                 case ANNOTATION_TYPE_INT:
-                    // TODO(b/151786433): Write annotation constant name instead of
-                    // annotation id literal.
-                    if (ANNOTATION_ID_RESET_STATE == annotation->annotationId) {
+                    if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
                         resetState = annotation->value.intValue;
                     } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
                         defaultState = annotation->value.intValue;
                     } else {
-                        fprintf(out, "            builder.addIntAnnotation((byte) %d, %d);\n",
-                                annotation->annotationId, annotation->value.intValue);
+                        fprintf(out, "            builder.addIntAnnotation(%s, %d);\n",
+                                annotationConstant.c_str(), annotation->value.intValue);
                     }
                     break;
                 case ANNOTATION_TYPE_BOOL:
-                    // TODO(b/151786433): Write annotation constant name instead of
-                    // annotation id literal.
-                    fprintf(out, "            builder.addBooleanAnnotation((byte) %d, %s);\n",
-                            annotation->annotationId,
+                    fprintf(out, "            builder.addBooleanAnnotation(%s, %s);\n",
+                            annotationConstant.c_str(),
                             annotation->value.boolValue ? "true" : "false");
                     break;
                 default:
@@ -81,9 +85,11 @@
             }
         }
         if (defaultState != -1 && resetState != -1) {
+            const string& annotationConstant =
+                    ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
             fprintf(out, "            if (arg%d == %d) {\n", argIndex, resetState);
-            fprintf(out, "                builder.addIntAnnotation((byte) %d, %d);\n",
-                    ANNOTATION_ID_RESET_STATE, defaultState);
+            fprintf(out, "                builder.addIntAnnotation(%s, %d);\n",
+                    annotationConstant.c_str(), defaultState);
             fprintf(out, "            }\n");
         }
         fprintf(out, "        }\n");
@@ -311,6 +317,7 @@
 
     write_java_atom_codes(out, atoms);
     write_java_enum_values(out, atoms);
+    write_java_annotation_constants(out);
 
     int errors = 0;
 
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
index c0d73fa..0c6c009 100644
--- a/tools/stats_log_api_gen/native_writer.cpp
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -21,6 +21,15 @@
 namespace android {
 namespace stats_log_api_gen {
 
+static void write_native_annotation_constants(FILE* out) {
+    fprintf(out, "// Annotation constants.\n");
+
+    for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
+        fprintf(out, "const uint8_t %s = %hhu;\n", name.c_str(), id);
+    }
+    fprintf(out, "\n");
+}
+
 static void write_annotations(FILE* out, int argIndex,
                               const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
                               const string& methodPrefix, const string& methodSuffix) {
@@ -31,33 +40,30 @@
     }
     const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
     for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
-        fprintf(out, "    if (code == %d) {\n", atomDecl->code);
+        const string atomConstant = make_constant_name(atomDecl->name);
+        fprintf(out, "    if (%s == code) {\n", atomConstant.c_str());
         const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
         int resetState = -1;
         int defaultState = -1;
         for (const shared_ptr<Annotation>& annotation : annotations) {
-            // TODO(b/151786433): Write atom constant name instead of atom id literal.
+            const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
             switch (annotation->type) {
-                // TODO(b/151776731): Check for reset state annotation and only include
-                // reset state when field value == default state annotation value.
                 case ANNOTATION_TYPE_INT:
-                    // TODO(b/151786433): Write annotation constant name instead of
-                    // annotation id literal.
-                    if (ANNOTATION_ID_RESET_STATE == annotation->annotationId) {
+                    if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
                         resetState = annotation->value.intValue;
                     } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
                         defaultState = annotation->value.intValue;
                     } else {
-                        fprintf(out, "        %saddInt32Annotation(%s%d, %d);\n",
+                        fprintf(out, "        %saddInt32Annotation(%s%s, %d);\n",
                                 methodPrefix.c_str(), methodSuffix.c_str(),
-                                annotation->annotationId, annotation->value.intValue);
+                                annotationConstant.c_str(), annotation->value.intValue);
                     }
                     break;
                 case ANNOTATION_TYPE_BOOL:
                     // TODO(b/151786433): Write annotation constant name instead of
                     // annotation id literal.
-                    fprintf(out, "        %saddBoolAnnotation(%s%d, %s);\n", methodPrefix.c_str(),
-                            methodSuffix.c_str(), annotation->annotationId,
+                    fprintf(out, "        %saddBoolAnnotation(%s%s, %s);\n", methodPrefix.c_str(),
+                            methodSuffix.c_str(), annotationConstant.c_str(),
                             annotation->value.boolValue ? "true" : "false");
                     break;
                 default:
@@ -65,9 +71,11 @@
             }
         }
         if (defaultState != -1 && resetState != -1) {
+            const string& annotationConstant =
+                    ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
             fprintf(out, "        if (arg%d == %d) {\n", argIndex, resetState);
-            fprintf(out, "            %saddInt32Annotation(%s%d, %d);\n", methodPrefix.c_str(),
-                    methodSuffix.c_str(), ANNOTATION_ID_RESET_STATE, defaultState);
+            fprintf(out, "            %saddInt32Annotation(%s%s, %d);\n", methodPrefix.c_str(),
+                    methodSuffix.c_str(), annotationConstant.c_str(), defaultState);
             fprintf(out, "        }\n");
         }
         fprintf(out, "    }\n");
@@ -314,6 +322,8 @@
         }
     }
 
+    write_native_annotation_constants(out);
+
     fprintf(out, "struct BytesField {\n");
     fprintf(out,
             "  BytesField(char const* array, size_t len) : arg(array), "
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index 480442f..d22acc6 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -149,42 +149,42 @@
 
 // The atom has only primary field but no exclusive state field.
 message BadStateAtom1 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
 }
 
 // Only primative types can be annotated.
 message BadStateAtom2 {
     repeated android.os.statsd.AttributionNode attribution = 1
-            [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
-    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+            [(android.os.statsd.state_field_option).primary_field = true];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
 }
 
 // Having 2 exclusive state field in the atom means the atom is badly designed.
 // E.g., putting bluetooth state and wifi state in the same atom.
 message BadStateAtom3 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
-    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
-    optional int32 state2 = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
+    optional int32 state2 = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
 }
 
 message GoodStateAtom1 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
-    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
 }
 
 // Atoms can have exclusive state field, but no primary field. That means
 // the state is globally exclusive (e.g., DisplayState).
 message GoodStateAtom2 {
     optional int32 uid = 1;
-    optional int32 state = 2 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
 }
 
 // We can have more than one primary fields. That means their combination is a
 // primary key.
 message GoodStateAtom3 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
-    optional int32 tid = 2 [(android.os.statsd.state_field_option).option = PRIMARY_FIELD];
-    optional int32 state = 3 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
+    optional int32 tid = 2 [(android.os.statsd.state_field_option).primary_field = true];
+    optional int32 state = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
 }
 
 message WhitelistedAtom {
@@ -214,7 +214,7 @@
 }
 
 message ModuleOneAndTwoAtom {
-    optional int32 field = 1 [(android.os.statsd.state_field_option).option = EXCLUSIVE_STATE];
+    optional int32 field = 1 [(android.os.statsd.state_field_option).exclusive_state = true];
 }
 
 message NoModuleAtom {
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index c654a1b..1504752 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -308,10 +308,10 @@
     EXPECT_EQ(1ul, annotationSet->size());
     annotationSetIt = annotationSet->begin();
     annotation = annotationSetIt->get();
-    EXPECT_EQ(ANNOTATION_ID_STATE_OPTION, annotation->annotationId);
+    EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
     EXPECT_EQ(3, annotation->atomId);
-    EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
-    EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
+    EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
+    EXPECT_TRUE(annotation->value.boolValue);
 
     signatureInfoMapIt++;
     signature = &signatureInfoMapIt->first;
@@ -378,10 +378,10 @@
     EXPECT_EQ(1ul, annotationSet->size());
     annotationSetIt = annotationSet->begin();
     annotation = annotationSetIt->get();
-    EXPECT_EQ(ANNOTATION_ID_STATE_OPTION, annotation->annotationId);
+    EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
     EXPECT_EQ(3, annotation->atomId);
-    EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
-    EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
+    EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
+    EXPECT_TRUE(annotation->value.boolValue);
 }
 
 }  // namespace stats_log_api_gen
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index 57b6f62..7d6d08e 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -38,6 +38,15 @@
 const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
 const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
 
+const map<AnnotationId, string> ANNOTATION_ID_CONSTANTS = {
+        {ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
+        {ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
+        {ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"},
+        {ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"},
+        {ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"},
+        {ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"},
+        {ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}};
+
 string make_constant_name(const string& str);
 
 const char* cpp_type_name(java_type_t type);
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 2029479..99beb7b 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -81,7 +81,6 @@
     libs: [
         "framework-annotations-lib",
         "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
-        "framework-telephony-stubs",
     ],
     srcs: [
         ":framework-wifi-updatable-sources",
diff --git a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
index de2f5d9..6c2e6dd 100644
--- a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
+++ b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
@@ -42,7 +42,7 @@
     public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0;
 
     /**
-     * East Connect R2 Success event: Configuration applied by Enrollee (Configurator mode).
+     * Easy Connect R2 Success event: Configuration applied by Enrollee (Configurator mode).
      * This is the last and final Easy Connect event when both the local device and remote device
      * implement R2. If either the local device or remote device implement R1, this event will never
      * be received, and the {@link #EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT} will be received.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index dfeea9f..f1be8b2 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1887,12 +1887,20 @@
      * <li> If user reset network settings, all added suggestions will be discarded. Apps can use
      * {@link #getNetworkSuggestions()} to check if their suggestions are in the device.</li>
      * <li> In-place modification of existing suggestions are allowed.
-     * If the provided suggestions {@link WifiNetworkSuggestion#equals(Object)} any previously
-     * provided suggestions by the app. Previous suggestions will be updated</li>
+     * <li>If the provided suggestions includes any previously provided suggestions by the app,
+     * previous suggestions will be updated.</li>
+     * <li>If one of the provided suggestions marks a previously unmetered suggestion as metered and
+     * the device is currently connected to that suggested network, then the device will disconnect
+     * from that network. The system will immediately re-evaluate all the network candidates
+     * and possibly reconnect back to the same suggestion. This disconnect is to make sure that any
+     * traffic flowing over unmetered networks isn't accidentally continued over a metered network.
+     * </li>
+     * </li>
      *
      * @param networkSuggestions List of network suggestions provided by the app.
      * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values.
      * @throws {@link SecurityException} if the caller is missing required permissions.
+     * @see WifiNetworkSuggestion#equals(Object)
      */
     @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
     public @NetworkSuggestionsStatusCode int addNetworkSuggestions(
@@ -4152,6 +4160,10 @@
      *
      * This function is used instead of a enableNetwork() and reconnect()
      *
+     * <li> This API will cause reconnect if the credentials of the current active
+     * connection has been changed.</li>
+     * <li> This API will cause reconnect if the current active connection is marked metered.</li>
+     *
      * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link
      *        getConfiguredNetworks}.
      * @param listener for callbacks on success or failure. Can be null.
@@ -4180,8 +4192,9 @@
      *
      * For an existing network, it accomplishes the task of updateNetwork()
      *
-     * This API will cause reconnect if the crecdentials of the current active
-     * connection has been changed.
+     * <li> This API will cause reconnect if the credentials of the current active
+     * connection has been changed.</li>
+     * <li> This API will cause disconnect if the current active connection is marked metered.</li>
      *
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index ed54ad1..737b7c7 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.MacAddress;
-import android.net.MatchAllNetworkSpecifier;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.os.Parcel;
@@ -553,13 +552,6 @@
     /** @hide */
     @Override
     public boolean canBeSatisfiedBy(NetworkSpecifier other) {
-        if (this == other) {
-            return true;
-        }
-        // Any generic requests should be satisifed by a specific wifi network.
-        if (other == null || other instanceof MatchAllNetworkSpecifier) {
-            return true;
-        }
         if (other instanceof WifiNetworkAgentSpecifier) {
             return ((WifiNetworkAgentSpecifier) other).satisfiesNetworkSpecifier(this);
         }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 4c524f4..cedf9b0 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -543,7 +543,7 @@
             wifiConfiguration.priority = mPriority;
             wifiConfiguration.meteredOverride =
                     mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
-                            : WifiConfiguration.METERED_OVERRIDE_NONE;
+                            : WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
             wifiConfiguration.carrierId = mCarrierId;
             wifiConfiguration.trusted = !mIsNetworkUntrusted;
             return wifiConfiguration;
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index 53a7d03..fc0ef46 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -382,11 +382,11 @@
     /**
      * Validate NetworkSpecifier matching.
      * a) Create a network specifier for WPA_PSK network
-     * b) Ensure that the specifier matches {@code null} and {@link MatchAllNetworkSpecifier}
+     * b) Ensure that the specifier does not match {@code null} and {@link MatchAllNetworkSpecifier}
      * specifiers.
      */
     @Test
-    public void testWifiNetworkSpecifierSatisfiesNullAndAllMatch() {
+    public void testWifiNetworkSpecifierDoesNotSatisfyNullAndAllMatch() {
         WifiConfiguration wifiConfiguration = new WifiConfiguration();
         wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
@@ -396,8 +396,8 @@
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration);
 
-        assertTrue(specifier.canBeSatisfiedBy(null));
-        assertTrue(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier()));
+        assertFalse(specifier.canBeSatisfiedBy(null));
+        assertFalse(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier()));
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index ac2f6b2..aca1909 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -56,7 +56,7 @@
                 .get(WifiConfiguration.KeyMgmt.NONE));
         assertTrue(suggestion.isAppInteractionRequired);
         assertFalse(suggestion.isUserInteractionRequired);
-        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_NOT_METERED,
                 suggestion.wifiConfiguration.meteredOverride);
         assertEquals(-1, suggestion.wifiConfiguration.priority);
         assertFalse(suggestion.isUserAllowedToManuallyConnect);
@@ -86,7 +86,7 @@
                 suggestion.wifiConfiguration.preSharedKey);
         assertTrue(suggestion.isAppInteractionRequired);
         assertFalse(suggestion.isUserInteractionRequired);
-        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_NOT_METERED,
                 suggestion.wifiConfiguration.meteredOverride);
         assertEquals(0, suggestion.wifiConfiguration.priority);
         assertFalse(suggestion.isUserAllowedToManuallyConnect);