Merge "Disable empty KeyguardCoordinatorTest test" into tm-dev
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
index 4ad015d..c92c634 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
@@ -20,6 +20,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
@@ -153,7 +154,8 @@
             while (state.keepRunning()) {
                 session.relayout(mWindow, mParams, mWidth, mHeight,
                         mViewVisibility.getAsInt(), mFlags, mOutFrames,
-                        mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls);
+                        mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
+                        new Bundle());
             }
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 90ec700..528be3c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -4891,13 +4891,15 @@
             filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
             filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
             filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
-            getContext().registerReceiver(this, filter);
+            getContext().registerReceiverForAllUsers(this, filter,
+                    /* broadcastPermission */ null, /* scheduler */ null);
             // Register for events related to sdcard installation.
             IntentFilter sdFilter = new IntentFilter();
             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
             sdFilter.addAction(Intent.ACTION_USER_STOPPED);
             sdFilter.addAction(Intent.ACTION_UID_REMOVED);
-            getContext().registerReceiver(this, sdFilter);
+            getContext().registerReceiverForAllUsers(this, sdFilter,
+                    /* broadcastPermission */ null, /* scheduler */ null);
         }
 
         @Override
@@ -4915,9 +4917,6 @@
                             }
                         }
                         return;
-                    case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
-                        pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-                        break;
                     case Intent.ACTION_USER_STOPPED:
                         final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                         if (userHandle >= 0) {
@@ -4932,6 +4931,18 @@
                         mRemovalHistory.delete(uid);
                         mLastOpScheduleExactAlarm.delete(uid);
                         return;
+                    case Intent.ACTION_PACKAGE_ADDED:
+                        if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                            final String packageUpdated = intent.getData().getSchemeSpecificPart();
+                            mHandler.obtainMessage(
+                                    AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
+                                    packageUpdated).sendToTarget();
+                        }
+                        mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
+                        return;
+                    case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+                        pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                        break;
                     case Intent.ACTION_PACKAGE_REMOVED:
                         if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                             // This package is being updated; don't kill its alarms.
@@ -4950,15 +4961,6 @@
                             }
                         }
                         break;
-                    case Intent.ACTION_PACKAGE_ADDED:
-                        if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
-                            final String packageUpdated = intent.getData().getSchemeSpecificPart();
-                            mHandler.obtainMessage(
-                                    AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
-                                    packageUpdated).sendToTarget();
-                        }
-                        mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
-                        return;
                 }
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkg : pkgList) {
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index dd102bd..e986b1a 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -667,8 +667,8 @@
     long getBucketExpiryTimeMs(String packageName, int userId, int bucket, long elapsedRealtimeMs) {
         ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
         AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
-                elapsedRealtimeMs, true);
-        if (appUsageHistory.bucketExpiryTimesMs == null) {
+                elapsedRealtimeMs, false /* create */);
+        if (appUsageHistory == null || appUsageHistory.bucketExpiryTimesMs == null) {
             return 0;
         }
         return appUsageHistory.bucketExpiryTimesMs.get(bucket, 0);
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 6a685a79..a157517 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -64,8 +64,6 @@
         "libwilhelm",
     ],
 
-    header_libs: ["bionic_libc_platform_headers"],
-
     compile_multilib: "both",
 
     cflags: [
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 815f945..12083b6 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,7 +15,6 @@
 
 #include <android-base/macros.h>
 #include <binder/IPCThreadState.h>
-#include <bionic/pac.h>
 #include <hwbinder/IPCThreadState.h>
 #include <utils/Log.h>
 #include <cutils/memory.h>
@@ -183,10 +182,6 @@
       ALOGV("app_process main with argv: %s", argv_String.string());
     }
 
-    // Because of applications that are using PAC instructions incorrectly, PAC
-    // is disabled in application processes for now.
-    ScopedDisablePAC x;
-
     AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
     // Process command line arguments
     // ignore argv[0]
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index c202f6f..6ef6845 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -52,6 +52,7 @@
         "-readability-braces-around-statements",
         "-readability-const-return-type",
         "-readability-convert-member-functions-to-static",
+        "-readability-duplicate-include",
         "-readability-else-after-return",
         "-readability-identifier-length",
         "-readability-named-parameter",
diff --git a/core/api/current.txt b/core/api/current.txt
index 19ffd36e..b5493a3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -3901,7 +3901,7 @@
     method public Object getAnimatedValue(String);
     method public long getCurrentPlayTime();
     method public long getDuration();
-    method @FloatRange(from=0, to=1) public static float getDurationScale();
+    method @FloatRange(from=0) public static float getDurationScale();
     method public static long getFrameDelay();
     method public int getRepeatCount();
     method public int getRepeatMode();
@@ -3941,7 +3941,7 @@
   }
 
   public static interface ValueAnimator.DurationScaleChangeListener {
-    method public void onChanged(float);
+    method public void onChanged(@FloatRange(from=0) float);
   }
 
 }
@@ -11300,6 +11300,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity);
     method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
     method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
+    method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
     field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED";
   }
 
@@ -16407,12 +16408,8 @@
 package android.graphics.text {
 
   public final class LineBreakConfig {
-    ctor public LineBreakConfig();
     method public int getLineBreakStyle();
     method public int getLineBreakWordStyle();
-    method public void set(@NonNull android.graphics.text.LineBreakConfig);
-    method public void setLineBreakStyle(int);
-    method public void setLineBreakWordStyle(int);
     field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1
     field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0
     field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2
@@ -16421,6 +16418,13 @@
     field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1
   }
 
+  public static final class LineBreakConfig.Builder {
+    ctor public LineBreakConfig.Builder();
+    method @NonNull public android.graphics.text.LineBreakConfig build();
+    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int);
+    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int);
+  }
+
   public class LineBreaker {
     method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
     field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
@@ -17408,7 +17412,7 @@
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES;
-    field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES;
+    field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SCALER_CROPPING_TYPE;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SCALER_DEFAULT_SECURE_IMAGE_SIZE;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS;
@@ -18193,7 +18197,7 @@
     method public int get10BitFormat();
     method @NonNull public java.util.List<android.util.Size> getAvailableSizes();
     method public int getFormat();
-    method public int getStreamUseCase();
+    method public long getStreamUseCase();
     method public boolean is10BitCapable();
     method public boolean isInput();
     method public boolean isMaximumSize();
@@ -18251,7 +18255,7 @@
     method public long getDynamicRangeProfile();
     method public int getMaxSharedSurfaceCount();
     method public int getMirrorMode();
-    method public int getStreamUseCase();
+    method public long getStreamUseCase();
     method @Nullable public android.view.Surface getSurface();
     method public int getSurfaceGroupId();
     method @NonNull public java.util.List<android.view.Surface> getSurfaces();
@@ -18261,7 +18265,7 @@
     method public void setDynamicRangeProfile(long);
     method public void setMirrorMode(int);
     method public void setPhysicalCameraId(@Nullable String);
-    method public void setStreamUseCase(int);
+    method public void setStreamUseCase(long);
     method public void setTimestampBase(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
@@ -45062,7 +45066,7 @@
   public static final class PrecomputedText.Params {
     method public int getBreakStrategy();
     method public int getHyphenationFrequency();
-    method @Nullable public android.graphics.text.LineBreakConfig getLineBreakConfig();
+    method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
     method @NonNull public android.text.TextDirectionHeuristic getTextDirection();
     method @NonNull public android.text.TextPaint getTextPaint();
   }
@@ -57352,7 +57356,8 @@
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
     method public int getLineBounds(int, android.graphics.Rect);
-    method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
+    method public int getLineBreakStyle();
+    method public int getLineBreakWordStyle();
     method public int getLineCount();
     method public int getLineHeight();
     method public float getLineSpacingExtra();
@@ -57480,7 +57485,8 @@
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int);
     method public void setLetterSpacing(float);
-    method public void setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
+    method public void setLineBreakStyle(int);
+    method public void setLineBreakWordStyle(int);
     method public void setLineHeight(@IntRange(from=0) @Px int);
     method public void setLineSpacing(float, float);
     method public void setLines(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 09d1114..5da1f39 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -244,6 +244,7 @@
     field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES";
     field public static final String READ_CARRIER_APP_INFO = "android.permission.READ_CARRIER_APP_INFO";
     field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
+    field public static final String READ_CLIPBOARD_IN_BACKGROUND = "android.permission.READ_CLIPBOARD_IN_BACKGROUND";
     field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
     field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
     field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
@@ -1128,7 +1129,7 @@
     field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE = "android.app.action.ROLE_HOLDER_PROVISION_MANAGED_PROFILE";
     field public static final String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER";
     field @Deprecated public static final String ACTION_STATE_USER_SETUP_COMPLETE = "android.app.action.STATE_USER_SETUP_COMPLETE";
-    field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER";
+    field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER";
     field public static final String EXTRA_FORCE_UPDATE_ROLE_HOLDER = "android.app.extra.FORCE_UPDATE_ROLE_HOLDER";
     field public static final String EXTRA_LOST_MODE_LOCATION = "android.app.extra.LOST_MODE_LOCATION";
     field public static final String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
@@ -1161,8 +1162,8 @@
     field public static final String REQUIRED_APP_MANAGED_PROFILE = "android.app.REQUIRED_APP_MANAGED_PROFILE";
     field public static final String REQUIRED_APP_MANAGED_USER = "android.app.REQUIRED_APP_MANAGED_USER";
     field public static final int RESULT_DEVICE_OWNER_SET = 123; // 0x7b
-    field public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; // 0x1
-    field public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; // 0x2
+    field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1; // 0x1
+    field public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2; // 0x2
     field public static final int RESULT_UPDATE_ROLE_HOLDER = 2; // 0x2
     field public static final int RESULT_WORK_PROFILE_CREATED = 122; // 0x7a
     field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
@@ -3192,6 +3193,7 @@
   }
 
   public class CrossProfileApps {
+    method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
     method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES}) public void startActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
   }
 
@@ -9791,6 +9793,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isMediaSharedWithParent();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
+    method public static boolean isRemoveResultSuccessful(int);
     method public boolean isRestrictedProfile();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
@@ -9808,7 +9811,10 @@
     field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
     field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2
     field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1
-    field public static final int REMOVE_RESULT_ERROR = 3; // 0x3
+    field public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; // 0xfffffffc
+    field public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+    field public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; // 0xfffffffd
+    field public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2; // 0xfffffffe
     field public static final int REMOVE_RESULT_REMOVED = 0; // 0x0
     field public static final int RESTRICTION_NOT_SET = 0; // 0x0
     field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 66f893d..db95a1f 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -96,7 +96,7 @@
 package android.animation {
 
   public class ValueAnimator extends android.animation.Animator {
-    method @MainThread public static void setDurationScale(@FloatRange(from=0, to=1) float);
+    method @MainThread public static void setDurationScale(@FloatRange(from=0) float);
   }
 
 }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index bca6b6a..6ab7ae6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -316,7 +316,7 @@
     @UnsupportedAppUsage
     @TestApi
     @MainThread
-    public static void setDurationScale(@FloatRange(from = 0, to = 1) float durationScale) {
+    public static void setDurationScale(@FloatRange(from = 0) float durationScale) {
         sDurationScale = durationScale;
         List<WeakReference<DurationScaleChangeListener>> listenerCopy;
 
@@ -340,7 +340,7 @@
      *
      * @return the duration scale.
      */
-    @FloatRange(from = 0, to = 1)
+    @FloatRange(from = 0)
     public static float getDurationScale() {
         return sDurationScale;
     }
@@ -1798,8 +1798,8 @@
     public interface DurationScaleChangeListener {
         /**
          * Called when the duration scale changes.
-         * @param scale the duration scalel
+         * @param scale the duration scale
          */
-        void onChanged(float scale);
+        void onChanged(@FloatRange(from = 0) float scale);
     }
 }
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 89854bb..150888c 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -24,6 +24,9 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -39,6 +42,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Pair;
 import android.util.Slog;
 import android.view.View;
@@ -520,6 +524,27 @@
     private final Map<NearbyMediaDevicesProvider, NearbyMediaDevicesProviderWrapper>
             nearbyMediaDevicesProviderMap = new HashMap<>();
 
+    /**
+     * Media controls based on {@link android.app.Notification.MediaStyle} notifications will have
+     * actions based on the media session's {@link android.media.session.PlaybackState}, rather than
+     * the notification's actions.
+     *
+     * These actions will be:
+     * - Play/Pause (depending on whether the current state is a playing state)
+     * - Previous (if declared), or a custom action if the slot is not reserved with
+     *   {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV}
+     * - Next (if declared), or a custom action if the slot is not reserved with
+     *   {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT}
+     * - Custom action
+     * - Custom action
+     *
+     * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
+     * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    private static final long MEDIA_CONTROL_SESSION_ACTIONS = 203800354L;
+
     @UnsupportedAppUsage
     private Context mContext;
     private IStatusBarService mService;
@@ -1127,6 +1152,20 @@
         }
     }
 
+    /**
+     * Checks whether the given package should use session-based actions for its media controls.
+     *
+     * @param packageName App posting media controls
+     * @param userId Current user ID
+     * @return true if the app supports session actions
+     *
+     * @hide
+     */
+    public static boolean useMediaSessionActionsForApp(String packageName, int userId) {
+        UserHandle handle = UserHandle.getUserHandleForUid(userId);
+        return CompatChanges.isChangeEnabled(MEDIA_CONTROL_SESSION_ACTIONS, packageName, handle);
+    }
+
     /** @hide */
     public static String windowStateToString(int state) {
         if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index bf6f634..6615374 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -154,6 +154,7 @@
 import android.net.wifi.WifiFrameworkInitializer;
 import android.net.wifi.nl80211.WifiNl80211Manager;
 import android.nfc.NfcManager;
+import android.ondevicepersonalization.OnDevicePersonalizationFrameworkInitializer;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.BatteryStatsManager;
@@ -1560,6 +1561,7 @@
             SafetyCenterFrameworkInitializer.registerServiceWrappers();
             ConnectivityFrameworkInitializerTiramisu.registerServiceWrappers();
             NearbyFrameworkInitializer.registerServiceWrappers();
+            OnDevicePersonalizationFrameworkInitializer.registerServiceWrappers();
         } finally {
             // If any of the above code throws, we're in a pretty bad shape and the process
             // will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4c7b910..27fe312 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -719,10 +719,11 @@
 
     /**
      * A {@code boolean} extra which determines whether to force a role holder update, regardless
-     * of any internal conditions {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER} might have.
+     * of any internal conditions {@link #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} might
+     * have.
      *
      * <p>This extra can be provided to intents with action {@link
-     * #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}.
+     * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER}.
      *
      * @hide
      */
@@ -3281,39 +3282,43 @@
      *
      * <p>The activity must handle the device policy management role holder update and set the
      * intent result to either {@link Activity#RESULT_OK} if the update was successful, {@link
-     * #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it encounters a problem
-     * that may be solved by relaunching it again, or {@link
-     * #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if it encounters a problem
-     * that will not be solved by relaunching it again.
+     * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR} if it encounters a
+     * problem that may be solved by relaunching it again, or {@link
+     * #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR} if it encounters a
+     * problem that will not be solved by relaunching it again.
      *
      * <p>If this activity has additional internal conditions which are not met, it should return
-     * {@link #RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR}.
+     * {@link #RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR}.
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP)
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     @SystemApi
-    public static final String ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER =
-            "android.app.action.UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER";
+    public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER =
+            "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER";
 
     /**
-     * Result code that can be returned by the {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}
-     * handler if it encounters a problem that may be solved by relaunching it again.
+     * Result code that can be returned by the {@link
+     * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if it encounters a problem
+     * that may be solved by relaunching it again.
      *
      * @hide
      */
     @SystemApi
-    public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR = 1;
+    public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_RECOVERABLE_ERROR =
+            1;
 
     /**
-     * Result code that can be returned by the {@link #ACTION_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER}
-     * handler if it encounters a problem that will not be solved by relaunching it again.
+     * Result code that can be returned by the {@link
+     * #ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER} handler if it encounters a problem that
+     * will not be solved by relaunching it again.
      *
      * @hide
      */
     @SystemApi
-    public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2;
+    public static final int RESULT_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR =
+            2;
 
     /**
      * An {@link Intent} extra which resolves to a custom user consent screen.
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 94f0561..b6917e26 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -104,7 +104,44 @@
                     mContext.getAttributionTag(),
                     component,
                     targetUser.getIdentifier(),
-                    true);
+                    true,
+                    null,
+                    null);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Starts the specified main activity of the caller package in the specified profile, launching
+     * in the specified activity.
+     *
+     * @param component The ComponentName of the activity to launch, it must be exported and has
+     *        action {@link android.content.Intent#ACTION_MAIN}, category
+     *        {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
+     *        be thrown.
+     * @param targetUser The UserHandle of the profile, must be one of the users returned by
+     *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
+     *        be thrown.
+     * @param callingActivity The activity to start the new activity from for the purposes of
+     *        deciding which task the new activity should belong to. If {@code null}, the activity
+     *        will always be started in a new task.
+     * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
+     */
+    public void startMainActivity(@NonNull ComponentName component,
+            @NonNull UserHandle targetUser,
+            @Nullable Activity callingActivity,
+            @Nullable Bundle options) {
+        try {
+            mService.startActivityAsUser(
+                    mContext.getIApplicationThread(),
+                    mContext.getPackageName(),
+                    mContext.getAttributionTag(),
+                    component,
+                    targetUser.getIdentifier(),
+                    true,
+                    callingActivity != null ? callingActivity.getActivityToken() : null,
+                    options);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
@@ -191,6 +228,48 @@
      * @param targetUser The UserHandle of the profile, must be one of the users returned by
      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
      *        be thrown.
+     * @param callingActivity The activity to start the new activity from for the purposes of
+     *        deciding which task the new activity should belong to. If {@code null}, the activity
+     *        will always be started in a new task.
+     * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+            android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES})
+    public void startActivity(
+            @NonNull ComponentName component,
+            @NonNull UserHandle targetUser,
+            @Nullable Activity callingActivity,
+            @Nullable Bundle options) {
+        try {
+            mService.startActivityAsUser(
+                    mContext.getIApplicationThread(),
+                    mContext.getPackageName(),
+                    mContext.getAttributionTag(),
+                    component,
+                    targetUser.getIdentifier(),
+                    false,
+                    callingActivity != null ? callingActivity.getActivityToken() : null,
+                    options);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Starts the specified activity of the caller package in the specified profile. Unlike
+     * {@link #startMainActivity}, this can start any activity of the caller package, not just
+     * the main activity.
+     * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
+     * or {@link android.Manifest.permission#START_CROSS_PROFILE_ACTIVITIES}
+     * permission and both the caller and target user profiles must be in the same profile group.
+     *
+     * @param component The ComponentName of the activity to launch. It must be exported.
+     * @param targetUser The UserHandle of the profile, must be one of the users returned by
+     *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
+     *        be thrown.
      * @hide
      */
     @SystemApi
@@ -201,7 +280,7 @@
         try {
             mService.startActivityAsUser(mContext.getIApplicationThread(),
                     mContext.getPackageName(), mContext.getAttributionTag(), component,
-                    targetUser.getIdentifier(), false);
+                    targetUser.getIdentifier(), false, null, null);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl
index e2850f1..4f2c106 100644
--- a/core/java/android/content/pm/ICrossProfileApps.aidl
+++ b/core/java/android/content/pm/ICrossProfileApps.aidl
@@ -29,7 +29,7 @@
 interface ICrossProfileApps {
     void startActivityAsUser(in IApplicationThread caller, in String callingPackage,
             in String callingFeatureId, in ComponentName component, int userId,
-            boolean launchMainActivity);
+            boolean launchMainActivity, in IBinder task, in Bundle options);
     void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage,
             in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity,
             in Bundle options);
diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java
index 7b24cc4..3952467 100644
--- a/core/java/android/hardware/CameraStreamStats.java
+++ b/core/java/android/hardware/CameraStreamStats.java
@@ -49,7 +49,7 @@
     private float[] mHistogramBins;
     private long[] mHistogramCounts;
     private long mDynamicRangeProfile;
-    private int mStreamUseCase;
+    private long mStreamUseCase;
 
     private static final String TAG = "CameraStreamStats";
 
@@ -73,7 +73,7 @@
     public CameraStreamStats(int width, int height, int format, float maxPreviewFps,
             int dataSpace, long usage, long requestCount, long errorCount,
             int startLatencyMs, int maxHalBuffers, int maxAppBuffers, long dynamicRangeProfile,
-            int streamUseCase) {
+            long streamUseCase) {
         mWidth = width;
         mHeight = height;
         mFormat = format;
@@ -135,7 +135,7 @@
         dest.writeFloatArray(mHistogramBins);
         dest.writeLongArray(mHistogramCounts);
         dest.writeLong(mDynamicRangeProfile);
-        dest.writeInt(mStreamUseCase);
+        dest.writeLong(mStreamUseCase);
     }
 
     public void readFromParcel(Parcel in) {
@@ -154,7 +154,7 @@
         mHistogramBins = in.createFloatArray();
         mHistogramCounts = in.createLongArray();
         mDynamicRangeProfile = in.readLong();
-        mStreamUseCase = in.readInt();
+        mStreamUseCase = in.readLong();
     }
 
     public int getWidth() {
@@ -217,7 +217,7 @@
         return mDynamicRangeProfile;
     }
 
-    public int getStreamUseCase() {
+    public long getStreamUseCase() {
         return mStreamUseCase;
     }
 }
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7bebe1f..b05e6d1 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3563,8 +3563,8 @@
      */
     @PublicKey
     @NonNull
-    public static final Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES =
-            new Key<int[]>("android.scaler.availableStreamUseCases", int[].class);
+    public static final Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES =
+            new Key<long[]>("android.scaler.availableStreamUseCases", long[].class);
 
     /**
      * <p>An array of mandatory stream combinations with stream use cases.
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 465abfb..a3bc665 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -66,7 +66,7 @@
         private final boolean mIsUltraHighResolution;
         private final boolean mIsMaximumSize;
         private final boolean mIs10BitCapable;
-        private final int mStreamUseCase;
+        private final long mStreamUseCase;
 
         /**
          * Create a new {@link MandatoryStreamInformation}.
@@ -168,7 +168,7 @@
          */
         public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format,
                 boolean isMaximumSize, boolean isInput, boolean isUltraHighResolution,
-                boolean is10BitCapable, @StreamUseCase int streamUseCase) {
+                boolean is10BitCapable, @StreamUseCase long streamUseCase) {
             if (availableSizes.isEmpty()) {
                 throw new IllegalArgumentException("No available sizes");
             }
@@ -308,9 +308,9 @@
          * For {@link MandatoryStreamInformation} belonging to other mandatory stream
          * combinations, the return value will be DEFAULT. </p>
          *
-         * @return the integer stream use case.
+         * @return the long integer stream use case.
          */
-        public @StreamUseCase int getStreamUseCase() {
+        public @StreamUseCase long getStreamUseCase() {
             return mStreamUseCase;
         }
 
@@ -365,15 +365,15 @@
     /**
      * Short hand for stream use cases
      */
-    private static final int STREAM_USE_CASE_PREVIEW =
+    private static final long STREAM_USE_CASE_PREVIEW =
             CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW;
-    private static final int STREAM_USE_CASE_STILL_CAPTURE =
+    private static final long STREAM_USE_CASE_STILL_CAPTURE =
             CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE;
-    private static final int STREAM_USE_CASE_RECORD =
+    private static final long STREAM_USE_CASE_RECORD =
             CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD;
-    private static final int STREAM_USE_CASE_PREVIEW_VIDEO_STILL =
+    private static final long STREAM_USE_CASE_PREVIEW_VIDEO_STILL =
             CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL;
-    private static final int STREAM_USE_CASE_VIDEO_CALL =
+    private static final long STREAM_USE_CASE_VIDEO_CALL =
             CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
 
     /**
@@ -471,12 +471,12 @@
     private static final class StreamTemplate {
         public int mFormat;
         public SizeThreshold mSizeThreshold;
-        public int mStreamUseCase;
+        public long mStreamUseCase;
         public StreamTemplate(int format, SizeThreshold sizeThreshold) {
             this(format, sizeThreshold, CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
         }
         public StreamTemplate(@Format int format, @NonNull SizeThreshold sizeThreshold,
-                @StreamUseCase int streamUseCase) {
+                @StreamUseCase long streamUseCase) {
             mFormat = format;
             mSizeThreshold = sizeThreshold;
             mStreamUseCase = streamUseCase;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 2350b7c..39cb7f3 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -918,9 +918,9 @@
      * @throws IllegalArgumentException If the streamUseCase isn't within the range of valid
      *                                  values.
      */
-    public void setStreamUseCase(@StreamUseCase int streamUseCase) {
+    public void setStreamUseCase(@StreamUseCase long streamUseCase) {
         // Verify that the value is in range
-        int maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
+        long maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
         if (streamUseCase > maxUseCaseValue &&
                 streamUseCase < CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
             throw new IllegalArgumentException("Not a valid stream use case value " +
@@ -938,7 +938,7 @@
      *
      * @return the currently set stream use case
      */
-    public int getStreamUseCase() {
+    public long getStreamUseCase() {
         return mStreamUseCase;
     }
 
@@ -1067,7 +1067,7 @@
         String physicalCameraId = source.readString();
         boolean isMultiResolutionOutput = source.readInt() == 1;
         int[] sensorPixelModesUsed = source.createIntArray();
-        int streamUseCase = source.readInt();
+        long streamUseCase = source.readLong();
 
         checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
         long dynamicRangeProfile = source.readLong();
@@ -1218,7 +1218,7 @@
         // writeList doesn't seem to work well with Integer list.
         dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed));
         dest.writeLong(mDynamicRangeProfile);
-        dest.writeInt(mStreamUseCase);
+        dest.writeLong(mStreamUseCase);
         dest.writeInt(mTimestampBase);
         dest.writeInt(mMirrorMode);
     }
@@ -1337,7 +1337,7 @@
     // Dynamic range profile
     private long mDynamicRangeProfile;
     // Stream use case
-    private int mStreamUseCase;
+    private long mStreamUseCase;
     // Timestamp base
     private int mTimestampBase;
     // Mirroring mode
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
index 2dd3aaa1..5c9989e 100644
--- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -27,6 +27,7 @@
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import android.annotation.NonNull;
+import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.net.NetworkIdentity;
 import android.net.NetworkStatsCollection;
@@ -47,6 +48,8 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.net.ProtocolException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -76,6 +79,15 @@
      */
     public static final String PREFIX_UID_TAG = "uid_tag";
 
+    /** @hide */
+    @StringDef(prefix = {"PREFIX_"}, value = {
+        PREFIX_XT,
+        PREFIX_UID,
+        PREFIX_UID_TAG,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Prefix {}
+
     private static final HashMap<String, String> sPrefixLegacyFileNameMap =
             new HashMap<String, String>() {{
                 put(PREFIX_XT, "netstats_xt.bin");
@@ -141,13 +153,13 @@
 
     // Get /data/system/netstats_*.bin legacy files. Does not check for existence.
     @NonNull
-    private static File getLegacyBinFileForPrefix(@NonNull String prefix) {
+    private static File getLegacyBinFileForPrefix(@NonNull @Prefix String prefix) {
         return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix));
     }
 
     // List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files.
     @NonNull
-    private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) {
+    private static ArrayList<File> getPlatformFileListForPrefix(@NonNull @Prefix String prefix) {
         final ArrayList<File> list = new ArrayList<>();
         final File platformFiles = new File(getPlatformBaseDir(), "netstats");
         if (platformFiles.exists()) {
@@ -207,7 +219,7 @@
      */
     @NonNull
     public static NetworkStatsCollection readPlatformCollection(
-            @NonNull String prefix, long bucketDuration) throws IOException {
+            @NonNull @Prefix String prefix, long bucketDuration) throws IOException {
         final NetworkStatsCollection.Builder builder =
                 new NetworkStatsCollection.Builder(bucketDuration);
 
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index de76c8f..f4ca1b5 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -165,6 +165,7 @@
             PROCESS_STATE_FOREGROUND,
             PROCESS_STATE_BACKGROUND,
             PROCESS_STATE_FOREGROUND_SERVICE,
+            PROCESS_STATE_CACHED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProcessState {
@@ -175,8 +176,9 @@
     public static final int PROCESS_STATE_FOREGROUND = 1;
     public static final int PROCESS_STATE_BACKGROUND = 2;
     public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
+    public static final int PROCESS_STATE_CACHED = 4;
 
-    public static final int PROCESS_STATE_COUNT = 4;
+    public static final int PROCESS_STATE_COUNT = 5;
 
     private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT];
 
@@ -186,6 +188,7 @@
         sProcessStateNames[PROCESS_STATE_FOREGROUND] = "fg";
         sProcessStateNames[PROCESS_STATE_BACKGROUND] = "bg";
         sProcessStateNames[PROCESS_STATE_FOREGROUND_SERVICE] = "fgs";
+        sProcessStateNames[PROCESS_STATE_CACHED] = "cached";
     }
 
     private static final int[] SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE = {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 5f9fdbf..06c35b5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -680,6 +680,8 @@
                 return BatteryConsumer.PROCESS_STATE_BACKGROUND;
             case BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE:
                 return BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
+            case BatteryStats.Uid.PROCESS_STATE_CACHED:
+                return BatteryConsumer.PROCESS_STATE_CACHED;
             default:
                 return BatteryConsumer.PROCESS_STATE_UNSPECIFIED;
         }
@@ -2681,7 +2683,7 @@
     public static final String[] RADIO_ACCESS_TECHNOLOGY_NAMES = {"Other", "LTE", "NR"};
 
     /**
-     * Returns the time in microseconds that the mobile radio has been active on a
+     * Returns the time in milliseconds that the mobile radio has been active on a
      * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
      * transmission power level.
      *
@@ -2700,6 +2702,46 @@
             @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
             long elapsedRealtimeMs);
 
+    /**
+     * Returns the time in milliseconds that the mobile radio has been actively transmitting data on
+     * a given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+     * transmission power level.
+     *
+     * @param rat            Radio Access Technology {@see RadioAccessTechnology}
+     * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+     *                       RADIO_ACCESS_TECHNOLOGY_NR. Use
+     *                       {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+     *                       Technologies.
+     * @param signalStrength the cellular signal strength. {@see CellSignalStrength#getLevel()}
+     * @param elapsedRealtimeMs current elapsed realtime
+     * @return time (in milliseconds) the mobile radio spent actively transmitting data in the
+     *         specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
+     *         data unavailable.
+     * @hide
+     */
+    public abstract long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
+            @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+            long elapsedRealtimeMs);
+
+    /**
+     * Returns the time in milliseconds that the mobile radio has been actively receiving data on a
+     * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+     * transmission power level.
+     *
+     * @param rat            Radio Access Technology {@see RadioAccessTechnology}
+     * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+     *                       RADIO_ACCESS_TECHNOLOGY_NR. Use
+     *                       {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+     *                       Technologies.
+     * @param elapsedRealtimeMs current elapsed realtime
+     * @return time (in milliseconds) the mobile radio spent actively receiving data in the
+     *         specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
+     *         data unavailable.
+     * @hide
+     */
+    public abstract long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
+            @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs);
+
     static final String[] WIFI_SUPPL_STATE_NAMES = {
         "invalid", "disconn", "disabled", "inactive", "scanning",
         "authenticating", "associating", "associated", "4-way-handshake",
@@ -2720,6 +2762,13 @@
     public static final long POWER_DATA_UNAVAILABLE = -1L;
 
     /**
+     * Returned value if duration data is unavailable.
+     *
+     * {@hide}
+     */
+    public static final long DURATION_UNAVAILABLE = -1L;
+
+    /**
      * Returns the battery consumption (in microcoulombs) of bluetooth, derived from on
      * device power measurement data.
      * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
@@ -4093,6 +4142,10 @@
                 "    Mmwave frequency (greater than 6GHz):\n"};
         final String signalStrengthHeader =
                 "      Signal Strength Time:\n";
+        final String txHeader =
+                "      Tx Time:\n";
+        final String rxHeader =
+                "      Rx Time: ";
         final String[] signalStrengthDescription = new String[]{
                 "        unknown:  ",
                 "        poor:     ",
@@ -4144,6 +4197,29 @@
                     sb.append(")\n");
                 }
 
+                sb.append(prefix);
+                sb.append(txHeader);
+                for (int strength = 0; strength < numSignalStrength; strength++) {
+                    final long timeMs = getActiveTxRadioDurationMs(rat, freqLvl, strength,
+                            rawRealtimeMs);
+                    if (timeMs <= 0) continue;
+                    hasFreqData = true;
+                    sb.append(prefix);
+                    sb.append(signalStrengthDescription[strength]);
+                    formatTimeMs(sb, timeMs);
+                    sb.append("(");
+                    sb.append(formatRatioLocked(timeMs, totalActiveTimesMs));
+                    sb.append(")\n");
+                }
+
+                sb.append(prefix);
+                sb.append(rxHeader);
+                final long rxTimeMs = getActiveRxRadioDurationMs(rat, freqLvl, rawRealtimeMs);
+                formatTimeMs(sb, rxTimeMs);
+                sb.append("(");
+                sb.append(formatRatioLocked(rxTimeMs, totalActiveTimesMs));
+                sb.append(")\n");
+
                 if (hasFreqData) {
                     hasData = true;
                     pw.print(sb);
diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java
index 368ee2d..a739ba3 100644
--- a/core/java/android/os/ParcelableHolder.java
+++ b/core/java/android/os/ParcelableHolder.java
@@ -179,7 +179,11 @@
      * Read ParcelableHolder from a parcel.
      */
     public void readFromParcel(@NonNull Parcel parcel) {
-        this.mStability = parcel.readInt();
+        int wireStability = parcel.readInt();
+        if (this.mStability != wireStability) {
+            throw new IllegalArgumentException("Expected stability " + this.mStability
+                                               + " but got " + wireStability);
+        }
 
         mParcelable = null;
 
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index 6051712..522807b 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -292,6 +292,10 @@
                 procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
                         .FOREGROUND_SERVICE;
                 break;
+            case BatteryConsumer.PROCESS_STATE_CACHED:
+                procState = BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsageSlice
+                        .CACHED;
+                break;
             default:
                 throw new IllegalArgumentException("Unknown process state: " + processState);
         }
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index 77d1498..91d231e 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -119,6 +119,8 @@
                     skipEmptyComponents);
             appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE,
                     skipEmptyComponents);
+            appendProcessStateData(sb, BatteryConsumer.PROCESS_STATE_CACHED,
+                    skipEmptyComponents);
             pw.print(sb);
         }
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 276578e..2448a05 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1703,12 +1703,40 @@
 
     /**
      * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
-     * an error occurred that prevented the user from being removed or set as ephemeral.
+     * an unknown error occurred that prevented the user from being removed or set as ephemeral.
      *
      * @hide
      */
     @SystemApi
-    public static final int REMOVE_RESULT_ERROR = 3;
+    public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1;
+
+    /**
+     * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+     * the user could not be removed due to a {@link #DISALLOW_REMOVE_MANAGED_PROFILE} or
+     * {@link #DISALLOW_REMOVE_USER} user restriction.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2;
+
+    /**
+     * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+     * user being removed does not exist.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3;
+
+    /**
+     * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+     * user being removed is a {@link UserHandle#SYSTEM} user which can't be removed.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4;
 
     /**
      * Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}.
@@ -1719,7 +1747,10 @@
             REMOVE_RESULT_REMOVED,
             REMOVE_RESULT_DEFERRED,
             REMOVE_RESULT_ALREADY_BEING_REMOVED,
-            REMOVE_RESULT_ERROR,
+            REMOVE_RESULT_ERROR_USER_RESTRICTION,
+            REMOVE_RESULT_ERROR_USER_NOT_FOUND,
+            REMOVE_RESULT_ERROR_SYSTEM_USER,
+            REMOVE_RESULT_ERROR_UNKNOWN,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface RemoveResult {}
@@ -4846,8 +4877,10 @@
      * the {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction
      *
      * @return the {@link RemoveResult} code: {@link #REMOVE_RESULT_REMOVED},
-     * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, or
-     * {@link #REMOVE_RESULT_ERROR}.
+     * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED},
+     * {@link #REMOVE_RESULT_ERROR_USER_RESTRICTION}, {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND},
+     * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, or {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error
+     * codes have negative values.
      *
      * @hide
      */
@@ -4864,6 +4897,19 @@
     }
 
     /**
+     * Check if {@link #removeUserWhenPossible} returned a success code which means that the user
+     * has been removed or is slated for removal.
+     *
+     * @param result is {@link #RemoveResult} code return by {@link #removeUserWhenPossible}.
+     * @return {@code true} if it is a success code.
+     * @hide
+     */
+    @SystemApi
+    public static boolean isRemoveResultSuccessful(@RemoveResult int result) {
+        return result >= 0;
+    }
+
+    /**
      * Updates the user's name.
      *
      * @param userId the user's integer id
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 7832dcc..c021c07 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -78,37 +78,10 @@
      */
     String getMountedObbPath(in String rawPath) = 24;
     /**
-     * Decrypts any encrypted volumes.
-     */
-    int decryptStorage(in String password) = 26;
-    /**
-     * Encrypts storage.
-     */
-    int encryptStorage(int type, in String password) = 27;
-    /**
-     * Changes the encryption password.
-     */
-    int changeEncryptionPassword(int type, in String password) = 28;
-    /**
      * Returns list of all mountable volumes for the specified userId
      */
     StorageVolume[] getVolumeList(int userId, in String callingPackage, int flags) = 29;
     /**
-     * Determines the encryption state of the volume.
-     * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
-     * values.
-     * Note that this has been replaced in most cases by the APIs in
-     * StorageManager (see isEncryptable and below)
-     * This is still useful to get the error state when encryption has failed
-     * and CryptKeeper needs to throw up a screen advising the user what to do
-     */
-    int getEncryptionState() = 31;
-    /**
-     * Verify the encryption password against the stored volume.  This method
-     * may only be called by the system process.
-     */
-    int verifyEncryptionPassword(in String password) = 32;
-    /**
      * Ensure that all directories along given path exist, creating parent
      * directories as needed. Validates that given path is absolute and that it
      * contains no relative "." or ".." paths or symlinks. Also ensures that
@@ -117,32 +90,6 @@
      */
     void mkdirs(in String callingPkg, in String path) = 34;
     /**
-     * Determines the type of the encryption password
-     * @return PasswordType
-     */
-    int getPasswordType() = 35;
-    /**
-     * Get password from vold
-     * @return password or empty string
-     */
-    String getPassword() = 36;
-    /**
-     * Securely clear password from vold
-     */
-    oneway void clearPassword() = 37;
-    /**
-     * Set a field in the crypto header.
-     * @param field field to set
-     * @param contents contents to set in field
-     */
-    oneway void setField(in String field, in String contents) = 38;
-    /**
-     * Gets a field from the crypto header.
-     * @param field field to get
-     * @return contents of field
-     */
-    String getField(in String field) = 39;
-    /**
      * Report the time of the last maintenance operation such as fstrim.
      * @return Timestamp of the last maintenance operation, in the
      *     System.currentTimeMillis() time base
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 312abf8..9971cbc 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -3044,14 +3044,4 @@
     public static final int CRYPT_TYPE_PATTERN = IVold.PASSWORD_TYPE_PATTERN;
     /** @hide */
     public static final int CRYPT_TYPE_PIN = IVold.PASSWORD_TYPE_PIN;
-
-    // Constants for the data available via StorageManagerService.getField.
-    /** @hide */
-    public static final String SYSTEM_LOCALE_KEY = "SystemLocale";
-    /** @hide */
-    public static final String OWNER_INFO_KEY = "OwnerInfo";
-    /** @hide */
-    public static final String PATTERN_VISIBLE_KEY = "PatternVisible";
-    /** @hide */
-    public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible";
 }
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 1008a2d..4731504 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -600,6 +600,13 @@
     public static final String NAMESPACE_SELECTION_TOOLBAR = "selection_toolbar";
 
     /**
+     * Definitions for voice interaction related functions.
+     *
+     * @hide
+     */
+    public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction";
+
+    /**
      * List of namespaces which can be read without READ_DEVICE_CONFIG permission
      *
      * @hide
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index a2938a8..ef792d4 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -252,6 +252,7 @@
         final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
         final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
         final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
+        final Bundle mSyncSeqIdBundle = new Bundle();
         private final Point mSurfaceSize = new Point();
         private final Point mLastSurfaceSize = new Point();
         private final Matrix mTmpMatrix = new Matrix();
@@ -391,7 +392,7 @@
             @Override
             public void resized(ClientWindowFrames frames, boolean reportDraw,
                     MergedConfiguration mergedConfiguration, boolean forceLayout,
-                    boolean alwaysConsumeSystemBars, int displayId) {
+                    boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {
                 Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
                         reportDraw ? 1 : 0,
                         mergedConfiguration);
@@ -1151,7 +1152,7 @@
                     final int relayoutResult = mSession.relayout(
                             mWindow, mLayout, mWidth, mHeight,
                             View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl,
-                            mInsetsState, mTempControls);
+                            mInsetsState, mTempControls, mSyncSeqIdBundle);
 
                     final int transformHint = SurfaceControl.rotationToBufferTransform(
                             (mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -1338,7 +1339,8 @@
                         mSurfaceCreated = true;
                         if (redrawNeeded) {
                             resetWindowPages();
-                            mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+                            mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
+                                                   Integer.MAX_VALUE);
                             processLocalColors(mPendingXOffset, mPendingXOffsetStep);
                             notifyColorsChanged();
                         }
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 9307e56..f31a690 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -99,7 +99,7 @@
         private final @Layout.HyphenationFrequency int mHyphenationFrequency;
 
         // The line break configuration for calculating text wrapping.
-        private final @Nullable LineBreakConfig mLineBreakConfig;
+        private final @NonNull LineBreakConfig mLineBreakConfig;
 
         /**
          * A builder for creating {@link Params}.
@@ -119,7 +119,7 @@
                     Layout.HYPHENATION_FREQUENCY_NORMAL;
 
             // The line break configuration for calculating text wrapping.
-            private @Nullable LineBreakConfig mLineBreakConfig;
+            private @NonNull LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
 
             /**
              * Builder constructor.
@@ -212,7 +212,7 @@
         // For the external developers, use Builder instead.
         /** @hide */
         public Params(@NonNull TextPaint paint,
-                @Nullable LineBreakConfig lineBreakConfig,
+                @NonNull LineBreakConfig lineBreakConfig,
                 @NonNull TextDirectionHeuristic textDir,
                 @Layout.BreakStrategy int strategy,
                 @Layout.HyphenationFrequency int frequency) {
@@ -260,11 +260,12 @@
         }
 
         /**
-         * Return the line break configuration for this text.
+         * Returns the {@link LineBreakConfig} for this text.
          *
-         * @return the current line break configuration, null if no line break configuration is set.
+         * @return the current line break configuration. The {@link LineBreakConfig} with default
+         * values will be returned if no line break configuration is set.
          */
-        public @Nullable LineBreakConfig getLineBreakConfig() {
+        public @NonNull LineBreakConfig getLineBreakConfig() {
             return mLineBreakConfig;
         }
 
@@ -297,9 +298,9 @@
         /** @hide */
         public @CheckResultUsableResult int checkResultUsable(@NonNull TextPaint paint,
                 @NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy,
-                @Layout.HyphenationFrequency int frequency, @Nullable LineBreakConfig lbConfig) {
+                @Layout.HyphenationFrequency int frequency, @NonNull LineBreakConfig lbConfig) {
             if (mBreakStrategy == strategy && mHyphenationFrequency == frequency
-                    && isLineBreakEquals(mLineBreakConfig, lbConfig)
+                    && mLineBreakConfig.equals(lbConfig)
                     && mPaint.equalsForTextMeasurement(paint)) {
                 return mTextDir == textDir ? USABLE : NEED_RECOMPUTE;
             } else {
@@ -308,29 +309,6 @@
         }
 
         /**
-         * Check the two LineBreakConfig instances are equal.
-         * This method assumes they are equal if one parameter is null and the other parameter has
-         * a LineBreakStyle value of LineBreakConfig.LINE_BREAK_STYLE_NONE.
-         *
-         * @param o1 the first LineBreakConfig instance.
-         * @param o2 the second LineBreakConfig instance.
-         * @return true if the two LineBreakConfig instances are equal.
-         */
-        private boolean isLineBreakEquals(LineBreakConfig o1, LineBreakConfig o2) {
-            if (Objects.equals(o1, o2)) {
-                return true;
-            }
-            if (o1 == null && (o2 != null
-                    && o2.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
-                return true;
-            } else if (o2 == null && (o1 != null
-                    && o1.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
-                return true;
-            }
-            return false;
-        }
-
-        /**
          * Check if the same text layout.
          *
          * @return true if this and the given param result in the same text layout
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index b10fc37..2f85d2b6 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -112,6 +112,7 @@
             b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
             b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
             b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
+            b.mLineBreakConfig = LineBreakConfig.NONE;
             return b;
         }
 
@@ -410,7 +411,8 @@
          *
          * @param lineBreakConfig the line break configuration for text wrapping.
          * @return this builder, useful for chaining.
-         * @see android.widget.TextView#setLineBreakConfig
+         * @see android.widget.TextView#setLineBreakStyle
+         * @see android.widget.TextView#setLineBreakWordStyle
          */
         @NonNull
         public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
@@ -454,7 +456,7 @@
         @Nullable private int[] mRightIndents;
         private int mJustificationMode;
         private boolean mAddLastLineLineSpacing;
-        private LineBreakConfig mLineBreakConfig;
+        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
 
         private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index c1413be..190adbd 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -249,19 +249,19 @@
             return;
         }
 
-        Rect handwritingArea = getViewHandwritingArea(connectedView);
-        if (handwritingArea != null) {
-            if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) {
-                startHandwriting(connectedView);
-            }
+        final Rect handwritingArea = getViewHandwritingArea(connectedView);
+        if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) {
+            startHandwriting(connectedView);
+        } else {
+            reset();
         }
-        reset();
     }
 
     /** For test only. */
     @VisibleForTesting
     public void startHandwriting(@NonNull View view) {
         mImm.startStylusHandwriting(view);
+        reset();
     }
 
     /**
@@ -287,7 +287,7 @@
         final View connectedView = getConnectedView();
         if (connectedView != null && connectedView.isAutoHandwritingEnabled()) {
             final Rect handwritingArea = getViewHandwritingArea(connectedView);
-            if (handwritingArea != null && contains(handwritingArea, x, y)) {
+            if (contains(handwritingArea, x, y)) {
                 return connectedView;
             }
         }
@@ -298,8 +298,7 @@
         for (HandwritableViewInfo viewInfo : handwritableViewInfos) {
             final View view = viewInfo.getView();
             if (!view.isAutoHandwritingEnabled()) continue;
-            final Rect rect = viewInfo.getHandwritingArea();
-            if (rect != null && contains(rect, x, y)) {
+            if (contains(viewInfo.getHandwritingArea(), x, y)) {
                 return viewInfo.getView();
             }
         }
@@ -315,12 +314,15 @@
     private static Rect getViewHandwritingArea(@NonNull View view) {
         final ViewParent viewParent = view.getParent();
         if (viewParent != null && view.isAttachedToWindow() && view.isAggregatedVisible()) {
-            Rect handwritingArea = view.getHandwritingArea();
-            if (handwritingArea == null) {
-                handwritingArea = new Rect(0, 0, view.getWidth(), view.getHeight());
+            final Rect localHandwritingArea = view.getHandwritingArea();
+            final Rect globalHandwritingArea = new Rect();
+            if (localHandwritingArea != null) {
+                globalHandwritingArea.set(localHandwritingArea);
+            } else {
+                globalHandwritingArea.set(0, 0, view.getWidth(), view.getHeight());
             }
-            if (viewParent.getChildVisibleRect(view, handwritingArea, null)) {
-                return handwritingArea;
+            if (viewParent.getChildVisibleRect(view, globalHandwritingArea, null)) {
+                return globalHandwritingArea;
             }
         }
         return null;
@@ -329,7 +331,8 @@
     /**
      * Return true if the (x, y) is inside by the given {@link Rect}.
      */
-    private boolean contains(@NonNull Rect rect, float x, float y) {
+    private boolean contains(@Nullable Rect rect, float x, float y) {
+        if (rect == null) return false;
         return x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom;
     }
 
@@ -481,17 +484,18 @@
             if (!mIsDirty) {
                 return true;
             }
-            final Rect localRect = view.getHandwritingArea();
-            if (localRect == null) {
+            final Rect handwritingArea = view.getHandwritingArea();
+            if (handwritingArea == null) {
                 return false;
             }
 
             ViewParent parent = view.getParent();
             if (parent != null) {
-                final Rect newRect = new Rect(localRect);
-                if (parent.getChildVisibleRect(view, newRect, null /* offset */)) {
-                    mHandwritingArea = newRect;
-                } else {
+                if (mHandwritingArea == null) {
+                    mHandwritingArea = new Rect();
+                }
+                mHandwritingArea.set(handwritingArea);
+                if (!parent.getChildVisibleRect(view, mHandwritingArea, null /* offset */)) {
                     mHandwritingArea = null;
                 }
             }
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 12421ed..1f6cee6 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -55,7 +55,8 @@
 
     void resized(in ClientWindowFrames frames, boolean reportDraw,
             in MergedConfiguration newMergedConfiguration,
-            boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId);
+            boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
+            int syncSeqId);
 
     /**
      * Called when the window insets configuration has changed.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 5c7c844..fd86900 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -104,7 +104,8 @@
             int requestedWidth, int requestedHeight, int viewVisibility,
             int flags, out ClientWindowFrames outFrames,
             out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
-            out InsetsState insetsState, out InsetsSourceControl[] activeControls);
+            out InsetsState insetsState, out InsetsSourceControl[] activeControls,
+            out Bundle bundle);
 
     /*
      * Notify the window manager that an application is relaunching and
@@ -142,7 +143,8 @@
      * is null if there is no sync required.
      */
     @UnsupportedAppUsage
-    oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
+    oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction,
+            int seqId);
 
     @UnsupportedAppUsage
     oneway void setInTouchMode(boolean showFocus);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c222991..1b8dc70 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12016,7 +12016,6 @@
 
     /**
      * Return the handwriting areas set on this view, in its local coordinates.
-     * Notice: the caller of this method should not modify the Rect returned.
      * @see #setHandwritingArea(Rect)
      *
      * @hide
@@ -12025,7 +12024,7 @@
     public Rect getHandwritingArea() {
         final ListenerInfo info = mListenerInfo;
         if (info != null) {
-            return info.mHandwritingArea;
+            return new Rect(info.mHandwritingArea);
         }
         return null;
     }
@@ -15617,7 +15616,7 @@
      * @param event the KeyEvent object that defines the button action
      */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) {
+        if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                 return true;
             }
@@ -15674,7 +15673,7 @@
      * @param event   The KeyEvent object that defines the button action.
      */
     public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (event.hasNoModifiers() && KeyEvent.isConfirmKey(keyCode)) {
+        if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                 return true;
             }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e79bdce..cdbf8b4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -552,7 +552,6 @@
 
     private final Rect mVisRect = new Rect(); // used to retrieve visible rect of focused view.
     private final Rect mTempRect = new Rect();
-    private final Rect mTempRect2 = new Rect();
 
     private final WindowLayout mWindowLayout = new WindowLayout();
 
@@ -830,6 +829,24 @@
 
     private int mLastTransformHint = Integer.MIN_VALUE;
 
+    /**
+     * A temporary object used so relayoutWindow can return the latest SyncSeqId
+     * system. The SyncSeqId system was designed to work without synchronous relayout
+     * window, and actually synchronous relayout window presents a problem.  We could have
+     * a sequence like this:
+     *    1. We send MSG_RESIZED to the client with a new syncSeqId to begin a new sync
+     *    2. Due to scheduling the client executes performTraversals before calling MSG_RESIZED
+     *    3. Coincidentally for some random reason it also calls relayout
+     *    4. It observes the new state from relayout, and so the next frame will contain the state
+     * However it hasn't received the seqId yet, and so under the designed operation of
+     * seqId flowing through MSG_RESIZED, the next frame wouldn't be synced. Since it
+     * contains our target sync state, we need to sync it! This problem won't come up once
+     * we get rid of synchronous relayout, until then, we use this bundle to channel the
+     * integer back over relayout.
+     */
+    private Bundle mRelayoutBundle = new Bundle();
+    private int mSyncSeqId;
+
     private String mTag = TAG;
 
     public ViewRootImpl(Context context, Display display) {
@@ -1205,8 +1222,7 @@
                         displayCutoutSafe, winConfig.getBounds(), winConfig.getWindowingMode(),
                         UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH,
                         mInsetsController.getRequestedVisibilities(),
-                        getAttachedWindowFrame(), 1f /* compactScale */,
-                        mTmpFrames.displayFrame, mTempRect2, mTmpFrames.frame);
+                        getAttachedWindowFrame(), 1f /* compactScale */, mTmpFrames);
                 setFrame(mTmpFrames.frame);
                 registerBackCallbackOnWindow();
                 if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
@@ -1711,6 +1727,7 @@
         mPendingBackDropFrame.set(backdropFrame);
         mForceNextWindowRelayout = forceNextWindowRelayout;
         mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
+        mSyncSeqId = args.argi4;
 
         if (msg == MSG_RESIZED_REPORT) {
             reportNextDraw();
@@ -4128,7 +4145,7 @@
         mDrawsNeededToReport = 0;
 
         try {
-            mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
+            mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
         } catch (RemoteException e) {
             Log.e(mTag, "Unable to report draw finished", e);
             mSurfaceChangedTransaction.apply();
@@ -8071,7 +8088,7 @@
                 requestedWidth, requestedHeight, viewVisibility,
                 insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                 mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
-                mTempControls);
+                mTempControls, mRelayoutBundle);
 
         final int transformHint = SurfaceControl.rotationToBufferTransform(
                 (mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -8497,7 +8514,7 @@
                             if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
                                     & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                                 mWindowSession.finishDrawing(
-                                        mWindow, null /* postDrawTransaction */);
+                                    mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
                             }
                         } catch (RemoteException e) {
                         }
@@ -8571,7 +8588,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
             MergedConfiguration mergedConfiguration, boolean forceLayout,
-            boolean alwaysConsumeSystemBars, int displayId) {
+                                 boolean alwaysConsumeSystemBars, int displayId, int seqId) {
         final Rect frame = frames.frame;
         final Rect backDropFrame = frames.backdropFrame;
         if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
@@ -8602,6 +8619,7 @@
         args.argi1 = forceLayout ? 1 : 0;
         args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
         args.argi3 = displayId;
+        args.argi4 = seqId;
         msg.obj = args;
         mHandler.sendMessage(msg);
     }
@@ -9986,11 +10004,11 @@
         @Override
         public void resized(ClientWindowFrames frames, boolean reportDraw,
                 MergedConfiguration mergedConfiguration, boolean forceLayout,
-                boolean alwaysConsumeSystemBars, int displayId) {
+                boolean alwaysConsumeSystemBars, int displayId, int seqId) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout,
-                        alwaysConsumeSystemBars, displayId);
+                        alwaysConsumeSystemBars, displayId, seqId);
             }
         }
 
diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java
index ad9f21b..a3b1313 100644
--- a/core/java/android/view/WindowLayout.java
+++ b/core/java/android/view/WindowLayout.java
@@ -42,6 +42,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.Log;
+import android.window.ClientWindowFrames;
 
 /**
  * Computes window frames.
@@ -56,15 +57,17 @@
     private final Rect mTempDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
     private final Rect mTempRect = new Rect();
 
-    public boolean computeFrames(WindowManager.LayoutParams attrs, InsetsState state,
+    public void computeFrames(WindowManager.LayoutParams attrs, InsetsState state,
             Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode,
             int requestedWidth, int requestedHeight, InsetsVisibilities requestedVisibilities,
-            Rect attachedWindowFrame, float compatScale, Rect outDisplayFrame, Rect outParentFrame,
-            Rect outFrame) {
+            Rect attachedWindowFrame, float compatScale, ClientWindowFrames outFrames) {
         final int type = attrs.type;
         final int fl = attrs.flags;
         final int pfl = attrs.privateFlags;
         final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
+        final Rect outDisplayFrame = outFrames.displayFrame;
+        final Rect outParentFrame = outFrames.parentFrame;
+        final Rect outFrame = outFrames.frame;
 
         // Compute bounds restricted by insets
         final Insets insets = state.calculateInsets(windowBounds, attrs.getFitInsetsTypes(),
@@ -95,7 +98,7 @@
         final DisplayCutout cutout = state.getDisplayCutout();
         final Rect displayCutoutSafeExceptMaybeBars = mTempDisplayCutoutSafeExceptMaybeBarsRect;
         displayCutoutSafeExceptMaybeBars.set(displayCutoutSafe);
-        boolean clippedByDisplayCutout = false;
+        outFrames.isParentFrameClippedByDisplayCutout = false;
         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS && !cutout.isEmpty()) {
             // Ensure that windows with a non-ALWAYS display cutout mode are laid out in
             // the cutout safe zone.
@@ -158,7 +161,7 @@
             if (!attachedInParent && !floatingInScreenWindow) {
                 mTempRect.set(outParentFrame);
                 outParentFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
-                clippedByDisplayCutout = !mTempRect.equals(outParentFrame);
+                outFrames.isParentFrameClippedByDisplayCutout = !mTempRect.equals(outParentFrame);
             }
             outDisplayFrame.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
         }
@@ -287,9 +290,7 @@
         }
 
         if (DEBUG) Log.d(TAG, "computeWindowFrames " + attrs.getTitle()
-                + " outFrame=" + outFrame.toShortString()
-                + " outParentFrame=" + outParentFrame.toShortString()
-                + " outDisplayFrame=" + outDisplayFrame.toShortString()
+                + " outFrames=" + outFrames
                 + " windowBounds=" + windowBounds.toShortString()
                 + " attachedWindowFrame=" + (attachedWindowFrame != null
                         ? attachedWindowFrame.toShortString()
@@ -302,8 +303,6 @@
                 + " attrs=" + attrs
                 + " state=" + state
                 + " requestedVisibilities=" + requestedVisibilities);
-
-        return clippedByDisplayCutout;
     }
 
     public static void computeSurfaceSize(WindowManager.LayoutParams attrs, Rect maxBounds,
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index a270c92..ad151df 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -22,6 +22,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -217,9 +218,13 @@
             throw new IllegalArgumentException(
                     "Invalid window token (never added or removed already)");
         }
+        removeSurface(state.mSurfaceControl);
+    }
 
+    /** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
+    protected void removeSurface(SurfaceControl sc) {
         try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
-            t.remove(state.mSurfaceControl).apply();
+            t.remove(sc).apply();
         }
     }
 
@@ -277,7 +282,7 @@
             int requestedWidth, int requestedHeight, int viewFlags, int flags,
             ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            InsetsSourceControl[] outActiveControls) {
+            InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
         final State state;
         synchronized (this) {
             state = mStateForWindow.get(window.asBinder());
@@ -354,7 +359,7 @@
 
     @Override
     public void finishDrawing(android.view.IWindow window,
-            android.view.SurfaceControl.Transaction postDrawTransaction) {
+            android.view.SurfaceControl.Transaction postDrawTransaction, int seqId) {
         synchronized (this) {
             final ResizeCompleteCallback c =
                 mResizeCompletionForWindow.get(window.asBinder());
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a8cc114..3c5007b 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -3121,17 +3121,19 @@
     }
 
     /**
-     * If autofill suggestions for a dialog-style UI are available for {@code view}, shows a dialog
-     * allowing the user to select a suggestion and returns {@code true}.
+     * If autofill suggestions for a
+     * <a href="{@docRoot}reference/android/service/autofill/Dataset.html#FillDialogUI">
+     * dialog-style UI</a> are available for {@code view}, shows a dialog allowing the user to
+     * select a suggestion and returns {@code true}.
      * <p>
      * The dialog may not be available if the autofill service does not support it, or if the
      * autofill request has not returned a response yet.
      * <p>
-     * It is recommended to call this method the first time a user focuses on an autofill-able form,
-     * and to avoid showing the input method if the dialog is shown. If this method returns
-     * {@code false}, you should then instead show the input method (assuming that is how the
-     * view normally handles the focus event). If the user re-focuses on the view, you should not
-     * call this method again so as to not disrupt usage of the input method.
+     * It is recommended apps to call this method the first time a user focuses on
+     * an autofill-able form, and to avoid showing the input method if the dialog is shown. If
+     * this method returns {@code false}, you should then instead show the input method (assuming
+     * that is how the view normally handles the focus event). If the user re-focuses on the view,
+     * you should not call this method again so as to not disrupt usage of the input method.
      *
      * @param view the view for which to show autofill suggestions. This is typically a view
      *             receiving a focus event. The autofill suggestions shown will include content for
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b076d39..3c8fcb9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -788,7 +788,8 @@
     private Layout mLayout;
     private boolean mLocalesChanged = false;
     private int mTextSizeUnit = -1;
-    private LineBreakConfig mLineBreakConfig = new LineBreakConfig();
+    private int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE;
+    private int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE;
 
     // This is used to reflect the current user preference for changing font weight and making text
     // more bold.
@@ -1457,13 +1458,12 @@
                     break;
 
                 case com.android.internal.R.styleable.TextView_lineBreakStyle:
-                    mLineBreakConfig.setLineBreakStyle(
-                            a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE));
+                    mLineBreakStyle = a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_lineBreakWordStyle:
-                    mLineBreakConfig.setLineBreakWordStyle(
-                            a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE));
+                    mLineBreakWordStyle = a.getInt(attr,
+                            LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeTextType:
@@ -4301,13 +4301,12 @@
             @LineBreakConfig.LineBreakStyle int lineBreakStyle,
             @LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
         boolean updated = false;
-        if (isLineBreakStyleSpecified && mLineBreakConfig.getLineBreakStyle() != lineBreakStyle) {
-            mLineBreakConfig.setLineBreakStyle(lineBreakStyle);
+        if (isLineBreakStyleSpecified && mLineBreakStyle != lineBreakStyle) {
+            mLineBreakStyle = lineBreakStyle;
             updated = true;
         }
-        if (isLineBreakWordStyleSpecified
-                && mLineBreakConfig.getLineBreakWordStyle() != lineBreakWordStyle) {
-            mLineBreakConfig.setLineBreakWordStyle(lineBreakWordStyle);
+        if (isLineBreakWordStyleSpecified && mLineBreakWordStyle != lineBreakWordStyle) {
+            mLineBreakWordStyle = lineBreakWordStyle;
             updated = true;
         }
         if (updated && mLayout != null) {
@@ -4871,50 +4870,72 @@
     }
 
     /**
-     * Sets line break configuration indicates which strategy needs to be used when calculating the
-     * text wrapping.
-     * <P>
-     * There are two types of line break rules that can be configured at the same time. One is
-     * line break style(lb) and the other is line break word style(lw). The line break style
-     * affects rule-based breaking. The line break word style affects dictionary-based breaking
-     * and provide phrase-based breaking opportunities. There are several types for the
-     * line break style:
+     * Set the line break style for text wrapping.
+     *
+     * The line break style to indicates the line break strategies can be used when
+     * calculating the text wrapping. The line break style affects rule-based breaking. It
+     * specifies the strictness of line-breaking rules.
+     * There are several types for the line break style:
      * {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE},
      * {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and
-     * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}.
-     * The type for the line break word style is
-     * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}.
-     * The default values of the line break style and the line break word style are
-     * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and
-     * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE} respectively, indicating that no line
-     * breaking rules are specified.
-     * See <a href="https://drafts.csswg.org/css-text/#line-break-property">
+     * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style
+     * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified.
+     * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">
      *         the line-break property</a>
      *
-     * @param lineBreakConfig the line break config for text wrapping.
+     * @param lineBreakStyle the line break style for the text.
      */
-    public void setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
-        Objects.requireNonNull(lineBreakConfig);
-        if (mLineBreakConfig.equals(lineBreakConfig)) {
-            return;
-        }
-        mLineBreakConfig.set(lineBreakConfig);
-        if (mLayout != null) {
-            nullLayouts();
-            requestLayout();
-            invalidate();
+    public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) {
+        if (mLineBreakStyle != lineBreakStyle) {
+            mLineBreakStyle = lineBreakStyle;
+            if (mLayout != null) {
+                nullLayouts();
+                requestLayout();
+                invalidate();
+            }
         }
     }
 
     /**
-     * Get the current line break configuration for text wrapping.
+     * Set the line break word style for text wrapping.
      *
-     * @return the current line break configuration to be used for text wrapping.
+     * The line break word style affects dictionary-based breaking and provide phrase-based
+     * breaking opportunities. The type for the line break word style is
+     * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break
+     * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule
+     * is specified.
+     * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property">
+     *         the word-break property</a>
+     *
+     * @param lineBreakWordStyle the line break word style for the tet
      */
-    public @NonNull LineBreakConfig getLineBreakConfig() {
-        LineBreakConfig lbConfig = new LineBreakConfig();
-        lbConfig.set(mLineBreakConfig);
-        return lbConfig;
+    public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
+        if (mLineBreakWordStyle != lineBreakWordStyle) {
+            mLineBreakWordStyle = lineBreakWordStyle;
+            if (mLayout != null) {
+                nullLayouts();
+                requestLayout();
+                invalidate();
+            }
+        }
+    }
+
+    /**
+     * Get the current line break style for text wrapping.
+     *
+     * @return the current line break style to be used for text wrapping.
+     */
+    public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() {
+        return mLineBreakStyle;
+    }
+
+    /**
+     * Get the current line word break style for text wrapping.
+     *
+     * @return the current line break word style to be used for text wrapping.
+     */
+    public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() {
+        return mLineBreakWordStyle;
     }
 
     /**
@@ -4924,7 +4945,8 @@
      * @see PrecomputedText
      */
     public @NonNull PrecomputedText.Params getTextMetricsParams() {
-        return new PrecomputedText.Params(new TextPaint(mTextPaint), mLineBreakConfig,
+        return new PrecomputedText.Params(new TextPaint(mTextPaint),
+                LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle),
                 getTextDirectionHeuristic(),
                 mBreakStrategy, mHyphenationFrequency);
     }
@@ -4941,13 +4963,9 @@
         mTextDir = params.getTextDirection();
         mBreakStrategy = params.getBreakStrategy();
         mHyphenationFrequency = params.getHyphenationFrequency();
-        if (params.getLineBreakConfig() != null) {
-            mLineBreakConfig.set(params.getLineBreakConfig());
-        } else {
-            // Set default value if the line break config in the PrecomputedText.Params is null.
-            mLineBreakConfig.setLineBreakStyle(DEFAULT_LINE_BREAK_STYLE);
-            mLineBreakConfig.setLineBreakWordStyle(DEFAULT_LINE_BREAK_WORD_STYLE);
-        }
+        LineBreakConfig lineBreakConfig = params.getLineBreakConfig();
+        mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
+        mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
         if (mLayout != null) {
             nullLayouts();
             requestLayout();
@@ -6486,7 +6504,8 @@
             }
             final @PrecomputedText.Params.CheckResultUsableResult int checkResult =
                     precomputed.getParams().checkResultUsable(getPaint(), mTextDir, mBreakStrategy,
-                            mHyphenationFrequency, mLineBreakConfig);
+                            mHyphenationFrequency, LineBreakConfig.getLineBreakConfig(
+                                    mLineBreakStyle, mLineBreakWordStyle));
             switch (checkResult) {
                 case PrecomputedText.Params.UNUSABLE:
                     throw new IllegalArgumentException(
@@ -9383,7 +9402,8 @@
                         .setHyphenationFrequency(mHyphenationFrequency)
                         .setJustificationMode(mJustificationMode)
                         .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
-                        .setLineBreakConfig(mLineBreakConfig);
+                        .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+                                mLineBreakStyle, mLineBreakWordStyle));
                 if (shouldEllipsize) {
                     builder.setEllipsize(mEllipsize)
                             .setEllipsizedWidth(ellipsisWidth);
@@ -9498,7 +9518,8 @@
                     .setHyphenationFrequency(mHyphenationFrequency)
                     .setJustificationMode(mJustificationMode)
                     .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
-                    .setLineBreakConfig(mLineBreakConfig);
+                    .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+                            mLineBreakStyle, mLineBreakWordStyle));
             if (shouldEllipsize) {
                 builder.setEllipsize(effectiveEllipsize)
                         .setEllipsizedWidth(ellipsisWidth);
@@ -9866,7 +9887,8 @@
                 .setJustificationMode(getJustificationMode())
                 .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                 .setTextDirection(getTextDirectionHeuristic())
-                .setLineBreakConfig(mLineBreakConfig);
+                .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+                        mLineBreakStyle, mLineBreakWordStyle));
 
         final StaticLayout layout = layoutBuilder.build();
 
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
index acf9882..5b915cc 100644
--- a/core/java/android/window/ClientWindowFrames.java
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -27,47 +27,55 @@
  */
 public class ClientWindowFrames implements Parcelable {
     /** The actual window bounds. */
-    public final @NonNull Rect frame;
+    public final @NonNull Rect frame = new Rect();
 
     /**
      * The container frame that is usually the same as display size. It may exclude the area of
      * insets if the window layout parameter has specified fit-insets-sides.
      */
-    public final @NonNull Rect displayFrame;
+    public final @NonNull Rect displayFrame = new Rect();
+
+    /**
+     * The frame to be referenced while applying gravity and MATCH_PARENT.
+     */
+    public final @NonNull Rect parentFrame = new Rect();
 
     /** The background area while the window is resizing. */
-    public final @NonNull Rect backdropFrame;
+    public final @NonNull Rect backdropFrame = new Rect();
+
+    public boolean isParentFrameClippedByDisplayCutout;
 
     public ClientWindowFrames() {
-        frame = new Rect();
-        displayFrame = new Rect();
-        backdropFrame = new Rect();
     }
 
     public ClientWindowFrames(ClientWindowFrames other) {
-        frame = new Rect(other.frame);
-        displayFrame = new Rect(other.displayFrame);
-        backdropFrame = new Rect(other.backdropFrame);
+        frame.set(other.frame);
+        displayFrame.set(other.displayFrame);
+        parentFrame.set(other.parentFrame);
+        backdropFrame.set(other.backdropFrame);
+        isParentFrameClippedByDisplayCutout = other.isParentFrameClippedByDisplayCutout;
     }
 
     private ClientWindowFrames(Parcel in) {
-        frame = Rect.CREATOR.createFromParcel(in);
-        displayFrame = Rect.CREATOR.createFromParcel(in);
-        backdropFrame = Rect.CREATOR.createFromParcel(in);
+        readFromParcel(in);
     }
 
     /** Needed for AIDL out parameters. */
     public void readFromParcel(Parcel in) {
         frame.readFromParcel(in);
         displayFrame.readFromParcel(in);
+        parentFrame.readFromParcel(in);
         backdropFrame.readFromParcel(in);
+        isParentFrameClippedByDisplayCutout = in.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         frame.writeToParcel(dest, flags);
         displayFrame.writeToParcel(dest, flags);
+        parentFrame.writeToParcel(dest, flags);
         backdropFrame.writeToParcel(dest, flags);
+        dest.writeBoolean(isParentFrameClippedByDisplayCutout);
     }
 
     @Override
@@ -75,7 +83,9 @@
         final StringBuilder sb = new StringBuilder(32);
         return "ClientWindowFrames{frame=" + frame.toShortString(sb)
                 + " display=" + displayFrame.toShortString(sb)
-                + " backdrop=" + backdropFrame.toShortString(sb) + "}";
+                + " parentFrame=" + parentFrame.toShortString(sb)
+                + " backdrop=" + backdropFrame.toShortString(sb)
+                + " parentClippedByDisplayCutout=" + isParentFrameClippedByDisplayCutout + "}";
     }
 
     @Override
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 5dbb551..d046cef 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -53,7 +53,7 @@
     private static final String TAG = "WindowOnBackDispatcher";
     private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
     private static final boolean IS_BACK_PREDICTABILITY_ENABLED = SystemProperties
-            .getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+            .getInt(BACK_PREDICTABILITY_PROP, 1) > 0;
 
     /** Convenience hashmap to quickly decide if a callback has been added. */
     private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5253956..3b46f62 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -166,7 +166,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    static final int VERSION = 206;
+    static final int VERSION = 207;
 
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
@@ -964,6 +964,16 @@
          * Timers for each combination of frequency range and signal strength.
          */
         public final StopwatchTimer[][] perStateTimers;
+        /**
+         * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
+         */
+        @Nullable
+        private LongSamplingCounter[][] mPerStateTxDurationMs = null;
+        /**
+         * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
+         */
+        @Nullable
+        private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
 
         RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
             perStateTimers =
@@ -1024,15 +1034,198 @@
         }
 
         /**
-         * Reset display timers.
+         * Returns the duration in milliseconds spent in a given state since the last mark.
+         */
+        public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
+                int signalStrength, long elapsedRealtimeMs) {
+            return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
+                    elapsedRealtimeMs * 1000) / 1000;
+        }
+
+        /**
+         * Set mark for all timers.
+         */
+        public void setMark(long elapsedRealtimeMs) {
+            final int size = perStateTimers.length;
+            for (int i = 0; i < size; i++) {
+                for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+                    perStateTimers[i][j].setMark(elapsedRealtimeMs);
+                }
+            }
+        }
+
+        /**
+         * Returns numbers of frequencies tracked for this RAT.
+         */
+        public int getFrequencyRangeCount() {
+            return perStateTimers.length;
+        }
+
+        /**
+         * Add TX time for a given state.
+         */
+        public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
+                int signalStrength, long durationMs) {
+            getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
+        }
+
+        /**
+         * Add TX time for a given frequency.
+         */
+        public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
+                long durationMs) {
+            getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
+        }
+
+        /**
+         * Reset radio access technology timers and counts.
          */
         public void reset(long elapsedRealtimeUs) {
             final int size = perStateTimers.length;
             for (int i = 0; i < size; i++) {
                 for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
                     perStateTimers[i][j].reset(false, elapsedRealtimeUs);
+                    if (mPerStateTxDurationMs == null) continue;
+                    mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
+                }
+                if (mPerFrequencyRxDurationMs == null) continue;
+                mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
+            }
+        }
+
+        /**
+         * Write data to summary parcel
+         */
+        public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
+            final int freqCount = perStateTimers.length;
+            out.writeInt(freqCount);
+            out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
+            for (int i = 0; i < freqCount; i++) {
+                for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+                    perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
                 }
             }
+
+            if (mPerStateTxDurationMs == null) {
+                out.writeInt(0);
+            } else {
+                out.writeInt(1);
+                for (int i = 0; i < freqCount; i++) {
+                    for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+                        mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
+                    }
+                }
+            }
+
+            if (mPerFrequencyRxDurationMs == null) {
+                out.writeInt(0);
+            } else {
+                out.writeInt(1);
+                for (int i = 0; i < freqCount; i++) {
+                    mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
+                }
+            }
+        }
+
+        /**
+         * Read data from summary parcel
+         */
+        public void readSummaryFromParcel(Parcel in) {
+            final int oldFreqCount = in.readInt();
+            final int oldSignalStrengthCount = in.readInt();
+            final int currFreqCount = perStateTimers.length;
+            final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+
+            for (int freq = 0; freq < oldFreqCount; freq++) {
+                for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
+                    if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
+                        // Mismatch with the summary parcel. Consume the data but don't use it.
+                        final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
+                                new TimeBase());
+                        // Consume perStateTimers data.
+                        temp.readSummaryFromParcelLocked(in);
+                    } else {
+                        perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
+                    }
+                }
+            }
+
+            if (in.readInt() == 1) {
+                for (int freq = 0; freq < oldFreqCount; freq++) {
+                    for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
+                        if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
+                            // Mismatch with the summary parcel. Consume the data but don't use it.
+                            final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
+                                    new TimeBase());
+                            // Consume mPerStateTxDurationMs data.
+                            temp.readSummaryFromParcelLocked(in);
+                        }
+                        getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
+                    }
+                }
+            }
+
+            if (in.readInt() == 1) {
+                for (int freq = 0; freq < oldFreqCount; freq++) {
+                    if (freq >= currFreqCount) {
+                        // Mismatch with the summary parcel. Consume the data but don't use it.
+                        final StopwatchTimer
+                                temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
+                        // Consume mPerFrequencyRxDurationMs data.
+                        temp.readSummaryFromParcelLocked(in);
+                        continue;
+                    }
+                    getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
+                }
+            }
+        }
+
+        private LongSamplingCounter getTxDurationCounter(
+                @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
+            if (mPerStateTxDurationMs == null) {
+                if (!make) return null;
+
+                final int freqCount = getFrequencyRangeCount();
+                final int signalStrengthCount = perStateTimers[0].length;
+                final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
+                mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
+                for (int freq = 0; freq < freqCount; freq++) {
+                    for (int strength = 0; strength < signalStrengthCount; strength++) {
+                        mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
+                    }
+                }
+            }
+            if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
+                Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+                        + ") requested in getTxDurationCounter");
+                return null;
+            }
+            if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
+                Slog.w(TAG, "Unexpected signal strength (" + signalStrength
+                        + ") requested in getTxDurationCounter");
+                return null;
+            }
+            return mPerStateTxDurationMs[frequencyRange][signalStrength];
+        }
+
+        private LongSamplingCounter getRxDurationCounter(
+                @ServiceState.FrequencyRange int frequencyRange, boolean make) {
+            if (mPerFrequencyRxDurationMs == null) {
+                if (!make) return null;
+
+                final int freqCount = getFrequencyRangeCount();
+                final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
+                mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
+                for (int freq = 0; freq < freqCount; freq++) {
+                    mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
+                }
+            }
+            if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
+                Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+                        + ") requested in getRxDurationCounter");
+                return null;
+            }
+            return mPerFrequencyRxDurationMs[frequencyRange];
         }
     }
 
@@ -1929,18 +2122,26 @@
         private final TimeBase mTimeBase;
         private final LongMultiStateCounter mCounter;
 
-        private TimeMultiStateCounter(TimeBase timeBase, Parcel in, long timestampMs) {
+        private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
+            this(timeBase, new LongMultiStateCounter(stateCount), timestampMs);
+        }
+
+        private TimeMultiStateCounter(TimeBase timeBase, LongMultiStateCounter counter,
+                long timestampMs) {
             mTimeBase = timeBase;
-            mCounter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+            mCounter = counter;
             mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
             timeBase.add(this);
         }
 
-        private TimeMultiStateCounter(TimeBase timeBase, int stateCount, long timestampMs) {
-            mTimeBase = timeBase;
-            mCounter = new LongMultiStateCounter(stateCount);
-            mCounter.setEnabled(mTimeBase.isRunning(), timestampMs);
-            timeBase.add(this);
+        @Nullable
+        private static TimeMultiStateCounter readFromParcel(Parcel in, TimeBase timeBase,
+                int stateCount, long timestampMs) {
+            LongMultiStateCounter counter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+            if (counter.getStateCount() != stateCount) {
+                return null;
+            }
+            return new TimeMultiStateCounter(timeBase, counter, timestampMs);
         }
 
         private void writeToParcel(Parcel out) {
@@ -3510,11 +3711,8 @@
 
         private TimeMultiStateCounter readTimeMultiStateCounter(Parcel in, TimeBase timeBase) {
             if (in.readBoolean()) {
-                final TimeMultiStateCounter counter =
-                        new TimeMultiStateCounter(timeBase, in, mClock.elapsedRealtime());
-                if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
-                    return counter;
-                }
+                return TimeMultiStateCounter.readFromParcel(in, timeBase,
+                        BatteryConsumer.PROCESS_STATE_COUNT, mClock.elapsedRealtime());
             }
             return null;
         }
@@ -3537,9 +3735,10 @@
                 // invalid.
                 TimeMultiStateCounter[] counters = new TimeMultiStateCounter[numCounters];
                 for (int i = 0; i < numCounters; i++) {
-                    final TimeMultiStateCounter counter =
-                            new TimeMultiStateCounter(timeBase, in, mClock.elapsedRealtime());
-                    if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
+                    final TimeMultiStateCounter counter = TimeMultiStateCounter.readFromParcel(in,
+                            timeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+                            mClock.elapsedRealtime());
+                    if (counter != null) {
                         counters[i] = counter;
                     } else {
                         valid = false;
@@ -8000,6 +8199,32 @@
                 elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
     }
 
+    @Override
+    public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
+            @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+            long elapsedRealtimeMs) {
+        final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+        if (stats == null) return DURATION_UNAVAILABLE;
+
+        final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
+                signalStrength, false);
+        if (counter == null) return DURATION_UNAVAILABLE;
+
+        return counter.getCountLocked(STATS_SINCE_CHARGED);
+    }
+
+    @Override
+    public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
+            @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
+        final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+        if (stats == null) return DURATION_UNAVAILABLE;
+
+        final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
+        if (counter == null) return DURATION_UNAVAILABLE;
+
+        return counter.getCountLocked(STATS_SINCE_CHARGED);
+    }
+
     @UnsupportedAppUsage
     @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
         return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
@@ -10744,11 +10969,9 @@
                             = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
                 }
                 if (in.readBoolean()) {
-                    final TimeMultiStateCounter counter =
-                            new TimeMultiStateCounter(mBsi.mOnBatteryTimeBase, in, timestampMs);
-                    if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
-                        mMobileRadioActiveTime = counter;
-                    }
+                    mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
+                            mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+                            timestampMs);
                 }
 
                 mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -10794,11 +11017,9 @@
 
             int stateCount = in.readInt();
             if (stateCount != 0) {
-                final TimeMultiStateCounter counter = new TimeMultiStateCounter(
-                        mBsi.mOnBatteryTimeBase, in, timestampMs);
-                if (stateCount == BatteryConsumer.PROCESS_STATE_COUNT) {
-                    mCpuActiveTimeMs = counter;
-                }
+                mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
+                        mBsi.mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+                        timestampMs);
             }
             mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
 
@@ -13482,6 +13703,67 @@
                     addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
                     mTmpRailStats.resetCellularTotalEnergyUsed();
                 }
+
+                // Proportionally smear Rx and Tx times across each RAt
+                final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
+                long[] perSignalStrengthActiveTimeMs = new long[levelCount];
+                long totalActiveTimeMs = 0;
+
+                for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+                    final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+                    if (ratStats == null) continue;
+
+                    final int freqCount = ratStats.getFrequencyRangeCount();
+                    for (int freq = 0; freq < freqCount; freq++) {
+                        for (int level = 0; level < levelCount; level++) {
+                            final long durationMs = ratStats.getTimeSinceMark(freq, level,
+                                    elapsedRealtimeMs);
+                            perSignalStrengthActiveTimeMs[level] += durationMs;
+                            totalActiveTimeMs += durationMs;
+                        }
+                    }
+                }
+
+                if (totalActiveTimeMs != 0) {
+                    // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
+                    // strength.
+                    for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+                        final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+                        if (ratStats == null) continue;
+
+                        final int freqCount = ratStats.getFrequencyRangeCount();
+                        for (int freq = 0; freq < freqCount; freq++) {
+                            long frequencyDurationMs = 0;
+                            for (int level = 0; level < levelCount; level++) {
+                                final long durationMs = ratStats.getTimeSinceMark(freq, level,
+                                        elapsedRealtimeMs);
+                                final long totalLvlDurationMs =
+                                        perSignalStrengthActiveTimeMs[level];
+                                if (totalLvlDurationMs == 0) continue;
+                                final long totalTxLvlDurations =
+                                        deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
+                                // Smear HAL provided Tx power level duration based on active modem
+                                // duration in a given state. (Add totalLvlDurationMs / 2 before
+                                // the integer division with totalLvlDurationMs for rounding.)
+                                final long proportionalTxDurationMs =
+                                        (durationMs * totalTxLvlDurations
+                                                + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
+                                ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
+                                frequencyDurationMs += durationMs;
+                            }
+                            final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
+                            // Smear HAL provided Rx power duration based on active modem
+                            // duration in a given state.  (Add totalActiveTimeMs / 2 before the
+                            // integer division with totalActiveTimeMs for rounding.)
+                            final long proportionalRxDurationMs =
+                                    (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
+                                            / 2)) / totalActiveTimeMs;
+                            ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
+                        }
+
+                        ratStats.setMark(elapsedRealtimeMs);
+                    }
+                }
             }
             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
                     elapsedRealtimeMs * 1000);
@@ -16887,14 +17169,18 @@
         mNextMaxDailyDeadlineMs = in.readLong();
         mBatteryTimeToFullSeconds = in.readLong();
 
-        mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in);
-
-        /**
-         * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
-         *          later when {@link #initMeasuredEnergyStatsLocked} is called.
-         */
-        mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(
-                mMeasuredEnergyStatsConfig, in);
+        final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in);
+        final MeasuredEnergyStats measuredEnergyStats =
+                MeasuredEnergyStats.createAndReadSummaryFromParcel(mMeasuredEnergyStatsConfig, in);
+        if (config != null && Arrays.equals(config.getStateNames(),
+                getBatteryConsumerProcessStateNames())) {
+            /**
+             * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled
+             *          later when {@link #initMeasuredEnergyStatsLocked} is called.
+             */
+            mMeasuredEnergyStatsConfig = config;
+            mGlobalMeasuredEnergyStats = measuredEnergyStats;
+        }
 
         mStartCount++;
 
@@ -16926,6 +17212,13 @@
             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
         }
+
+        final int numRat = in.readInt();
+        for (int i = 0; i < numRat; i++) {
+            if (in.readInt() == 0) continue;
+            getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
+        }
+
         mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
@@ -16986,7 +17279,6 @@
                 getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
             }
         }
-
         int NKW = in.readInt();
         if (NKW > 10000) {
             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
@@ -17114,11 +17406,9 @@
                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
                 }
                 if (in.readBoolean()) {
-                    TimeMultiStateCounter counter = new TimeMultiStateCounter(
-                            mOnBatteryTimeBase, in, elapsedRealtimeMs);
-                    if (counter.getStateCount() == BatteryConsumer.PROCESS_STATE_COUNT) {
-                        u.mMobileRadioActiveTime = counter;
-                    }
+                    u.mMobileRadioActiveTime = TimeMultiStateCounter.readFromParcel(in,
+                            mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+                            elapsedRealtimeMs);
                 }
                 u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
             }
@@ -17168,11 +17458,9 @@
 
             int stateCount = in.readInt();
             if (stateCount != 0) {
-                final TimeMultiStateCounter counter = new TimeMultiStateCounter(
-                        mOnBatteryTimeBase, in, mClock.elapsedRealtime());
-                if (stateCount == BatteryConsumer.PROCESS_STATE_COUNT) {
-                    u.mCpuActiveTimeMs = counter;
-                }
+                u.mCpuActiveTimeMs = TimeMultiStateCounter.readFromParcel(in,
+                        mOnBatteryTimeBase, BatteryConsumer.PROCESS_STATE_COUNT,
+                        mClock.elapsedRealtime());
             }
             u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
 
@@ -17431,6 +17719,17 @@
             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
         }
+        final int numRat = mPerRatBatteryStats.length;
+        out.writeInt(numRat);
+        for (int i = 0; i < numRat; i++) {
+            final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
+            if (ratStat == null) {
+                out.writeInt(0);
+                continue;
+            }
+            out.writeInt(1);
+            ratStat.writeSummaryToParcel(out, nowRealtime);
+        }
         mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
         mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
         mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
@@ -18007,9 +18306,15 @@
         mLastWriteTimeMs = in.readLong();
         mBatteryTimeToFullSeconds = in.readLong();
 
-        mMeasuredEnergyStatsConfig = MeasuredEnergyStats.Config.createFromParcel(in);
-        mGlobalMeasuredEnergyStats =
+
+        final MeasuredEnergyStats.Config config = MeasuredEnergyStats.Config.createFromParcel(in);
+        final MeasuredEnergyStats measuredEnergyStats =
                 MeasuredEnergyStats.createFromParcel(mMeasuredEnergyStatsConfig, in);
+        if (config != null && Arrays.equals(config.getStateNames(),
+                getBatteryConsumerProcessStateNames())) {
+            mMeasuredEnergyStatsConfig = config;
+            mGlobalMeasuredEnergyStats = measuredEnergyStats;
+        }
 
         mRpmStats.clear();
         int NRPMS = in.readInt();
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index 7262e84..7fb8696 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -194,6 +194,7 @@
             return mSupportedMultiStateBuckets[index];
         }
 
+        @NonNull
         public String[] getStateNames() {
             return mStateNames;
         }
@@ -321,6 +322,10 @@
             LongMultiStateCounter multiStateCounter = null;
             if (in.readBoolean()) {
                 multiStateCounter = LongMultiStateCounter.CREATOR.createFromParcel(in);
+                if (mConfig == null
+                        || multiStateCounter.getStateCount() != mConfig.getStateNames().length) {
+                    multiStateCounter = null;
+                }
             }
 
             if (index < mAccumulatedChargeMicroCoulomb.length) {
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 6673f67..842d72a 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -51,10 +51,10 @@
     @Override
     public void resized(ClientWindowFrames frames, boolean reportDraw,
             MergedConfiguration mergedConfiguration, boolean forceLayout,
-            boolean alwaysConsumeSystemBars, int displayId) {
+            boolean alwaysConsumeSystemBars, int displayId, int seqId) {
         if (reportDraw) {
             try {
-                mSession.finishDrawing(this, null /* postDrawTransaction */);
+                mSession.finishDrawing(this, null /* postDrawTransaction */, seqId);
             } catch (RemoteException e) {
             }
         }
diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java
index 299cbe1..bd27e60 100644
--- a/core/java/com/android/internal/widget/CachingIconView.java
+++ b/core/java/com/android/internal/widget/CachingIconView.java
@@ -23,6 +23,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
@@ -35,6 +36,9 @@
 import android.widget.ImageView;
 import android.widget.RemoteViews;
 
+import com.android.internal.R;
+
+import java.io.IOException;
 import java.util.Objects;
 import java.util.function.Consumer;
 
@@ -55,9 +59,42 @@
     private int mBackgroundColor;
     private boolean mWillBeForceHidden;
 
+    private int mMaxDrawableWidth = -1;
+    private int mMaxDrawableHeight = -1;
+
+    public CachingIconView(Context context) {
+        this(context, null, 0, 0);
+    }
+
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public CachingIconView(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0, 0);
+    }
+
+    public CachingIconView(Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public CachingIconView(Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        if (attrs == null) {
+            return;
+        }
+
+        TypedArray ta = context.obtainStyledAttributes(attrs,
+                R.styleable.CachingIconView, defStyleAttr, defStyleRes);
+        mMaxDrawableWidth = ta.getDimensionPixelSize(R.styleable
+                .CachingIconView_maxDrawableWidth, -1);
+        mMaxDrawableHeight = ta.getDimensionPixelSize(R.styleable
+                .CachingIconView_maxDrawableHeight, -1);
+        ta.recycle();
     }
 
     @Override
@@ -66,15 +103,31 @@
         if (!testAndSetCache(icon)) {
             mInternalSetDrawable = true;
             // This calls back to setImageDrawable, make sure we don't clear the cache there.
-            super.setImageIcon(icon);
+            Drawable drawable = loadSizeRestrictedIcon(icon);
+            if (drawable == null) {
+                super.setImageIcon(icon);
+            } else {
+                super.setImageDrawable(drawable);
+            }
             mInternalSetDrawable = false;
         }
     }
 
+    @Nullable
+    private Drawable loadSizeRestrictedIcon(@Nullable Icon icon) {
+        try {
+            return LocalImageResolver.resolveImage(icon, getContext(), mMaxDrawableWidth,
+                    mMaxDrawableHeight);
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
     @Override
-    public Runnable setImageIconAsync(@Nullable Icon icon) {
+    public Runnable setImageIconAsync(@Nullable final Icon icon) {
         resetCache();
-        return super.setImageIconAsync(icon);
+        Drawable drawable = loadSizeRestrictedIcon(icon);
+        return () -> setImageDrawable(drawable);
     }
 
     @Override
@@ -83,14 +136,34 @@
         if (!testAndSetCache(resId)) {
             mInternalSetDrawable = true;
             // This calls back to setImageDrawable, make sure we don't clear the cache there.
-            super.setImageResource(resId);
+            Drawable drawable = loadSizeRestrictedDrawable(resId);
+            if (drawable == null) {
+                super.setImageResource(resId);
+            } else {
+                super.setImageDrawable(drawable);
+            }
             mInternalSetDrawable = false;
         }
     }
 
+    @Nullable
+    private Drawable loadSizeRestrictedDrawable(@DrawableRes int resId) {
+        try {
+            return LocalImageResolver.resolveImage(resId, getContext(), mMaxDrawableWidth,
+                    mMaxDrawableHeight);
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
     @Override
     public Runnable setImageResourceAsync(@DrawableRes int resId) {
         resetCache();
+        Drawable drawable = loadSizeRestrictedDrawable(resId);
+        if (drawable != null) {
+            return () -> setImageDrawable(drawable);
+        }
+
         return super.setImageResourceAsync(resId);
     }
 
@@ -98,13 +171,35 @@
     @RemotableViewMethod(asyncImpl="setImageURIAsync")
     public void setImageURI(@Nullable Uri uri) {
         resetCache();
-        super.setImageURI(uri);
+        Drawable drawable = loadSizeRestrictedUri(uri);
+        if (drawable == null) {
+            super.setImageURI(uri);
+        } else {
+            mInternalSetDrawable = true;
+            super.setImageDrawable(drawable);
+            mInternalSetDrawable = false;
+        }
+    }
+
+    @Nullable
+    private Drawable loadSizeRestrictedUri(@Nullable Uri uri) {
+        try {
+            return LocalImageResolver.resolveImage(uri, getContext(), mMaxDrawableWidth,
+                    mMaxDrawableHeight);
+        } catch (IOException e) {
+            return null;
+        }
     }
 
     @Override
     public Runnable setImageURIAsync(@Nullable Uri uri) {
         resetCache();
-        return super.setImageURIAsync(uri);
+        Drawable drawable = loadSizeRestrictedUri(uri);
+        if (drawable == null) {
+            return super.setImageURIAsync(uri);
+        } else {
+            return () -> setImageDrawable(drawable);
+        }
     }
 
     @Override
@@ -307,4 +402,18 @@
     public void setWillBeForceHidden(boolean forceHidden) {
         mWillBeForceHidden = forceHidden;
     }
+
+    /**
+     * Returns the set maximum width of drawable in pixels. -1 if not set.
+     */
+    public int getMaxDrawableWidth() {
+        return mMaxDrawableWidth;
+    }
+
+    /**
+     * Returns the set maximum height of drawable in pixels. -1 if not set.
+     */
+    public int getMaxDrawableHeight() {
+        return mMaxDrawableHeight;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 851e8e0..3494c9e 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -53,7 +53,6 @@
     VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, int userId, int flags);
     VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId);
     void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle);
-    boolean checkVoldPassword(int userId);
     int getCredentialType(int userId);
     byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
     void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in LockscreenCredential managedUserPassword);
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index 616b699..66a3ff9 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -16,21 +16,25 @@
 
 package com.android.internal.widget;
 
+import android.annotation.DrawableRes;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.ImageDecoder;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.util.Size;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
 
 /** A class to extract Drawables from a MessagingStyle/ConversationStyle message. */
 public class LocalImageResolver {
-    private static final String TAG = LocalImageResolver.class.getSimpleName();
 
-    private static final int MAX_SAFE_ICON_SIZE_PX = 480;
+    @VisibleForTesting
+    static final int DEFAULT_MAX_SAFE_ICON_SIZE_PX = 480;
 
     /**
      * Resolve an image from the given Uri using {@link ImageDecoder}
@@ -38,9 +42,9 @@
     public static Drawable resolveImage(Uri uri, Context context) throws IOException {
         final ImageDecoder.Source source =
                 ImageDecoder.createSource(context.getContentResolver(), uri);
-        final Drawable drawable =
-                ImageDecoder.decodeDrawable(source, LocalImageResolver::onHeaderDecoded);
-        return drawable;
+        return ImageDecoder.decodeDrawable(source,
+                (decoder, info, s) -> LocalImageResolver.onHeaderDecoded(decoder, info,
+                        DEFAULT_MAX_SAFE_ICON_SIZE_PX, DEFAULT_MAX_SAFE_ICON_SIZE_PX));
     }
 
     /**
@@ -48,17 +52,49 @@
      * using {@link Icon#loadDrawable(Context)} otherwise.  This will correctly apply the Icon's,
      * tint, if present, to the drawable.
      */
-    public static Drawable resolveImage(Icon icon, Context context) throws IOException {
-        Uri uri = getResolvableUri(icon);
-        if (uri != null) {
-            Drawable result = resolveImage(uri, context);
-            if (icon.hasTint()) {
-                result.mutate();
-                result.setTintList(icon.getTintList());
-                result.setTintBlendMode(icon.getTintBlendMode());
-            }
-            return result;
+    public static Drawable resolveImage(@Nullable Icon icon, Context context)
+            throws IOException {
+        return resolveImage(icon, context, DEFAULT_MAX_SAFE_ICON_SIZE_PX,
+                DEFAULT_MAX_SAFE_ICON_SIZE_PX);
+    }
+
+    /**
+     * Get the drawable from Icon using {@link ImageDecoder} if it contains a Uri, or
+     * using {@link Icon#loadDrawable(Context)} otherwise.  This will correctly apply the Icon's,
+     * tint, if present, to the drawable.
+     */
+    @Nullable
+    public static Drawable resolveImage(@Nullable Icon icon, Context context, int maxWidth,
+            int maxHeight)
+            throws IOException {
+        if (icon == null) {
+            return null;
         }
+
+        switch (icon.getType()) {
+            case Icon.TYPE_URI:
+            case Icon.TYPE_URI_ADAPTIVE_BITMAP:
+                Uri uri = getResolvableUri(icon);
+                if (uri != null) {
+                    Drawable result = resolveImage(uri, context, maxWidth, maxHeight);
+                    return tintDrawable(icon, result);
+                }
+                break;
+            case Icon.TYPE_RESOURCE:
+                Drawable result = resolveImage(icon.getResId(), context, maxWidth, maxHeight);
+                if (result != null) {
+                    return tintDrawable(icon, result);
+                }
+                break;
+            case Icon.TYPE_BITMAP:
+            case Icon.TYPE_ADAPTIVE_BITMAP:
+                return resolveBitmapImage(icon, context, maxWidth, maxHeight);
+            case Icon.TYPE_DATA:    // We can't really improve on raw data images.
+            default:
+                break;
+        }
+
+        // Fallback to straight drawable load if we fail with more efficient approach.
         return icon.loadDrawable(context);
     }
 
@@ -66,7 +102,71 @@
             throws IOException {
         final ImageDecoder.Source source =
                 ImageDecoder.createSource(context.getContentResolver(), uri);
+        return resolveImage(source, maxWidth, maxHeight);
+    }
+
+    /**
+     * Attempts to resolve the resource as a bitmap drawable constrained within max sizes.
+     *
+     * @return decoded drawable or null if the passed resource is not a straight bitmap
+     */
+    @Nullable
+    public static Drawable resolveImage(@DrawableRes int resId, Context context, int maxWidth,
+            int maxHeight)
+            throws IOException {
+        final ImageDecoder.Source source = ImageDecoder.createSource(context.getResources(), resId);
+        // It's possible that the resource isn't an actual bitmap drawable so this decode can fail.
+        // Return null in that case.
+        try {
+            return resolveImage(source, maxWidth, maxHeight);
+        } catch (ImageDecoder.DecodeException e) {
+            return null;
+        }
+    }
+
+    @Nullable
+    private static Drawable resolveBitmapImage(Icon icon, Context context, int maxWidth,
+            int maxHeight) {
+        Bitmap bitmap = icon.getBitmap();
+        if (bitmap == null) {
+            return null;
+        }
+
+        if (bitmap.getWidth() > maxWidth || bitmap.getHeight() > maxHeight) {
+            Icon smallerIcon = icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP
+                    ? Icon.createWithAdaptiveBitmap(bitmap) : Icon.createWithBitmap(bitmap);
+            // We don't want to modify the source icon, create a copy.
+            smallerIcon.setTintList(icon.getTintList())
+                    .setTintBlendMode(icon.getTintBlendMode())
+                    .scaleDownIfNecessary(maxWidth, maxHeight);
+            return smallerIcon.loadDrawable(context);
+        }
+
+        return icon.loadDrawable(context);
+    }
+
+    @Nullable
+    private static Drawable tintDrawable(Icon icon, @Nullable Drawable drawable) {
+        if (drawable == null) {
+            return null;
+        }
+
+        if (icon.hasTint()) {
+            drawable.mutate();
+            drawable.setTintList(icon.getTintList());
+            drawable.setTintBlendMode(icon.getTintBlendMode());
+        }
+
+        return drawable;
+    }
+
+    private static Drawable resolveImage(ImageDecoder.Source source, int maxWidth, int maxHeight)
+            throws IOException {
         return ImageDecoder.decodeDrawable(source, (decoder, info, unused) -> {
+            if (maxWidth <= 0 || maxHeight <= 0) {
+                return;
+            }
+
             final Size size = info.getSize();
             if (size.getWidth() > size.getHeight()) {
                 if (size.getWidth() > maxWidth) {
@@ -88,11 +188,12 @@
     }
 
     private static void onHeaderDecoded(ImageDecoder decoder, ImageDecoder.ImageInfo info,
-            ImageDecoder.Source source) {
+            int maxWidth, int maxHeight) {
         final Size size = info.getSize();
         final int originalSize = Math.max(size.getHeight(), size.getWidth());
-        final double ratio = (originalSize > MAX_SAFE_ICON_SIZE_PX)
-                ? originalSize * 1f / MAX_SAFE_ICON_SIZE_PX
+        final int maxSize = Math.max(maxWidth, maxHeight);
+        final double ratio = (originalSize > maxSize)
+                ? originalSize * 1f / maxSize
                 : 1.0;
         decoder.setTargetSampleSize(getPowerOfTwoForSampleRatio(ratio));
     }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 521b2f6..a94b307 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -526,20 +526,6 @@
     }
 
     /**
-     * Check to see if vold already has the password.
-     * Note that this also clears vold's copy of the password.
-     * @return Whether the vold password matches or not.
-     */
-    public boolean checkVoldPassword(int userId) {
-        try {
-            return getLockSettings().checkVoldPassword(userId);
-        } catch (RemoteException re) {
-            Log.e(TAG, "failed to check vold password", re);
-            return false;
-        }
-    }
-
-    /**
      * Returns the password history hash factor, needed to check new password against password
      * history with {@link #checkPasswordHistory(byte[], byte[], int)}
      */
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 4aa00f6..3a76745 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -361,7 +361,7 @@
                 "libwuffs_mirror_release_c",
             ],
         },
-        linux_glibc: {
+        host_linux: {
             srcs: [
                 "android_content_res_ApkAssets.cpp",
                 "android_database_CursorWindow.cpp",
diff --git a/core/proto/android/os/batteryusagestats.proto b/core/proto/android/os/batteryusagestats.proto
index cc90e05..856bc83 100644
--- a/core/proto/android/os/batteryusagestats.proto
+++ b/core/proto/android/os/batteryusagestats.proto
@@ -76,6 +76,7 @@
                 FOREGROUND = 1;
                 BACKGROUND = 2;
                 FOREGROUND_SERVICE = 3;
+                CACHED = 4;
             }
 
             optional ProcessState process_state = 2;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d652b2f..729bc82 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6051,10 +6051,10 @@
     <permission android:name="android.permission.MANAGE_APPOPS"
                 android:protectionLevel="signature" />
 
-    <!-- @hide Permission that allows background clipboard access.
-         <p>Not for use by third-party applications. -->
+    <!-- @SystemApi Permission that allows background clipboard access.
+         @hide Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND"
-        android:protectionLevel="signature" />
+        android:protectionLevel="internal|role" />
     <!-- @hide Permission that suppresses the notification when the clipboard is accessed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SUPPRESS_CLIPBOARD_ACCESS_NOTIFICATION"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 81a79c5..a7f2aa7 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -49,6 +49,8 @@
         android:layout_marginStart="@dimen/notification_icon_circle_start"
         android:background="@drawable/notification_icon_circle"
         android:padding="@dimen/notification_icon_circle_padding"
+        android:maxDrawableWidth="@dimen/notification_icon_circle_size"
+        android:maxDrawableHeight="@dimen/notification_icon_circle_size"
         />
 
     <!-- extends ViewGroup -->
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index c6983ae..fd787f6 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -45,6 +45,8 @@
         android:layout_marginStart="@dimen/notification_icon_circle_start"
         android:background="@drawable/notification_icon_circle"
         android:padding="@dimen/notification_icon_circle_padding"
+        android:maxDrawableWidth="@dimen/notification_icon_circle_size"
+        android:maxDrawableHeight="@dimen/notification_icon_circle_size"
         />
 
     <FrameLayout
@@ -136,7 +138,7 @@
 
         </LinearLayout>
 
-        <ImageView
+        <com.android.internal.widget.CachingIconView
             android:id="@+id/right_icon"
             android:layout_width="@dimen/notification_right_icon_size"
             android:layout_height="@dimen/notification_right_icon_size"
@@ -148,6 +150,8 @@
             android:clipToOutline="true"
             android:importantForAccessibility="no"
             android:scaleType="centerCrop"
+            android:maxDrawableWidth="@dimen/notification_right_icon_size"
+            android:maxDrawableHeight="@dimen/notification_right_icon_size"
             />
 
         <FrameLayout
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index f163ed5..8b3b795 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -13,7 +13,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<ImageView
+<com.android.internal.widget.CachingIconView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/right_icon"
     android:layout_width="@dimen/notification_right_icon_size"
@@ -25,4 +25,6 @@
     android:clipToOutline="true"
     android:importantForAccessibility="no"
     android:scaleType="centerCrop"
+    android:maxDrawableWidth="@dimen/notification_right_icon_size"
+    android:maxDrawableHeight="@dimen/notification_right_icon_size"
     />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index da5f899..b3203ae 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5479,9 +5479,9 @@
             <enum name="none" value="0" />
             <!-- Use the least restrictive rule for line-breaking. -->
             <enum name="loose" value="1" />
-            <!-- Indicate breaking text with the most comment set of line-breaking rules. -->
+            <!-- Indicates breaking text with the most comment set of line-breaking rules. -->
             <enum name="normal" value="2" />
-            <!-- ndicates breaking text with the most strictest line-breaking rules. -->
+            <!-- Indicates breaking text with the most strictest line-breaking rules. -->
             <enum name="strict" value="3" />
         </attr>
         <!-- Specify the phrase-based line break can be used when calculating the text wrapping.-->
@@ -9807,4 +9807,12 @@
         of the supported locale. {@link android.app.LocaleConfig} -->
         <attr name="name" />
     </declare-styleable>
+
+    <!-- @hide -->
+    <declare-styleable name="CachingIconView">
+        <!-- Maximum width of displayed drawable. Drawables exceeding this size will be downsampled. -->
+        <attr name="maxDrawableWidth" format="dimension"/>
+        <!-- Maximum width of height drawable. Drawables exceeding this size will be downsampled. -->
+        <attr name="maxDrawableHeight" format="dimension"/>
+    </declare-styleable>
     </resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 2dc17b8..0a4c4c0 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -148,6 +148,10 @@
     <public name="supportsInlineSuggestionsWithTouchExploration" />
     <public name="lineBreakStyle" />
     <public name="lineBreakWordStyle" />
+    <!-- @hide -->
+    <public name="maxDrawableWidth" />
+    <!-- @hide -->
+    <public name="maxDrawableHeight" />
   </staging-public-group>
 
   <staging-public-group type="id" first-id="0x01de0000">
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index 6a53f68..19bb718 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -188,6 +188,9 @@
                 case BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE:
                     label = "FGS";
                     break;
+                case BatteryConsumer.PROCESS_STATE_CACHED:
+                    label = "cached";
+                    break;
                 default:
                     continue;
             }
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
index 23b12cf..fd08e3c 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
@@ -242,13 +242,17 @@
                 BatteryConsumer.PROCESS_STATE_BACKGROUND);
         final BatteryConsumer.Key keyFgs = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
                 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+        final BatteryConsumer.Key keyCached = uidBuilder.getKey(BatteryConsumer.POWER_COMPONENT_CPU,
+                BatteryConsumer.PROCESS_STATE_CACHED);
 
         uidBuilder.setConsumedPower(keyFg, 9100, BatteryConsumer.POWER_MODEL_POWER_PROFILE)
                 .setUsageDurationMillis(keyFg, 8100)
                 .setConsumedPower(keyBg, 9200, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
                 .setUsageDurationMillis(keyBg, 8200)
                 .setConsumedPower(keyFgs, 9300, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
-                .setUsageDurationMillis(keyFgs, 8300);
+                .setUsageDurationMillis(keyFgs, 8300)
+                .setConsumedPower(keyCached, 9400, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY)
+                .setUsageDurationMillis(keyFgs, 8400);
 
         builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid1)
                 .setPackageWithHighestDrain("myPackage1")
diff --git a/core/tests/coretests/res/drawable/big_a.png b/core/tests/coretests/res/drawable/big_a.png
new file mode 100644
index 0000000..dc059a3
--- /dev/null
+++ b/core/tests/coretests/res/drawable/big_a.png
Binary files differ
diff --git a/core/tests/coretests/res/layout/caching_icon_view_test_max_size.xml b/core/tests/coretests/res/layout/caching_icon_view_test_max_size.xml
new file mode 100644
index 0000000..9a03446
--- /dev/null
+++ b/core/tests/coretests/res/layout/caching_icon_view_test_max_size.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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.internal.widget.CachingIconView
+          xmlns:android="http://schemas.android.com/apk/res/android"
+          android:id="@+id/caching_icon_view"
+          android:layout_width="120dp"
+          android:layout_height="120dp"
+          android:maxDrawableWidth="80dp"
+          android:maxDrawableHeight="80dp" />
diff --git a/core/tests/coretests/res/layout/caching_icon_view_test_no_max_size.xml b/core/tests/coretests/res/layout/caching_icon_view_test_no_max_size.xml
new file mode 100644
index 0000000..a213a97
--- /dev/null
+++ b/core/tests/coretests/res/layout/caching_icon_view_test_no_max_size.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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.internal.widget.CachingIconView
+          xmlns:android="http://schemas.android.com/apk/res/android"
+          android:id="@+id/caching_icon_view"
+          android:layout_width="120dp"
+          android:layout_height="120dp" />
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index f5cbffb..7ccb9d9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -17,6 +17,8 @@
 package com.android.internal.os;
 
 import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
 import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
 import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
@@ -24,7 +26,10 @@
 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
 
+import static org.mockito.Mockito.mock;
+
 import android.app.ActivityManager;
+import android.app.usage.NetworkStatsManager;
 import android.os.BatteryStats;
 import android.os.BatteryStats.HistoryItem;
 import android.os.BatteryStats.Uid.Sensor;
@@ -34,6 +39,7 @@
 import android.telephony.Annotation;
 import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.SparseIntArray;
@@ -48,6 +54,8 @@
 
 import junit.framework.TestCase;
 
+import org.mockito.Mock;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
@@ -72,6 +80,13 @@
     private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID);
     private static final WorkSource WS = new WorkSource(UID);
 
+    enum ModemState {
+        SLEEP, IDLE, RECEIVING, TRANSMITTING
+    }
+
+    @Mock
+    NetworkStatsManager mNetworkStatsManager;
+
     /**
      * Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
      */
@@ -1173,69 +1188,29 @@
     }
 
     @SmallTest
-    public void testGetPerStateActiveRadioDurationMs() {
+    public void testGetPerStateActiveRadioDurationMs_noModemActivity() {
         final MockClock clock = new MockClock(); // holds realtime and uptime in ms
         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
-        final int ratCount = BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
+        final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
         final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
         final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
 
         final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+        final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+        final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
         for (int rat = 0; rat < ratCount; rat++) {
             for (int freq = 0; freq < frequencyCount; freq++) {
+                // Should have no RX data without Modem Activity Info
+                expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
                     expectedDurationsMs[rat][freq][txLvl] = 0;
+                    // Should have no TX data without Modem Activity Info
+                    expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
                 }
             }
         }
 
-        class ModemAndBatteryState {
-            public long currentTimeMs = 100;
-            public boolean onBattery = false;
-            public boolean modemActive = false;
-            @Annotation.NetworkType
-            public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-            @BatteryStats.RadioAccessTechnology
-            public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
-            @ServiceState.FrequencyRange
-            public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
-            public SparseIntArray currentSignalStrengths = new SparseIntArray();
-
-            void setOnBattery(boolean onBattery) {
-                this.onBattery = onBattery;
-                bi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
-                        currentTimeMs * 1000);
-            }
-
-            void setModemActive(boolean active) {
-                modemActive = active;
-                final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
-                        : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
-                bi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
-            }
-
-            void setRatType(@Annotation.NetworkType int dataType,
-                    @BatteryStats.RadioAccessTechnology int rat) {
-                currentNetworkDataType = dataType;
-                currentRat = rat;
-                bi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
-                        currentFrequencyRange);
-            }
-
-            void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
-                currentFrequencyRange = frequency;
-                bi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
-                        ServiceState.STATE_IN_SERVICE, frequency);
-            }
-
-            void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
-                currentSignalStrengths.put(rat, strength);
-                final int size = currentSignalStrengths.size();
-                final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
-                bi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
-            }
-        }
-        final ModemAndBatteryState state = new ModemAndBatteryState();
+        final ModemAndBatteryState state = new ModemAndBatteryState(bi, null);
 
         IntConsumer incrementTime = inc -> {
             state.currentTimeMs += inc;
@@ -1253,6 +1228,7 @@
             expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
         };
 
+
         state.setOnBattery(false);
         state.setModemActive(false);
         state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
@@ -1260,95 +1236,367 @@
         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // While not on battery, the timers should not increase.
         state.setModemActive(true);
         incrementTime.accept(100);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
         incrementTime.accept(200);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
         incrementTime.accept(500);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
         incrementTime.accept(300);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
         incrementTime.accept(400);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
                 CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
         incrementTime.accept(500);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
         // start counting up.
         state.setOnBattery(true);
         incrementTime.accept(600);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
-
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
         // Changing LTE signal strength should be tracked.
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
         incrementTime.accept(700);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
         incrementTime.accept(800);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
         incrementTime.accept(900);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
                 CellSignalStrength.SIGNAL_STRENGTH_GREAT);
         incrementTime.accept(1000);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // Change in the signal strength of nonactive RAT should not affect anything.
         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
         incrementTime.accept(1100);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // Changing to OTHER Rat should start tracking the poor signal strength.
         state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
         incrementTime.accept(1200);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // Noting frequency change should not affect non NR Rat.
         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
         incrementTime.accept(1300);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
         incrementTime.accept(1400);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // Noting frequency change should not affect non NR Rat.
         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
         incrementTime.accept(1500);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
 
         // Modem no longer active, should not be tracking any more.
         state.setModemActive(false);
         incrementTime.accept(1500);
-        checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+    }
 
+    @SmallTest
+    public void testGetPerStateActiveRadioDurationMs_withModemActivity() {
+        final MockClock clock = new MockClock(); // holds realtime and uptime in ms
+        final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
+        bi.setPowerProfile(mock(PowerProfile.class));
+        final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
+        final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
+        final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
+
+        final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+        final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+        final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+        for (int rat = 0; rat < ratCount; rat++) {
+            for (int freq = 0; freq < frequencyCount; freq++) {
+                if (rat != RADIO_ACCESS_TECHNOLOGY_NR
+                        && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                    // Only the NR RAT should have per frequency data.
+                    expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+                } else {
+                    expectedRxDurationsMs[rat][freq] = 0;
+                }
+                expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+
+                for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+                    expectedDurationsMs[rat][freq][txLvl] = 0;
+
+                    if (rat != RADIO_ACCESS_TECHNOLOGY_NR
+                            && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                        // Only the NR RAT should have per frequency data.
+                        expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+                    } else {
+                        expectedTxDurationsMs[rat][freq][txLvl] = 0;
+                    }
+                    expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+                }
+            }
+        }
+
+        final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
+        final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai);
+
+        IntConsumer incrementTime = inc -> {
+            state.currentTimeMs += inc;
+            clock.realtime = clock.uptime = state.currentTimeMs;
+
+            // If the device is not on battery, no timers should increment.
+            if (!state.onBattery) return;
+            // If the modem is not active, no timers should increment.
+            if (!state.modemActive) return;
+
+            final int currRat = state.currentRat;
+            final int currFreqRange =
+                    currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
+            int currSignalStrength = state.currentSignalStrengths.get(currRat);
+
+            expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+
+            // Evaluate the HAL provided time in states.
+            switch (state.modemState) {
+                case SLEEP:
+                    long sleepMs = state.modemActivityInfo.getSleepTimeMillis();
+                    state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc);
+                    break;
+                case IDLE:
+                    long idleMs = state.modemActivityInfo.getIdleTimeMillis();
+                    state.modemActivityInfo.setIdleTimeMillis(idleMs + inc);
+                    break;
+                case RECEIVING:
+                    long rxMs = state.modemActivityInfo.getReceiveTimeMillis();
+                    state.modemActivityInfo.setReceiveTimeMillis(rxMs + inc);
+                    expectedRxDurationsMs[currRat][currFreqRange] += inc;
+                    break;
+                case TRANSMITTING:
+                    int[] txMs = state.modemActivityInfo.getTransmitTimeMillis();
+                    txMs[currSignalStrength] += inc;
+                    state.modemActivityInfo.setTransmitTimeMillis(txMs);
+                    expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+                    break;
+            }
+        };
+
+        state.setOnBattery(false);
+        state.setModemActive(false);
+        state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+                CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // While not on battery, the timers should not increase.
+        state.setModemActive(true);
+        incrementTime.accept(100);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+        incrementTime.accept(200);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+                CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+        incrementTime.accept(500);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
+        incrementTime.accept(300);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
+        incrementTime.accept(400);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
+        incrementTime.accept(500);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Data will now be available.
+        for (int rat = 0; rat < ratCount; rat++) {
+            for (int freq = 0; freq < frequencyCount; freq++) {
+                if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+                        || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                    // Only the NR RAT should have per frequency data.
+                    expectedRxDurationsMs[rat][freq] = 0;
+                }
+                for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+                    if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+                            || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                        // Only the NR RAT should have per frequency data.
+                        expectedTxDurationsMs[rat][freq][txLvl] = 0;
+                    }
+                }
+            }
+        }
+
+        // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
+        // start counting up.
+        state.setOnBattery(true);
+        incrementTime.accept(300);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(500);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(600);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+        // Changing LTE signal strength should be tracked.
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_POOR);
+        incrementTime.accept(300);
+        state.setModemState(ModemState.SLEEP);
+        incrementTime.accept(1000);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(700);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+        incrementTime.accept(800);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(222);
+        state.setModemState(ModemState.IDLE);
+        incrementTime.accept(111);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(7777);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+        incrementTime.accept(88);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(900);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_GREAT);
+        incrementTime.accept(123);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(333);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(1000);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(555);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Change in the signal strength of nonactive RAT should not affect anything.
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+                CellSignalStrength.SIGNAL_STRENGTH_POOR);
+        incrementTime.accept(631);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(321);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(99);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Changing to OTHER Rat should start tracking the poor signal strength.
+        state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+        incrementTime.accept(1200);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Noting frequency change should not affect non NR Rat.
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
+        incrementTime.accept(444);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(1300);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
+        state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+        incrementTime.accept(1400);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Frequency changed to low.
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
+        incrementTime.accept(852);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(157);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(1500);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Modem no longer active, should not be tracking any more.
+        state.setModemActive(false);
+        incrementTime.accept(1500);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
     }
 
     private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
@@ -1426,28 +1674,124 @@
     }
 
     private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
+            long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs,
             BatteryStatsImpl bi, long currentTimeMs) {
         for (int rat = 0; rat < expectedDurationsMs.length; rat++) {
             final long[][] expectedRatDurationsMs = expectedDurationsMs[rat];
             for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) {
+                final long expectedRxDurationMs = expectedRxDurationsMs[rat][freq];
+
+                // Build a verbose fail message, just in case.
+                final StringBuilder rxFailSb = new StringBuilder();
+                rxFailSb.append("Wrong time in Rx state for RAT:");
+                rxFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+                rxFailSb.append(", frequency:");
+                rxFailSb.append(ServiceState.frequencyRangeToString(freq));
+                assertEquals(rxFailSb.toString(), expectedRxDurationMs,
+                        bi.getActiveRxRadioDurationMs(rat, freq, currentTimeMs));
+
                 final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
                 for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
                     final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength];
+                    final long expectedTxDurationMs = expectedTxDurationsMs[rat][freq][strength];
                     final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq,
                             strength, currentTimeMs);
 
-                    // Build a verbose fail message, just in case.
-                    final StringBuilder sb = new StringBuilder();
-                    sb.append("Wrong time in state for RAT:");
-                    sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
-                    sb.append(", frequency:");
-                    sb.append(ServiceState.frequencyRangeToString(freq));
-                    sb.append(", strength:");
-                    sb.append(strength);
+                    final StringBuilder failSb = new StringBuilder();
+                    failSb.append("Wrong time in state for RAT:");
+                    failSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+                    failSb.append(", frequency:");
+                    failSb.append(ServiceState.frequencyRangeToString(freq));
+                    failSb.append(", strength:");
+                    failSb.append(strength);
+                    assertEquals(failSb.toString(), expectedSignalStrengthDurationMs,
+                            actualDurationMs);
 
-                    assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs);
+                    final StringBuilder txFailSb = new StringBuilder();
+                    txFailSb.append("Wrong time in Tx state for RAT:");
+                    txFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+                    txFailSb.append(", frequency:");
+                    txFailSb.append(ServiceState.frequencyRangeToString(freq));
+                    txFailSb.append(", strength:");
+                    txFailSb.append(strength);
+                    assertEquals(txFailSb.toString(), expectedTxDurationMs,
+                            bi.getActiveTxRadioDurationMs(rat, freq, strength, currentTimeMs));
                 }
             }
         }
     }
+
+    private class ModemAndBatteryState {
+        public long currentTimeMs = 100;
+        public boolean onBattery = false;
+        public boolean modemActive = false;
+        @Annotation.NetworkType
+        public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        @BatteryStats.RadioAccessTechnology
+        public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+        @ServiceState.FrequencyRange
+        public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+        public SparseIntArray currentSignalStrengths = new SparseIntArray();
+        public ModemState modemState = ModemState.SLEEP;
+        public ModemActivityInfo modemActivityInfo;
+
+        private final MockBatteryStatsImpl mBsi;
+
+        ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai) {
+            mBsi = bsi;
+            modemActivityInfo = mai;
+        }
+
+        void setOnBattery(boolean onBattery) {
+            this.onBattery = onBattery;
+            mBsi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
+                    currentTimeMs * 1000);
+            mBsi.setOnBatteryInternal(onBattery);
+            noteModemControllerActivity();
+        }
+
+        void setModemActive(boolean active) {
+            modemActive = active;
+            final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+                    : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+            mBsi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
+            noteModemControllerActivity();
+        }
+
+        void setRatType(@Annotation.NetworkType int dataType,
+                @BatteryStats.RadioAccessTechnology int rat) {
+            currentNetworkDataType = dataType;
+            currentRat = rat;
+            mBsi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
+                    currentFrequencyRange);
+        }
+
+        void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
+            currentFrequencyRange = frequency;
+            mBsi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
+                    ServiceState.STATE_IN_SERVICE, frequency);
+        }
+
+        void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
+            currentSignalStrengths.put(rat, strength);
+            final int size = currentSignalStrengths.size();
+            final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
+            mBsi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
+        }
+
+        void setModemState(ModemState state) {
+            modemState = state;
+        }
+
+        void noteModemControllerActivity() {
+            if (modemActivityInfo == null) return;
+            modemActivityInfo.setTimestamp(currentTimeMs);
+            ModemActivityInfo copy = new ModemActivityInfo(modemActivityInfo.getTimestampMillis(),
+                    modemActivityInfo.getSleepTimeMillis(), modemActivityInfo.getIdleTimeMillis(),
+                    modemActivityInfo.getTransmitTimeMillis().clone(),
+                    modemActivityInfo.getReceiveTimeMillis());
+            mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE,
+                    currentTimeMs, currentTimeMs, mNetworkStatsManager);
+        }
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
index 5adc9bd..483224c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -20,6 +20,7 @@
 import static android.os.BatteryConsumer.POWER_MODEL_MEASURED_ENERGY;
 import static android.os.BatteryConsumer.POWER_MODEL_UNDEFINED;
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 
@@ -83,7 +84,7 @@
         final Parcel parcel = Parcel.obtain();
         parcel.writeParcelable(outBatteryUsageStats, 0);
 
-        assertThat(parcel.dataSize()).isLessThan(7000);
+        assertThat(parcel.dataSize()).isLessThan(8000);
 
         parcel.setDataPosition(0);
 
@@ -155,10 +156,11 @@
         assertThat(dump).contains("cpu(fg): 2333 apps: 1333 duration: 3s 332ms");
         assertThat(dump).contains("cpu(bg): 2444 apps: 1444 duration: 4s 442ms");
         assertThat(dump).contains("cpu(fgs): 2555 apps: 1555 duration: 5s 552ms");
+        assertThat(dump).contains("cpu(cached): 123 apps: 123 duration: 456ms");
         assertThat(dump).contains("FOO: 20200 apps: 10200 duration: 20s 400ms");
-        assertThat(dump).contains("UID 271: 1200 fg: 1777 bg: 1888 fgs: 1999 ( screen=300 "
-                + "cpu=400 (600ms) cpu:fg=1777 (7s 771ms) cpu:bg=1888 (8s 881ms) "
-                + "cpu:fgs=1999 (9s 991ms) FOO=500 )");
+        assertThat(dump).contains("UID 271: 1200 fg: 1777 bg: 1888 fgs: 1999 cached: 123 "
+                + "( screen=300 cpu=400 (600ms) cpu:fg=1777 (7s 771ms) cpu:bg=1888 (8s 881ms) "
+                + "cpu:fgs=1999 (9s 991ms) cpu:cached=123 (456ms) FOO=500 )");
         assertThat(dump).contains("User 42: 30.0 ( cpu=10.0 (30ms) FOO=20.0 )");
     }
 
@@ -193,13 +195,15 @@
                         5321, 7432, 423, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 745,
                         POWER_MODEL_UNDEFINED,
                         956, 1167, 1478,
-                        true, 3554, 3776, 3998, 3554, 15542, 3776, 17762, 3998, 19982);
+                        true, 3554, 3776, 3998, 444, 3554, 15542, 3776, 17762, 3998, 19982,
+                        444, 1110);
             } else if (uidBatteryConsumer.getUid() == APP_UID2) {
                 assertUidBatteryConsumer(uidBatteryConsumer, 1332, "bar",
                         1111, 2222, 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444,
                         BatteryConsumer.POWER_MODEL_POWER_PROFILE,
                         555, 666, 777,
-                        true, 1777, 1888, 1999, 1777, 7771, 1888, 8881, 1999, 9991);
+                        true, 1777, 1888, 1999, 321, 1777, 7771, 1888, 8881, 1999, 9991,
+                        321, 654);
             } else {
                 fail("Unexpected UID " + uidBatteryConsumer.getUid());
             }
@@ -267,17 +271,17 @@
                 1000, 2000,
                 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400,
                 BatteryConsumer.POWER_MODEL_POWER_PROFILE, 500, 600, 800,
-                1777, 7771, 1888, 8881, 1999, 9991);
+                1777, 7771, 1888, 8881, 1999, 9991, 123, 456);
 
         addAggregateBatteryConsumer(builder,
                 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0,
                 10100, 10200, 10300, 10400,
-                1333, 3331, 1444, 4441, 1555, 5551);
+                1333, 3331, 1444, 4441, 1555, 5551, 123, 456);
 
         addAggregateBatteryConsumer(builder,
                 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 30000,
                 20100, 20200, 20300, 20400,
-                2333, 3332, 2444, 4442, 2555, 5552);
+                2333, 3332, 2444, 4442, 2555, 5552, 123, 456);
 
         if (includeUserBatteryConsumer) {
             builder.getOrCreateUserBatteryConsumerBuilder(USER_ID)
@@ -310,23 +314,23 @@
                 4321, 5432,
                 123, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 345, POWER_MODEL_MEASURED_ENERGY,
                 456, 567, 678,
-                1777, 7771, 1888, 8881, 1999, 9991);
+                1777, 7771, 1888, 8881, 1999, 9991, 321, 654);
 
         addUidBatteryConsumer(builder, batteryStats, APP_UID2, "bar",
                 1111, 2222,
                 333, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 444,
                 BatteryConsumer.POWER_MODEL_POWER_PROFILE, 555, 666, 777,
-                1777, 7771, 1888, 8881, 1999, 9991);
+                1777, 7771, 1888, 8881, 1999, 9991, 321, 654);
 
         addAggregateBatteryConsumer(builder,
                 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0,
                 10123, 10234, 10345, 10456,
-                4333, 3334, 5444, 4445, 6555, 5556);
+                4333, 3334, 5444, 4445, 6555, 5556, 321, 654);
 
         addAggregateBatteryConsumer(builder,
                 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 12345,
                 20111, 20222, 20333, 20444,
-                7333, 3337, 8444, 4448, 9555, 5559);
+                7333, 3337, 8444, 4448, 9555, 5559, 123, 456);
 
         return builder;
     }
@@ -337,7 +341,7 @@
             int screenPowerModel, double cpuPower, int cpuPowerModel, double customComponentPower,
             int cpuDuration, int customComponentDuration, double cpuPowerForeground,
             int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground,
-            double cpuPowerFgs, int cpuDurationFgs) {
+            double cpuPowerFgs, int cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) {
         final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(uid);
         final UidBatteryConsumer.Builder uidBuilder =
                 builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid);
@@ -365,6 +369,9 @@
             final BatteryConsumer.Key cpuFgsKey = uidBuilder.getKey(
                     BatteryConsumer.POWER_COMPONENT_CPU,
                     BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+            final BatteryConsumer.Key cachedKey = uidBuilder.getKey(
+                    BatteryConsumer.POWER_COMPONENT_CPU,
+                    BatteryConsumer.PROCESS_STATE_CACHED);
             uidBuilder
                     .setConsumedPower(cpuFgKey, cpuPowerForeground,
                             BatteryConsumer.POWER_MODEL_POWER_PROFILE)
@@ -374,7 +381,10 @@
                     .setUsageDurationMillis(cpuBgKey, cpuDurationBackground)
                     .setConsumedPower(cpuFgsKey, cpuPowerFgs,
                             BatteryConsumer.POWER_MODEL_POWER_PROFILE)
-                    .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs);
+                    .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs)
+                    .setConsumedPower(cachedKey, cpuPowerCached,
+                            BatteryConsumer.POWER_MODEL_POWER_PROFILE)
+                    .setUsageDurationMillis(cachedKey, cpuDurationCached);
         }
     }
 
@@ -382,7 +392,7 @@
             double consumedPower, int cpuPower, int customComponentPower, int cpuDuration,
             int customComponentDuration, double cpuPowerForeground, long cpuDurationForeground,
             double cpuPowerBackground, long cpuDurationBackground, double cpuPowerFgs,
-            long cpuDurationFgs) {
+            long cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) {
         final AggregateBatteryConsumer.Builder aggBuilder =
                 builder.getAggregateBatteryConsumerBuilder(scope)
                         .setConsumedPower(consumedPower)
@@ -406,6 +416,9 @@
             final BatteryConsumer.Key cpuFgsKey = aggBuilder.getKey(
                     BatteryConsumer.POWER_COMPONENT_CPU,
                     BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+            final BatteryConsumer.Key cpuCachedKey = aggBuilder.getKey(
+                    BatteryConsumer.POWER_COMPONENT_CPU,
+                    BatteryConsumer.PROCESS_STATE_CACHED);
             aggBuilder
                     .setConsumedPower(cpuFgKey, cpuPowerForeground,
                             BatteryConsumer.POWER_MODEL_POWER_PROFILE)
@@ -415,7 +428,10 @@
                     .setUsageDurationMillis(cpuBgKey, cpuDurationBackground)
                     .setConsumedPower(cpuFgsKey, cpuPowerFgs,
                             BatteryConsumer.POWER_MODEL_POWER_PROFILE)
-                    .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs);
+                    .setUsageDurationMillis(cpuFgsKey, cpuDurationFgs)
+                    .setConsumedPower(cpuCachedKey, cpuPowerCached,
+                            BatteryConsumer.POWER_MODEL_POWER_PROFILE)
+                    .setUsageDurationMillis(cpuCachedKey, cpuDurationCached);
         }
     }
 
@@ -432,7 +448,7 @@
                         1000, 2000, 300, BatteryConsumer.POWER_MODEL_POWER_PROFILE, 400,
                         BatteryConsumer.POWER_MODEL_POWER_PROFILE,
                         500, 600, 800,
-                        true, 1777, 1888, 1999, 1777, 7771, 1888, 8881, 1999, 9991);
+                        true, 1777, 1888, 1999, 123, 1777, 7771, 1888, 8881, 1999, 9991, 123, 456);
             } else {
                 fail("Unexpected UID " + uidBatteryConsumer.getUid());
             }
@@ -484,8 +500,10 @@
             int cpuPowerModel, double customComponentPower, int cpuDuration,
             int customComponentDuration, boolean processStateDataIncluded,
             double totalPowerForeground, double totalPowerBackground, double totalPowerFgs,
-            double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground,
-            int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs) {
+            double totalPowerCached, double cpuPowerForeground, int cpuDurationForeground,
+            double cpuPowerBackground,
+            int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs,
+            int cpuPowerCached, int cpuDurationCached) {
         assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(consumedPower);
         assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo(
                 packageWithHighestDrain);
@@ -525,6 +543,10 @@
                     new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY,
                             PROCESS_STATE_FOREGROUND_SERVICE)))
                     .isEqualTo(totalPowerFgs);
+            assertThat(uidBatteryConsumer.getConsumedPower(
+                    new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY,
+                            PROCESS_STATE_CACHED)))
+                    .isEqualTo(totalPowerCached);
         }
 
         final BatteryConsumer.Key cpuFgKey = uidBatteryConsumer.getKey(
@@ -563,6 +585,19 @@
         } else {
             assertThat(cpuFgsKey).isNotNull();
         }
+
+        final BatteryConsumer.Key cachedKey = uidBatteryConsumer.getKey(
+                BatteryConsumer.POWER_COMPONENT_CPU,
+                BatteryConsumer.PROCESS_STATE_CACHED);
+        if (processStateDataIncluded) {
+            assertThat(cachedKey).isNotNull();
+            assertThat(uidBatteryConsumer.getConsumedPower(cachedKey))
+                    .isEqualTo(cpuPowerCached);
+            assertThat(uidBatteryConsumer.getUsageDurationMillis(cachedKey))
+                    .isEqualTo(cpuDurationCached);
+        } else {
+            assertThat(cpuFgsKey).isNotNull();
+        }
     }
 
     private void assertUserBatteryConsumer(UserBatteryConsumer userBatteryConsumer,
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index 448f666..fdbf071 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -145,10 +145,14 @@
         final BatteryConsumer.Key fgs = uidConsumer.getKey(
                 BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+        final BatteryConsumer.Key cached = uidConsumer.getKey(
+                BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+                BatteryConsumer.PROCESS_STATE_CACHED);
 
         assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.081);
         assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.0416666);
         assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
+        assertThat(uidConsumer.getConsumedPower(cached)).isWithin(PRECISION).of(0);
     }
 
     @Test
@@ -261,10 +265,14 @@
         final BatteryConsumer.Key fgs = uidConsumer.getKey(
                 BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
+        final BatteryConsumer.Key cached = uidConsumer.getKey(
+                BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+                BatteryConsumer.PROCESS_STATE_CACHED);
 
         assertThat(uidConsumer.getConsumedPower(foreground)).isWithin(PRECISION).of(0.4965352);
         assertThat(uidConsumer.getConsumedPower(background)).isWithin(PRECISION).of(0.3255208);
         assertThat(uidConsumer.getConsumedPower(fgs)).isWithin(PRECISION).of(0);
+        assertThat(uidConsumer.getConsumedPower(cached)).isWithin(PRECISION).of(0);
     }
 
 
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index b89e8bc..ec45a01 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -232,7 +232,7 @@
         assertThat(entry3.handlerClassName).isEqualTo(
                 "com.android.internal.os.LooperStatsTest$TestHandlerSecond");
         assertThat(entry3.messageName).startsWith(
-                "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda4");
+                "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda5");
         assertThat(entry3.messageCount).isEqualTo(1);
         assertThat(entry3.recordedMessageCount).isEqualTo(1);
         assertThat(entry3.exceptionCount).isEqualTo(0);
diff --git a/core/tests/coretests/src/com/android/internal/widget/CachingIconViewTest.java b/core/tests/coretests/src/com/android/internal/widget/CachingIconViewTest.java
new file mode 100644
index 0000000..0d4b449
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/CachingIconViewTest.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 static com.google.common.truth.Truth.assertThat;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.graphics.drawable.InsetDrawable;
+import android.net.Uri;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CachingIconViewTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+    }
+
+    @Test
+    public void customDrawable_setImageIcon_skipsResizeSuccessfully() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageIcon(Icon.createWithResource(mContext, R.drawable.custom_drawable));
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(InsetDrawable.class);
+    }
+
+    @Test
+    public void customDrawable_setImageIconAsync_skipsResizeSuccessfully() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageIconAsync(Icon.createWithResource(mContext, R.drawable.custom_drawable)).run();
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(InsetDrawable.class);
+    }
+
+    @Test
+    public void customDrawable_setImageResource_skipsResizeSuccessfully() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageResource(R.drawable.custom_drawable);
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(InsetDrawable.class);
+    }
+
+    @Test
+    public void customDrawable_setImageResourceAsync_skipsResizeSuccessfully() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageResourceAsync(R.drawable.custom_drawable).run();
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(InsetDrawable.class);
+    }
+
+    @Test
+    public void customDrawable_setImageUri_skipsResizeSuccessfully() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageURI(Uri.parse(
+                "android.resource://com.android.frameworks.coretests/"
+                        + R.drawable.custom_drawable));
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(InsetDrawable.class);
+    }
+
+    @Test
+    public void customDrawable_setImageUriAsync_skipsResizeSuccessfully() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageURIAsync(Uri.parse(
+                "android.resource://com.android.frameworks.coretests/"
+                        + R.drawable.custom_drawable)).run();
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(InsetDrawable.class);
+    }
+
+    @Test
+    public void maxDrawableDimensionsSet_setImageIcon_resizesImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageIcon(Icon.createWithResource(mContext, R.drawable.big_a));
+
+        assertDrawableResized(view);
+    }
+
+    @Test
+    public void maxDrawableWithNoDimensionsSet_setImageIcon_doesNotResizeImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_no_max_size, null);
+        view.setImageIcon(Icon.createWithResource(mContext, R.drawable.big_a));
+
+        assertDrawableNotResized(view);
+    }
+
+    @Test
+    public void maxDrawableDimensionsSet_setImageIconAsync_resizesImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageIconAsync(Icon.createWithResource(mContext, R.drawable.big_a)).run();
+
+        assertDrawableResized(view);
+    }
+
+    @Test
+    public void maxDrawableWithNoDimensionsSet_setImageIconAsync_doesNotResizeImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_no_max_size, null);
+        view.setImageIconAsync(Icon.createWithResource(mContext, R.drawable.big_a)).run();
+
+        assertDrawableNotResized(view);
+    }
+
+    @Test
+    public void maxDrawableDimensionsSet_setImageResource_resizesImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageResource(R.drawable.big_a);
+
+        assertDrawableResized(view);
+    }
+
+    @Test
+    public void maxDrawableWithNoDimensionsSet_setImageResource_doesNotResizeImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_no_max_size, null);
+        view.setImageResource(R.drawable.big_a);
+
+        assertDrawableNotResized(view);
+    }
+
+    @Test
+    public void maxDrawableDimensionsSet_setImageResourceAsync_resizesImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageResourceAsync(R.drawable.big_a).run();
+
+        assertDrawableResized(view);
+    }
+
+    @Test
+    public void maxDrawableWithNoDimensionsSet_setImageResourceAsync_doesNotResizeImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_no_max_size, null);
+        view.setImageResourceAsync(R.drawable.big_a).run();
+
+        assertDrawableNotResized(view);
+    }
+
+    @Test
+    public void maxDrawableDimensionsSet_setImageUri_resizesImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageURI(Uri.parse(
+                "android.resource://com.android.frameworks.coretests/" + R.drawable.big_a));
+
+        assertDrawableResized(view);
+    }
+
+    @Test
+    public void maxDrawableWithNoDimensionsSet_setImageUri_doesNotResizeImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_no_max_size, null);
+        view.setImageURI(Uri.parse(
+                "android.resource://com.android.frameworks.coretests/" + R.drawable.big_a));
+
+        assertDrawableNotResized(view);
+    }
+
+    @Test
+    public void maxDrawableDimensionsSet_setImageUriAsync_resizesImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_max_size, null);
+        view.setImageURIAsync(Uri.parse(
+                "android.resource://com.android.frameworks.coretests/" + R.drawable.big_a)).run();
+
+        assertDrawableResized(view);
+    }
+
+    @Test
+    public void maxDrawableWithNoDimensionsSet_setImageUriAsync_doesNotResizeImageIcon() {
+        CachingIconView view = (CachingIconView) LayoutInflater.from(mContext).inflate(
+                R.layout.caching_icon_view_test_no_max_size, null);
+        view.setImageURIAsync(Uri.parse(
+                "android.resource://com.android.frameworks.coretests/" + R.drawable.big_a)).run();
+
+        assertDrawableNotResized(view);
+    }
+
+
+    private void assertDrawableResized(@Nullable CachingIconView view) {
+        assertThat(view).isNotNull();
+        int maxSize =
+                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80f,
+                        mContext.getResources().getDisplayMetrics());
+        assertThat(view.getMaxDrawableHeight()).isEqualTo(maxSize);
+        assertThat(view.getMaxDrawableWidth()).isEqualTo(maxSize);
+
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+        assertThat(bitmapDrawable.getBitmap().getWidth()).isLessThan(maxSize + 1);
+        assertThat(bitmapDrawable.getBitmap().getHeight()).isLessThan(maxSize + 1);
+    }
+
+    private void assertDrawableNotResized(@Nullable CachingIconView view) {
+        assertThat(view).isNotNull();
+        int maxSize =
+                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80f,
+                        mContext.getResources().getDisplayMetrics());
+        assertThat(view.getMaxDrawableHeight()).isEqualTo(-1);
+        assertThat(view.getMaxDrawableWidth()).isEqualTo(-1);
+
+        Drawable drawable = view.getDrawable();
+        assertThat(drawable).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+        assertThat(bitmapDrawable.getBitmap().getWidth()).isGreaterThan(maxSize);
+        assertThat(bitmapDrawable.getBitmap().getHeight()).isGreaterThan(maxSize);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
new file mode 100644
index 0000000..8dcb4a2
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.content.Context;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.frameworks.coretests.R;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4ClassRunner.class)
+public class LocalImageResolverTest {
+
+    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+    @Test
+    public void resolveImage_largeBitmapIcon_defaultSize_resizeToDefaultSize() throws
+            IOException {
+        Icon icon = Icon.createWithBitmap(
+                BitmapFactory.decodeResource(mContext.getResources(), R.drawable.big_a));
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+
+        assertThat(d).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) d;
+        // No isLessOrEqualThan sadly.
+        assertThat(bd.getBitmap().getWidth()).isLessThan(
+                LocalImageResolver.DEFAULT_MAX_SAFE_ICON_SIZE_PX + 1);
+        assertThat(bd.getBitmap().getHeight()).isLessThan(
+                LocalImageResolver.DEFAULT_MAX_SAFE_ICON_SIZE_PX + 1);
+    }
+
+    @Test
+    public void resolveImage_largeAdaptiveBitmapIcon_defaultSize_resizeToDefaultSize() throws
+            IOException {
+        Icon icon = Icon.createWithAdaptiveBitmap(
+                BitmapFactory.decodeResource(mContext.getResources(), R.drawable.big_a));
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+
+        assertThat(d).isInstanceOf(AdaptiveIconDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) ((AdaptiveIconDrawable) d).getForeground();
+        // No isLessOrEqualThan sadly.
+        assertThat(bd.getBitmap().getWidth()).isLessThan(
+                LocalImageResolver.DEFAULT_MAX_SAFE_ICON_SIZE_PX + 1);
+        assertThat(bd.getBitmap().getHeight()).isLessThan(
+                LocalImageResolver.DEFAULT_MAX_SAFE_ICON_SIZE_PX + 1);
+    }
+
+    @Test
+    public void resolveImage_largeResourceIcon_defaultSize_resizeToDefaultSize() throws
+            IOException {
+        Icon icon = Icon.createWithResource(mContext, R.drawable.big_a);
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+
+        assertThat(d).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) d;
+        // No isLessOrEqualThan sadly.
+        assertThat(bd.getBitmap().getWidth()).isLessThan(
+                LocalImageResolver.DEFAULT_MAX_SAFE_ICON_SIZE_PX + 1);
+        assertThat(bd.getBitmap().getHeight()).isLessThan(
+                LocalImageResolver.DEFAULT_MAX_SAFE_ICON_SIZE_PX + 1);
+    }
+
+    @Test
+    public void resolveImage_largeResourceIcon_passedSize_resizeToDefinedSize() throws
+            IOException {
+        Icon icon = Icon.createWithResource(mContext, R.drawable.big_a);
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext, 100, 50);
+
+        assertThat(d).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) d;
+        assertThat(bd.getBitmap().getWidth()).isLessThan(101);
+        assertThat(bd.getBitmap().getHeight()).isLessThan(51);
+    }
+
+    @Test
+    public void resolveImage_largeBitmapIcon_passedSize_resizeToDefinedSize() throws
+            IOException {
+        Icon icon = Icon.createWithBitmap(
+                BitmapFactory.decodeResource(mContext.getResources(), R.drawable.big_a));
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext, 100, 50);
+
+        assertThat(d).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) d;
+        assertThat(bd.getBitmap().getWidth()).isLessThan(101);
+        assertThat(bd.getBitmap().getHeight()).isLessThan(51);
+    }
+
+    @Test
+    public void resolveImage_largeAdaptiveBitmapIcon_passedSize_resizeToDefinedSize() throws
+            IOException {
+        Icon icon = Icon.createWithAdaptiveBitmap(
+                BitmapFactory.decodeResource(mContext.getResources(), R.drawable.big_a));
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext, 100, 50);
+
+        assertThat(d).isInstanceOf(AdaptiveIconDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) ((AdaptiveIconDrawable) d).getForeground();
+        assertThat(bd.getBitmap().getWidth()).isLessThan(101);
+        assertThat(bd.getBitmap().getHeight()).isLessThan(51);
+    }
+
+
+    @Test
+    public void resolveImage_smallResourceIcon_defaultSize_untouched() throws IOException {
+        Icon icon = Icon.createWithResource(mContext, R.drawable.test32x24);
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+
+        assertThat(d).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) d;
+        assertThat(bd.getBitmap().getWidth()).isEqualTo(32);
+        assertThat(bd.getBitmap().getHeight()).isEqualTo(24);
+    }
+
+    @Test
+    public void resolveImage_smallBitmapIcon_defaultSize_untouched() throws IOException {
+        Icon icon = Icon.createWithBitmap(
+                BitmapFactory.decodeResource(mContext.getResources(), R.drawable.test32x24));
+        final int originalWidth = icon.getBitmap().getWidth();
+        final int originalHeight = icon.getBitmap().getHeight();
+
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+
+        assertThat(d).isInstanceOf(BitmapDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) d;
+        assertThat(bd.getBitmap().getWidth()).isEqualTo(originalWidth);
+        assertThat(bd.getBitmap().getHeight()).isEqualTo(originalHeight);
+    }
+
+    @Test
+    public void resolveImage_smallAdaptiveBitmapIcon_defaultSize_untouched() throws IOException {
+        Icon icon = Icon.createWithAdaptiveBitmap(
+                BitmapFactory.decodeResource(mContext.getResources(), R.drawable.test32x24));
+        final int originalWidth = icon.getBitmap().getWidth();
+        final int originalHeight = icon.getBitmap().getHeight();
+
+        Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+        assertThat(d).isInstanceOf(AdaptiveIconDrawable.class);
+        BitmapDrawable bd = (BitmapDrawable) ((AdaptiveIconDrawable) d).getForeground();
+        assertThat(bd.getBitmap().getWidth()).isEqualTo(originalWidth);
+        assertThat(bd.getBitmap().getHeight()).isEqualTo(originalHeight);
+
+    }
+}
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index d1873a0..2d1db71 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -76,5 +76,8 @@
         <permission name="android.permission.FORCE_STOP_PACKAGES" />
         <permission name="android.permission.ACCESS_FPS_COUNTER" />
         <permission name="android.permission.CHANGE_CONFIGURATION" />
+        <permission name="android.permission.LOG_COMPAT_CHANGE" />
+        <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+        <permission name="android.permission.READ_DEVICE_CONFIG" />
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c3b0017..3e91eed 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -452,6 +452,7 @@
         <permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
         <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
         <permission name="android.permission.NEARBY_WIFI_DEVICES" />
+        <permission name="android.permission.MANAGE_WIFI_INTERFACES" />
         <permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
         <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
              P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index df2b2a3..e898f57 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1309,6 +1309,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "-711194343": {
+      "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_BACK_PREVIEW",
+      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+    },
     "-706481945": {
       "message": "TaskFragment parent info changed name=%s parentTaskId=%d",
       "level": "VERBOSE",
@@ -2587,6 +2593,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "599897753": {
+      "message": "Previous Activity is %s. Back type is %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_BACK_PREVIEW",
+      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+    },
     "600140673": {
       "message": "checkBootAnimationComplete: Waiting for anim complete",
       "level": "INFO",
@@ -2671,12 +2683,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "664667685": {
-      "message": "Activity %s: enableOnBackInvokedCallback=false. Returning null BackNavigationInfo.",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_BACK_PREVIEW",
-      "at": "com\/android\/server\/wm\/BackNavigationController.java"
-    },
     "665256544": {
       "message": "All windows drawn!",
       "level": "DEBUG",
@@ -2887,6 +2893,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/TaskFragment.java"
     },
+    "948208142": {
+      "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_BACK_PREVIEW",
+      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+    },
     "950074526": {
       "message": "setLockTaskMode: Can't lock due to auth",
       "level": "WARN",
@@ -3103,6 +3115,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
+    "1172542963": {
+      "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_BACK_PREVIEW",
+      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+    },
     "1178653181": {
       "message": "Old wallpaper still the target.",
       "level": "VERBOSE",
@@ -3415,11 +3433,11 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
-    "1554795024": {
-      "message": "Previous Activity is %s",
+    "1544805551": {
+      "message": "Skipping app transition animation. task=%s",
       "level": "DEBUG",
       "group": "WM_DEBUG_BACK_PREVIEW",
-      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+      "at": "com\/android\/server\/wm\/Task.java"
     },
     "1557732761": {
       "message": "For Intent %s bringing to top: %s",
diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java
index cffdf28..d083e44 100644
--- a/graphics/java/android/graphics/text/LineBreakConfig.java
+++ b/graphics/java/android/graphics/text/LineBreakConfig.java
@@ -26,7 +26,7 @@
 /**
  * Indicates the strategies can be used when calculating the text wrapping.
  *
- * See <a href="https://drafts.csswg.org/css-text/#line-break-property">the line-break property</a>
+ * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">the line-break property</a>
  */
 public final class LineBreakConfig {
 
@@ -78,21 +78,87 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface LineBreakWordStyle {}
 
-    private @LineBreakStyle int mLineBreakStyle = LINE_BREAK_STYLE_NONE;
-    private @LineBreakWordStyle int mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_NONE;
+    /**
+     * A builder for creating {@link LineBreakConfig}.
+     */
+    public static final class Builder {
+        // The line break style for the LineBreakConfig.
+        private @LineBreakStyle int mLineBreakStyle = LineBreakConfig.LINE_BREAK_STYLE_NONE;
 
-    public LineBreakConfig() {
+        // The line break word style for the LineBreakConfig.
+        private @LineBreakWordStyle int mLineBreakWordStyle =
+                LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE;
+
+        /**
+         * Builder constructor with line break parameters.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Set the line break style.
+         *
+         * @param lineBreakStyle the new line break style.
+         * @return this Builder
+         */
+        public @NonNull Builder setLineBreakStyle(@LineBreakStyle int lineBreakStyle) {
+            mLineBreakStyle = lineBreakStyle;
+            return this;
+        }
+
+        /**
+         * Set the line break word style.
+         *
+         * @param lineBreakWordStyle the new line break word style.
+         * @return this Builder
+         */
+        public @NonNull Builder setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) {
+            mLineBreakWordStyle = lineBreakWordStyle;
+            return this;
+        }
+
+        /**
+         * Build the {@link LineBreakConfig}
+         *
+         * @return the LineBreakConfig instance.
+         */
+        public @NonNull LineBreakConfig build() {
+            return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle);
+        }
     }
 
     /**
-     * Set the line break configuration.
+     * Create the LineBreakConfig instance.
      *
-     * @param lineBreakConfig the new line break configuration.
+     * @param lineBreakStyle the line break style for text wrapping.
+     * @param lineBreakWordStyle the line break word style for text wrapping.
+     * @return the {@link LineBreakConfig} instance.
+     * @hide
      */
-    public void set(@NonNull LineBreakConfig lineBreakConfig) {
-        Objects.requireNonNull(lineBreakConfig);
-        mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
-        mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
+    public static @NonNull LineBreakConfig getLineBreakConfig(@LineBreakStyle int lineBreakStyle,
+            @LineBreakWordStyle int lineBreakWordStyle) {
+        LineBreakConfig.Builder builder = new LineBreakConfig.Builder();
+        return builder.setLineBreakStyle(lineBreakStyle)
+                .setLineBreakWordStyle(lineBreakWordStyle)
+                .build();
+    }
+
+    /** @hide */
+    public static final LineBreakConfig NONE =
+            new Builder().setLineBreakStyle(LINE_BREAK_STYLE_NONE)
+                    .setLineBreakWordStyle(LINE_BREAK_WORD_STYLE_NONE).build();
+
+    private final @LineBreakStyle int mLineBreakStyle;
+    private final @LineBreakWordStyle int mLineBreakWordStyle;
+
+    /**
+     * Constructor with the line break parameters.
+     * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance.
+     */
+    private LineBreakConfig(@LineBreakStyle int lineBreakStyle,
+            @LineBreakWordStyle int lineBreakWordStyle) {
+        mLineBreakStyle = lineBreakStyle;
+        mLineBreakWordStyle = lineBreakWordStyle;
     }
 
     /**
@@ -105,15 +171,6 @@
     }
 
     /**
-     * Set the line break style.
-     *
-     * @param lineBreakStyle the new line break style.
-     */
-    public void setLineBreakStyle(@LineBreakStyle int lineBreakStyle) {
-        mLineBreakStyle = lineBreakStyle;
-    }
-
-    /**
      * Get the line break word style.
      *
      * @return The current line break word style to be used for the text wrapping.
@@ -122,15 +179,6 @@
         return mLineBreakWordStyle;
     }
 
-    /**
-     * Set the line break word style.
-     *
-     * @param lineBreakWordStyle the new line break word style.
-     */
-    public void setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) {
-        mLineBreakWordStyle = lineBreakWordStyle;
-    }
-
     @Override
     public boolean equals(Object o) {
         if (o == null) return false;
diff --git a/libs/WindowManager/OWNERS b/libs/WindowManager/OWNERS
index 2c61df9..780e4c1 100644
--- a/libs/WindowManager/OWNERS
+++ b/libs/WindowManager/OWNERS
@@ -1,3 +1,6 @@
 set noparent
 
 include /services/core/java/com/android/server/wm/OWNERS
+
+# Give submodule owners in shell resource approval
+per-file Shell/res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 8d5fdfb..08cb252 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -52,14 +52,17 @@
  */
 public class BackAnimationController implements RemoteCallable<BackAnimationController> {
 
-    private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
-    public static final boolean IS_ENABLED = SystemProperties
-            .getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
     private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP =
             "persist.debug.back_predictability_progress_threshold";
+    // By default, enable new back dispatching without any animations.
+    private static final int BACK_PREDICTABILITY_PROP =
+            SystemProperties.getInt("persist.debug.back_predictability", 1);
+    public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0;
     private static final int PROGRESS_THRESHOLD = SystemProperties
             .getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
     private static final String TAG = "BackAnimationController";
+    @VisibleForTesting
+    boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0;
 
     /**
      * Location of the initial touch event of the back gesture.
@@ -255,7 +258,7 @@
                         backNavigationInfo.getTaskWindowConfiguration());
             }
             mTransaction.apply();
-        } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
+        } else if (shouldDispatchToLauncher(backType)) {
             targetCallback = mBackToLauncherCallback;
         } else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
             targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
@@ -309,7 +312,7 @@
 
         BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
         IOnBackInvokedCallback targetCallback = null;
-        if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
+        if (shouldDispatchToLauncher(backType)) {
             targetCallback = mBackToLauncherCallback;
         } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
                 || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
@@ -330,8 +333,7 @@
             return;
         }
         int backType = mBackNavigationInfo.getType();
-        boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
-                && mBackToLauncherCallback != null;
+        boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType);
         IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
                 ? mBackToLauncherCallback
                 : mBackNavigationInfo.getOnBackInvokedCallback();
@@ -356,6 +358,17 @@
         }
     }
 
+    private boolean shouldDispatchToLauncher(int backType) {
+        return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
+                && mBackToLauncherCallback != null
+                && mEnableAnimations;
+    }
+
+    @VisibleForTesting
+    void setEnableAnimations(boolean shouldEnable) {
+        mEnableAnimations = shouldEnable;
+    }
+
     private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
         if (callback == null) {
             return;
@@ -468,7 +481,7 @@
             return;
         }
         RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
-        if (animationTarget != null && mTriggerBack) {
+        if (animationTarget != null) {
             if (animationTarget.leash != null && animationTarget.leash.isValid()) {
                 mTransaction.remove(animationTarget.leash);
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 51067a4..4583389 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -344,7 +344,7 @@
         @Override
         public void resized(ClientWindowFrames frames, boolean reportDraw,
                 MergedConfiguration newMergedConfiguration, boolean forceLayout,
-                boolean alwaysConsumeSystemBars, int displayId) {}
+                boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {}
 
         @Override
         public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b52c8d1..5246117 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -98,6 +98,7 @@
     private WindowContainerToken mWinToken2;
     private int mDividePosition;
     private boolean mInitialized = false;
+    private boolean mFreezeDividerWindow = false;
     private int mOrientation;
     private int mRotation;
 
@@ -225,11 +226,6 @@
         mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
         initDividerPosition(mTempRect);
 
-        if (mInitialized) {
-            release();
-            init();
-        }
-
         return true;
     }
 
@@ -298,20 +294,37 @@
     }
 
     /** Releases the surface holding the current {@link DividerView}. */
-    public void release() {
+    public void release(SurfaceControl.Transaction t) {
         if (!mInitialized) return;
         mInitialized = false;
-        mSplitWindowManager.release();
+        mSplitWindowManager.release(t);
         mDisplayImeController.removePositionProcessor(mImePositionProcessor);
         mImePositionProcessor.reset();
     }
 
+    public void release() {
+        release(null /* t */);
+    }
+
+    /** Releases and re-inflates {@link DividerView} on the root surface. */
+    public void update(SurfaceControl.Transaction t) {
+        if (!mInitialized) return;
+        mSplitWindowManager.release(t);
+        mImePositionProcessor.reset();
+        mSplitWindowManager.init(this, mInsetsState);
+    }
+
     @Override
     public void insetsChanged(InsetsState insetsState) {
         mInsetsState.set(insetsState);
         if (!mInitialized) {
             return;
         }
+        if (mFreezeDividerWindow) {
+            // DO NOT change its layout before transition actually run because it might cause
+            // flicker.
+            return;
+        }
         mSplitWindowManager.onInsetsChanged(insetsState);
     }
 
@@ -323,6 +336,10 @@
         }
     }
 
+    public void setFreezeDividerWindow(boolean freezeDividerWindow) {
+        mFreezeDividerWindow = freezeDividerWindow;
+    }
+
     /**
      * Updates bounds with the passing position. Usually used to update recording bounds while
      * performing animation or dragging divider bar to resize the splits.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 4903f9d..833d9d5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -58,6 +58,9 @@
     private SurfaceControl mLeash;
     private DividerView mDividerView;
 
+    // Used to "pass" a transaction to WWM.remove so that view removal can be synchronized.
+    private SurfaceControl.Transaction mSyncTransaction = null;
+
     public interface ParentContainerCallbacks {
         void attachToParentSurface(SurfaceControl.Builder b);
         void onLeashReady(SurfaceControl leash);
@@ -130,22 +133,38 @@
      * Releases the surface control of the current {@link DividerView} and tear down the view
      * hierarchy.
      */
-    void release() {
+    void release(@Nullable SurfaceControl.Transaction t) {
         if (mDividerView != null) {
             mDividerView = null;
         }
 
         if (mViewHost != null){
+            mSyncTransaction = t;
             mViewHost.release();
+            mSyncTransaction = null;
             mViewHost = null;
         }
 
         if (mLeash != null) {
-            new SurfaceControl.Transaction().remove(mLeash).apply();
+            if (t == null) {
+                new SurfaceControl.Transaction().remove(mLeash).apply();
+            } else {
+                t.remove(mLeash);
+            }
             mLeash = null;
         }
     }
 
+    @Override
+    protected void removeSurface(SurfaceControl sc) {
+        // This gets called via SurfaceControlViewHost.release()
+        if (mSyncTransaction != null) {
+            mSyncTransaction.remove(sc);
+        } else {
+            super.removeSurface(sc);
+        }
+    }
+
     void setInteractive(boolean interactive) {
         if (mDividerView == null) return;
         mDividerView.setInteractive(interactive);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 3115f8a..11633a9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -253,11 +253,11 @@
     private WindowManager.LayoutParams getDismissTargetLayoutParams() {
         final Point windowSize = new Point();
         mWindowManager.getDefaultDisplay().getRealSize(windowSize);
-
+        int height = Math.min(windowSize.y, mDismissAreaHeight);
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 WindowManager.LayoutParams.MATCH_PARENT,
-                mDismissAreaHeight,
-                0, windowSize.y - mDismissAreaHeight,
+                height,
+                0, windowSize.y - height,
                 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 48dd1fe..ec1ddf0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -29,6 +29,7 @@
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.view.WindowManager.transitTypeToString;
 import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -1171,6 +1172,8 @@
                 updateUnfoldBounds();
                 return;
             }
+
+            mSplitLayout.update(null /* t */);
             onLayoutSizeChanged(mSplitLayout);
         }
     }
@@ -1198,7 +1201,6 @@
         if (!ENABLE_SHELL_TRANSITIONS) return;
 
         final SurfaceControl.Transaction t = mTransactionPool.acquire();
-        setDividerVisibility(false, t);
         mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
         mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
         updateWindowBounds(mSplitLayout, wct);
@@ -1255,8 +1257,15 @@
             @Nullable TransitionRequestInfo request) {
         final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
         if (triggerTask == null) {
-            // Still want to monitor everything while in split-screen, so return non-null.
-            return mMainStage.isActive() ? new WindowContainerTransaction() : null;
+            if (mMainStage.isActive()) {
+                if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) {
+                    mSplitLayout.setFreezeDividerWindow(true);
+                }
+                // Still want to monitor everything while in split-screen, so return non-null.
+                return new WindowContainerTransaction();
+            } else {
+                return null;
+            }
         } else if (triggerTask.displayId != mDisplayId) {
             // Skip handling task on the other display.
             return null;
@@ -1352,8 +1361,14 @@
             // If we're not in split-mode, just abort so something else can handle it.
             if (!mMainStage.isActive()) return false;
 
+            mSplitLayout.setFreezeDividerWindow(false);
             for (int iC = 0; iC < info.getChanges().size(); ++iC) {
                 final TransitionInfo.Change change = info.getChanges().get(iC);
+                if (change.getMode() == TRANSIT_CHANGE
+                        && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
+                    mSplitLayout.update(startTransaction);
+                }
+
                 final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                 if (taskInfo == null || !taskInfo.hasParentTask()) continue;
                 final StageTaskListener stage = getStageOfTask(taskInfo);
@@ -1368,10 +1383,6 @@
                         Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
                                 + " with " + taskInfo.taskId + " before startAnimation().");
                     }
-                } else if (info.getType() == TRANSIT_CHANGE
-                        && change.getStartRotation() != change.getEndRotation()) {
-                    // Show the divider after transition finished.
-                    setDividerVisibility(true, finishTransaction);
                 }
             }
             if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 1bef552e..49f907b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -62,6 +62,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.hardware.HardwareBuffer;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
@@ -243,7 +244,7 @@
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout");
             session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0,
                     tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState,
-                    tmpControls);
+                    tmpControls, new Bundle());
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         } catch (RemoteException e) {
             snapshotSurface.clearWindowSynced();
@@ -517,7 +518,7 @@
 
     private void reportDrawn() {
         try {
-            mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+            mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
         } catch (RemoteException e) {
             clearWindowSynced();
         }
@@ -534,7 +535,7 @@
         @Override
         public void resized(ClientWindowFrames frames, boolean reportDraw,
                 MergedConfiguration mergedConfiguration, boolean forceLayout,
-                boolean alwaysConsumeSystemBars, int displayId) {
+                boolean alwaysConsumeSystemBars, int displayId, int seqId) {
             if (mOuter != null) {
                 mOuter.mSplashScreenExecutor.execute(() -> {
                     if (mergedConfiguration != null
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 9054685..3e7ee25 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -78,6 +78,7 @@
         MockitoAnnotations.initMocks(this);
         mController = new BackAnimationController(
                 mShellExecutor, mTransaction, mActivityTaskManager, mContext);
+        mController.setEnableAnimations(true);
     }
 
     private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index 9bb54a1..2e5078d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -61,7 +61,7 @@
     public void testInitRelease() {
         mSplitWindowManager.init(mSplitLayout, new InsetsState());
         assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull();
-        mSplitWindowManager.release();
+        mSplitWindowManager.release(null /* t */);
         assertThat(mSplitWindowManager.getSurfaceControl()).isNull();
     }
 }
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 63b831d..c80fb18 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -118,7 +118,7 @@
                 "libz",
             ],
         },
-        linux_glibc: {
+        host_linux: {
             srcs: [
                 "CursorWindow.cpp",
             ],
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index bcfe9c3..30ca7d15 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -135,7 +135,7 @@
     skpCaptureEnabled = debuggingEnabled && base::GetBoolProperty(PROPERTY_CAPTURE_SKP_ENABLED, false);
 
     SkAndroidFrameworkTraceUtil::setEnableTracing(
-            base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false));
+            base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, true));
 
     runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false);
 
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 055dbb2..99508a2 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -48,8 +48,6 @@
     TRANSACTION_isObbMounted,
     TRANSACTION_getMountedObbPath,
     TRANSACTION_isExternalStorageEmulated,
-    TRANSACTION_decryptStorage,
-    TRANSACTION_encryptStorage,
 };
 
 class BpMountService: public BpInterface<IMountService>
@@ -517,40 +515,6 @@
         path = reply.readString16();
         return true;
     }
-
-    int32_t decryptStorage(const String16& password)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
-        data.writeString16(password);
-        if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) {
-            ALOGD("decryptStorage could not contact remote\n");
-            return -1;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("decryptStorage caught exception %d\n", err);
-            return err;
-        }
-        return reply.readInt32();
-    }
-
-    int32_t encryptStorage(const String16& password)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
-        data.writeString16(password);
-        if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) {
-            ALOGD("encryptStorage could not contact remote\n");
-            return -1;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("encryptStorage caught exception %d\n", err);
-            return err;
-        }
-        return reply.readInt32();
-    }
 };
 
 IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IStorageManager")
diff --git a/libs/storage/include/storage/IMountService.h b/libs/storage/include/storage/IMountService.h
index 5b07318..5a9c39b 100644
--- a/libs/storage/include/storage/IMountService.h
+++ b/libs/storage/include/storage/IMountService.h
@@ -70,8 +70,6 @@
             const sp<IObbActionListener>& token, const int32_t nonce) = 0;
     virtual bool isObbMounted(const String16& filename) = 0;
     virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
-    virtual int32_t decryptStorage(const String16& password) = 0;
-    virtual int32_t encryptStorage(const String16& password) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 3fb3fd4..5c90fd0 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -44,8 +44,6 @@
     <string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
     <!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
     <string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
-    <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. -->
-    <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string>
 
     <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
     <string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index d6b6bf8..3c790f0 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -27,8 +27,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.storage.IStorageManager;
-import android.os.storage.StorageManager;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.Slog;
@@ -66,10 +64,8 @@
 
     Handler mHandler;
     IBackupManager mBackupManager;
-    IStorageManager mStorageManager;
     FullObserver mObserver;
     int mToken;
-    boolean mIsEncrypted;
     boolean mDidAcknowledge;
     String mAction;
 
@@ -144,7 +140,6 @@
         }
 
         mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
-        mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
 
         mHandler = new ObserverHandler(getApplicationContext());
         final Object oldObserver = getLastNonConfigurationInstance();
@@ -248,20 +243,13 @@
             mDenyButton.setEnabled(!mDidAcknowledge);
         }
 
-        // We vary the password prompt depending on whether one is predefined, and whether
-        // the device is encrypted.
-        mIsEncrypted = deviceIsEncrypted();
+        // We vary the password prompt depending on whether one is predefined.
         if (!haveBackupPassword()) {
             curPwDesc.setVisibility(View.GONE);
             mCurPassword.setVisibility(View.GONE);
             if (layoutId == R.layout.confirm_backup) {
                 TextView encPwDesc = findViewById(R.id.enc_password_desc);
-                if (mIsEncrypted) {
-                    encPwDesc.setText(R.string.backup_enc_password_required);
-                    monitorEncryptionPassword();
-                } else {
-                    encPwDesc.setText(R.string.backup_enc_password_optional);
-                }
+                encPwDesc.setText(R.string.backup_enc_password_optional);
             }
         }
     }
@@ -312,20 +300,6 @@
         }
     }
 
-    boolean deviceIsEncrypted() {
-        try {
-            return mStorageManager.getEncryptionState()
-                     != StorageManager.ENCRYPTION_STATE_NONE
-                && mStorageManager.getPasswordType()
-                     != StorageManager.CRYPT_TYPE_DEFAULT;
-        } catch (Exception e) {
-            // If we can't talk to the storagemanager service we have a serious problem; fail
-            // "secure" i.e. assuming that the device is encrypted.
-            Slog.e(TAG, "Unable to communicate with storagemanager service: " + e.getMessage());
-            return true;
-        }
-    }
-
     boolean haveBackupPassword() {
         try {
             return mBackupManager.hasBackupPassword();
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index f681ba1..06f2a62 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -327,16 +327,11 @@
          * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
          *            for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
          *            counting iface stats.
-         * @param set usage state of this {@link Entry}. Should be one of the following
-         *            values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+         * @param set usage state of this {@link Entry}.
          * @param tag tag of this {@link Entry}.
-         * @param metered metered state of this {@link Entry}. Should be one of the following
-         *                values: {link #METERED_YES}, {link #METERED_NO}.
-         * @param roaming roaming state of this {@link Entry}. Should be one of the following
-         *                values: {link #ROAMING_YES}, {link #ROAMING_NO}.
-         * @param defaultNetwork default network status of this {@link Entry}. Should be one
-         *                       of the following values: {link #DEFAULT_NETWORK_YES},
-         *                       {link #DEFAULT_NETWORK_NO}.
+         * @param metered metered state of this {@link Entry}.
+         * @param roaming roaming state of this {@link Entry}.
+         * @param defaultNetwork default network status of this {@link Entry}.
          * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
          *                represent the contents of IP packets, including IP headers.
          * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
@@ -401,8 +396,7 @@
         }
 
         /**
-         * @return the set state of this entry. Should be one of the following
-         * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+         * @return the set state of this entry.
          */
         @State public int getSet() {
             return set;
@@ -416,24 +410,21 @@
         }
 
         /**
-         * @return the metered state. Should be one of the following
-         * values: {link #METERED_YES}, {link #METERED_NO}.
+         * @return the metered state.
          */
         @Meteredness public int getMetered() {
             return metered;
         }
 
         /**
-         * @return the roaming state. Should be one of the following
-         * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
+         * @return the roaming state.
          */
         @Roaming public int getRoaming() {
             return roaming;
         }
 
         /**
-         * @return the default network state. Should be one of the following
-         * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}.
+         * @return the default network state.
          */
         @DefaultNetwork public int getDefaultNetwork() {
             return defaultNetwork;
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index bd70396..579e3d7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1344,7 +1344,9 @@
     <string name="notice_header" translatable="false"></string>
 
     <!-- Name of the phone device. [CHAR LIMIT=30] -->
-    <string name="media_transfer_this_device_name">This phone</string>
+    <string name="media_transfer_this_device_name" product="default">This phone</string>
+    <!-- Name of the tablet device. [CHAR LIMIT=30] -->
+    <string name="media_transfer_this_device_name" product="tablet">This tablet</string>
     <!-- Name of the phone device with an active remote session. [CHAR LIMIT=30] -->
     <string name="media_transfer_this_phone">This phone</string>
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e7765e6..e93371d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -536,6 +536,7 @@
     <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
     <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
     <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
+    <uses-permission android:name="android.permission.MANAGE_WIFI_INTERFACES" />
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
     <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
          P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e24b2d6..4b45cc3 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -314,6 +314,11 @@
     <!-- To change system captions state -->
     <uses-permission android:name="android.permission.SET_SYSTEM_AUDIO_CAPTION" />
 
+    <!-- Compat framework -->
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+
     <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/layout/dream_overlay_complication_clock_date.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
index 91d81a2..cb63300 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
@@ -19,6 +19,7 @@
     android:id="@+id/date_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding"
     android:gravity="center_horizontal"
     android:textColor="@android:color/white"
     android:shadowColor="@color/keyguard_shadow_color"
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
index 3900ea5..76fe58c 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
@@ -19,6 +19,7 @@
     android:id="@+id/weather_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding"
     android:textColor="@android:color/white"
     android:shadowColor="@color/keyguard_shadow_color"
     android:shadowRadius="?attr/shadowRadius"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 52ec516..ffae601 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1376,6 +1376,7 @@
     <dimen name="dream_overlay_complication_weather_text_size">18sp</dimen>
     <dimen name="dream_overlay_complication_preview_text_size">36sp</dimen>
     <dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen>
+    <dimen name="dream_overlay_complication_shadow_padding">2dp</dimen>
 
     <!-- The position of the end guide, which dream overlay complications can align their start with
          if their end is aligned with the parent end. Represented as the percentage over from the
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1ef6dea..3858f9c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -326,7 +326,6 @@
     private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private final Executor mBackgroundExecutor;
     private SensorPrivacyManager mSensorPrivacyManager;
-    private int mFaceAuthUserId;
 
     /**
      * Short delay before restarting fingerprint authentication after a successful try. This should
@@ -1030,8 +1029,8 @@
         boolean cameraPrivacyEnabled = false;
         if (mSensorPrivacyManager != null) {
             cameraPrivacyEnabled = mSensorPrivacyManager
-                    .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
-                    mFaceAuthUserId);
+                    .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+                    SensorPrivacyManager.Sensors.CAMERA);
         }
 
         if (msgId == FaceManager.FACE_ERROR_CANCELED
@@ -2599,7 +2598,6 @@
             // This would need to be updated for multi-sensor devices
             final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
                     && mFaceSensorProperties.get(0).supportsFaceDetection;
-            mFaceAuthUserId = userId;
             if (isEncryptedOrLockdown(userId) && supportsFaceDetection) {
                 mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 4b86862..498e715 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -119,9 +119,13 @@
         if (useInvertedAlphaColor) {
             canvas.drawColor(bgColor)
         }
+
+        // We may clear the color(if useInvertedAlphaColor is true) of the rounded corner rects
+        // before drawing rounded corners. If the cutout happens to be inside one of these rects, it
+        // will be cleared, so we have to draw rounded corners before cutout.
+        drawRoundedCorners(canvas)
         // Cutouts are drawn in DisplayCutoutBaseView.onDraw()
         super.onDraw(canvas)
-        drawRoundedCorners(canvas)
 
         debugTransparentRegionPaint?.let {
             calculateTransparentRect()
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index b8b4092..dfb27ef 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -89,6 +89,7 @@
     private boolean mPaused = false;
     private boolean mScreenOff = false;
     private int mLastSensorValue = -1;
+    private DozeMachine.State mState = DozeMachine.State.UNINITIALIZED;
 
     /**
      * Debug value used for emulating various display brightness buckets:
@@ -135,6 +136,7 @@
 
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+        mState = newState;
         switch (newState) {
             case INITIALIZED:
                 resetBrightnessToDefault();
@@ -262,8 +264,9 @@
      */
     private int clampToDimBrightnessForScreenOff(int brightness) {
         final boolean screenTurningOff =
-                mDozeParameters.shouldClampToDimBrightness()
-                        || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP;
+                (mDozeParameters.shouldClampToDimBrightness()
+                        || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP)
+                && mState == DozeMachine.State.INITIALIZED;
         if (screenTurningOff
                 && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) {
             return Math.max(
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 2db3de1..61cfe92 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -145,7 +145,7 @@
     /***************************************/
     // 900 - media
     public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true);
-    public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true);
+    public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false);
     public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, true);
     public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true);
     public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c01d2c3..736e2e0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1706,14 +1706,6 @@
                 if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
                 return;
             }
-
-            if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
-                if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
-                // Without this, settings is not enabled until the lock screen first appears
-                setShowingLocked(false);
-                hideLocked();
-                return;
-            }
         }
 
         if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 510d15b..ffdd537 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -137,7 +137,6 @@
     private MediaCarouselController mMediaCarouselController;
     private final MediaOutputDialogFactory mMediaOutputDialogFactory;
     private final FalsingManager mFalsingManager;
-    private final MediaFlags mMediaFlags;
 
     // Used for swipe-to-dismiss logging.
     protected boolean mIsImpressed = false;
@@ -156,7 +155,7 @@
             Lazy<MediaDataManager> lazyMediaDataManager,
             MediaOutputDialogFactory mediaOutputDialogFactory,
             MediaCarouselController mediaCarouselController,
-            FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) {
+            FalsingManager falsingManager, SystemClock systemClock) {
         mContext = context;
         mBackgroundExecutor = backgroundExecutor;
         mActivityStarter = activityStarter;
@@ -167,7 +166,6 @@
         mMediaOutputDialogFactory = mediaOutputDialogFactory;
         mMediaCarouselController = mediaCarouselController;
         mFalsingManager = falsingManager;
-        mMediaFlags = mediaFlags;
         mSystemClock = systemClock;
         loadDimens();
 
@@ -506,9 +504,8 @@
         List<MediaAction> actionIcons = data.getActions();
         List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
 
-        // If the session actions flag is enabled, but we're still using the regular layout, use
-        // the session actions anyways
-        if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) {
+        // If we got session actions, use those instead
+        if (data.getSemanticActions() != null) {
             MediaButton semanticActions = data.getSemanticActions();
 
             actionIcons = new ArrayList<MediaAction>();
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 9e14fe9..ea92abd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -610,7 +610,8 @@
         var actionIcons: List<MediaAction> = emptyList()
         var actionsToShowCollapsed: List<Int> = emptyList()
         var semanticActions: MediaButton? = null
-        if (mediaFlags.areMediaSessionActionsEnabled() && mediaController.playbackState != null) {
+        if (mediaFlags.areMediaSessionActionsEnabled(sbn.packageName, sbn.user.identifier) &&
+                mediaController.playbackState != null) {
             semanticActions = createActionsFromState(sbn.packageName, mediaController)
         } else {
             val actions = createActionsFromNotification(sbn)
@@ -726,7 +727,7 @@
                 }
             }
 
-            // Finally, assign the remaining button slots: C A play/pause B D
+            // Finally, assign the remaining button slots: play/pause A B C D
             // A = previous, else custom action (if not reserved)
             // B = next, else custom action (if not reserved)
             // C and D are always custom actions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
index dd35a9a..f5200f9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.media
 
+import android.app.StatusBarManager
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
@@ -26,16 +27,17 @@
     /**
      * Check whether media control actions should be based on PlaybackState instead of notification
      */
-    fun areMediaSessionActionsEnabled(): Boolean {
-        return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
+    fun areMediaSessionActionsEnabled(packageName: String, userId: Int): Boolean {
+        val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, userId)
+        // Allow global override with flag
+        return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
     }
 
     /**
      * Check whether media controls should use the new session-based layout
      */
     fun useMediaSessionLayout(): Boolean {
-        return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) &&
-            featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT)
+        return featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index d1b569f..4640205 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -241,7 +241,13 @@
 
     private void addNonFirstPageAnimators(int page) {
         Pair<HeightExpansionAnimator, TouchAnimator> pair = createSecondaryPageAnimators(page);
-        mNonFirstPageQSAnimators.put(page, pair);
+        if (pair != null) {
+            // pair is null in one of two cases:
+            // * mPagedTileLayout is null, meaning we are still setting up.
+            // * the page has no tiles
+            // In either case, don't add the animators to the map.
+            mNonFirstPageQSAnimators.put(page, pair);
+        }
     }
 
     @Override
@@ -518,6 +524,13 @@
         SideLabelTileLayout qqsLayout = (SideLabelTileLayout) mQuickQsPanel.getTileLayout();
         View view = mQs.getView();
         List<String> specs = mPagedLayout.getSpecsForPage(page);
+        if (specs.isEmpty()) {
+            // specs should not be empty in a valid secondary page, as we scrolled to it.
+            // We may crash later on because there's a null animator.
+            specs = mQsPanelController.getHost().mTileSpecs;
+            Log.e(TAG, "Trying to create animators for empty page " + page + ". Tiles: " + specs);
+            // return null;
+        }
 
         int row = -1;
         int lastTileTop = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 8c08873..f2dd770 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -102,7 +102,7 @@
     private int mTopViewMeasureHeight;
 
     @NonNull
-    private List<String> mRssiIgnoredSlots;
+    private List<String> mRssiIgnoredSlots = List.of();
     private boolean mIsSingleCarrier;
 
     private boolean mHasCenterCutout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ccec0c2..16ddb0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -293,6 +293,14 @@
         }
     }
 
+    /**
+     * Cleanup
+     */
+    public void destroy() {
+        mHandler.removeCallbacksAndMessages(null);
+        mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
+    }
+
     private void handleAlignStateChanged(int alignState) {
         String alignmentIndication = "";
         if (alignState == DockManager.ALIGN_STATE_POOR) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 94a6d3e..66c1d87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -507,12 +507,11 @@
                 Math.max(cx + cy, cx + (h - cy)),
                 Math.max((w - cx) + cy, (w - cx) + (h - cy)));
 
-        riv.setRevealParameters(cx, cy, r);
-        riv.setPendingIntent(pendingIntent);
+        riv.getController().setRevealParams(new RemoteInputView.RevealParams(cx, cy, r));
         riv.getController().setPendingIntent(pendingIntent);
-        riv.setRemoteInput(inputs, input, editedSuggestionInfo);
         riv.getController().setRemoteInput(input);
         riv.getController().setRemoteInputs(inputs);
+        riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
         riv.focusAnimated();
         if (userMessageContent != null) {
             riv.setEditTextContent(userMessageContent);
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 9cb5dc5..adb4ce6 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
@@ -413,7 +413,10 @@
             if (mExpandedRemoteInput != null) {
                 mExpandedRemoteInput.onNotificationUpdateOrReset();
                 if (mExpandedRemoteInput.isActive()) {
-                    mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
+                    if (mExpandedRemoteInputController != null) {
+                        mPreviousExpandedRemoteInputIntent =
+                                mExpandedRemoteInputController.getPendingIntent();
+                    }
                     mCachedExpandedRemoteInput = mExpandedRemoteInput;
                     mCachedExpandedRemoteInputViewController = mExpandedRemoteInputController;
                     mExpandedRemoteInput.dispatchStartTemporaryDetach();
@@ -460,7 +463,10 @@
             if (mHeadsUpRemoteInput != null) {
                 mHeadsUpRemoteInput.onNotificationUpdateOrReset();
                 if (mHeadsUpRemoteInput.isActive()) {
-                    mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
+                    if (mHeadsUpRemoteInputController != null) {
+                        mPreviousHeadsUpRemoteInputIntent =
+                                mHeadsUpRemoteInputController.getPendingIntent();
+                    }
                     mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
                     mCachedHeadsUpRemoteInputViewController = mHeadsUpRemoteInputController;
                     mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
@@ -961,14 +967,16 @@
 
     private void transferRemoteInputFocus(int visibleType) {
         if (visibleType == VISIBLE_TYPE_HEADSUP
-                && mHeadsUpRemoteInput != null
-                && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) {
-            mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput);
+                && mHeadsUpRemoteInputController != null
+                && mExpandedRemoteInputController != null
+                && mExpandedRemoteInputController.isActive()) {
+            mHeadsUpRemoteInputController.stealFocusFrom(mExpandedRemoteInputController);
         }
         if (visibleType == VISIBLE_TYPE_EXPANDED
-                && mExpandedRemoteInput != null
-                && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) {
-            mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput);
+                && mExpandedRemoteInputController != null
+                && mHeadsUpRemoteInputController != null
+                && mHeadsUpRemoteInputController.isActive()) {
+            mExpandedRemoteInputController.stealFocusFrom(mHeadsUpRemoteInputController);
         }
     }
 
@@ -1313,7 +1321,6 @@
                     // If we find a matching action in the new notification, focus, otherwise close.
                     Notification.Action[] actions = entry.getSbn().getNotification().actions;
                     if (existingPendingIntent != null) {
-                        result.mView.setPendingIntent(existingPendingIntent);
                         result.mController.setPendingIntent(existingPendingIntent);
                     }
                     if (result.mController.updatePendingIntentFromActions(actions)) {
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 be1aa10..27cc326 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
@@ -758,29 +758,30 @@
             mDebugTextUsedYPositions.clear();
         }
         int y = mTopPadding;
-        drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding");
+        drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding = "+y);
 
         y = getLayoutHeight();
-        drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight()");
+        drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = "+y);
 
         y = (int) mMaxLayoutHeight;
-        drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight");
+        drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = "+y);
 
         if (mKeyguardBottomPadding >= 0) {
             y = getHeight() - (int) mKeyguardBottomPadding;
             drawDebugInfo(canvas, y, Color.GRAY,
-                    /* label= */ "getHeight() - mKeyguardBottomPadding");
+                    /* label= */ "getHeight() - mKeyguardBottomPadding = "+y);
         }
 
         y = getHeight() - getEmptyBottomMargin();
-        drawDebugInfo(canvas, y, Color.GREEN, /* label= */ "getHeight() - getEmptyBottomMargin()");
+        drawDebugInfo(canvas, y, Color.GREEN,
+                /* label= */ "getHeight() - getEmptyBottomMargin() = "+y);
 
         y = (int) (mAmbientState.getStackY());
-        drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY()");
+        drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = "+y);
 
         y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight());
         drawDebugInfo(canvas, y, Color.BLUE,
-                /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight()");
+                /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = "+y);
     }
 
     private void drawDebugInfo(Canvas canvas, int y, int color, String label) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 952cd9a..e1f8c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -202,12 +202,10 @@
             float newHeight = state.height;
             float newNotificationEnd = newYTranslation + newHeight;
             boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned();
-            final boolean shadeClosedWithHUN =
-                    ambientState.isShadeOpening() && !ambientState.isShadeExpanded();
             if (mClipNotificationScrollToTop
                     && (!state.inShelf || (isHeadsUp && !firstHeadsUp))
                     && newYTranslation < clipStart
-                    && shadeClosedWithHUN) {
+                    && !ambientState.isShadeExpanded()) {
                 // The previous view is overlapping on top, clip!
                 float overlapAmount = clipStart - newYTranslation;
                 state.clipTopAmount = (int) overlapAmount;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 48949f92..4d6d05f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -22,8 +22,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.app.ActivityManager;
 import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
@@ -75,7 +73,6 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -111,21 +108,15 @@
     private ProgressBar mProgressBar;
     private ImageView mDelete;
     private ImageView mDeleteBg;
-    // TODO(b/193539698): remove reveal param fields, turn them into parameters where needed
-    private int mRevealCx;
-    private int mRevealCy;
-    private int mRevealR;
     private boolean mColorized;
     private int mTint;
     private boolean mResetting;
+    @Nullable private RevealParams mRevealParams;
 
     // TODO(b/193539698): move these to a Controller
     private RemoteInputController mController;
     private final UiEventLogger mUiEventLogger;
     private NotificationEntry mEntry;
-    private PendingIntent mPendingIntent;
-    private RemoteInput mRemoteInput;
-    private RemoteInput[] mRemoteInputs;
     private boolean mRemoved;
     private NotificationViewWrapper mWrapper;
 
@@ -397,9 +388,8 @@
         // During removal, we get reattached and lose focus. Not hiding in that
         // case to prevent flicker.
         if (!mRemoved) {
-            if (animate && mRevealR > 0) {
-                Animator reveal = ViewAnimationUtils.createCircularReveal(
-                        this, mRevealCx, mRevealCy, mRevealR, 0);
+            if (animate && mRevealParams != null && mRevealParams.radius > 0) {
+                Animator reveal = mRevealParams.createCircularHideAnimator(this);
                 reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
                 reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
                 reveal.addListener(new AnimatorListenerAdapter() {
@@ -454,30 +444,12 @@
         mController.removeSpinning(mEntry.getKey(), mToken);
     }
 
-    public void setPendingIntent(PendingIntent pendingIntent) {
-        mPendingIntent = pendingIntent;
+    public void setHintText(CharSequence hintText) {
+        mEditText.setHint(hintText);
     }
 
-    /**
-     * Sets the remote input for this view.
-     *
-     * @param remoteInputs The remote inputs that need to be sent to the app.
-     * @param remoteInput The remote input that needs to be activated.
-     * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or
-     *         {@code null} if the user is not editing a smart reply.
-     */
-    public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput,
-            @Nullable EditedSuggestionInfo editedSuggestionInfo) {
-        mRemoteInputs = remoteInputs;
-        mRemoteInput = remoteInput;
-        mEditText.setHint(mRemoteInput.getLabel());
-        mEditText.setSupportedMimeTypes(remoteInput.getAllowedDataTypes());
-
-        mEntry.editedSuggestionInfo = editedSuggestionInfo;
-        if (editedSuggestionInfo != null) {
-            mEntry.remoteInputText = editedSuggestionInfo.originalText;
-            mEntry.remoteInputAttachment = null;
-        }
+    public void setSupportedMimeTypes(Collection<String> mimeTypes) {
+        mEditText.setSupportedMimeTypes(mimeTypes);
     }
 
     /** Populates the text field of the remote input with the given content. */
@@ -486,9 +458,8 @@
     }
 
     public void focusAnimated() {
-        if (getVisibility() != VISIBLE) {
-            Animator animator = ViewAnimationUtils.createCircularReveal(
-                    this, mRevealCx, mRevealCy, 0, mRevealR);
+        if (getVisibility() != VISIBLE && mRevealParams != null) {
+            Animator animator = mRevealParams.createCircularRevealAnimator(this);
             animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
             animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
             animator.start();
@@ -587,30 +558,12 @@
         return mEditText.isFocused() && mEditText.isEnabled();
     }
 
-    // TODO(b/193539698): move this to the controller
-    public void stealFocusFrom(RemoteInputView other) {
-        other.close();
-        setPendingIntent(other.mPendingIntent);
-        setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo);
-        setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR);
-        getController().setPendingIntent(other.mPendingIntent);
-        getController().setRemoteInput(other.mRemoteInput);
-        getController().setRemoteInputs(other.mRemoteInputs);
-        focus();
-    }
-
-    public PendingIntent getPendingIntent() {
-        return mPendingIntent;
-    }
-
     public void setRemoved() {
         mRemoved = true;
     }
 
-    public void setRevealParameters(int cx, int cy, int r) {
-        mRevealCx = cx;
-        mRevealCy = cy;
-        mRevealR = r;
+    public void setRevealParameters(@Nullable RevealParams revealParams) {
+        mRevealParams = revealParams;
     }
 
     @Override
@@ -938,4 +891,24 @@
         }
 
     }
+
+    public static class RevealParams {
+        final int centerX;
+        final int centerY;
+        final int radius;
+
+        public RevealParams(int centerX, int centerY, int radius) {
+            this.centerX = centerX;
+            this.centerY = centerY;
+            this.radius = radius;
+        }
+
+        Animator createCircularRevealAnimator(View view) {
+            return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0);
+        }
+
+        Animator createCircularHideAnimator(View view) {
+            return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
index ef0a5b4..bd87875 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
@@ -33,7 +33,9 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager
 import com.android.systemui.statusbar.RemoteInputController
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo
 import com.android.systemui.statusbar.policy.RemoteInputView.NotificationRemoteInputEvent
+import com.android.systemui.statusbar.policy.RemoteInputView.RevealParams
 import com.android.systemui.statusbar.policy.dagger.RemoteInputViewScope
 import javax.inject.Inject
 
@@ -41,6 +43,8 @@
     fun bind()
     fun unbind()
 
+    val isActive: Boolean
+
     /**
      * A [NotificationRemoteInputManager.BouncerChecker] that will be used to determine if the
      * device needs to be unlocked before sending the RemoteInput.
@@ -55,6 +59,14 @@
     /** Other [RemoteInput]s from the notification associated with this Controller. */
     var remoteInputs: Array<RemoteInput>?
 
+    var revealParams: RevealParams?
+
+    /**
+     * Sets the smart reply that should be inserted in the remote input, or `null` if the user is
+     * not editing a smart reply.
+     */
+    fun setEditedSuggestionInfo(info: EditedSuggestionInfo?)
+
     /**
      * Tries to find an action in {@param actions} that matches the current pending intent
      * of this view and updates its state to that of the found action
@@ -68,6 +80,19 @@
 
     /** Unregisters a listener previously registered via [addOnSendRemoteInputListener] */
     fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener)
+
+    fun close()
+
+    fun focus()
+
+    fun stealFocusFrom(other: RemoteInputViewController) {
+        other.close()
+        remoteInput = other.remoteInput
+        remoteInputs = other.remoteInputs
+        revealParams = other.revealParams
+        pendingIntent = other.pendingIntent
+        focus()
+    }
 }
 
 /** Listener for send events  */
@@ -100,15 +125,41 @@
 
     private var isBound = false
 
-    override var pendingIntent: PendingIntent? = null
     override var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? = null
+
     override var remoteInput: RemoteInput? = null
+        set(value) {
+            field = value
+            value?.takeIf { isBound }?.let {
+                view.setHintText(it.label)
+                view.setSupportedMimeTypes(it.allowedDataTypes)
+            }
+        }
+
+    override var pendingIntent: PendingIntent? = null
     override var remoteInputs: Array<RemoteInput>? = null
 
+    override var revealParams: RevealParams? = null
+        set(value) {
+            field = value
+            if (isBound) {
+                view.setRevealParameters(value)
+            }
+        }
+
+    override val isActive: Boolean get() = view.isActive
+
     override fun bind() {
         if (isBound) return
         isBound = true
 
+        // TODO: refreshUI method?
+        remoteInput?.let {
+            view.setHintText(it.label)
+            view.setSupportedMimeTypes(it.allowedDataTypes)
+        }
+        view.setRevealParameters(revealParams)
+
         view.addOnEditTextFocusChangedListener(onFocusChangeListener)
         view.addOnSendRemoteInputListener(onSendRemoteInputListener)
     }
@@ -121,6 +172,14 @@
         view.removeOnSendRemoteInputListener(onSendRemoteInputListener)
     }
 
+    override fun setEditedSuggestionInfo(info: EditedSuggestionInfo?) {
+        entry.editedSuggestionInfo = info
+        if (info != null) {
+            entry.remoteInputText = info.originalText
+            entry.remoteInputAttachment = null
+        }
+    }
+
     override fun updatePendingIntentFromActions(actions: Array<Notification.Action>?): Boolean {
         actions ?: return false
         val current: Intent = pendingIntent?.intent ?: return false
@@ -132,8 +191,7 @@
             pendingIntent = actionIntent
             remoteInput = input
             remoteInputs = inputs
-            view.pendingIntent = actionIntent
-            view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */)
+            setEditedSuggestionInfo(null)
             return true
         }
         return false
@@ -148,6 +206,14 @@
         onSendListeners.remove(listener)
     }
 
+    override fun close() {
+        view.close()
+    }
+
+    override fun focus() {
+        view.focus()
+    }
+
     private val onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
         remoteInputQuickSettingsDisabler.setRemoteInputActive(hasFocus)
     }
@@ -217,11 +283,12 @@
      * @return returns intent with granted URI permissions that should be used immediately
      */
     private fun prepareRemoteInput(remoteInput: RemoteInput): Intent =
-            if (entry.remoteInputAttachment == null) prepareRemoteInputFromText(remoteInput)
-            else prepareRemoteInputFromData(
-                    remoteInput,
-                    entry.remoteInputMimeType,
-                    entry.remoteInputUri)
+        if (entry.remoteInputAttachment == null)
+            prepareRemoteInputFromText(remoteInput)
+        else prepareRemoteInputFromData(
+                remoteInput,
+                entry.remoteInputMimeType,
+                entry.remoteInputUri)
 
     private fun prepareRemoteInputFromText(remoteInput: RemoteInput): Intent {
         val results = Bundle()
@@ -232,11 +299,10 @@
         view.clearAttachment()
         entry.remoteInputUri = null
         entry.remoteInputMimeType = null
-        if (entry.editedSuggestionInfo == null) {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
-        } else {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
-        }
+        val resultSource = entry.editedSuggestionInfo
+                ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT }
+                ?: RemoteInput.SOURCE_CHOICE
+        RemoteInput.setResultsSource(fillInIntent, resultSource)
         return fillInIntent
     }
 
@@ -266,11 +332,10 @@
         entry.remoteInputText = fullText
 
         // mirror prepareRemoteInputFromText for text input
-        if (entry.editedSuggestionInfo == null) {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
-        } else if (entry.remoteInputAttachment == null) {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
-        }
+        val resultSource = entry.editedSuggestionInfo
+                ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT }
+                ?: RemoteInput.SOURCE_CHOICE
+        RemoteInput.setResultsSource(fillInIntent, resultSource)
         return fillInIntent
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index badafa4..f4b378e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -27,6 +27,7 @@
 import static com.android.systemui.doze.DozeMachine.State.FINISH;
 import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
 import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotSame;
@@ -468,37 +469,39 @@
     public void transitionToDoze_shouldClampBrightness_afterTimeout_clampsToDim() {
         when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
                 PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
-        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
         when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE);
 
         // If we're dozing after a timeout, and playing the unlocked screen animation, we should
         // stay at or below dim brightness, because the screen dims just before timeout.
         assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
+
+        // Once we transition to Doze, use the doze brightness
+        mScreen.transitionTo(INITIALIZED, DOZE);
+        assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
     }
 
     @Test
     public void transitionToDoze_shouldClampBrightness_notAfterTimeout_doesNotClampToDim() {
         when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
                 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
-        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
         when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(true);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE);
 
         // If we're playing the unlocked screen off animation after a power button press, we should
         // leave the brightness alone.
         assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+
+        mScreen.transitionTo(INITIALIZED, DOZE);
+        assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
     }
 
     @Test
     public void transitionToDoze_noClampBrightness_afterTimeout_noScreenOff_doesNotClampToDim() {
         when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
                 PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
-        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
         when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -514,11 +517,9 @@
                 PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
         when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
                 WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
-        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
         when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE);
 
         assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
     }
@@ -529,7 +530,6 @@
                 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
         when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
                 WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
-        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
         when(mDozeParameters.shouldClampToDimBrightness()).thenReturn(false);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index dcbe0ab..daf81bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -37,7 +37,6 @@
 import org.mockito.Mock
 import org.mockito.MockitoAnnotations
 import javax.inject.Provider
-import org.mockito.Mockito.`when` as whenever
 
 private val DATA = MediaData(
     userId = -1,
@@ -83,7 +82,6 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
         mediaCarouselController = MediaCarouselController(
             context,
             mediaControlPanelFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index cb68d81..90eff1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -101,7 +101,6 @@
     @Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory
     @Mock private lateinit var mediaCarouselController: MediaCarouselController
     @Mock private lateinit var falsingManager: FalsingManager
-    @Mock private lateinit var mediaFlags: MediaFlags
     private lateinit var appIcon: ImageView
     private lateinit var albumView: ImageView
     private lateinit var titleText: TextView
@@ -147,7 +146,7 @@
 
         player = MediaControlPanel(context, bgExecutor, activityStarter, broadcastSender,
             mediaViewController, seekBarViewModel, Lazy { mediaDataManager },
-            mediaOutputDialogFactory, mediaCarouselController, falsingManager, mediaFlags, clock)
+            mediaOutputDialogFactory, mediaCarouselController, falsingManager, clock)
         whenever(seekBarViewModel.progress).thenReturn(seekBarData)
 
         // Set up mock views for the players
@@ -215,9 +214,6 @@
                 device = device,
                 active = true,
                 resumeAction = null)
-
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false)
-        whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false)
     }
 
     /**
@@ -295,9 +291,6 @@
 
     @Test
     fun bindSemanticActionsOldLayout() {
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
-        whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false)
-
         val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
         val semanticActions = MediaButton(
             playOrPause = MediaAction(icon, Runnable {}, "play"),
@@ -332,9 +325,6 @@
 
     @Test
     fun bindSemanticActionsNewLayout() {
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
-        whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true)
-
         val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
         val semanticActions = MediaButton(
                 playOrPause = MediaAction(icon, Runnable {}, "play"),
@@ -381,9 +371,6 @@
 
     @Test
     fun bindNotificationActionsNewLayout() {
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
-        whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true)
-
         val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
         val actions = listOf(
             MediaAction(icon, Runnable {}, "previous"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 925ae30..be2450d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.statusbar.SbnBuilder
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
@@ -37,6 +38,7 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito
@@ -167,7 +169,7 @@
         whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA)
         whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf(mediaRecommendationItem))
         whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L)
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false)
+        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(false)
     }
 
     @After
@@ -594,7 +596,7 @@
     @Test
     fun testPlaybackActions_noState_usesNotification() {
         val desc = "Notification Action"
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true)
         whenever(controller.playbackState).thenReturn(null)
 
         val notifWithAction = SbnBuilder().run {
@@ -621,7 +623,7 @@
     @Test
     fun testPlaybackActions_hasPrevNext() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true)
         val stateActions = PlaybackState.ACTION_PLAY or
                 PlaybackState.ACTION_SKIP_TO_PREVIOUS or
                 PlaybackState.ACTION_SKIP_TO_NEXT
@@ -669,7 +671,7 @@
     @Test
     fun testPlaybackActions_noPrevNext_usesCustom() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder = PlaybackState.Builder()
                 .setActions(stateActions)
@@ -707,7 +709,7 @@
     @Test
     fun testPlaybackActions_reservedSpace() {
         val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
-        whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true)
         val stateActions = PlaybackState.ACTION_PLAY
         val stateBuilder = PlaybackState.Builder()
                 .setActions(stateActions)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 3c1a73e..ad643fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -226,6 +226,10 @@
     @After
     public void tearDown() throws Exception {
         mTextView.setAnimationsEnabled(true);
+        if (mController != null) {
+            mController.destroy();
+            mController = null;
+        }
     }
 
     private void createController() {
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 20a3fda..3a0a7c9 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
@@ -114,15 +114,13 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
-    private void setTestPendingIntent(RemoteInputView view, RemoteInputViewController controller) {
+    private void setTestPendingIntent(RemoteInputViewController controller) {
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
                 new Intent(TEST_ACTION), PendingIntent.FLAG_MUTABLE);
         RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).build();
         RemoteInput[] inputs = {input};
 
-        view.setPendingIntent(pendingIntent);
         controller.setPendingIntent(pendingIntent);
-        view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */);
         controller.setRemoteInput(input);
         controller.setRemoteInputs(inputs);
     }
@@ -137,7 +135,7 @@
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
         RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view, controller);
+        setTestPendingIntent(controller);
 
         view.focus();
 
@@ -177,7 +175,7 @@
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
         RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view, controller);
+        setTestPendingIntent(controller);
 
         view.focus();
 
@@ -235,7 +233,7 @@
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
         RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view, controller);
+        setTestPendingIntent(controller);
 
         // Open view, send a reply
         view.focus();
@@ -265,7 +263,7 @@
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
         RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view, controller);
+        setTestPendingIntent(controller);
 
         // Open view, attach an image
         view.focus();
diff --git a/proto/src/camera.proto b/proto/src/camera.proto
index 4082118..38d74e4 100644
--- a/proto/src/camera.proto
+++ b/proto/src/camera.proto
@@ -66,5 +66,5 @@
     // The dynamic range profile of the stream
     optional int64 dynamic_range_profile = 14;
     // The stream use case
-    optional int32 stream_use_case = 15;
+    optional int64 stream_use_case = 15;
 }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index e10151d..1af35af 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -89,8 +89,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
-import android.os.storage.IStorageManager;
-import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -325,7 +323,6 @@
     private final ActivityManagerInternal mActivityManagerInternal;
     private PowerManager mPowerManager;
     private final AlarmManager mAlarmManager;
-    private final IStorageManager mStorageManager;
     private final BackupManagerConstants mConstants;
     private final BackupWakeLock mWakelock;
     private final BackupHandler mBackupHandler;
@@ -536,7 +533,6 @@
         mBackupPasswordManager = null;
         mPackageManagerBinder = null;
         mActivityManager = null;
-        mStorageManager = null;
         mBackupManagerBinder = null;
         mScheduledBackupEligibility = null;
     }
@@ -560,7 +556,6 @@
 
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
 
         Objects.requireNonNull(parent, "parent cannot be null");
         mBackupManagerBinder = BackupManagerService.asInterface(parent.asBinder());
@@ -2077,26 +2072,6 @@
         }
     }
 
-    /** For adb backup/restore. */
-    public boolean deviceIsEncrypted() {
-        try {
-            return mStorageManager.getEncryptionState()
-                    != StorageManager.ENCRYPTION_STATE_NONE
-                    && mStorageManager.getPasswordType()
-                    != StorageManager.CRYPT_TYPE_DEFAULT;
-        } catch (Exception e) {
-            // If we can't talk to the storagemanager service we have a serious problem; fail
-            // "secure" i.e. assuming that the device is encrypted.
-            Slog.e(
-                    TAG,
-                    addUserIdToLogMessage(
-                            mUserId,
-                            "Unable to communicate with storagemanager service: "
-                                    + e.getMessage()));
-            return true;
-        }
-    }
-
     // ----- Full-data backup scheduling -----
 
     /**
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 7ee307e..ec58e17 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -320,12 +320,6 @@
         try {
             boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
 
-            // Only allow encrypted backups of encrypted devices
-            if (mUserBackupManagerService.deviceIsEncrypted() && !encrypting) {
-                Slog.e(TAG, "Unencrypted backup of encrypted device; aborting");
-                return;
-            }
-
             OutputStream finalOutput = ofstream;
 
             // Verify that the given password matches the currently-active
diff --git a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
index 1ba198a..823743d 100644
--- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
+++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
@@ -94,7 +94,7 @@
             int reason) {
         if (DEBUG) {
             Log.i(TAG, "onDevice_Disconnected() " + btDeviceToString(device));
-            Log.d(TAG, "  reason=" + disconnectReasonText(reason));
+            Log.d(TAG, "  reason=" + disconnectReasonToString(reason));
         }
 
         final MacAddress macAddress = MacAddress.fromString(device.getAddress());
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index be2b7f7..f1fa982 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -131,7 +131,7 @@
         final UserManager userManager = context.getSystemService(UserManager.class);
         final int result = userManager.removeUserWhenPossible(
                 UserHandle.of(userId), /* overrideDevicePolicy= */ false);
-        if (result == UserManager.REMOVE_RESULT_ERROR) {
+        if (!UserManager.isRemoveResultSuccessful(result)) {
             Slogf.e(TAG, "Can't remove user %d", userId);
             return false;
         }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7075ed3..677fc79 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3129,203 +3129,6 @@
         }
     }
 
-    @Override
-    public int getEncryptionState() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-                "no permission to access the crypt keeper");
-
-        try {
-            return mVold.fdeComplete();
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
-        }
-    }
-
-    @Override
-    public int decryptStorage(String password) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-                "no permission to access the crypt keeper");
-
-        if (TextUtils.isEmpty(password)) {
-            throw new IllegalArgumentException("password cannot be empty");
-        }
-
-        if (DEBUG_EVENTS) {
-            Slog.i(TAG, "decrypting storage...");
-        }
-
-        try {
-            mVold.fdeCheckPassword(password);
-            mHandler.postDelayed(() -> {
-                try {
-                    mVold.fdeRestart();
-                } catch (Exception e) {
-                    Slog.wtf(TAG, e);
-                }
-            }, DateUtils.SECOND_IN_MILLIS);
-            return 0;
-        } catch (ServiceSpecificException e) {
-            Slog.e(TAG, "fdeCheckPassword failed", e);
-            return e.errorCode;
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
-        }
-    }
-
-    @Override
-    public int encryptStorage(int type, String password) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
-            password = "";
-        } else if (TextUtils.isEmpty(password)) {
-            throw new IllegalArgumentException("password cannot be empty");
-        }
-
-        if (DEBUG_EVENTS) {
-            Slog.i(TAG, "encrypting storage...");
-        }
-
-        try {
-            mVold.fdeEnable(type, password, 0);
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return -1;
-        }
-
-        return 0;
-    }
-
-    /** Set the password for encrypting the main key.
-     *  @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
-     *  @param password The password to set.
-     */
-    @Override
-    public int changeEncryptionPassword(int type, String password) {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        if (StorageManager.isFileEncryptedNativeOnly()) {
-            // Not supported on FBE devices
-            return -1;
-        }
-
-        if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
-            password = "";
-        } else if (TextUtils.isEmpty(password)) {
-            throw new IllegalArgumentException("password cannot be empty");
-        }
-
-        if (DEBUG_EVENTS) {
-            Slog.i(TAG, "changing encryption password...");
-        }
-
-        try {
-            mVold.fdeChangePassword(type, password);
-            return 0;
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return -1;
-        }
-    }
-
-    /**
-     * Validate a user-supplied password string with cryptfs
-     */
-    @Override
-    public int verifyEncryptionPassword(String password) throws RemoteException {
-        // Only the system process is permitted to validate passwords
-        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
-            throw new SecurityException("no permission to access the crypt keeper");
-        }
-
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        if (TextUtils.isEmpty(password)) {
-            throw new IllegalArgumentException("password cannot be empty");
-        }
-
-        if (DEBUG_EVENTS) {
-            Slog.i(TAG, "validating encryption password...");
-        }
-
-        try {
-            mVold.fdeVerifyPassword(password);
-            return 0;
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return -1;
-        }
-    }
-
-    /**
-     * Get the type of encryption used to encrypt the main key.
-     * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
-     */
-    @Override
-    public int getPasswordType() {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        try {
-            return mVold.fdeGetPasswordType();
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return -1;
-        }
-    }
-
-    /**
-     * Set a field in the crypto header.
-     * @param field field to set
-     * @param contents contents to set in field
-     */
-    @Override
-    public void setField(String field, String contents) throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        if (!StorageManager.isBlockEncrypted()) {
-            // Only supported on FDE devices
-            return;
-        }
-
-        try {
-            mVold.fdeSetField(field, contents);
-            return;
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return;
-        }
-    }
-
-    /**
-     * Gets a field from the crypto header.
-     * @param field field to get
-     * @return contents of field
-     */
-    @Override
-    public String getField(String field) throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        if (!StorageManager.isBlockEncrypted()) {
-            // Only supported on FDE devices
-            return null;
-        }
-
-        try {
-            return mVold.fdeGetField(field);
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return null;
-        }
-    }
-
     /**
      * Is userdata convertible to file based encryption?
      * @return non zero for convertible
@@ -3408,33 +3211,6 @@
     }
 
     @Override
-    public String getPassword() throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-                "only keyguard can retrieve password");
-
-        try {
-            return mVold.fdeGetPassword();
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return null;
-        }
-    }
-
-    @Override
-    public void clearPassword() throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-                "only keyguard can clear password");
-
-        try {
-            mVold.fdeClearPassword();
-            return;
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return;
-        }
-    }
-
-    @Override
     public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
 
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 7cd45fe..ea1e335 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -28,7 +28,6 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.BatteryConsumer.POWER_COMPONENT_ANY;
 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
-import static android.os.BatteryConsumer.PROCESS_STATE_COUNT;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
 import static android.os.BatteryConsumer.PROCESS_STATE_UNSPECIFIED;
@@ -38,7 +37,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX;
-import static com.android.server.am.BaseAppStateTracker.ONE_MINUTE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -71,7 +69,6 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.server.am.AppBatteryTracker.AppBatteryPolicy;
 import com.android.server.am.AppRestrictionController.UidBatteryUsageProvider;
-import com.android.server.am.BaseAppStateTracker.Injector;
 import com.android.server.pm.UserManagerInternal;
 
 import java.io.PrintWriter;
@@ -684,7 +681,7 @@
         static final int BATTERY_USAGE_INDEX_FOREGROUND = PROCESS_STATE_FOREGROUND;
         static final int BATTERY_USAGE_INDEX_BACKGROUND = PROCESS_STATE_BACKGROUND;
         static final int BATTERY_USAGE_INDEX_FOREGROUND_SERVICE = PROCESS_STATE_FOREGROUND_SERVICE;
-        static final int BATTERY_USAGE_COUNT = PROCESS_STATE_COUNT;
+        static final int BATTERY_USAGE_COUNT = 4;
 
         static final Dimensions[] BATT_DIMENS = new Dimensions[] {
                 new Dimensions(AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_POWER_COMPONENTS,
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 193cc5f..5af73c9 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -275,6 +275,7 @@
      */
     synchronized void reset(boolean featureEnabled) {
         Log.i(TAG, "Resetting");
+        releaseSpat();
         mState = STATE_UNINITIALIZED;
         mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
         mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
@@ -831,10 +832,10 @@
             try {
                 mSpat.registerHeadTrackingCallback(null);
                 mSpat.release();
-                mSpat = null;
             } catch (RemoteException e) {
                 Log.e(TAG, "Can't set release spatializer cleanly", e);
             }
+            mSpat = null;
         }
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 7765ab3..9ae6750 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -136,8 +136,8 @@
         try {
             if (mSensorPrivacyManager != null
                     && mSensorPrivacyManager
-                    .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
-                    getTargetUserId())) {
+                    .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+                    SensorPrivacyManager.Sensors.CAMERA)) {
                 onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
                         0 /* vendorCode */);
                 mCallback.onClientFinished(this, false /* success */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index efedcf8..ded1810 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -96,7 +96,8 @@
     protected void startHalOperation() {
         if (mSensorPrivacyManager != null
                 && mSensorPrivacyManager
-                .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) {
+                .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+                    SensorPrivacyManager.Sensors.CAMERA)) {
             onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
             mCallback.onClientFinished(this, false /* success */);
             return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 8d76e9f..1935a5b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -109,7 +109,8 @@
 
         if (mSensorPrivacyManager != null
                 && mSensorPrivacyManager
-                .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) {
+                .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+                SensorPrivacyManager.Sensors.CAMERA)) {
             onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
             mCallback.onClientFinished(this, false /* success */);
             return;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 52834cb..436cc69 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -252,8 +252,6 @@
 
     private final RebootEscrowManager mRebootEscrowManager;
 
-    private boolean mFirstCallToVold;
-
     // Current password metric for all users on the device. Updated when user unlocks
     // the device or changes password. Removed when user is stopped.
     @GuardedBy("this")
@@ -597,8 +595,6 @@
         mStrongAuth = injector.getStrongAuth();
         mActivityManager = injector.getActivityManager();
 
-        mFirstCallToVold = true;
-
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_STARTING);
@@ -2474,77 +2470,6 @@
         });
     }
 
-    private LockscreenCredential createPattern(String patternString) {
-        final byte[] patternBytes = patternString.getBytes();
-        LockscreenCredential pattern = LockscreenCredential.createPattern(
-                LockPatternUtils.byteArrayToPattern(patternBytes));
-        Arrays.fill(patternBytes, (byte) 0);
-        return pattern;
-    }
-
-    @Override
-    public boolean checkVoldPassword(int userId) {
-        if (!mFirstCallToVold) {
-            return false;
-        }
-        mFirstCallToVold = false;
-
-        checkPasswordReadPermission();
-
-        // There's no guarantee that this will safely connect, but if it fails
-        // we will simply show the lock screen when we shouldn't, so relatively
-        // benign. There is an outside chance something nasty would happen if
-        // this service restarted before vold stales out the password in this
-        // case. The nastiness is limited to not showing the lock screen when
-        // we should, within the first minute of decrypting the phone if this
-        // service can't connect to vold, it restarts, and then the new instance
-        // does successfully connect.
-        final IStorageManager service = mInjector.getStorageManager();
-        // TODO(b/120484642): Update vold to return a password as a byte array
-        String password;
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            password = service.getPassword();
-            service.clearPassword();
-        } catch (RemoteException e) {
-            Slog.w(TAG, "vold getPassword() failed", e);
-            return false;
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-        if (TextUtils.isEmpty(password)) {
-            return false;
-        }
-
-        try {
-            final LockscreenCredential credential;
-            switch (getCredentialTypeInternal(userId)) {
-                case CREDENTIAL_TYPE_PATTERN:
-                    credential = createPattern(password);
-                    break;
-                case CREDENTIAL_TYPE_PIN:
-                    credential = LockscreenCredential.createPin(password);
-                    break;
-                case CREDENTIAL_TYPE_PASSWORD:
-                    credential = LockscreenCredential.createPassword(password);
-                    break;
-                default:
-                    credential = null;
-                    Slog.e(TAG, "Unknown credential type");
-            }
-
-            if (credential != null
-                    && checkCredential(credential, userId, null /* progressCallback */)
-                                .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
-                return true;
-            }
-        } catch (Exception e) {
-            Slog.e(TAG, "checkVoldPassword failed: ", e);
-        }
-
-        return false;
-    }
-
     private void removeUser(int userId, boolean unknownUser) {
         Slog.i(TAG, "RemoveUser: " + userId);
         removeBiometricsForUser(userId);
diff --git a/services/core/java/com/android/server/pm/AppIdSettingMap.java b/services/core/java/com/android/server/pm/AppIdSettingMap.java
index bbef237..b41a0b8 100644
--- a/services/core/java/com/android/server/pm/AppIdSettingMap.java
+++ b/services/core/java/com/android/server/pm/AppIdSettingMap.java
@@ -17,46 +17,131 @@
 package com.android.server.pm;
 
 import android.os.Process;
+import android.util.Log;
 
+import com.android.server.utils.WatchedArrayList;
 import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.Watcher;
 
 /**
- * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID.
+ * A wrapper over {@link WatchedArrayList} that tracks the current (app ID -> SettingBase) mapping
+ * for non-system apps. Also tracks system app settings in an {@link WatchedSparseArray}.
  */
-public class AppIdSettingMap extends WatchedSparseArray<SettingBase> {
-    private int mCurrentMaxAppId;
+final class AppIdSettingMap {
+    /**
+     * We use an ArrayList instead of an SparseArray for non system apps because the number of apps
+     * might be big, and only ArrayList gives us a constant lookup time. For a given app ID, the
+     * index to the corresponding SettingBase object is (appId - FIRST_APPLICATION_ID). If an app ID
+     * doesn't exist (i.e., app is not installed), we fill the corresponding entry with null.
+     */
+    private WatchedArrayList<SettingBase> mNonSystemSettings = new WatchedArrayList<>();
+    private WatchedSparseArray<SettingBase> mSystemSettings = new WatchedSparseArray<>();
+    private int mFirstAvailableAppId = Process.FIRST_APPLICATION_UID;
 
-    @Override
-    public void put(int key, SettingBase value) {
-        if (key > mCurrentMaxAppId) {
-            mCurrentMaxAppId = key;
+    /** Returns true if the requested AppID was valid and not already registered. */
+    public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {
+        if (appId >= Process.FIRST_APPLICATION_UID) {
+            int size = mNonSystemSettings.size();
+            final int index = appId - Process.FIRST_APPLICATION_UID;
+            // fill the array until our index becomes valid
+            while (index >= size) {
+                mNonSystemSettings.add(null);
+                size++;
+            }
+            if (mNonSystemSettings.get(index) != null) {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Adding duplicate app id: " + appId
+                                + " name=" + name);
+                return false;
+            }
+            mNonSystemSettings.set(index, setting);
+        } else {
+            if (mSystemSettings.get(appId) != null) {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Adding duplicate shared id: " + appId
+                                + " name=" + name);
+                return false;
+            }
+            mSystemSettings.put(appId, setting);
         }
-        super.put(key, value);
+        return true;
     }
 
-    @Override
+    public SettingBase getSetting(int appId) {
+        if (appId >= Process.FIRST_APPLICATION_UID) {
+            final int size = mNonSystemSettings.size();
+            final int index = appId - Process.FIRST_APPLICATION_UID;
+            return index < size ? mNonSystemSettings.get(index) : null;
+        } else {
+            return mSystemSettings.get(appId);
+        }
+    }
+
+    public void removeSetting(int appId) {
+        if (appId >= Process.FIRST_APPLICATION_UID) {
+            final int size = mNonSystemSettings.size();
+            final int index = appId - Process.FIRST_APPLICATION_UID;
+            if (index < size) {
+                mNonSystemSettings.set(index, null);
+            }
+        } else {
+            mSystemSettings.remove(appId);
+        }
+        setFirstAvailableAppId(appId + 1);
+    }
+
+    // This should be called (at least) whenever an application is removed
+    private void setFirstAvailableAppId(int uid) {
+        if (uid > mFirstAvailableAppId) {
+            mFirstAvailableAppId = uid;
+        }
+    }
+
+    public void replaceSetting(int appId, SettingBase setting) {
+        if (appId >= Process.FIRST_APPLICATION_UID) {
+            final int size = mNonSystemSettings.size();
+            final int index = appId - Process.FIRST_APPLICATION_UID;
+            if (index < size) {
+                mNonSystemSettings.set(index, setting);
+            } else {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Error in package manager settings: calling replaceAppIdLpw to"
+                                + " replace SettingBase at appId=" + appId
+                                + " but nothing is replaced.");
+            }
+        } else {
+            mSystemSettings.put(appId, setting);
+        }
+    }
+
+    /** Returns a new AppID or -1 if we could not find an available AppID to assign */
+    public int acquireAndRegisterNewAppId(SettingBase obj) {
+        final int size = mNonSystemSettings.size();
+        for (int i = mFirstAvailableAppId - Process.FIRST_APPLICATION_UID; i < size; i++) {
+            if (mNonSystemSettings.get(i) == null) {
+                mNonSystemSettings.set(i, obj);
+                return Process.FIRST_APPLICATION_UID + i;
+            }
+        }
+
+        // None left?
+        if (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) {
+            return -1;
+        }
+
+        mNonSystemSettings.add(obj);
+        return Process.FIRST_APPLICATION_UID + size;
+    }
+
     public AppIdSettingMap snapshot() {
         AppIdSettingMap l = new AppIdSettingMap();
-        snapshot(l, this);
+        mNonSystemSettings.snapshot(l.mNonSystemSettings, mNonSystemSettings);
+        mSystemSettings.snapshot(l.mSystemSettings, mSystemSettings);
         return l;
     }
 
-    /**
-     * @return the maximum of all the App IDs that have been added to the map. 0 if map is empty.
-     */
-    public int getCurrentMaxAppId() {
-        return mCurrentMaxAppId;
-    }
-
-    /**
-     * @return the next available App ID that has not been added to the map
-     */
-    public int getNextAvailableAppId() {
-        if (mCurrentMaxAppId == 0) {
-            // No app id has been added yet
-            return Process.FIRST_APPLICATION_UID;
-        } else {
-            return mCurrentMaxAppId + 1;
-        }
+    public void registerObserver(Watcher observer) {
+        mNonSystemSettings.registerObserver(observer);
+        mSystemSettings.registerObserver(observer);
     }
 }
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index b307984..89f8be2 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -112,7 +112,9 @@
             String callingFeatureId,
             ComponentName component,
             @UserIdInt int userId,
-            boolean launchMainActivity) throws RemoteException {
+            boolean launchMainActivity,
+            IBinder targetTask,
+            Bundle options) throws RemoteException {
         Objects.requireNonNull(callingPackage);
         Objects.requireNonNull(component);
 
@@ -145,8 +147,12 @@
         if (launchMainActivity) {
             launchIntent.setAction(Intent.ACTION_MAIN);
             launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            if (targetTask == null) {
+                launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            } else {
+                launchIntent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            }
             // Only package name is set here, as opposed to component name, because intent action
             // and category are ignored if component name is present while we are resolving intent.
             launchIntent.setPackage(component.getPackageName());
@@ -170,15 +176,20 @@
         }
         verifyActivityCanHandleIntentAndExported(launchIntent, component, callingUid, userId);
 
+        // Always show the cross profile animation
+        if (options == null) {
+            options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+        } else {
+            options.putAll(ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle());
+        }
+
         launchIntent.setPackage(null);
         launchIntent.setComponent(component);
         mInjector.getActivityTaskManagerInternal().startActivityAsUser(
                 caller, callingPackage, callingFeatureId, launchIntent,
-                /* resultTo= */ null,
-                Intent.FLAG_ACTIVITY_NEW_TASK,
-                launchMainActivity
-                        ? ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle()
-                        : null,
+                targetTask,
+                /* startFlags= */ 0,
+                options,
                 userId);
     }
 
@@ -225,6 +236,13 @@
 
         verifyActivityCanHandleIntent(launchIntent, callingUid, userId);
 
+        // Always show the cross profile animation
+        if (options == null) {
+            options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+        } else {
+            options.putAll(ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle());
+        }
+
         mInjector.getActivityTaskManagerInternal()
                 .startActivityAsUser(
                         caller,
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6ccaae1..698dbe9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -62,7 +62,6 @@
 import android.os.Message;
 import android.os.PatternMatcher;
 import android.os.PersistableBundle;
-import android.os.Process;
 import android.os.SELinux;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -408,8 +407,6 @@
         int[] excludedUserIds;
     }
 
-    private static int mFirstAvailableUid = Process.FIRST_APPLICATION_UID;
-
     /** Map from volume UUID to {@link VersionInfo} */
     @Watched
     private final WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>();
@@ -472,10 +469,8 @@
 
     @Watched
     final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>();
-    @Watched
+    @Watched(manual = true)
     private final AppIdSettingMap mAppIds;
-    @Watched
-    private final AppIdSettingMap mOtherAppIds;
 
     // For reading/writing settings file.
     @Watched
@@ -565,7 +560,6 @@
         mCrossProfileIntentResolvers.registerObserver(mObserver);
         mSharedUsers.registerObserver(mObserver);
         mAppIds.registerObserver(mObserver);
-        mOtherAppIds.registerObserver(mObserver);
         mRenamedPackages.registerObserver(mObserver);
         mNextAppLinkGeneration.registerObserver(mObserver);
         mDefaultBrowserApp.registerObserver(mObserver);
@@ -592,7 +586,6 @@
         mLock = new PackageManagerTracedLock();
         mPackages.putAll(pkgSettings);
         mAppIds = new AppIdSettingMap();
-        mOtherAppIds = new AppIdSettingMap();
         mSystemDir = null;
         mPermissions = null;
         mRuntimePermissionsPersistence = null;
@@ -629,7 +622,6 @@
 
         mLock = lock;
         mAppIds = new AppIdSettingMap();
-        mOtherAppIds = new AppIdSettingMap();
         mPermissions = new LegacyPermissionSettings(lock);
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
                 runtimePermissionsPersistence, new Consumer<Integer>() {
@@ -710,7 +702,6 @@
                 mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
         mSharedUsers.snapshot(r.mSharedUsers);
         mAppIds = r.mAppIds.snapshot();
-        mOtherAppIds = r.mOtherAppIds.snapshot();
         WatchedArrayList.snapshot(
                 mPastSignatures, r.mPastSignatures);
         WatchedArrayMap.snapshot(
@@ -782,7 +773,7 @@
         SharedUserSetting s = mSharedUsers.get(name);
         if (s == null && create) {
             s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
-            s.mAppId = acquireAndRegisterNewAppIdLPw(s);
+            s.mAppId = mAppIds.acquireAndRegisterNewAppId(s);
             if (s.mAppId < 0) {
                 // < 0 means we couldn't assign a userid; throw exception
                 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
@@ -890,7 +881,7 @@
                 pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
                 usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
         p.setAppId(uid);
-        if (registerExistingAppIdLPw(uid, p, name)) {
+        if (mAppIds.registerExistingAppId(uid, p, name)) {
             mPackages.put(name, p);
             return p;
         }
@@ -909,7 +900,7 @@
         }
         s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
         s.mAppId = uid;
-        if (registerExistingAppIdLPw(uid, s, name)) {
+        if (mAppIds.registerExistingAppId(uid, s, name)) {
             mSharedUsers.put(name, s);
             return s;
         }
@@ -1210,11 +1201,11 @@
         final boolean createdNew;
         if (p.getAppId() == 0 || forceNew) {
             // Assign new user ID
-            p.setAppId(acquireAndRegisterNewAppIdLPw(p));
+            p.setAppId(mAppIds.acquireAndRegisterNewAppId(p));
             createdNew = true;
         } else {
             // Add new setting to list of user IDs
-            createdNew = registerExistingAppIdLPw(p.getAppId(), p, p.getPackageName());
+            createdNew = mAppIds.registerExistingAppId(p.getAppId(), p, p.getPackageName());
         }
         if (p.getAppId() < 0) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -1304,11 +1295,11 @@
         Object userIdPs = getSettingLPr(p.getAppId());
         if (sharedUser == null) {
             if (userIdPs != null && userIdPs != p) {
-                replaceAppIdLPw(p.getAppId(), p);
+                mAppIds.replaceSetting(p.getAppId(), p);
             }
         } else {
             if (userIdPs != null && userIdPs != sharedUser) {
-                replaceAppIdLPw(p.getAppId(), sharedUser);
+                mAppIds.replaceSetting(p.getAppId(), sharedUser);
             }
         }
     }
@@ -1357,73 +1348,22 @@
         mInstallerPackages.remove(packageName);
     }
 
-    /** Returns true if the requested AppID was valid and not already registered. */
-    private boolean registerExistingAppIdLPw(int appId, SettingBase obj, Object name) {
-        if (appId > Process.LAST_APPLICATION_UID) {
-            return false;
-        }
-
-        if (appId >= Process.FIRST_APPLICATION_UID) {
-            if (mAppIds.get(appId) != null) {
-                PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "Adding duplicate app id: " + appId
-                        + " name=" + name);
-                return false;
-            }
-            mAppIds.put(appId, obj);
-        } else {
-            if (mOtherAppIds.get(appId) != null) {
-                PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "Adding duplicate shared id: " + appId
-                                + " name=" + name);
-                return false;
-            }
-            mOtherAppIds.put(appId, obj);
-        }
-        return true;
-    }
-
     /** Gets the setting associated with the provided App ID */
     public SettingBase getSettingLPr(int appId) {
-        if (appId >= Process.FIRST_APPLICATION_UID) {
-            return mAppIds.get(appId);
-        } else {
-            return mOtherAppIds.get(appId);
-        }
+        return mAppIds.getSetting(appId);
     }
 
     /** Unregisters the provided app ID. */
     void removeAppIdLPw(int appId) {
-        if (appId >= Process.FIRST_APPLICATION_UID) {
-            mAppIds.remove(appId);
-        } else {
-            mOtherAppIds.remove(appId);
-        }
-        setFirstAvailableUid(appId + 1);
+        mAppIds.removeSetting(appId);
     }
-
-    private void replaceAppIdLPw(int appId, SettingBase obj) {
-        if (appId >= Process.FIRST_APPLICATION_UID) {
-            if (appId <= mAppIds.getCurrentMaxAppId()) {
-                mAppIds.put(appId, obj);
-            } else {
-                PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "Error in package manager settings: calling replaceAppIdLpw to"
-                                + " replace SettingBase at appId=" + appId
-                                + " but nothing is replaced.");
-            }
-        } else {
-            mOtherAppIds.put(appId, obj);
-        }
-    }
-
     /**
      * Transparently convert a SharedUserSetting into PackageSettings without changing appId.
      * The sharedUser passed to this method has to be {@link SharedUserSetting#isSingleUser()}.
      */
     void convertSharedUserSettingsLPw(SharedUserSetting sharedUser) {
         final PackageSetting ps = sharedUser.getPackageSettings().valueAt(0);
-        replaceAppIdLPw(sharedUser.getAppId(), ps);
+        mAppIds.replaceSetting(sharedUser.getAppId(), ps);
 
         // Unlink the SharedUserSetting
         ps.setSharedUserAppId(INVALID_UID);
@@ -4287,32 +4227,6 @@
         }
     }
 
-    // This should be called (at least) whenever an application is removed
-    private void setFirstAvailableUid(int uid) {
-        if (uid > mFirstAvailableUid) {
-            mFirstAvailableUid = uid;
-        }
-    }
-
-    /** Returns a new AppID or -1 if we could not find an available AppID to assign */
-    private int acquireAndRegisterNewAppIdLPw(SettingBase obj) {
-        final int nextAvailableAppId = mAppIds.getNextAvailableAppId();
-        for (int uid = mFirstAvailableUid; uid < nextAvailableAppId; uid++) {
-            if (mAppIds.get(uid) == null) {
-                mAppIds.put(uid, obj);
-                return uid;
-            }
-        }
-
-        // None left?
-        if (nextAvailableAppId > Process.LAST_APPLICATION_UID) {
-            return -1;
-        }
-
-        mAppIds.put(nextAvailableAppId, obj);
-        return nextAvailableAppId;
-    }
-
     public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) {
         if (mVerifierDeviceIdentity == null) {
             mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1cf2dc5..25fe000 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -488,7 +488,8 @@
         mShortcutBitmapSaver = new ShortcutBitmapSaver(this);
         mShortcutDumpFiles = new ShortcutDumpFiles(this);
         mIsAppSearchEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true);
+                SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true)
+                && !injectIsLowRamDevice();
 
         if (onlyForPackageManagerApis) {
             return; // Don't do anything further.  For unit tests only.
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 88a298a..9c74dd7 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -52,9 +52,6 @@
       "options": [
         {
           "include-filter": "com.google.android.security.gts.PackageVerifierTest"
-        },
-        {
-          "exclude-filter": "com.google.android.security.gts.PackageVerifierTest#testAdbInstall_timeout_allowed"
         }
       ]
     },
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index eae7658..34b7ad4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4638,12 +4638,12 @@
             final String restriction = getUserRemovalRestriction(userId);
             if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
                 Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
-                return UserManager.REMOVE_RESULT_ERROR;
+                return UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION;
             }
         }
         if (userId == UserHandle.USER_SYSTEM) {
             Slog.e(LOG_TAG, "System user cannot be removed.");
-            return UserManager.REMOVE_RESULT_ERROR;
+            return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER;
         }
 
         final long ident = Binder.clearCallingIdentity();
@@ -4655,7 +4655,7 @@
                     if (userData == null) {
                         Slog.e(LOG_TAG,
                                 "Cannot remove user " + userId + ", invalid user id provided.");
-                        return UserManager.REMOVE_RESULT_ERROR;
+                        return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
                     }
 
                     if (mRemovingUserIds.get(userId)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e79148d..dc5b325 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -792,7 +792,7 @@
         public void onWakeUp() {
             synchronized (mLock) {
                 if (shouldEnableWakeGestureLp()
-                        && mBatteryManagerInternal.getPlugType() != BATTERY_PLUGGED_WIRELESS) {
+                        && getBatteryManagerInternal().getPlugType() != BATTERY_PLUGGED_WIRELESS) {
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
                             "Wake Up");
                     wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java
index 990b21c..1cc0539 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHalConcurrentCaptureHandler.java
@@ -20,6 +20,7 @@
 import android.media.permission.SafeCloseable;
 import android.media.soundtrigger.ModelParameterRange;
 import android.media.soundtrigger.PhraseRecognitionEvent;
+import android.media.soundtrigger.PhraseRecognitionExtra;
 import android.media.soundtrigger.PhraseSoundModel;
 import android.media.soundtrigger.Properties;
 import android.media.soundtrigger.RecognitionConfig;
@@ -392,7 +393,7 @@
     private static void notifyAbort(int modelHandle, LoadedModel model) {
         switch (model.type) {
             case SoundModelType.GENERIC: {
-                RecognitionEvent event = new RecognitionEvent();
+                RecognitionEvent event = newEmptyRecognitionEvent();
                 event.status = RecognitionStatus.ABORTED;
                 event.type = SoundModelType.GENERIC;
                 model.callback.recognitionCallback(modelHandle, event);
@@ -400,7 +401,7 @@
             break;
 
             case SoundModelType.KEYPHRASE: {
-                PhraseRecognitionEvent event = new PhraseRecognitionEvent();
+                PhraseRecognitionEvent event = newEmptyPhraseRecognitionEvent();
                 event.common.status = RecognitionStatus.ABORTED;
                 event.common.type = SoundModelType.KEYPHRASE;
                 model.callback.phraseRecognitionCallback(modelHandle, event);
@@ -415,6 +416,19 @@
         mNotifier.unregisterListener(this);
     }
 
+    private static PhraseRecognitionEvent newEmptyPhraseRecognitionEvent() {
+        PhraseRecognitionEvent result = new PhraseRecognitionEvent();
+        result.common = newEmptyRecognitionEvent();
+        result.phraseExtras = new PhraseRecognitionExtra[0];
+        return result;
+    }
+
+    private static RecognitionEvent newEmptyRecognitionEvent() {
+        RecognitionEvent result = new RecognitionEvent();
+        result.data = new byte[0];
+        return result;
+    }
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // All methods below do trivial delegation - no interesting logic.
     @Override
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a8dd856..c0cdec9 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -657,7 +657,7 @@
         for (int i = mTransitionInfoList.size() - 2; i >= 0; i--) {
             final TransitionInfo prevInfo = mTransitionInfoList.get(i);
             if (prevInfo.mIsDrawn || !prevInfo.mLastLaunchedActivity.mVisibleRequested) {
-                abort(prevInfo, "nothing will be drawn");
+                scheduleCheckActivityToBeDrawn(prevInfo.mLastLaunchedActivity, 0 /* delay */);
             }
         }
     }
@@ -757,6 +757,10 @@
     /** Makes sure that the reference to the removed activity is cleared. */
     void notifyActivityRemoved(@NonNull ActivityRecord r) {
         mLastTransitionInfo.remove(r);
+        final TransitionInfo info = getActiveTransitionInfo(r);
+        if (info != null) {
+            abort(info, "removed");
+        }
 
         final int packageUid = r.info.applicationInfo.uid;
         final PackageCompatStateInfo compatStateInfo = mPackageUidToCompatStateInfo.get(packageUid);
diff --git a/services/core/java/com/android/server/wm/BLASTSync.md b/services/core/java/com/android/server/wm/BLASTSync.md
new file mode 100644
index 0000000..2f39d6d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BLASTSync.md
@@ -0,0 +1,108 @@
+= What does it mean for BLAST Sync to work? =
+There are two BLAST sync primitives on the server side, BLASTSyncEngine and applyWithNextDraw.
+Both of them are used to solve subclasses of this category of problem:
+ 1. You have some server side changes, which will trigger both WM/SysUI initiated SurfaceControl.Transactions, 
+    and also trigger a client redraw/update
+ 2. You want to synchronize the redraw of those clients with the application of those WM/SysUI side changes.
+
+Put simply, you would like to synchronize the graphical effects of some WM changes with the graphical output of various windows
+observing those changes.
+
+To talk about exactly what the primitives guarantee, we need to clarify what we mean by server side changes. 
+In this document we will use a term syncable state to refer to any state mutated under the WindowManager lock
+which when observed by the client, produces a visible outcome in the produced frame. 
+For example the current Configuration. 
+
+The guarantee provided by Server-side BLAST Sync Primitives is thus:
+Guarantee 1:	If you make a set of changes to syncable state, at the same time that you begin a sync, 
+then the first frame drawn by the client after observing the syncable state will be sent in a transaction
+to the consumer of the sync which was begun, rather than directly sent to SurfaceFlinger.
+
+Here "at the same time" means in the same critical section (while holding the WM lock)
+For example this guarantee means that you can write code like:
+	window.performConfigurationChange(someConfiguration)
+	window.applyOnNextDraw(consumer)
+And the consumer will always be passed the first frame containing the configuration change. This can work with any 
+syncable state not just Configuration.
+
+The following is the protocol and additional requirements for BLAST sync, and an analysis of why it is correct. Due to time
+constraints we analyze it for a single window only (as this is actually the hard part).
+
+Protocol requirements:
+    Server protocol, precondition, begin a syncSeqId integer per window at 0:
+        SA: Enter the critical section
+        SB: Change syncable state, any number of times, prepare any number of syncs (and
+            increment the seqId if a sync was prepared, assosciate it with the sync)
+        SC: Leave the critical section
+        SD: Send syncable state updates to the client, always paired with the current seqId
+        SE: When the client calls finishDrawing, execute the consumer for each sync with
+            seqId <= the seqId which the client passed to finishDrawing
+    Client protocol:
+        CA: Observe state and seqid changes up until a fixed frame deadline, then execute performTraversals
+        CB: If the seqId is incremeneted at the time of the frame deadline, configure the renderer to
+            redirect the next draw in to a transaction, record the seqId at the time
+        CC: When the draw is finished, send the transaction containing the draw to WM with the
+            previously recorded seqId
+    Additional requirements/assumptions:
+        1. The server may only send changes to the syncable state paired with the seqId. The client may
+           only receive them together (e.g. not from other sources)
+        2. In between changing and sending syncable state, the lock must be released and acquired again
+        3. The client wont draw a frame reflecting syncable state changes without passing through "performTraversals"
+        4. Drawing never fails
+        5. There are no blocking calls between the client or the server
+            
+Note that the server can begin the protocol at any time, so it may be possible for the client to proceed through
+phases SA, SB, SC, and SD multiple times before the client receives any messages.
+
+To show that the guarantee can't be violated, we use a notation of sequences, where we describe interleaving
+of protocol events. For duplicate events, we attach a number, e.g. SA_1, SA_2.
+
+We proceed by contradiction, imagine there was some sequence (..., SA_N, ...) for which the guarantee was
+not upheld. This means that either
+    1. finishDrawing with the assosciate seqId was never sent to the server OR
+    2. It was sent too late (after the first frame was sent to SF instead of WM) OR
+    3. It was sent too early (not containing the state changes originating with SA_N)
+If it was sent neither too late, nor too early, and contained the assosciated seqId, then protocol step SE
+says that the frame will be passed to the consumer and we uphold our guarantee.
+
+The first case is impossible because step SD says that the server always sends the seqId if a sync was prepared.
+If we send it the client must receive it. Since we only increment the seqId, and the client only takes the
+seqId from us (requirement 1, protocol step SB), the received ID must be higher than the clients previous seqId.
+CA says that performTraversals will execute, and CB says that when it does, if the seqId is higher than before
+it will schedule the render to sync. Requirement 4 says drawing never fails, so CC must execute, and so we will always
+eventually send every seqId (or a seqId > than it) back to the server.
+
+It also can't be sent too late. By requirement 2 we must release and acquire the lock
+after after changing and before emitting syncable state changes. This means it's guaranteed
+that even in an ordering like AcquireLock, ChangeState, PrepareSync, Release lock we can't
+send the state changes before prepareSync, and so they can always include at least the seqId
+assosciated with changestate (or a later one).
+Since we only receive the SeqId with the State changes (requirement 1),
+and we wont draw state changes without passing through perform traversals (requirement 3) the first frame
+containing the state change must have been generated by a call to performTraversals which also observed
+the seqId change, and so it will appropriately configure the renderer.
+
+By the same argument it can't be sent too early! Since we only send seqIds we receive from the server, 
+and we only send seqIds after completing a drawing pass of the assosciated state.
+
+So we can see that no matter at what time the server makes syncable state changes, the first frame will
+always be delivered to the draw handler. Assuming that the client and server uphold this protocol and these
+requirements.
+
+The trickiest part of the implementation at the moment is due to assosciating seqId. Currently we send one of the most
+most important pieces of syncable state (configuration) over multiple channels. Namely ClientTransaction
+and MSG_RESIZED. The ordering of these relative to sync preparation in server code is undefined, in fact we have cases like
+this all the time:
+    acquireLock()
+    changeConfiguration()
+    // time passes, but still in critical section
+    prepareSync()
+    releaseLock()
+This is exactly the kind of case Guarantee 1 mentions as an example. In previous incarnations of the code this worked
+because relayoutWindow needed to acquire the same lock and relayoutWindow was a necessary part of completing sync.
+
+Now that we have no barrier, that could create issues, because at the time we change configuration (and send the change
+to the client via ClientTransaction), we haven't even incremented the seqId yet, and so how can the client observe it
+at the same time as the state? We solve this by pushing all client communication through a handler thread that has to
+acquire the lock. This ensures we uphold requirement 2.
+    
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 23f14a7..dbc0141 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -25,6 +25,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
+import android.os.Bundle;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemProperties;
@@ -44,7 +45,11 @@
 class BackNavigationController {
 
     private static final String TAG = "BackNavigationController";
-    private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
+    // By default, enable new back dispatching without any animations.
+    private static final int BACK_PREDICTABILITY_PROP =
+            SystemProperties.getInt("persist.debug.back_predictability", 1);
+    private static final int ANIMATIONS_MASK = 1 << 1;
+    private static final int SCREENSHOT_MASK = 1 << 2;
 
     @Nullable
     private TaskSnapshotController mTaskSnapshotController;
@@ -53,11 +58,15 @@
      * Returns true if the back predictability feature is enabled
      */
     static boolean isEnabled() {
-        return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+        return BACK_PREDICTABILITY_PROP > 0;
     }
 
     static boolean isScreenshotEnabled() {
-        return false;
+        return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0;
+    }
+
+    private static boolean isAnimationEnabled() {
+        return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0;
     }
 
     /**
@@ -93,14 +102,17 @@
         ActivityRecord prev;
         WindowContainer<?> removedWindowContainer;
         ActivityRecord activityRecord;
+        ActivityRecord prevTaskTopActivity = null;
         SurfaceControl animationLeashParent;
         WindowConfiguration taskWindowConfiguration;
         HardwareBuffer screenshotBuffer = null;
+        SurfaceControl screenshotSurface;
         int prevTaskId;
         int prevUserId;
         RemoteAnimationTarget topAppTarget;
         SurfaceControl animLeash;
-        IOnBackInvokedCallback callback = null;
+        IOnBackInvokedCallback applicationCallback = null;
+        IOnBackInvokedCallback systemCallback = null;
 
         synchronized (task.mWmService.mGlobalLock) {
 
@@ -116,15 +128,14 @@
                 removedWindowContainer = activityRecord;
                 taskWindowConfiguration = window.getWindowConfiguration();
             }
-            IOnBackInvokedCallback applicationCallback = null;
-            IOnBackInvokedCallback systemCallback = null;
             if (window != null) {
                 applicationCallback = window.getApplicationOnBackInvokedCallback();
-                callback = applicationCallback;
-                if (callback == null) {
-                    systemCallback = window.getSystemOnBackInvokedCallback();
-                    callback = systemCallback;
-                }
+                systemCallback = window.getSystemOnBackInvokedCallback();
+            }
+            if (applicationCallback == null && systemCallback == null) {
+                // Return null when either there's no window, or apps have just initialized and
+                // have not finished registering callbacks.
+                return null;
             }
 
             ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, "
@@ -133,24 +144,24 @@
                     task, activityRecord, applicationCallback, systemCallback);
 
             // TODO Temp workaround for Sysui until b/221071505 is fixed
-            if (activityRecord == null && callback != null) {
+            if (activityRecord == null && applicationCallback != null) {
                 return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
                         null /* topWindowLeash */, null /* screenshotSurface */,
                         null /* screenshotBuffer */, null /* taskWindowConfiguration */,
                         null /* onBackNavigationDone */,
-                        callback /* onBackInvokedCallback */);
+                        applicationCallback /* onBackInvokedCallback */);
             }
 
             // For IME and Home, either a callback is registered, or we do nothing. In both cases,
             // we don't need to pass the leashes below.
             if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible()
                     || activityRecord.isActivityTypeHome()) {
-                if (callback != null) {
+                if (applicationCallback != null) {
                     return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
                             null /* topWindowLeash */, null /* screenshotSurface */,
                             null /* screenshotBuffer */, null /* taskWindowConfiguration */,
                             null /* onBackNavigationDone */,
-                            callback /* onBackInvokedCallback */);
+                            applicationCallback /* onBackInvokedCallback */);
                 } else {
                     return null;
                 }
@@ -159,12 +170,12 @@
             prev = task.getActivity(
                     (r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity());
 
-            if (callback != null) {
+            if (applicationCallback != null) {
                 return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
                         null /* topWindowLeash */, null /* screenshotSurface */,
                         null /* screenshotBuffer */, null /* taskWindowConfiguration */,
                         null /* onBackNavigationDone */,
-                        callback /* onBackInvokedCallback */);
+                        applicationCallback /* onBackInvokedCallback */);
             } else if (prev != null) {
                 backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
             } else if (task.returnsToHomeRootTask()) {
@@ -188,8 +199,8 @@
             prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
             prevUserId = prevTask != null ? prevTask.mUserId : 0;
 
-            ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s",
-                    prev != null ? prev.mActivityComponent : null);
+            ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. "
+                    + "Back type is %s", prev != null ? prev.mActivityComponent : null, backType);
 
             //TODO(207481538) Remove once the infrastructure to support per-activity screenshot is
             // implemented. For now we simply have the mBackScreenshots hash map that dumbly
@@ -204,6 +215,7 @@
                 return null;
             }
             // Prepare a leash to animate the current top window
+            // TODO(b/220934562): Use surface animator to better manage animation conflicts.
             animLeash = removedWindowContainer.makeAnimationLeash()
                     .setName("BackPreview Leash for " + removedWindowContainer)
                     .setHidden(false)
@@ -231,12 +243,30 @@
                     activityRecord.windowType);
         }
 
-        SurfaceControl.Builder builder = new SurfaceControl.Builder()
+        screenshotSurface = new SurfaceControl.Builder()
                 .setName("BackPreview Screenshot for " + prev)
                 .setParent(animationLeashParent)
                 .setHidden(false)
-                .setBLASTLayer();
-        SurfaceControl screenshotSurface = builder.build();
+                .setBLASTLayer()
+                .build();
+        if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) {
+            task.mBackGestureStarted = true;
+            // Make launcher show from behind by marking its top activity as visible and
+            // launch-behind to bump its visibility for the duration of the back gesture.
+            prevTaskTopActivity = prevTask.getTopNonFinishingActivity();
+            if (prevTaskTopActivity != null) {
+                if (!prevTaskTopActivity.mVisibleRequested) {
+                    prevTaskTopActivity.setVisibility(true);
+                }
+                prevTaskTopActivity.mLaunchTaskBehind = true;
+                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                        "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+                        prevTaskTopActivity);
+                prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible(
+                        null /* starting */, 0 /* configChanges */,
+                        false /* preserveWindows */);
+            }
+        }
 
         // Find a screenshot of the previous activity
 
@@ -253,17 +283,20 @@
 
         WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
         try {
-            activityRecord.token.linkToDeath(
-                    () -> resetSurfaces(finalRemovedWindowContainer), 0);
+            activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0);
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to link to death", e);
             resetSurfaces(removedWindowContainer);
             return null;
         }
 
-        RemoteCallback onBackNavigationDone = new RemoteCallback(
-                result -> resetSurfaces(finalRemovedWindowContainer
-                ));
+        int finalBackType = backType;
+        final IOnBackInvokedCallback callback =
+                applicationCallback != null ? applicationCallback : systemCallback;
+        ActivityRecord finalPrevTaskTopActivity = prevTaskTopActivity;
+        RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
+                result, finalRemovedWindowContainer, finalBackType, task,
+                finalPrevTaskTopActivity));
         return new BackNavigationInfo(backType,
                 topAppTarget,
                 screenshotSurface,
@@ -273,6 +306,39 @@
                 callback);
     }
 
+    private void onBackNavigationDone(
+            Bundle result, WindowContainer windowContainer, int backType,
+            Task task, ActivityRecord prevTaskTopActivity) {
+        SurfaceControl surfaceControl = windowContainer.getSurfaceControl();
+        boolean triggerBack = result != null
+                ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK)
+                : false;
+        ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+                + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity);
+
+        if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) {
+            if (triggerBack) {
+                if (surfaceControl != null && surfaceControl.isValid()) {
+                    // When going back to home, hide the task surface before it is re-parented to
+                    // avoid flicker.
+                    SurfaceControl.Transaction t = windowContainer.getSyncTransaction();
+                    t.hide(surfaceControl);
+                    t.apply();
+                }
+            }
+            if (prevTaskTopActivity != null && !triggerBack) {
+                // Restore the launch-behind state.
+                task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token);
+                prevTaskTopActivity.mLaunchTaskBehind = false;
+                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                        "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+                        prevTaskTopActivity);
+            }
+        } else {
+            task.mBackGestureStarted = false;
+        }
+        resetSurfaces(windowContainer);
+    }
 
     private HardwareBuffer getActivitySnapshot(@NonNull Task task,
             ComponentName activityComponent) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 59ba4e7..73673202 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -145,7 +145,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
 import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
-import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
@@ -4504,56 +4503,38 @@
 
         mTmpUpdateAllDrawn.clear();
 
-        int repeats = 0;
-        do {
-            repeats++;
-            if (repeats > 6) {
-                Slog.w(TAG, "Animation repeat aborted after too many iterations");
-                clearLayoutNeeded();
-                break;
-            }
+        if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
+                pendingLayoutChanges);
 
-            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
-                    pendingLayoutChanges);
+        if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+            mWallpaperController.adjustWallpaperWindows();
+        }
 
-            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                mWallpaperController.adjustWallpaperWindows();
-            }
-
-            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
-                if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                if (updateOrientation()) {
-                    setLayoutNeeded();
-                    sendNewConfiguration();
-                }
-            }
-
-            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+        if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
+            if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
+            if (updateOrientation()) {
                 setLayoutNeeded();
+                sendNewConfiguration();
             }
+        }
 
-            // FIRST LOOP: Perform a layout, if needed.
-            if (repeats < LAYOUT_REPEAT_THRESHOLD) {
-                performLayout(repeats == 1, false /* updateInputWindows */);
-            } else {
-                Slog.w(TAG, "Layout repeat skipped after too many iterations");
-            }
+        if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+            setLayoutNeeded();
+        }
 
-            // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
-            pendingLayoutChanges = 0;
+        // Perform a layout, if needed.
+        performLayout(true /* initial */, false /* updateInputWindows */);
+        pendingLayoutChanges = 0;
 
-            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
-            try {
-                mDisplayPolicy.beginPostLayoutPolicyLw();
-                forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
-                pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
-            } finally {
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-            }
-            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
-                    "after finishPostLayoutPolicyLw", pendingLayoutChanges);
-            mInsetsStateController.onPostLayout();
-        } while (pendingLayoutChanges != 0);
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
+        try {
+            mDisplayPolicy.beginPostLayoutPolicyLw();
+            forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
+            mDisplayPolicy.finishPostLayoutPolicyLw();
+        } finally {
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+        }
+        mInsetsStateController.onPostLayout();
 
         mTmpApplySurfaceChangesTransactionState.reset();
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4148d8b..bb5dacc 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -42,11 +42,9 @@
 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -79,7 +77,6 @@
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
 import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
 import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
@@ -136,6 +133,7 @@
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants;
 import android.view.accessibility.AccessibilityManager;
+import android.window.ClientWindowFrames;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -340,15 +338,12 @@
     private static final Rect sTmpRect2 = new Rect();
     private static final Rect sTmpLastParentFrame = new Rect();
     private static final Rect sTmpDisplayCutoutSafe = new Rect();
-    private static final Rect sTmpDisplayFrame = new Rect();
-    private static final Rect sTmpParentFrame = new Rect();
-    private static final Rect sTmpFrame = new Rect();
+    private static final ClientWindowFrames sTmpClientFrames = new ClientWindowFrames();
 
     private final WindowLayout mWindowLayout = new WindowLayout();
 
     private WindowState mTopFullscreenOpaqueWindowState;
     private boolean mTopIsFullscreen;
-    private boolean mForceStatusBar;
     private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
     private boolean mForceShowSystemBars;
 
@@ -940,6 +935,26 @@
                 break;
         }
 
+        if (LayoutParams.isSystemAlertWindowType(attrs.type)) {
+            float maxOpacity = mService.mMaximumObscuringOpacityForTouch;
+            if (attrs.alpha > maxOpacity
+                    && (attrs.flags & FLAG_NOT_TOUCHABLE) != 0
+                    && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) {
+                // The app is posting a SAW with the intent of letting touches pass through, but
+                // they are going to be deemed untrusted and will be blocked. Try to honor the
+                // intent of letting touches pass through at the cost of 0.2 opacity for app
+                // compatibility reasons. More details on b/218777508.
+                Slog.w(TAG, String.format(
+                        "App %s has a system alert window (type = %d) with FLAG_NOT_TOUCHABLE and "
+                                + "LayoutParams.alpha = %.2f > %.2f, setting alpha to %.2f to "
+                                + "let touches pass through (if this is isn't desirable, remove "
+                                + "flag FLAG_NOT_TOUCHABLE).",
+                        attrs.packageName, attrs.type, attrs.alpha, maxOpacity, maxOpacity));
+                attrs.alpha = maxOpacity;
+                win.mWinAnimator.mAlpha = maxOpacity;
+            }
+        }
+
         // Check if alternate bars positions were updated.
         if (mStatusBarAlt == win) {
             mStatusBarAltPosition = getAltBarPosition(attrs);
@@ -1474,8 +1489,8 @@
                     displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH,
                     UNSPECIFIED_LENGTH, win.getRequestedVisibilities(),
                     null /* attachedWindowFrame */, win.mGlobalScale,
-                    sTmpDisplayFrame, sTmpParentFrame, sTmpFrame);
-            controller.computeSimulatedState(win, displayFrames, sTmpFrame);
+                    sTmpClientFrames);
+            controller.computeSimulatedState(win, displayFrames, sTmpClientFrames.frame);
         }
     }
 
@@ -1518,12 +1533,12 @@
 
         sTmpLastParentFrame.set(pf);
 
-        final boolean clippedByDisplayCutout = mWindowLayout.computeFrames(attrs,
-                win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
+        mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe,
                 win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,
                 win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,
-                df, pf, f);
-        windowFrames.setParentFrameWasClippedByDisplayCutout(clippedByDisplayCutout);
+                sTmpClientFrames);
+        windowFrames.setParentFrameWasClippedByDisplayCutout(
+                sTmpClientFrames.isParentFrameClippedByDisplayCutout);
 
         if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
                 + ": sim=#" + Integer.toHexString(attrs.softInputMode)
@@ -1536,7 +1551,7 @@
             windowFrames.setContentChanged(true);
         }
 
-        win.setFrame();
+        win.setFrames(sTmpClientFrames);
     }
 
     WindowState getTopFullscreenOpaqueWindow() {
@@ -1558,7 +1573,6 @@
         mStatusBarBackgroundWindows.clear();
         mStatusBarColorCheckedBounds.setEmpty();
         mStatusBarBackgroundCheckedBounds.setEmpty();
-        mForceStatusBar = false;
 
         mAllowLockscreenWhenOn = false;
         mShowingDream = false;
@@ -1599,9 +1613,6 @@
                 && attrs.type < FIRST_SYSTEM_WINDOW;
         if (mTopFullscreenOpaqueWindowState == null) {
             final int fl = attrs.flags;
-            if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
-                mForceStatusBar = true;
-            }
             if (win.isDreamWindow()) {
                 // If the lockscreen was showing when the dream started then wait
                 // for the dream to draw before hiding the lockscreen.
@@ -1710,21 +1721,9 @@
     }
 
     /**
-     * Called following layout of all windows and after policy has been applied
-     * to each window. If in this function you do
-     * something that may have modified the animation state of another window,
-     * be sure to return non-zero in order to perform another pass through layout.
-     *
-     * @return Return any bit set of
-     *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
-     *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
-     *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER}, or
-     *         {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
+     * Called following layout of all windows and after policy has been applied to each window.
      */
-    public int finishPostLayoutPolicyLw() {
-        int changes = 0;
-        boolean topIsFullscreen = false;
-
+    public void finishPostLayoutPolicyLw() {
         // If we are not currently showing a dream then remember the current
         // lockscreen state.  We will use this to determine whether the dream
         // started while the lockscreen was showing and remember this state
@@ -1733,41 +1732,6 @@
             mDreamingLockscreen = mService.mPolicy.isKeyguardShowingAndNotOccluded();
         }
 
-        if (getStatusBar() != null) {
-            if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar
-                    + " top=" + mTopFullscreenOpaqueWindowState);
-            final boolean forceShowStatusBar = (getStatusBar().getAttrs().privateFlags
-                    & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
-
-            boolean topAppHidesStatusBar = topAppHidesStatusBar();
-            if (mForceStatusBar || forceShowStatusBar) {
-                if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
-                // Maintain fullscreen layout until incoming animation is complete.
-                topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
-            } else if (mTopFullscreenOpaqueWindowState != null) {
-                topIsFullscreen = topAppHidesStatusBar;
-                // The subtle difference between the window for mTopFullscreenOpaqueWindowState
-                // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window
-                // requests to hide the status bar.  Not sure if there is another way that to be the
-                // case though.
-                if (!topIsFullscreen) {
-                    topAppHidesStatusBar = false;
-                }
-            }
-            StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
-            if (statusBar != null) {
-                statusBar.setTopAppHidesStatusBar(topAppHidesStatusBar);
-            }
-        }
-
-        if (mTopIsFullscreen != topIsFullscreen) {
-            if (!topIsFullscreen) {
-                // Force another layout when status bar becomes fully shown.
-                changes |= FINISH_LAYOUT_REDO_LAYOUT;
-            }
-            mTopIsFullscreen = topIsFullscreen;
-        }
-
         updateSystemBarAttributes();
 
         if (mShowingDream != mLastShowingDream) {
@@ -1777,7 +1741,6 @@
         }
 
         mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
-        return changes;
     }
 
     /**
@@ -2441,6 +2404,18 @@
         mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible;
         mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
 
+        final boolean topAppHidesStatusBar = topAppHidesStatusBar();
+        if (getStatusBar() != null) {
+            final StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
+            if (statusBar != null) {
+                statusBar.setTopAppHidesStatusBar(topAppHidesStatusBar);
+            }
+        }
+
+        // If the top app is not fullscreen, only the default rotation animation is allowed.
+        mTopIsFullscreen = topAppHidesStatusBar
+                && (mNotificationShade == null || !mNotificationShade.isVisible());
+
         int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
         appearance = configureStatusBarOpacity(appearance);
         appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible,
@@ -2781,7 +2756,6 @@
             }
         }
         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
-        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
         pw.print(prefix); pw.print("mForceShowNavigationBarEnabled=");
         pw.print(mForceShowNavigationBarEnabled);
         pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 0c609191..9ad25ac8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -232,14 +232,14 @@
             int requestedWidth, int requestedHeight, int viewFlags, int flags,
             ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            InsetsSourceControl[] outActiveControls) {
+            InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
         int res = mService.relayoutWindow(this, window, attrs,
                 requestedWidth, requestedHeight, viewFlags, flags,
                 outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
-                outActiveControls);
+                outActiveControls, outSyncSeqIdBundle);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
@@ -265,9 +265,9 @@
 
     @Override
     public void finishDrawing(IWindow window,
-            @Nullable SurfaceControl.Transaction postDrawTransaction) {
+            @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
         if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
-        mService.finishDrawingWindow(this, window, postDrawTransaction);
+        mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cd7ebe3..f71bd72 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -72,6 +72,7 @@
 import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
 import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -609,6 +610,12 @@
 
     boolean mLastSurfaceShowing = true;
 
+    /**
+     * Tracks if a back gesture is in progress.
+     * Skips any system transition animations if this is set to {@code true}.
+     */
+    boolean mBackGestureStarted = false;
+
     private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
             Intent _affinityIntent, String _affinity, String _rootAffinity,
             ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
@@ -1623,12 +1630,16 @@
     }
 
     ActivityRecord performClearTop(ActivityRecord newR, int launchFlags) {
+        // The task should be preserved for putting new activity in case the last activity is
+        // finished if it is normal launch mode and not single top ("clear-task-top").
+        mReuseTask = true;
         mTaskSupervisor.beginDeferResume();
         final ActivityRecord result;
         try {
             result = clearTopActivities(newR, launchFlags);
         } finally {
             mTaskSupervisor.endDeferResume();
+            mReuseTask = false;
         }
         return result;
     }
@@ -3322,6 +3333,14 @@
                     }
                 });
             }
+        } else if (mBackGestureStarted) {
+            // Cancel playing transitions if a back navigation animation is in progress.
+            // This bit is set by {@link BackNavigationController} when a back gesture is started.
+            // It is used as a one-off transition overwrite that is cleared when the back gesture
+            // is committed and triggers a transition, or when the gesture is cancelled.
+            mBackGestureStarted = false;
+            mDisplayContent.mSkipAppTransitionAnimation = true;
+            ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this);
         } else {
             super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6718235..d5f7a22 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -745,6 +745,9 @@
 
     private final DisplayHashController mDisplayHashController;
 
+    volatile float mMaximumObscuringOpacityForTouch =
+            InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH;
+
     @VisibleForTesting
     final WindowContextListenerController mWindowContextListenerController =
             new WindowContextListenerController();
@@ -782,6 +785,8 @@
                 DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
         private final Uri mDisplaySettingsPathUri = Settings.Global.getUriFor(
                 DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
+        private final Uri mMaximumObscuringOpacityForTouchUri = Settings.Global.getUriFor(
+                Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
 
         public SettingsObserver() {
             super(new Handler());
@@ -806,6 +811,8 @@
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(mDisplaySettingsPathUri, false, this,
                     UserHandle.USER_ALL);
+            resolver.registerContentObserver(mMaximumObscuringOpacityForTouchUri, false, this,
+                    UserHandle.USER_ALL);
         }
 
         @Override
@@ -849,6 +856,11 @@
                 return;
             }
 
+            if (mMaximumObscuringOpacityForTouchUri.equals(uri)) {
+                updateMaximumObscuringOpacityForTouch();
+                return;
+            }
+
             @UpdateAnimationScaleMode
             final int mode;
             if (mWindowAnimationScaleUri.equals(uri)) {
@@ -868,6 +880,14 @@
         void loadSettings() {
             updateSystemUiSettings(false /* handleChange */);
             updatePointerLocation();
+            updateMaximumObscuringOpacityForTouch();
+        }
+
+        void updateMaximumObscuringOpacityForTouch() {
+            ContentResolver resolver = mContext.getContentResolver();
+            mMaximumObscuringOpacityForTouch = Settings.Global.getFloat(resolver,
+                    Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
+                    InputManager.DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
         }
 
         void updateSystemUiSettings(boolean handleChange) {
@@ -2192,7 +2212,7 @@
             int requestedWidth, int requestedHeight, int viewVisibility, int flags,
             ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            InsetsSourceControl[] outActiveControls) {
+            InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
         Arrays.fill(outActiveControls, null);
         int result = 0;
         boolean configChanged;
@@ -2617,7 +2637,7 @@
     }
 
     void finishDrawingWindow(Session session, IWindow client,
-            @Nullable SurfaceControl.Transaction postDrawTransaction) {
+            @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
         if (postDrawTransaction != null) {
             postDrawTransaction.sanitize();
         }
@@ -2628,7 +2648,7 @@
                 WindowState win = windowForClientLocked(session, client, false);
                 ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
                         win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
-                if (win != null && win.finishDrawing(postDrawTransaction)) {
+                if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
                     if (win.hasWallpaper()) {
                         win.getDisplayContent().pendingLayoutChanges |=
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index db687f6..f667392 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1393,13 +1393,13 @@
     }
 
     // TODO(b/161810301): Make the frame be passed from the client side.
-    void setFrame() {
-        // TODO(b/161810301): Set the window frame here. We don't have to do it now because
-        //                    DisplayPolicy has already done it for the window.
-
+    void setFrames(ClientWindowFrames clientWindowFrames) {
         mHaveFrame = true;
 
         final WindowFrames windowFrames = mWindowFrames;
+        windowFrames.mDisplayFrame.set(clientWindowFrames.displayFrame);
+        windowFrames.mParentFrame.set(clientWindowFrames.parentFrame);
+        windowFrames.mFrame.set(clientWindowFrames.frame);
 
         if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
             mLastRequestedWidth = mRequestedWidth;
@@ -3946,7 +3946,7 @@
 
         try {
             mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
-                    forceRelayout, alwaysConsumeSystemBars, displayId);
+                forceRelayout, alwaysConsumeSystemBars, displayId, Integer.MAX_VALUE);
             if (drawPending && reportOrientation && mOrientationChanging) {
                 mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
                 ProtoLog.v(WM_DEBUG_ORIENTATION,
@@ -5938,7 +5938,7 @@
         super.finishSync(outMergedTransaction, cancel);
     }
 
-    boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
+    boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
         if (mOrientationChangeRedrawRequestTime > 0) {
             final long duration =
                     SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
@@ -5985,7 +5985,7 @@
 
     void immediatelyNotifyBlastSync() {
         prepareDrawHandlers();
-        finishDrawing(null);
+        finishDrawing(null, Integer.MAX_VALUE);
         mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
         if (!useBLASTSync()) return;
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index f05658b..e096687 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -494,9 +494,9 @@
 
         final ArgumentCaptor<AlarmManagerService.UninstallReceiver> packageReceiverCaptor =
                 ArgumentCaptor.forClass(AlarmManagerService.UninstallReceiver.class);
-        verify(mMockContext).registerReceiver(packageReceiverCaptor.capture(),
+        verify(mMockContext).registerReceiverForAllUsers(packageReceiverCaptor.capture(),
                 argThat((filter) -> filter.hasAction(Intent.ACTION_PACKAGE_ADDED)
-                        && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)));
+                        && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)), isNull(), isNull());
         mPackageChangesReceiver = packageReceiverCaptor.getValue();
 
         assertEquals(mService.mExactAlarmCandidates, Collections.emptySet());
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
index 41d46f2..534d0a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
@@ -21,7 +21,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import android.app.AlarmManager;
 import android.content.Context;
@@ -71,10 +70,10 @@
                 .strictness(Strictness.LENIENT)
                 .mockStatic(LocalServices.class)
                 .startMocking();
-        when(mIrs.getContext()).thenReturn(mContext);
-        when(mIrs.getCompleteEconomicPolicyLocked()).thenReturn(mEconomicPolicy);
-        when(mIrs.getLock()).thenReturn(mIrs);
-        when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class));
+        doReturn(mContext).when(mIrs).getContext();
+        doReturn(mEconomicPolicy).when(mIrs).getCompleteEconomicPolicyLocked();
+        doReturn(mIrs).when(mIrs).getLock();
+        doReturn(mock(AlarmManager.class)).when(mContext).getSystemService(Context.ALARM_SERVICE);
         mScribe = new MockScribe(mIrs);
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
index ab29e59..c2cf2ff 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
@@ -109,6 +109,7 @@
         long lastReclamationTime = System.currentTimeMillis();
         long remainingConsumableNarcs = 2000L;
         long consumptionLimit = 500_000L;
+        when(mIrs.getConsumptionLimitLocked()).thenReturn(consumptionLimit);
 
         Ledger ledger = mScribeUnderTest.getLedgerLocked(TEST_USER_ID, TEST_PACKAGE);
         ledger.recordTransaction(new Ledger.Transaction(0, 1000L, 1, null, 2000, 0));
@@ -119,8 +120,13 @@
         mScribeUnderTest.setConsumptionLimitLocked(consumptionLimit);
         mScribeUnderTest.adjustRemainingConsumableNarcsLocked(
                 remainingConsumableNarcs - consumptionLimit);
-        mScribeUnderTest.writeImmediatelyForTesting();
 
+        assertEquals(lastReclamationTime, mScribeUnderTest.getLastReclamationTimeLocked());
+        assertEquals(remainingConsumableNarcs,
+                mScribeUnderTest.getRemainingConsumableNarcsLocked());
+        assertEquals(consumptionLimit, mScribeUnderTest.getSatiatedConsumptionLimitLocked());
+
+        mScribeUnderTest.writeImmediatelyForTesting();
         mScribeUnderTest.loadFromDiskLocked();
 
         assertEquals(lastReclamationTime, mScribeUnderTest.getLastReclamationTimeLocked());
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 152f3b3..e3be3a7 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -64,6 +64,7 @@
         "testng",
         "junit",
         "platform-compat-test-rules",
+        "ActivityContext",
     ],
 
     aidl: {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 1f016fb..56c5150 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -28,6 +28,8 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -61,10 +63,12 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.TestUtils;
+import com.android.internal.compat.IPlatformCompat;
 import com.android.server.LocalServices;
 import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener;
 import com.android.server.accessibility.magnification.FullScreenMagnificationController;
 import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.accessibility.magnification.WindowMagnificationManager;
 import com.android.server.accessibility.test.MessageCapturingHandler;
 import com.android.server.pm.UserManagerInternal;
@@ -185,7 +189,7 @@
         mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState);
     }
 
-    private void setupAccessibilityServiceConnection() {
+    private void setupAccessibilityServiceConnection(int serviceInfoFlag) {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
         when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
@@ -193,7 +197,12 @@
         mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
 
         when(mMockBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient);
+        when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class));
+        when(mMockSystemSupport.getMagnificationProcessor()).thenReturn(
+                mock(MagnificationProcessor.class));
         mTestableContext.addMockService(COMPONENT_NAME, mMockBinder);
+
+        mMockServiceInfo.flags = serviceInfoFlag;
         mAccessibilityServiceConnection = new AccessibilityServiceConnection(
                 userState,
                 mTestableContext,
@@ -256,7 +265,7 @@
     @SmallTest
     @Test
     public void testOnSystemActionsChanged() throws Exception {
-        setupAccessibilityServiceConnection();
+        setupAccessibilityServiceConnection(0);
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
 
@@ -376,7 +385,7 @@
     @SmallTest
     @Test
     public void testOnClientChange_boundServiceCanControlMagnification_requestConnection() {
-        setupAccessibilityServiceConnection();
+        setupAccessibilityServiceConnection(0);
         when(mMockSecurityPolicy.canControlMagnification(any())).thenReturn(true);
 
         // Invokes client change to trigger onUserStateChanged.
@@ -385,6 +394,29 @@
         verify(mMockWindowMagnificationMgr).requestConnection(true);
     }
 
+    @Test
+    public void testUnbindIme_whenServiceUnbinds() {
+        setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+        mAccessibilityServiceConnection.unbindLocked();
+        verify(mMockSystemSupport, atLeastOnce()).unbindImeLocked(mAccessibilityServiceConnection);
+    }
+
+    @Test
+    public void testUnbindIme_whenServiceCrashed() {
+        setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+        mAccessibilityServiceConnection.binderDied();
+        verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection);
+    }
+
+    @Test
+    public void testUnbindIme_whenServiceStopsRequestingIme() {
+        setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+        doCallRealMethod().when(mMockServiceInfo).updateDynamicallyConfigurableProperties(
+                any(IPlatformCompat.class), any(AccessibilityServiceInfo.class));
+        mAccessibilityServiceConnection.setServiceInfo(new AccessibilityServiceInfo());
+        verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection);
+    }
+
     public static class FakeInputFilter extends AccessibilityInputFilter {
         FakeInputFilter(Context context,
                 AccessibilityManagerService service) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index 3cb5d5f..ce322f7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -20,6 +20,7 @@
 import android.Manifest;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.ActivityOptions;
 import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.app.admin.DevicePolicyManagerInternal;
@@ -46,6 +47,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.SparseArray;
 
+import com.android.activitycontext.ActivityContext;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
 import com.android.server.LocalServices;
@@ -240,7 +242,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PRIMARY_USER).getIdentifier(),
-                                true));
+                                true,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -265,7 +269,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PRIMARY_USER).getIdentifier(),
-                                false));
+                                false,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -292,7 +298,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                true));
+                                true,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -319,7 +327,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                false));
+                                false,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -344,7 +354,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                true));
+                                true,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -369,7 +381,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                false));
+                                false,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -396,7 +410,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                true));
+                                true,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -440,7 +456,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                false));
+                                false,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -465,7 +483,9 @@
                                 FEATURE_ID,
                                 new ComponentName(PACKAGE_TWO, "test"),
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                true));
+                                true,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -490,7 +510,9 @@
                                 FEATURE_ID,
                                 new ComponentName(PACKAGE_TWO, "test"),
                                 UserHandle.of(PROFILE_OF_PRIMARY_USER).getIdentifier(),
-                                false));
+                                false,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -515,7 +537,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(SECONDARY_USER).getIdentifier(),
-                                true));
+                                true,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -540,7 +564,9 @@
                                 FEATURE_ID,
                                 ACTIVITY_COMPONENT,
                                 UserHandle.of(SECONDARY_USER).getIdentifier(),
-                                false));
+                                false,
+                                /* targetTask */ null,
+                                /* options */ null));
 
         verify(mActivityTaskManagerInternal, never())
                 .startActivityAsUser(
@@ -564,7 +590,9 @@
                 FEATURE_ID,
                 ACTIVITY_COMPONENT,
                 UserHandle.of(PRIMARY_USER).getIdentifier(),
-                true);
+                true,
+                /* targetTask */ null,
+                /* options */ null);
 
         verify(mActivityTaskManagerInternal)
                 .startActivityAsUser(
@@ -578,6 +606,44 @@
                         eq(PRIMARY_USER));
     }
 
+    @Test
+    public void startActivityAsUser_sameTask_fromProfile_success() throws Exception {
+        mTestInjector.setCallingUserId(PROFILE_OF_PRIMARY_USER);
+
+        Bundle options = ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+        IBinder result = ActivityContext.getWithContext(activity -> {
+            try {
+                IBinder targetTask = activity.getActivityToken();
+                mCrossProfileAppsServiceImpl.startActivityAsUser(
+                        mIApplicationThread,
+                        PACKAGE_ONE,
+                        FEATURE_ID,
+                        ACTIVITY_COMPONENT,
+                        UserHandle.of(PRIMARY_USER).getIdentifier(),
+                        true,
+                        targetTask,
+                        options);
+                return targetTask;
+            } catch (Exception re) {
+                return null;
+            }
+        });
+        if (result == null) {
+            throw new Exception();
+        }
+
+        verify(mActivityTaskManagerInternal)
+                .startActivityAsUser(
+                        nullable(IApplicationThread.class),
+                        eq(PACKAGE_ONE),
+                        eq(FEATURE_ID),
+                        any(Intent.class),
+                        eq(result),
+                        anyInt(),
+                        eq(options),
+                        eq(PRIMARY_USER));
+    }
+
     private void mockAppsInstalled(String packageName, int user, boolean installed) {
         when(mPackageManagerInternal.getPackageInfo(
                 eq(packageName),
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index c7b5547..06b7112 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -316,7 +316,8 @@
                 asHandle(currentUser));
         try {
             assertThat(mUserManager.removeUserWhenPossible(user1.getUserHandle(),
-                    /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+                    /* overrideDevicePolicy= */ false))
+                            .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION);
         } finally {
             mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
                     asHandle(currentUser));
@@ -353,7 +354,8 @@
     @Test
     public void testRemoveUserWhenPossible_systemUserReturnsError() throws Exception {
         assertThat(mUserManager.removeUserWhenPossible(UserHandle.SYSTEM,
-                /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+                /* overrideDevicePolicy= */ false))
+                        .isEqualTo(UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER);
 
         assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
     }
@@ -363,7 +365,8 @@
     public void testRemoveUserWhenPossible_invalidUserReturnsError() throws Exception {
         assertThat(hasUser(Integer.MAX_VALUE)).isFalse();
         assertThat(mUserManager.removeUserWhenPossible(UserHandle.of(Integer.MAX_VALUE),
-                /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+                /* overrideDevicePolicy= */ false))
+                        .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND);
     }
 
     @MediumTest
diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
index d76a1de..83139b0 100644
--- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java
@@ -692,23 +692,12 @@
     public void testSetNavBarMode_invalidInputThrowsError() throws RemoteException {
         int navBarModeInvalid = -1;
 
-        assertThrows(UnsupportedOperationException.class,
+        assertThrows(IllegalArgumentException.class,
                 () -> mStatusBarManagerService.setNavBarMode(navBarModeInvalid));
         verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt());
     }
 
     @Test
-    public void testSetNavBarMode_noOverlayManagerDoesNotEnable() throws RemoteException {
-        mOverlayManager = null;
-        int navBarModeKids = StatusBarManager.NAV_BAR_MODE_KIDS;
-
-        mStatusBarManagerService.setNavBarMode(navBarModeKids);
-
-        assertEquals(navBarModeKids, mStatusBarManagerService.getNavBarMode());
-        verify(mOverlayManager, never()).setEnabledExclusiveInCategory(anyString(), anyInt());
-    }
-
-    @Test
     public void testSetNavBarMode_noPackageDoesNotEnable() throws Exception {
         mContext.setMockPackageManager(mPackageManager);
         when(mPackageManager.getPackageInfo(anyString(),
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index d4d8b868..7689e08 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -256,6 +256,14 @@
         mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity);
 
         verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity));
+
+        // If an activity is removed immediately before visibility update, it should cancel too.
+        final ActivityRecord removedImm = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        clearInvocations(mLaunchObserver);
+        onActivityLaunched(removedImm);
+        removedImm.removeImmediately();
+        // Verify any() instead of proto because the field of record may be changed.
+        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(any());
     }
 
     @Test
@@ -299,15 +307,16 @@
     @Test
     public void testOnReportFullyDrawn() {
         // Create an invisible event that should be cancelled after the next event starts.
-        onActivityLaunched(mTrampolineActivity);
-        mTrampolineActivity.mVisibleRequested = false;
+        final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        onActivityLaunched(prev);
+        prev.mVisibleRequested = false;
 
         mActivityOptions = ActivityOptions.makeBasic();
         mActivityOptions.setSourceInfo(SourceInfo.TYPE_LAUNCHER, SystemClock.uptimeMillis() - 10);
         onIntentStarted(mTopActivity.intent);
         notifyActivityLaunched(START_SUCCESS, mTopActivity);
         verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());
-        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
+        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(prev));
 
         // The activity reports fully drawn before windows drawn, then the fully drawn event will
         // be pending (see {@link WindowingModeTransitionInfo#pendingFullyDrawn}).
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index c21a5b6..92550a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -30,7 +30,10 @@
 import android.annotation.NonNull;
 import android.hardware.HardwareBuffer;
 import android.platform.test.annotations.Presubmit;
+import android.window.BackEvent;
 import android.window.BackNavigationInfo;
+import android.window.IOnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
 import android.window.TaskSnapshot;
 
 import org.junit.Before;
@@ -42,15 +45,19 @@
 public class BackNavigationControllerTests extends WindowTestsBase {
 
     private BackNavigationController mBackNavigationController;
+    private IOnBackInvokedCallback mOnBackInvokedCallback;
 
     @Before
     public void setUp() throws Exception {
         mBackNavigationController = new BackNavigationController();
+        mOnBackInvokedCallback = createBackCallback();
     }
 
     @Test
     public void backTypeHomeWhenBackToLauncher() {
         Task task = createTopTaskWithActivity();
+        registerSystemOnBackInvokedCallback();
+
         BackNavigationInfo backNavigationInfo =
                 mBackNavigationController.startBackNavigation(task, new StubTransaction());
         assertThat(backNavigationInfo).isNotNull();
@@ -63,6 +70,8 @@
         Task taskA = createTask(mDefaultDisplay);
         createActivityRecord(taskA);
         Task task = createTopTaskWithActivity();
+        registerSystemOnBackInvokedCallback();
+
         BackNavigationInfo backNavigationInfo =
                 mBackNavigationController.startBackNavigation(task, new StubTransaction());
         assertThat(backNavigationInfo).isNotNull();
@@ -75,6 +84,8 @@
         Task task = createTopTaskWithActivity();
         mAtm.setFocusedTask(task.mTaskId,
                 createAppWindow(task, FIRST_APPLICATION_WINDOW, "window").mActivityRecord);
+        registerSystemOnBackInvokedCallback();
+
         BackNavigationInfo backNavigationInfo =
                 mBackNavigationController.startBackNavigation(task, new StubTransaction());
         assertThat(backNavigationInfo).isNotNull();
@@ -89,6 +100,7 @@
     public void backNavInfoFullyPopulated() {
         Task task = createTopTaskWithActivity();
         createAppWindow(task, FIRST_APPLICATION_WINDOW, "window");
+        registerSystemOnBackInvokedCallback();
 
         // We need a mock screenshot so
         TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController();
@@ -104,6 +116,30 @@
         assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
     }
 
+    @Test
+    public void preparesForBackToHome() {
+        Task task = createTopTaskWithActivity();
+        ActivityRecord activity = task.getTopActivity(false, false);
+        registerSystemOnBackInvokedCallback();
+
+        BackNavigationInfo backNavigationInfo =
+                mBackNavigationController.startBackNavigation(task, new StubTransaction());
+        assertThat(typeToString(backNavigationInfo.getType()))
+                .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
+    }
+
+    @Test
+    public void backTypeCallback() {
+        Task task = createTopTaskWithActivity();
+        ActivityRecord activity = task.getTopActivity(false, false);
+        registerApplicationOnBackInvokedCallback();
+
+        BackNavigationInfo backNavigationInfo =
+                mBackNavigationController.startBackNavigation(task, new StubTransaction());
+        assertThat(typeToString(backNavigationInfo.getType()))
+                .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+    }
+
     @NonNull
     private TaskSnapshotController createMockTaskSnapshotController() {
         TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class);
@@ -126,4 +162,30 @@
         mAtm.setFocusedTask(task.mTaskId, record);
         return task;
     }
+
+    private void registerSystemOnBackInvokedCallback() {
+        mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
+                mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
+    }
+
+    private void registerApplicationOnBackInvokedCallback() {
+        mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
+                mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+    }
+
+    private IOnBackInvokedCallback createBackCallback() {
+        return new IOnBackInvokedCallback.Stub() {
+            @Override
+            public void onBackStarted() { }
+
+            @Override
+            public void onBackProgressed(BackEvent backEvent) { }
+
+            @Override
+            public void onBackCancelled() { }
+
+            @Override
+            public void onBackInvoked() { }
+        };
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 636c6bc..9304761 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -259,6 +259,20 @@
     }
 
     @Test
+    public void testPerformClearTop() {
+        final Task task = createTask(mDisplayContent);
+        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
+        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build();
+        // Detach from process so the activities can be removed from hierarchy when finishing.
+        activity1.detachFromProcess();
+        activity2.detachFromProcess();
+        assertNull(task.performClearTop(activity1, 0 /* launchFlags */));
+        assertFalse(task.hasChild());
+        // In real case, the task should be preserved for adding new activity.
+        assertTrue(task.isAttached());
+    }
+
+    @Test
     public void testRemoveChildForOverlayTask() {
         final Task task = createTask(mDisplayContent);
         final int taskId = task.mTaskId;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 7dfb5ae..4f35d55 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -44,7 +44,7 @@
     @Override
     public void resized(ClientWindowFrames frames, boolean reportDraw,
             MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars,
-            int displayId) throws RemoteException {
+            int displayId, int seqId) throws RemoteException {
     }
 
     @Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index c4547f6..7e5d017 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -692,7 +692,8 @@
         statusBar.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
         final SurfaceControl.Transaction postDrawTransaction =
                 mock(SurfaceControl.Transaction.class);
-        final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction);
+        final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction,
+                Integer.MAX_VALUE);
         assertFalse(layoutNeeded);
 
         transactionCommittedListener.onTransactionCommitted();
@@ -742,7 +743,7 @@
         player.finish();
 
         // The controller should be cleared if the target windows are drawn.
-        statusBar.finishDrawing(mWm.mTransactionFactory.get());
+        statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE);
         statusBar.setOrientationChanging(false);
         assertNull(mDisplayContent.getAsyncRotationController());
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
index 7d2e9bf..ea18e58 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
@@ -45,6 +45,7 @@
 import android.view.WindowInsets;
 import android.view.WindowLayout;
 import android.view.WindowManager;
+import android.window.ClientWindowFrames;
 
 import androidx.test.filters.SmallTest;
 
@@ -71,9 +72,7 @@
     private static final Insets WATERFALL_INSETS = Insets.of(6, 0, 12, 0);
 
     private final WindowLayout mWindowLayout = new WindowLayout();
-    private final Rect mDisplayFrame = new Rect();
-    private final Rect mParentFrame = new Rect();
-    private final Rect mFrame = new Rect();
+    private final ClientWindowFrames mOutFrames = new ClientWindowFrames();
 
     private WindowManager.LayoutParams mAttrs;
     private InsetsState mState;
@@ -108,7 +107,7 @@
     private void computeFrames() {
         mWindowLayout.computeFrames(mAttrs, mState, mDisplayCutoutSafe, mWindowBounds,
                 mWindowingMode, mRequestedWidth, mRequestedHeight, mRequestedVisibilities,
-                mAttachedWindowFrame, mCompatScale, mDisplayFrame, mParentFrame, mFrame);
+                mAttachedWindowFrame, mCompatScale, mOutFrames);
     }
 
     private void addDisplayCutout() {
@@ -146,9 +145,9 @@
     public void defaultParams() {
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -157,9 +156,9 @@
         mRequestedHeight = UNSPECIFIED_LENGTH;
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -173,9 +172,9 @@
         mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+        assertRect(0, STATUS_BAR_HEIGHT, width, STATUS_BAR_HEIGHT + height, mOutFrames.frame);
     }
 
     @Test
@@ -186,9 +185,12 @@
         mRequestedHeight = UNSPECIFIED_LENGTH;
         computeFrames();
 
-        assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, mFrame);
+        assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+                mOutFrames.displayFrame);
+        assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+                mOutFrames.parentFrame);
+        assertRect(0, top, DISPLAY_WIDTH, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT,
+                mOutFrames.frame);
     }
 
     @Test
@@ -196,9 +198,9 @@
         mAttrs.setFitInsetsTypes(WindowInsets.Type.statusBars());
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame);
     }
 
     @Test
@@ -206,9 +208,9 @@
         mAttrs.setFitInsetsTypes(WindowInsets.Type.navigationBars());
         computeFrames();
 
-        assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mFrame);
+        assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+        assertInsetByTopBottom(0, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -216,9 +218,9 @@
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetByTopBottom(0, 0, mDisplayFrame);
-        assertInsetByTopBottom(0, 0, mParentFrame);
-        assertInsetByTopBottom(0, 0, mFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.frame);
     }
 
     @Test
@@ -226,9 +228,9 @@
         mAttrs.setFitInsetsSides(WindowInsets.Side.all());
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -236,9 +238,9 @@
         mAttrs.setFitInsetsSides(WindowInsets.Side.TOP);
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, 0, mOutFrames.frame);
     }
 
     @Test
@@ -246,9 +248,9 @@
         mAttrs.setFitInsetsSides(0);
         computeFrames();
 
-        assertInsetByTopBottom(0, 0, mDisplayFrame);
-        assertInsetByTopBottom(0, 0, mParentFrame);
-        assertInsetByTopBottom(0, 0, mFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.frame);
     }
 
     @Test
@@ -257,9 +259,9 @@
         mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
         computeFrames();
 
-        assertInsetByTopBottom(0, 0, mDisplayFrame);
-        assertInsetByTopBottom(0, 0, mParentFrame);
-        assertInsetByTopBottom(0, 0, mFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.frame);
     }
 
     @Test
@@ -269,9 +271,9 @@
         mAttrs.setFitInsetsIgnoringVisibility(true);
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -282,9 +284,9 @@
         mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
         computeFrames();
 
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mDisplayFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mParentFrame);
-        assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, NAVIGATION_BAR_HEIGHT, mOutFrames.displayFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.parentFrame);
+        assertInsetByTopBottom(STATUS_BAR_HEIGHT, IME_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -295,11 +297,11 @@
         computeFrames();
 
         assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
-                mDisplayFrame);
+                mOutFrames.displayFrame);
         assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
-                mParentFrame);
+                mOutFrames.parentFrame);
         assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
-                mFrame);
+                mOutFrames.frame);
     }
 
     @Test
@@ -310,11 +312,11 @@
         computeFrames();
 
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mDisplayFrame);
+                mOutFrames.displayFrame);
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mParentFrame);
+                mOutFrames.parentFrame);
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mFrame);
+                mOutFrames.frame);
     }
 
     @Test
@@ -325,9 +327,9 @@
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mDisplayFrame);
-        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mParentFrame);
-        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrame);
+        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame);
+        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame);
+        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame);
     }
 
     @Test
@@ -342,9 +344,9 @@
         mAttrs.privateFlags |= PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
         computeFrames();
 
-        assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayFrame);
-        assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mParentFrame);
-        assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mFrame);
+        assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.displayFrame);
+        assertRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, mOutFrames.parentFrame);
+        assertRect(0, 0, DISPLAY_WIDTH, height + DISPLAY_CUTOUT_HEIGHT, mOutFrames.frame);
     }
 
     @Test
@@ -357,11 +359,11 @@
         computeFrames();
 
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mDisplayFrame);
+                mOutFrames.displayFrame);
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mParentFrame);
+                mOutFrames.parentFrame);
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mFrame);
+                mOutFrames.frame);
     }
 
     @Test
@@ -371,9 +373,9 @@
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mDisplayFrame);
-        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mParentFrame);
-        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mFrame);
+        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.displayFrame);
+        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.parentFrame);
+        assertInsetBy(WATERFALL_INSETS.left, 0, WATERFALL_INSETS.right, 0, mOutFrames.frame);
     }
 
     @Test
@@ -384,11 +386,11 @@
         computeFrames();
 
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mDisplayFrame);
+                mOutFrames.displayFrame);
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mParentFrame);
+                mOutFrames.parentFrame);
         assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
-                mFrame);
+                mOutFrames.frame);
     }
 
     @Test
@@ -398,8 +400,8 @@
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetByTopBottom(0, 0, mDisplayFrame);
-        assertInsetByTopBottom(0, 0, mParentFrame);
-        assertInsetByTopBottom(0, 0, mFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.displayFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.parentFrame);
+        assertInsetByTopBottom(0, 0, mOutFrames.frame);
     }
 }
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 6d7895f..6a3aa78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -504,7 +504,7 @@
         assertTrue(win.useBLASTSync());
         final SurfaceControl.Transaction drawT = new StubTransaction();
         win.prepareDrawHandlers();
-        assertTrue(win.finishDrawing(drawT));
+        assertTrue(win.finishDrawing(drawT, Integer.MAX_VALUE));
         assertEquals(drawT, handledT[0]);
         assertFalse(win.useBLASTSync());
 
@@ -693,7 +693,7 @@
             doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */,
                     anyBoolean() /* reportDraw */, any() /* mergedConfig */,
                     anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */,
-                    anyInt() /* displayId */);
+                    anyInt() /* displayId */, anyInt() /* seqId */);
         } catch (RemoteException ignored) {
         }
         win.reportResized();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 5a95210..3988892 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -67,6 +67,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SharedMemory;
+import android.provider.DeviceConfig;
 import android.service.voice.HotwordDetectedResult;
 import android.service.voice.HotwordDetectionService;
 import android.service.voice.HotwordDetector;
@@ -110,12 +111,20 @@
     private static final String TAG = "HotwordDetectionConnection";
     static final boolean DEBUG = false;
 
+    private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds";
     // TODO: These constants need to be refined.
     private static final long VALIDATION_TIMEOUT_MILLIS = 4000;
     private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000;
     private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
             Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
     private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
+    /**
+     * Time after which each HotwordDetectionService process is stopped and replaced by a new one.
+     * 0 indicates no restarts.
+     */
+    private static final int RESTART_PERIOD_SECONDS =
+            DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION,
+                    KEY_RESTART_PERIOD_IN_SECONDS, 0);
     private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
 
     // Hotword metrics
@@ -134,6 +143,7 @@
     // TODO: This may need to be a Handler(looper)
     private final ScheduledExecutorService mScheduledExecutorService =
             Executors.newSingleThreadScheduledExecutor();
+    @Nullable private final ScheduledFuture<?> mCancellationTaskFuture;
     private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
     private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
     private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
@@ -150,7 +160,6 @@
     private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
     private Instant mLastRestartInstant;
 
-    private ScheduledFuture<?> mCancellationTaskFuture;
     private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture;
     private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
 
@@ -196,16 +205,20 @@
         mLastRestartInstant = Instant.now();
         updateStateAfterProcessStart(options, sharedMemory);
 
-        // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
-        // until the current session is closed.
-        mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
-            Slog.v(TAG, "Time to restart the process, TTL has passed");
-            synchronized (mLock) {
-                restartProcessLocked();
-                HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
-                        HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
-            }
-        }, 30, 30, TimeUnit.MINUTES);
+        if (RESTART_PERIOD_SECONDS <= 0) {
+            mCancellationTaskFuture = null;
+        } else {
+            // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
+            // until the current session is closed.
+            mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
+                Slog.v(TAG, "Time to restart the process, TTL has passed");
+                synchronized (mLock) {
+                    restartProcessLocked();
+                    HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
+                            HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
+                }
+            }, RESTART_PERIOD_SECONDS, RESTART_PERIOD_SECONDS, TimeUnit.SECONDS);
+        }
     }
 
     private void initAudioFlingerLocked() {
@@ -346,7 +359,9 @@
             removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
         }
         mIdentity = null;
-        mCancellationTaskFuture.cancel(/* may interrupt */ true);
+        if (mCancellationTaskFuture != null) {
+            mCancellationTaskFuture.cancel(/* may interrupt */ true);
+        }
         if (mAudioFlinger != null) {
             mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
         }
@@ -764,6 +779,7 @@
     }
 
     public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("RESTART_PERIOD_SECONDS="); pw.println(RESTART_PERIOD_SECONDS);
         pw.print(prefix);
         pw.print("mBound=" + mRemoteHotwordDetectionService.isBound());
         pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger);
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 3a3b363..d2a4c3e 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1090,6 +1090,13 @@
      */
     public static final int NO_RETRY_FAILURE = 0x1000B;
 
+    /**
+     * Traffic descriptors in DataCallResponse is empty.
+     *
+     * @hide
+     */
+    public static final int NO_TRAFFIC_DESCRIPTORS = 0x1000C;
+
     private static final Map<Integer, String> sFailCauseMap;
     static {
         sFailCauseMap = new HashMap<>();
@@ -1524,6 +1531,7 @@
         sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
         sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED");
         sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE");
+        sFailCauseMap.put(NO_TRAFFIC_DESCRIPTORS, "NO_TRAFFIC_DESCRIPTORS");
     }
 
     private DataFailCause() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5ef22de..3f430ab 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8352,24 +8352,6 @@
     }
 
     /**
-     * Get P-CSCF address from PCO after data connection is established or modified.
-     * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
-     * @return array of P-CSCF address
-     * @hide
-     */
-    public String[] getPcscfAddress(String apnType) {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony == null)
-                return new String[0];
-            return telephony.getPcscfAddress(apnType, getOpPackageName(), getAttributionTag());
-        } catch (RemoteException e) {
-            return new String[0];
-        }
-    }
-
-
-    /**
      * Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot.
      * Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to
      * recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index fc94ebf..532679c 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1103,8 +1103,10 @@
         sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType));
         sb.append(", ").append(mMvnoMatchData);
         sb.append(", ").append(mPermanentFailed);
-        sb.append(", ").append(mNetworkTypeBitmask);
-        sb.append(", ").append(mLingeringNetworkTypeBitmask);
+        sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString(
+                mNetworkTypeBitmask));
+        sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString(
+                mLingeringNetworkTypeBitmask));
         sb.append(", ").append(mApnSetId);
         sb.append(", ").append(mCarrierId);
         sb.append(", ").append(mSkip464Xlat);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index dc96b35..a5e2c1f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -978,14 +978,6 @@
      boolean isManualNetworkSelectionAllowed(int subId);
 
     /**
-     * Get P-CSCF address from PCO after data connection is established or modified.
-     * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
-     * @param callingPackage The package making the call.
-     * @param callingFeatureId The feature in the package.
-     */
-    String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId);
-
-    /**
      * Set IMS registration state
      */
     void setImsRegistrationState(boolean registered);
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 0423b7a..ff24d16 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -32,7 +32,7 @@
         "libui-types",
     ],
     target: {
-        linux_glibc: {
+        host_linux: {
             static_libs: [
                 // libbinder is only available for linux
                 "libbinder",