Merge "Fix typo in AAPT2 error message" into main
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 52a761f..31d2ecd 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -34,6 +34,7 @@
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.os.Process;
 import android.system.SystemCleaner;
 import android.util.Log;
 
@@ -638,6 +639,12 @@
      * @hide
      */
     public void enableCleaner() {
+        // JobParameters objects are passed by reference in local Binder
+        // transactions for clients running as SYSTEM. The life cycle of the
+        // JobParameters objects are no longer controlled by the client.
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            return;
+        }
         if (mJobCleanupCallback == null) {
             initCleaner(new JobCleanupCallback(IJobCallback.Stub.asInterface(callback), jobId));
         }
diff --git a/core/api/current.txt b/core/api/current.txt
index b400f37..4f91361 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6858,27 +6858,36 @@
 
   @FlaggedApi("android.app.api_rich_ongoing") public static class Notification.ProgressStyle extends android.app.Notification.Style {
     ctor public Notification.ProgressStyle();
+    method @NonNull public android.app.Notification.ProgressStyle addProgressPoint(@NonNull android.app.Notification.ProgressStyle.Point);
     method @NonNull public android.app.Notification.ProgressStyle addProgressSegment(@NonNull android.app.Notification.ProgressStyle.Segment);
-    method @NonNull public android.app.Notification.ProgressStyle addProgressStep(@NonNull android.app.Notification.ProgressStyle.Step);
     method public int getProgress();
     method @Nullable public android.graphics.drawable.Icon getProgressEndIcon();
     method public int getProgressMax();
+    method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Point> getProgressPoints();
     method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Segment> getProgressSegments();
     method @Nullable public android.graphics.drawable.Icon getProgressStartIcon();
-    method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Step> getProgressSteps();
     method @Nullable public android.graphics.drawable.Icon getProgressTrackerIcon();
     method public boolean isProgressIndeterminate();
     method public boolean isStyledByProgress();
     method @NonNull public android.app.Notification.ProgressStyle setProgress(int);
     method @NonNull public android.app.Notification.ProgressStyle setProgressEndIcon(@Nullable android.graphics.drawable.Icon);
     method @NonNull public android.app.Notification.ProgressStyle setProgressIndeterminate(boolean);
+    method @NonNull public android.app.Notification.ProgressStyle setProgressPoints(@NonNull java.util.List<android.app.Notification.ProgressStyle.Point>);
     method @NonNull public android.app.Notification.ProgressStyle setProgressSegments(@NonNull java.util.List<android.app.Notification.ProgressStyle.Segment>);
     method @NonNull public android.app.Notification.ProgressStyle setProgressStartIcon(@Nullable android.graphics.drawable.Icon);
-    method @NonNull public android.app.Notification.ProgressStyle setProgressSteps(@NonNull java.util.List<android.app.Notification.ProgressStyle.Step>);
     method @NonNull public android.app.Notification.ProgressStyle setProgressTrackerIcon(@Nullable android.graphics.drawable.Icon);
     method @NonNull public android.app.Notification.ProgressStyle setStyledByProgress(boolean);
   }
 
+  public static final class Notification.ProgressStyle.Point {
+    ctor public Notification.ProgressStyle.Point(int);
+    method @ColorInt public int getColor();
+    method public int getId();
+    method public int getPosition();
+    method @NonNull public android.app.Notification.ProgressStyle.Point setColor(@ColorInt int);
+    method @NonNull public android.app.Notification.ProgressStyle.Point setId(int);
+  }
+
   public static final class Notification.ProgressStyle.Segment {
     ctor public Notification.ProgressStyle.Segment(int);
     method @ColorInt public int getColor();
@@ -6888,15 +6897,6 @@
     method @NonNull public android.app.Notification.ProgressStyle.Segment setId(int);
   }
 
-  public static final class Notification.ProgressStyle.Step {
-    ctor public Notification.ProgressStyle.Step(int);
-    method @ColorInt public int getColor();
-    method public int getId();
-    method public int getPosition();
-    method @NonNull public android.app.Notification.ProgressStyle.Step setColor(@ColorInt int);
-    method @NonNull public android.app.Notification.ProgressStyle.Step setId(int);
-  }
-
   public abstract static class Notification.Style {
     ctor @Deprecated public Notification.Style();
     method public android.app.Notification build();
@@ -8787,7 +8787,7 @@
   @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public abstract class AppFunctionService extends android.app.Service {
     ctor public AppFunctionService();
     method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
-    method @Deprecated @MainThread public abstract void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>);
+    method @Deprecated @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>);
     method @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>);
     field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
   }
@@ -8822,13 +8822,12 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionResponse> CREATOR;
     field public static final String PROPERTY_RETURN_VALUE = "returnValue";
     field public static final int RESULT_APP_UNKNOWN_ERROR = 2; // 0x2
-    field public static final int RESULT_CANCELLED = 7; // 0x7
+    field public static final int RESULT_CANCELLED = 6; // 0x6
     field public static final int RESULT_DENIED = 1; // 0x1
-    field public static final int RESULT_DISABLED = 6; // 0x6
+    field public static final int RESULT_DISABLED = 5; // 0x5
     field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3
     field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4
     field public static final int RESULT_OK = 0; // 0x0
-    field public static final int RESULT_TIMED_OUT = 5; // 0x5
   }
 
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5b556cc..95d3ea5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1960,8 +1960,12 @@
 
         @Override
         public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
-            PropertyInvalidatedCache.dumpCacheInfo(pfd, args);
-            IoUtils.closeQuietly(pfd);
+            try {
+                PropertyInvalidatedCache.dumpCacheInfo(pfd, args);
+                BroadcastStickyCache.dump(pfd);
+            } finally {
+                IoUtils.closeQuietly(pfd);
+            }
         }
 
         private File getDatabasesDir(Context context) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f27dc32..5907af0 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -10153,6 +10153,9 @@
         }
 
         p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
+        final int sizePosition = p.dataPosition();
+        // Write size placeholder. With this size we can easily skip it in native.
+        p.writeInt(0);
 
         int numAttributionWithNotesAppOps = notedAppOps.size();
         p.writeInt(numAttributionWithNotesAppOps);
@@ -10169,6 +10172,12 @@
                 }
             }
         }
+
+        final int payloadPosition = p.dataPosition();
+        p.setDataPosition(sizePosition);
+        // Total header size including 4 bytes size itself.
+        p.writeInt(payloadPosition - sizePosition);
+        p.setDataPosition(payloadPosition);
     }
 
     /**
@@ -10182,6 +10191,8 @@
      * @hide
      */
     public static void readAndLogNotedAppops(@NonNull Parcel p) {
+        // Skip size.
+        p.readInt();
         int numAttributionsWithNotedAppOps = p.readInt();
 
         for (int i = 0; i < numAttributionsWithNotedAppOps; i++) {
diff --git a/core/java/android/app/BroadcastStickyCache.java b/core/java/android/app/BroadcastStickyCache.java
index d6f061b..ea81731 100644
--- a/core/java/android/app/BroadcastStickyCache.java
+++ b/core/java/android/app/BroadcastStickyCache.java
@@ -27,16 +27,21 @@
 import android.net.nsd.NsdManager;
 import android.net.wifi.WifiManager;
 import android.net.wifi.p2p.WifiP2pManager;
+import android.os.ParcelFileDescriptor;
 import android.os.SystemProperties;
 import android.os.UpdateLock;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
+import android.util.IndentingPrintWriter;
 import android.view.WindowManagerPolicyConstants;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastPrintWriter;
 
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /** @hide */
@@ -214,6 +219,41 @@
         }
     }
 
+    public static void dump(@NonNull ParcelFileDescriptor pfd) {
+        if (!Flags.useStickyBcastCache()) {
+            return;
+        }
+        final PrintWriter pw = new FastPrintWriter(new FileOutputStream(pfd.getFileDescriptor()));
+        synchronized (sCachedStickyBroadcasts) {
+            dumpLocked(pw);
+        }
+        pw.flush();
+    }
+
+    @GuardedBy("sCachedStickyBroadcasts")
+    private static void dumpLocked(@NonNull PrintWriter pw) {
+        final IndentingPrintWriter ipw = new IndentingPrintWriter(
+                pw, "  " /* singleIndent */, "  " /* prefix */);
+        ipw.println("Cached sticky broadcasts:");
+        ipw.increaseIndent();
+        final int count = sCachedStickyBroadcasts.size();
+        if (count == 0) {
+            ipw.println("<empty>");
+        } else {
+            for (int i = 0; i < count; ++i) {
+                final CachedStickyBroadcast cachedStickyBroadcast = sCachedStickyBroadcasts.get(i);
+                ipw.print("Entry #"); ipw.print(i); ipw.println(":");
+                ipw.increaseIndent();
+                ipw.print("filter="); ipw.println(cachedStickyBroadcast.filter.toLongString());
+                ipw.print("intent="); ipw.println(cachedStickyBroadcast.intent);
+                ipw.print("version="); ipw.println(cachedStickyBroadcast.version);
+                ipw.print("handle="); ipw.println(cachedStickyBroadcast.propertyHandle);
+                ipw.decreaseIndent();
+            }
+        }
+        ipw.decreaseIndent();
+    }
+
     private static final class CachedStickyBroadcast {
         @NonNull public final IntentFilter filter;
         @Nullable public Intent intent;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 34d0f3b..0812a13 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1637,16 +1637,16 @@
     public static final String EXTRA_PROGRESS_SEGMENTS = "android.progressSegments";
 
     /**
-     * {@link #extras} key: an arraylist of {@link android.app.Notification.ProgressStyle.Step}
+     * {@link #extras} key: an arraylist of {@link ProgressStyle.Point}
      * bundles provided by a
      * {@link android.app.Notification.ProgressStyle} notification as supplied to
-     * {@link ProgressStyle#setProgressSteps}
-     * or {@link ProgressStyle#addProgressStep(ProgressStyle.Step)}.
+     * {@link ProgressStyle#setProgressPoints}
+     * or {@link ProgressStyle#addProgressPoint(ProgressStyle.Point)}.
      * This extra is a parcelable array list of bundles.
      * @hide
      */
     @FlaggedApi(Flags.FLAG_API_RICH_ONGOING)
-    public static final String EXTRA_PROGRESS_STEPS = "android.progressSteps";
+    public static final String EXTRA_PROGRESS_POINTS = "android.progressPoints";
 
     /**
      * {@link #extras} key: whether the progress bar should be styled by its progress as
@@ -11159,7 +11159,7 @@
 
     /**
      * A Notification Style used to to define a notification whose expanded state includes
-     * a highly customizable progress bar with segments, steps, a custom tracker icon,
+     * a highly customizable progress bar with segments, points, a custom tracker icon,
      * and custom icons at the start and end of the progress bar.
      *
      * This style is suggested for use cases where the app is showing a tracker to the
@@ -11185,8 +11185,8 @@
      *       .addProgressSegment(new Segment(552).setColor(Color.YELLOW))
      *       .addProgressSegment(new Segment(253).setColor(Color.YELLOW))
      *       .addProgressSegment(new Segment(94).setColor(Color.BLUE))
-     *       .addProgressStep(new Step(60).setColor(Color.RED))
-     *       .addProgressStep(new Step(560).setColor(Color.YELLOW))
+     *       .addProgressPoint(new Point(60).setColor(Color.RED))
+     *       .addProgressPoint(new Point(560).setColor(Color.YELLOW))
      *   )
      * </pre>
      *
@@ -11202,14 +11202,14 @@
         private static final String KEY_ELEMENT_ID = "id";
         private static final String KEY_ELEMENT_COLOR = "colorInt";
         private static final String KEY_SEGMENT_LENGTH = "length";
-        private static final String KEY_STEP_POSITION = "position";
+        private static final String KEY_POINT_POSITION = "position";
 
         private static final int MAX_PROGRESS_SEGMENT_LIMIT = 15;
-        private static final int MAX_PROGRESS_STEP_LIMIT = 5;
+        private static final int MAX_PROGRESS_STOP_LIMIT = 5;
         private static final int DEFAULT_PROGRESS_MAX = 100;
 
         private List<Segment> mProgressSegments = new ArrayList<>();
-        private List<Step> mProgressSteps = new ArrayList<>();
+        private List<Point> mProgressPoints = new ArrayList<>();
 
         private int mProgress = 0;
 
@@ -11246,7 +11246,7 @@
                 nonIndeterminateCheckResult = !Objects.equals(mProgress, progressStyle.mProgress)
                         || !Objects.equals(mIsStyledByProgress, progressStyle.mIsStyledByProgress)
                         || !Objects.equals(mProgressSegments, progressStyle.mProgressSegments)
-                        || !Objects.equals(mProgressSteps, progressStyle.mProgressSteps)
+                        || !Objects.equals(mProgressPoints, progressStyle.mProgressPoints)
                         || !Objects.equals(mTrackerIcon, progressStyle.mTrackerIcon);
             }
 
@@ -11300,48 +11300,47 @@
         }
 
         /**
-         * Gets the steps that are displayed on the progress bar.
+         * Gets the points that are displayed on the progress bar.
          *.
-         * @see #setProgressSteps
-         * @see #addProgressStep
-         * @see Step
+         * @see #setProgressPoints
+         * @see #addProgressPoint
+         * @see Point
          */
-        public @NonNull List<Step> getProgressSteps() {
-            return mProgressSteps;
+        public @NonNull List<Point> getProgressPoints() {
+            return mProgressPoints;
         }
 
         /**
-         * Replaces all the progress steps.
+         * Replaces all the progress points.
          *
-         * Steps are designated points within a progressbar to visualize
-         * distinct stages or milestones.
-         * For example, you might use steps to mark stops in a multi-stop
-         * navigation journey, where each step represents a destination.
-         * @see Step
+         * Points within a progress bar are used to visualize distinct stages or milestones.
+         * For example, you might use points to mark stops in a multi-stop
+         * navigation journey, where each point represents a destination.
+         * @see Point
          */
-        public @NonNull ProgressStyle setProgressSteps(@NonNull List<Step> steps) {
-            mProgressSteps = new ArrayList<>(steps);
+        public @NonNull ProgressStyle setProgressPoints(@NonNull List<Point> points) {
+            mProgressPoints = new ArrayList<>(points);
             return this;
         }
 
         /**
-         * Adds another step.
+         * Adds another point.
          *
-         * Steps are designated points within a progressbar to visualize
-         * distinct stages or milestones.
-         * For example, you might use steps to mark stops in a multi-stop
-         * navigation journey, where each step represents a destination.
+         * Points within a progress bar are used to visualize distinct stages or milestones.
          *
-         * Steps can be added in any order, as their
+         * For example, you might use points to mark stops in a multi-stop
+         * navigation journey, where each point represents a destination.
+         *
+         * Points can be added in any order, as their
          * position within the progress bar is determined by their individual
-         * {@link Step#getPosition()}.
-         * @see Step
+         * {@link Point#getPosition()}.
+         * @see Point
          */
-        public @NonNull ProgressStyle addProgressStep(@NonNull Step step) {
-            if (mProgressSteps == null) {
-                mProgressSteps = new ArrayList<>();
+        public @NonNull ProgressStyle addProgressPoint(@NonNull Point point) {
+            if (mProgressPoints == null) {
+                mProgressPoints = new ArrayList<>();
             }
-            mProgressSteps.add(step);
+            mProgressPoints.add(point);
 
             return this;
         }
@@ -11414,7 +11413,7 @@
          * When specified, the following fields are ignored:
          * @see #setProgress
          * @see #setProgressSegments
-         * @see #setProgressSteps
+         * @see #setProgressPoints
          * @see #setProgressTrackerIcon
          * @see #setStyledByProgress
          *
@@ -11435,7 +11434,7 @@
         }
 
         /**
-         * Indicates whether the segments and steps will be styled differently
+         * Indicates whether the segments and points will be styled differently
          * based on whether they are behind or ahead of the current progress.
          * When true, segments appearing ahead of the current progress will be given a
          * slightly different appearance to indicate that it is part of the progress bar
@@ -11558,8 +11557,8 @@
             super.addExtras(extras);
             extras.putParcelableArrayList(EXTRA_PROGRESS_SEGMENTS,
                     getProgressSegmentsAsBundleList(mProgressSegments));
-            extras.putParcelableArrayList(EXTRA_PROGRESS_STEPS,
-                    getProgressStepsAsBundleList(mProgressSteps));
+            extras.putParcelableArrayList(EXTRA_PROGRESS_POINTS,
+                    getProgressPointsAsBundleList(mProgressPoints));
 
             extras.putInt(EXTRA_PROGRESS, mProgress);
             extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mIndeterminate);
@@ -11599,8 +11598,8 @@
             mTrackerIcon = extras.getParcelable(EXTRA_PROGRESS_TRACKER_ICON, Icon.class);
             mStartIcon = extras.getParcelable(EXTRA_PROGRESS_START_ICON, Icon.class);
             mEndIcon = extras.getParcelable(EXTRA_PROGRESS_END_ICON, Icon.class);
-            mProgressSteps = getProgressStepsFromBundleList(
-                    extras.getParcelableArrayList(EXTRA_PROGRESS_STEPS, Bundle.class));
+            mProgressPoints = getProgressPointsFromBundleList(
+                    extras.getParcelableArrayList(EXTRA_PROGRESS_POINTS, Bundle.class));
         }
 
         /**
@@ -11613,6 +11612,30 @@
             // actually be included.
             return true;
         }
+        /**
+         * @hide
+         */
+        @Override
+        public RemoteViews makeContentView(boolean increasedHeight) {
+            final StandardTemplateParams p = mBuilder.mParams.reset()
+                    .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL)
+                    .hideProgress(true)
+                    .fillTextsFrom(mBuilder);
+
+            return getStandardView(mBuilder.getBaseLayoutResource(), p, null /* result */);
+        }
+        /**
+         * @hide
+         */
+        @Override
+        public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
+            final StandardTemplateParams p = mBuilder.mParams.reset()
+                    .viewType(StandardTemplateParams.VIEW_TYPE_HEADS_UP)
+                    .hideProgress(true)
+                    .fillTextsFrom(mBuilder);
+
+            return getStandardView(mBuilder.getHeadsUpBaseLayoutResource(), p, null /* result */);
+        }
 
         private static @NonNull ArrayList<Bundle> getProgressSegmentsAsBundleList(
                 @Nullable List<Segment> progressSegments) {
@@ -11660,48 +11683,48 @@
             return segments;
         }
 
-        private static @NonNull ArrayList<Bundle> getProgressStepsAsBundleList(
-                @Nullable List<Step> progressSteps) {
-            final ArrayList<Bundle> steps = new ArrayList<>();
-            if (progressSteps != null && !progressSteps.isEmpty()) {
-                for (int i = 0; i < progressSteps.size(); i++) {
-                    final Step step = progressSteps.get(i);
-                    if (step.getPosition() < 0) {
+        private static @NonNull ArrayList<Bundle> getProgressPointsAsBundleList(
+                @Nullable List<Point> progressPoints) {
+            final ArrayList<Bundle> points = new ArrayList<>();
+            if (progressPoints != null && !progressPoints.isEmpty()) {
+                for (int i = 0; i < progressPoints.size(); i++) {
+                    final Point point = progressPoints.get(i);
+                    if (point.getPosition() < 0) {
                         continue;
                     }
 
                     final Bundle bundle = new Bundle();
-                    bundle.putInt(KEY_STEP_POSITION, step.getPosition());
-                    bundle.putInt(KEY_ELEMENT_ID, step.getId());
-                    bundle.putInt(KEY_ELEMENT_COLOR, step.getColor());
+                    bundle.putInt(KEY_POINT_POSITION, point.getPosition());
+                    bundle.putInt(KEY_ELEMENT_ID, point.getId());
+                    bundle.putInt(KEY_ELEMENT_COLOR, point.getColor());
 
-                    steps.add(bundle);
+                    points.add(bundle);
                 }
             }
 
-            return steps;
+            return points;
         }
 
-        private static @NonNull List<Step> getProgressStepsFromBundleList(
-                @Nullable List<Bundle> stepBundleList) {
-            final ArrayList<Step> steps = new ArrayList<>();
+        private static @NonNull List<Point> getProgressPointsFromBundleList(
+                @Nullable List<Bundle> pointBundleList) {
+            final ArrayList<Point> points = new ArrayList<>();
 
-            if (stepBundleList != null && !stepBundleList.isEmpty()) {
-                for (int i = 0; i < stepBundleList.size(); i++) {
-                    final Bundle segmentBundle = stepBundleList.get(i);
-                    final int position = segmentBundle.getInt(KEY_STEP_POSITION);
+            if (pointBundleList != null && !pointBundleList.isEmpty()) {
+                for (int i = 0; i < pointBundleList.size(); i++) {
+                    final Bundle pointBundle = pointBundleList.get(i);
+                    final int position = pointBundle.getInt(KEY_POINT_POSITION);
                     if (position < 0) {
                         continue;
                     }
-                    final int id = segmentBundle.getInt(KEY_ELEMENT_ID);
-                    final int color = segmentBundle.getInt(KEY_ELEMENT_COLOR,
+                    final int id = pointBundle.getInt(KEY_ELEMENT_ID);
+                    final int color = pointBundle.getInt(KEY_ELEMENT_COLOR,
                             Notification.COLOR_DEFAULT);
-                    final Step step = new Step(position).setId(id).setColor(color);
-                    steps.add(step);
+                    final Point point = new Point(position).setId(id).setColor(color);
+                    points.add(point);
                 }
             }
 
-            return steps;
+            return points;
         }
 
         /**
@@ -11776,7 +11799,7 @@
             public boolean equals(Object o) {
                 if (this == o) return true;
                 if (o == null || getClass() != o.getClass()) return false;
-                Segment segment = (Segment) o;
+                final Segment segment = (Segment) o;
                 return mLength == segment.mLength && mId == segment.mId
                         && mColor == segment.mColor;
             }
@@ -11788,13 +11811,12 @@
         }
 
         /**
-         * A step within the progress bar, defining its position and color.
-         * Steps are designated points within a progressbar to visualize
-         * distinct stages or milestones.
-         * For example, you might use steps to mark stops in a multi-stop
-         * navigation journey, where each step represents a destination.
+         * A point within the progress bar, defining its position and color.
+         * Points within a progress bar are used to visualize distinct stages or milestones.
+         * For example, you might use points to mark stops in a multi-stop
+         * navigation journey, where each point represents a destination.
          */
-        public static final class Step {
+        public static final class Point {
 
             private int mPosition;
             private int mId;
@@ -11802,19 +11824,19 @@
             private int mColor = Notification.COLOR_DEFAULT;
 
             /**
-             * Create a step element.
-             * The position of this step on the progress bar
+             * Create a point element.
+             * The position of this point on the progress bar
              * relative to {@link ProgressStyle#getProgressMax}
              * @param position
              * See {@link #getPosition}
              */
-            public Step(int position) {
+            public Point(int position) {
                 mPosition = position;
             }
 
             /**
-             * Gets the position of this Step.
-             * The position of this step on the progress bar
+             * Gets the position of this Point.
+             * The position of this point on the progress bar
              * relative to {@link ProgressStyle#getProgressMax}.
              */
             public int getPosition() {
@@ -11832,7 +11854,7 @@
             /**
              * Optional ID used to uniquely identify the element across updates.
              */
-            public @NonNull Step setId(int id) {
+            public @NonNull Point setId(int id) {
                 mId = id;
                 return this;
             }
@@ -11850,7 +11872,7 @@
             /**
              * Optional color of this Segment
              */
-            public @NonNull Step setColor(@ColorInt int color) {
+            public @NonNull Point setColor(@ColorInt int color) {
                 mColor = color;
                 return this;
             }
@@ -11862,9 +11884,9 @@
             public boolean equals(Object o) {
                 if (this == o) return true;
                 if (o == null || getClass() != o.getClass()) return false;
-                Step step = (Step) o;
-                return mPosition == step.mPosition && mId == step.mId
-                        && mColor == step.mColor;
+                final Point point = (Point) o;
+                return mPosition == point.mPosition && mId == point.mId
+                        && mColor == point.mColor;
             }
 
             @Override
diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java
index 8e41773..7a68a65 100644
--- a/core/java/android/app/appfunctions/AppFunctionService.java
+++ b/core/java/android/app/appfunctions/AppFunctionService.java
@@ -35,6 +35,7 @@
 import android.os.CancellationSignal;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
+import android.util.Log;
 
 import java.util.function.Consumer;
 
@@ -166,9 +167,13 @@
      */
     @MainThread
     @Deprecated
-    public abstract void onExecuteFunction(
+    public void onExecuteFunction(
             @NonNull ExecuteAppFunctionRequest request,
-            @NonNull Consumer<ExecuteAppFunctionResponse> callback);
+            @NonNull Consumer<ExecuteAppFunctionResponse> callback) {
+        Log.w(
+                "AppFunctionService",
+                "Calling deprecated default implementation of onExecuteFunction");
+    }
 
     /**
      * Called by the system to execute a specific app function.
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
index 2851e92..a879b1b 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
@@ -96,17 +96,14 @@
      */
     public static final int RESULT_INVALID_ARGUMENT = 4;
 
-    /** The operation was timed out. */
-    public static final int RESULT_TIMED_OUT = 5;
-
     /** The caller tried to execute a disabled app function. */
-    public static final int RESULT_DISABLED = 6;
+    public static final int RESULT_DISABLED = 5;
 
     /**
      * The operation was cancelled. Use this error code to report that a cancellation is done after
      * receiving a cancellation signal.
      */
-    public static final int RESULT_CANCELLED = 7;
+    public static final int RESULT_CANCELLED = 6;
 
     /** The result code of the app function execution. */
     @ResultCode private final int mResultCode;
@@ -282,7 +279,6 @@
                 RESULT_APP_UNKNOWN_ERROR,
                 RESULT_INTERNAL_ERROR,
                 RESULT_INVALID_ARGUMENT,
-                RESULT_TIMED_OUT,
                 RESULT_DISABLED,
                 RESULT_CANCELLED
             })
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index e598097..36e816a 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -455,6 +455,11 @@
     public abstract void onPresentation(int displayId, boolean isShown);
 
     /**
+     * Called upon the usage of stylus.
+     */
+    public abstract void stylusGestureStarted(long eventTime);
+
+    /**
      * Describes the requested power state of the display.
      *
      * This object is intended to describe the general characteristics of the
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b9b5295..c41e626 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3088,8 +3088,9 @@
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
             "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
-            "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw",
-            "Esw", "Ewa", "Elw", "Eec", "Esc", "Eds"
+            "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa",
+            "Etw", "Esw", "Ewa", "Elw", "Esc",
+            "Eds"
     };
 
     @FunctionalInterface
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d82af55..a2c41c1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2092,23 +2092,6 @@
     public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
 
     /**
-     * Activity Action: Show Zen Mode visual effects configuration settings.
-     *
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ZEN_MODE_BLOCKED_EFFECTS_SETTINGS =
-            "android.settings.ZEN_MODE_BLOCKED_EFFECTS_SETTINGS";
-
-    /**
-     * Activity Action: Show Zen Mode onboarding activity.
-     *
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ZEN_MODE_ONBOARDING = "android.settings.ZEN_MODE_ONBOARDING";
-
-    /**
      * Activity Action: Show Zen Mode (aka Do Not Disturb) priority configuration settings.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -8748,35 +8731,6 @@
         /** @hide */ public static final int ZEN_DURATION_FOREVER = 0;
 
         /**
-         * If nonzero, will show the zen upgrade notification when the user toggles DND on/off.
-         * @hide
-         */
-        @Readable
-        public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification";
-
-        /**
-         * If nonzero, will show the zen update settings suggestion.
-         * @hide
-         */
-        @Readable
-        public static final String SHOW_ZEN_SETTINGS_SUGGESTION = "show_zen_settings_suggestion";
-
-        /**
-         * If nonzero, zen has not been updated to reflect new changes.
-         * @hide
-         */
-        @Readable
-        public static final String ZEN_SETTINGS_UPDATED = "zen_settings_updated";
-
-        /**
-         * If nonzero, zen setting suggestion has been viewed by user
-         * @hide
-         */
-        @Readable
-        public static final String ZEN_SETTINGS_SUGGESTION_VIEWED =
-                "zen_settings_suggestion_viewed";
-
-        /**
          * Whether the in call notification is enabled to play sound during calls.  The value is
          * boolean (1 or 0).
          * @hide
@@ -18072,10 +18026,6 @@
             MOVED_TO_SECURE = new HashSet<>(8);
             MOVED_TO_SECURE.add(Global.INSTALL_NON_MARKET_APPS);
             MOVED_TO_SECURE.add(Global.ZEN_DURATION);
-            MOVED_TO_SECURE.add(Global.SHOW_ZEN_UPGRADE_NOTIFICATION);
-            MOVED_TO_SECURE.add(Global.SHOW_ZEN_SETTINGS_SUGGESTION);
-            MOVED_TO_SECURE.add(Global.ZEN_SETTINGS_UPDATED);
-            MOVED_TO_SECURE.add(Global.ZEN_SETTINGS_SUGGESTION_VIEWED);
             MOVED_TO_SECURE.add(Global.CHARGING_SOUNDS_ENABLED);
             MOVED_TO_SECURE.add(Global.CHARGING_VIBRATION_ENABLED);
             MOVED_TO_SECURE.add(Global.NOTIFICATION_BUBBLES);
@@ -18910,40 +18860,6 @@
         @Readable
         public static final String SHOW_MUTE_IN_CRASH_DIALOG = "show_mute_in_crash_dialog";
 
-
-        /**
-         * If nonzero, will show the zen upgrade notification when the user toggles DND on/off.
-         * @hide
-         * @deprecated - Use {@link android.provider.Settings.Secure#SHOW_ZEN_UPGRADE_NOTIFICATION}
-         */
-        @Deprecated
-        public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification";
-
-        /**
-         * If nonzero, will show the zen update settings suggestion.
-         * @hide
-         * @deprecated - Use {@link android.provider.Settings.Secure#SHOW_ZEN_SETTINGS_SUGGESTION}
-         */
-        @Deprecated
-        public static final String SHOW_ZEN_SETTINGS_SUGGESTION = "show_zen_settings_suggestion";
-
-        /**
-         * If nonzero, zen has not been updated to reflect new changes.
-         * @deprecated - Use {@link android.provider.Settings.Secure#ZEN_SETTINGS_UPDATED}
-         * @hide
-         */
-        @Deprecated
-        public static final String ZEN_SETTINGS_UPDATED = "zen_settings_updated";
-
-        /**
-         * If nonzero, zen setting suggestion has been viewed by user
-         * @hide
-         * @deprecated - Use {@link android.provider.Settings.Secure#ZEN_SETTINGS_SUGGESTION_VIEWED}
-         */
-        @Deprecated
-        public static final String ZEN_SETTINGS_SUGGESTION_VIEWED =
-                "zen_settings_suggestion_viewed";
-
         /**
          * Backup and restore agent timeout parameters.
          * These parameters are represented by a comma-delimited key-value list.
diff --git a/core/java/android/tracing/TEST_MAPPING b/core/java/android/tracing/TEST_MAPPING
new file mode 100644
index 0000000..b51d19d
--- /dev/null
+++ b/core/java/android/tracing/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "postsubmit": [
+    {
+      "name": "TracingTests"
+    },
+    {
+      "name": "ProtologPerfTests"
+    }
+  ]
+}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0582afe..381006c 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1345,7 +1345,7 @@
     }
 
     /**
-     * <p>Sets the desired about of HDR headroom to be used when rendering as a ratio of
+     * <p>Sets the desired amount of HDR headroom to be used when rendering as a ratio of
      * targetHdrPeakBrightnessInNits / targetSdrWhitePointInNits. Only applies when
      * {@link #setColorMode(int)} is {@link ActivityInfo#COLOR_MODE_HDR}</p>
      *
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 70ac12f..b22aa22 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -162,6 +162,13 @@
 }
 
 flag {
+    name: "enable_a11y_metrics"
+    namespace: "lse_desktop_experience"
+    description: "Whether to enable log collection for a11y actions in desktop windowing mode"
+    bug: "341319597"
+}
+
+flag {
     name: "enable_caption_compat_inset_force_consumption"
     namespace: "lse_desktop_experience"
     description: "Enables force-consumption of caption bar insets for immersive apps in freeform"
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index fef5e83..4aebde5 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -26,6 +26,7 @@
 import android.os.RemoteException;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,38 +38,40 @@
      * @deprecated Legacy system channel, which is no longer used,
      */
     @Deprecated public static String VIRTUAL_KEYBOARD  = "VIRTUAL_KEYBOARD";
-    public static String PHYSICAL_KEYBOARD = "PHYSICAL_KEYBOARD";
-    public static String SECURITY = "SECURITY";
-    public static String CAR_MODE = "CAR_MODE";
-    public static String ACCOUNT = "ACCOUNT";
-    public static String DEVELOPER = "DEVELOPER";
-    public static String DEVELOPER_IMPORTANT = "DEVELOPER_IMPORTANT";
-    public static String UPDATES = "UPDATES";
-    public static String NETWORK_STATUS = "NETWORK_STATUS";
-    public static String NETWORK_ALERTS = "NETWORK_ALERTS";
-    public static String NETWORK_AVAILABLE = "NETWORK_AVAILABLE";
-    public static String VPN = "VPN";
+    public static final String PHYSICAL_KEYBOARD = "PHYSICAL_KEYBOARD";
+    public static final String SECURITY = "SECURITY";
+    public static final String CAR_MODE = "CAR_MODE";
+    public static final String ACCOUNT = "ACCOUNT";
+    public static final String DEVELOPER = "DEVELOPER";
+    public static final String DEVELOPER_IMPORTANT = "DEVELOPER_IMPORTANT";
+    public static final String UPDATES = "UPDATES";
+    public static final String NETWORK_STATUS = "NETWORK_STATUS";
+    public static final String NETWORK_ALERTS = "NETWORK_ALERTS";
+    public static final String NETWORK_AVAILABLE = "NETWORK_AVAILABLE";
+    public static final String VPN = "VPN";
     /**
      * @deprecated Legacy device admin channel with low importance which is no longer used,
      *  Use the high importance {@link #DEVICE_ADMIN} channel instead.
      */
-    @Deprecated public static String DEVICE_ADMIN_DEPRECATED = "DEVICE_ADMIN";
-    public static String DEVICE_ADMIN = "DEVICE_ADMIN_ALERTS";
-    public static String ALERTS = "ALERTS";
-    public static String RETAIL_MODE = "RETAIL_MODE";
-    public static String USB = "USB";
-    public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
-    public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP";
+    @Deprecated public static final String DEVICE_ADMIN_DEPRECATED = "DEVICE_ADMIN";
+    public static final String DEVICE_ADMIN = "DEVICE_ADMIN_ALERTS";
+    public static final String ALERTS = "ALERTS";
+    public static final String RETAIL_MODE = "RETAIL_MODE";
+    public static final String USB = "USB";
+    public static final String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
+    public static final String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP";
     /**
      * @deprecated Legacy system changes channel with low importance which is no longer used,
      *  Use the default importance {@link #SYSTEM_CHANGES} channel instead.
      */
-    @Deprecated public static String SYSTEM_CHANGES_DEPRECATED = "SYSTEM_CHANGES";
-    public static String SYSTEM_CHANGES = "SYSTEM_CHANGES_ALERTS";
-    public static String DO_NOT_DISTURB = "DO_NOT_DISTURB";
-    public static String ACCESSIBILITY_MAGNIFICATION = "ACCESSIBILITY_MAGNIFICATION";
-    public static String ACCESSIBILITY_SECURITY_POLICY = "ACCESSIBILITY_SECURITY_POLICY";
-    public static String ABUSIVE_BACKGROUND_APPS = "ABUSIVE_BACKGROUND_APPS";
+    @Deprecated public static final String SYSTEM_CHANGES_DEPRECATED = "SYSTEM_CHANGES";
+    public static final String SYSTEM_CHANGES = "SYSTEM_CHANGES_ALERTS";
+    public static final String ACCESSIBILITY_MAGNIFICATION = "ACCESSIBILITY_MAGNIFICATION";
+    public static final String ACCESSIBILITY_SECURITY_POLICY = "ACCESSIBILITY_SECURITY_POLICY";
+    public static final String ABUSIVE_BACKGROUND_APPS = "ABUSIVE_BACKGROUND_APPS";
+
+    @VisibleForTesting
+    static final String OBSOLETE_DO_NOT_DISTURB = "DO_NOT_DISTURB";
 
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -193,11 +196,6 @@
                 .build());
         channelsList.add(systemChanges);
 
-        NotificationChannel dndChanges = new NotificationChannel(DO_NOT_DISTURB,
-                context.getString(R.string.notification_channel_do_not_disturb),
-                NotificationManager.IMPORTANCE_LOW);
-        channelsList.add(dndChanges);
-
         final NotificationChannel newFeaturePrompt = new NotificationChannel(
                 ACCESSIBILITY_MAGNIFICATION,
                 context.getString(R.string.notification_channel_accessibility_magnification),
@@ -218,6 +216,9 @@
         channelsList.add(abusiveBackgroundAppsChannel);
 
         nm.createNotificationChannels(channelsList);
+
+        // Delete channels created by previous Android versions that are no longer used.
+        nm.deleteNotificationChannel(OBSOLETE_DO_NOT_DISTURB);
     }
 
     private static String getDeviceAdminNotificationChannelName(Context context) {
diff --git a/core/java/com/android/internal/protolog/TEST_MAPPING b/core/java/com/android/internal/protolog/TEST_MAPPING
index 37d57ee..b51d19d 100644
--- a/core/java/com/android/internal/protolog/TEST_MAPPING
+++ b/core/java/com/android/internal/protolog/TEST_MAPPING
@@ -1,6 +1,9 @@
 {
   "postsubmit": [
     {
+      "name": "TracingTests"
+    },
+    {
       "name": "ProtologPerfTests"
     }
   ]
diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h
index 21b5b13..e3e17ee 100644
--- a/core/jni/jni_wrappers.h
+++ b/core/jni/jni_wrappers.h
@@ -79,13 +79,14 @@
     jniMethodFormat = value;
 }
 
-// Potentially translates the given JNINativeMethods if setJniMethodFormat has been set.
-// Has no effect otherwise
-inline const JNINativeMethod* maybeRenameJniMethods(const JNINativeMethod* gMethods,
-                                                    int numMethods) {
+// Register the native methods, potenially applying the jniMethodFormat if it has been set.
+static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className,
+                                                       const JNINativeMethod* gMethods,
+                                                       int numMethods) {
     if (jniMethodFormat.empty()) {
-        return gMethods;
+        return jniRegisterNativeMethods(env, className, gMethods, numMethods);
     }
+
     // Make a copy of gMethods with reformatted method names.
     JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods];
     LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods");
@@ -103,13 +104,17 @@
         std::strcpy(modifiedNameChars, modifiedName.c_str());
         modifiedMethods[i].name = modifiedNameChars;
     }
-    return modifiedMethods;
+    int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods);
+    for (int i = 0; i < numMethods; i++) {
+        delete[] modifiedMethods[i].name;
+    }
+    delete[] modifiedMethods;
+    return res;
 }
 
 static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
                                        const JNINativeMethod* gMethods, int numMethods) {
-    const JNINativeMethod* modifiedMethods = maybeRenameJniMethods(gMethods, numMethods);
-    int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods);
+    int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods);
     LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
     return res;
 }
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d634210..7aca535 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5818,16 +5818,6 @@
 
     <!-- Title for the notification channel notifying user of settings system changes. [CHAR LIMIT=NONE] -->
     <string name="notification_channel_system_changes">System changes</string>
-    <!-- Title for the notification channel notifying user of do not disturb system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
-    <string name="notification_channel_do_not_disturb">Do Not Disturb</string>
-    <!-- Title of notification indicating do not disturb visual interruption settings have changed when upgrading to P -->
-    <string name="zen_upgrade_notification_visd_title">New: Do Not Disturb is hiding notifications</string>
-    <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
-    <string name="zen_upgrade_notification_visd_content">Tap to learn more and change.</string>
-    <!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
-    <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string>
-    <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
-    <string name="zen_upgrade_notification_content">Tap to check what\'s blocked.</string>
 
     <!-- Notification permission informational notification text -->
     <!-- Title for notification inviting users to review their notification settings [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0ccef91..d5298ac 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3937,7 +3937,6 @@
   <java-symbol type="string" name="notification_channel_usb" />
   <java-symbol type="string" name="notification_channel_heavy_weight_app" />
   <java-symbol type="string" name="notification_channel_system_changes" />
-  <java-symbol type="string" name="notification_channel_do_not_disturb" />
   <java-symbol type="string" name="notification_channel_accessibility_magnification" />
   <java-symbol type="string" name="notification_channel_accessibility_security_policy" />
   <java-symbol type="string" name="notification_channel_display" />
@@ -4164,11 +4163,6 @@
   <!-- For Wear devices -->
   <java-symbol type="array" name="config_wearActivityModeRadios" />
 
-  <java-symbol type="string" name="zen_upgrade_notification_title" />
-  <java-symbol type="string" name="zen_upgrade_notification_content" />
-  <java-symbol type="string" name="zen_upgrade_notification_visd_title" />
-  <java-symbol type="string" name="zen_upgrade_notification_visd_content" />
-
   <java-symbol type="string" name="review_notification_settings_title" />
   <java-symbol type="string" name="review_notification_settings_text" />
   <java-symbol type="string" name="review_notification_settings_remind_me_action" />
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index e9b137c..48e2620 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -2301,13 +2301,13 @@
 
     @Test
     @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
-    public void progressStyle_onProgressStepChange_visiblyDifferent() {
+    public void progressStyle_onProgressPointChange_visiblyDifferent() {
         final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.ProgressStyle()
-                        .addProgressStep(new Notification.ProgressStyle.Step(10)));
+                        .addProgressPoint(new Notification.ProgressStyle.Point(10)));
         final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.ProgressStyle()
-                        .addProgressStep(new Notification.ProgressStyle.Step(12)));
+                        .addProgressPoint(new Notification.ProgressStyle.Point(12)));
 
         assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2))
                 .isTrue();
@@ -2315,13 +2315,13 @@
 
     @Test
     @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
-    public void indeterminateProgressStyle_onProgressStepChange_visiblyNotDifferent() {
+    public void indeterminateProgressStyle_onProgressPointChange_visiblyNotDifferent() {
         final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true)
-                        .addProgressStep(new Notification.ProgressStyle.Step(10)));
+                        .addProgressPoint(new Notification.ProgressStyle.Point(10)));
         final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true)
-                        .addProgressStep(new Notification.ProgressStyle.Step(12)));
+                        .addProgressPoint(new Notification.ProgressStyle.Point(12)));
 
         assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2))
                 .isFalse();
diff --git a/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java b/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java
new file mode 100644
index 0000000..0bf406c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.notification;
+
+import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS;
+import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_MAGNIFICATION;
+import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_SECURITY_POLICY;
+import static com.android.internal.notification.SystemNotificationChannels.ACCOUNT;
+import static com.android.internal.notification.SystemNotificationChannels.ALERTS;
+import static com.android.internal.notification.SystemNotificationChannels.CAR_MODE;
+import static com.android.internal.notification.SystemNotificationChannels.DEVELOPER;
+import static com.android.internal.notification.SystemNotificationChannels.DEVELOPER_IMPORTANT;
+import static com.android.internal.notification.SystemNotificationChannels.DEVICE_ADMIN;
+import static com.android.internal.notification.SystemNotificationChannels.FOREGROUND_SERVICE;
+import static com.android.internal.notification.SystemNotificationChannels.HEAVY_WEIGHT_APP;
+import static com.android.internal.notification.SystemNotificationChannels.NETWORK_ALERTS;
+import static com.android.internal.notification.SystemNotificationChannels.NETWORK_AVAILABLE;
+import static com.android.internal.notification.SystemNotificationChannels.NETWORK_STATUS;
+import static com.android.internal.notification.SystemNotificationChannels.OBSOLETE_DO_NOT_DISTURB;
+import static com.android.internal.notification.SystemNotificationChannels.PHYSICAL_KEYBOARD;
+import static com.android.internal.notification.SystemNotificationChannels.RETAIL_MODE;
+import static com.android.internal.notification.SystemNotificationChannels.SECURITY;
+import static com.android.internal.notification.SystemNotificationChannels.SYSTEM_CHANGES;
+import static com.android.internal.notification.SystemNotificationChannels.UPDATES;
+import static com.android.internal.notification.SystemNotificationChannels.USB;
+import static com.android.internal.notification.SystemNotificationChannels.VPN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.verify;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.testing.TestableContext;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class SystemNotificationChannelsTest {
+
+    @Rule public TestableContext mContext = new TestableContext(
+            ApplicationProvider.getApplicationContext());
+
+    @Mock private NotificationManager mNm;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext.addMockSystemService(NotificationManager.class, mNm);
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void createAll_createsExpectedChannels() {
+        ArgumentCaptor<List<NotificationChannel>> createdChannelsCaptor =
+                ArgumentCaptor.forClass(List.class);
+
+        SystemNotificationChannels.createAll(mContext);
+
+        verify(mNm).createNotificationChannels(createdChannelsCaptor.capture());
+        List<NotificationChannel> createdChannels = createdChannelsCaptor.getValue();
+        assertThat(createdChannels.stream().map(NotificationChannel::getId).toList())
+                .containsExactly(PHYSICAL_KEYBOARD, SECURITY, CAR_MODE, ACCOUNT, DEVELOPER,
+                        DEVELOPER_IMPORTANT, UPDATES, NETWORK_STATUS, NETWORK_ALERTS,
+                        NETWORK_AVAILABLE, VPN, DEVICE_ADMIN, ALERTS, RETAIL_MODE, USB,
+                        FOREGROUND_SERVICE, HEAVY_WEIGHT_APP, SYSTEM_CHANGES,
+                        ACCESSIBILITY_MAGNIFICATION, ACCESSIBILITY_SECURITY_POLICY,
+                        ABUSIVE_BACKGROUND_APPS);
+    }
+
+    @Test
+    public void createAll_deletesObsoleteChannels() {
+        ArgumentCaptor<String> deletedChannelCaptor = ArgumentCaptor.forClass(String.class);
+
+        SystemNotificationChannels.createAll(mContext);
+
+        verify(mNm, atLeastOnce()).deleteNotificationChannel(deletedChannelCaptor.capture());
+        List<String> deletedChannels = deletedChannelCaptor.getAllValues();
+        assertThat(deletedChannels).containsExactly(OBSOLETE_DO_NOT_DISTURB);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index af4a0c5..03b7c8b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -2001,6 +2001,10 @@
             // in bubble bar mode, let the request to show the expanded view come from launcher.
             // only collapse here if we're collapsing.
             if (mLayerView != null && !isExpanded) {
+                if (mBubblePositioner.isImeVisible()) {
+                    // If we're collapsing, hide the IME
+                    hideCurrentInputMethod();
+                }
                 mLayerView.collapse();
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index ec235a5..2a90017 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -353,6 +353,11 @@
         if (isDragging != mIsDragging) {
             mIsDragging = isDragging;
             updateSamplingState();
+
+            if (isDragging && mPositioner.isImeVisible()) {
+                // Hide the IME when dragging begins
+                mManager.hideCurrentInputMethod();
+            }
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
index b1b7d05..5a277316f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
@@ -19,6 +19,7 @@
 import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.protolog.ProtoLog
 import com.android.internal.util.FrameworkStatsLog
+import com.android.window.flags.Flags
 import com.android.wm.shell.EventLogTags
 import com.android.wm.shell.protolog.ShellProtoLogGroup
 
@@ -79,7 +80,8 @@
         )
         logTaskUpdate(
             FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED,
-            sessionId, taskUpdate)
+            sessionId, taskUpdate
+        )
     }
 
     /**
@@ -95,7 +97,8 @@
         )
         logTaskUpdate(
             FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED,
-            sessionId, taskUpdate)
+            sessionId, taskUpdate
+        )
     }
 
     /**
@@ -111,7 +114,46 @@
         )
         logTaskUpdate(
             FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED,
-            sessionId, taskUpdate)
+            sessionId, taskUpdate
+        )
+    }
+
+    /**
+     * Logs that a task resize event is starting with [taskSizeUpdate] within a
+     * Desktop mode [sessionId].
+     */
+    fun logTaskResizingStarted(sessionId: Int, taskSizeUpdate: TaskSizeUpdate) {
+        if (!Flags.enableResizingMetrics()) return
+
+        ProtoLog.v(
+            ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+            "DesktopModeLogger: Logging task resize is starting, session: %s taskId: %s",
+            sessionId,
+            taskSizeUpdate.instanceId
+        )
+        logTaskSizeUpdated(
+            FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE,
+            sessionId, taskSizeUpdate
+        )
+    }
+
+    /**
+     * Logs that a task resize event is ending with [taskSizeUpdate] within a
+     * Desktop mode [sessionId].
+     */
+    fun logTaskResizingEnded(sessionId: Int, taskSizeUpdate: TaskSizeUpdate) {
+        if (!Flags.enableResizingMetrics()) return
+
+        ProtoLog.v(
+            ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+            "DesktopModeLogger: Logging task resize is ending, session: %s taskId: %s",
+            sessionId,
+            taskSizeUpdate.instanceId
+        )
+        logTaskSizeUpdated(
+            FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE,
+            sessionId, taskSizeUpdate
+        )
     }
 
     private fun logTaskUpdate(taskEvent: Int, sessionId: Int, taskUpdate: TaskUpdate) {
@@ -162,6 +204,34 @@
         )
     }
 
+    private fun logTaskSizeUpdated(
+        resizingStage: Int,
+        sessionId: Int,
+        taskSizeUpdate: TaskSizeUpdate
+    ) {
+        FrameworkStatsLog.write(
+            DESKTOP_MODE_TASK_SIZE_UPDATED_ATOM_ID,
+            /* resize_trigger */
+            taskSizeUpdate.resizeTrigger?.trigger ?: ResizeTrigger.UNKNOWN_RESIZE_TRIGGER.trigger,
+            /* resizing_stage */
+            resizingStage,
+            /* input_method */
+            taskSizeUpdate.inputMethod?.method ?: InputMethod.UNKNOWN_INPUT_METHOD.method,
+            /* desktop_mode_session_id */
+            sessionId,
+            /* instance_id */
+            taskSizeUpdate.instanceId,
+            /* uid */
+            taskSizeUpdate.uid,
+            /* task_height */
+            taskSizeUpdate.taskHeight,
+            /* task_width */
+            taskSizeUpdate.taskWidth,
+            /* display_area */
+            taskSizeUpdate.displayArea
+        )
+    }
+
     companion object {
         /**
          * Describes a task position and dimensions.
@@ -188,13 +258,35 @@
             val visibleTaskCount: Int,
         )
 
+        /**
+         * Describes a task size update (resizing, snapping or maximizing to
+         * stable bounds).
+         *
+         * @property resizeTrigger the trigger for task resize
+         * @property inputMethod the input method for resizing this task
+         * @property instanceId instance id of the task
+         * @property uid uid of the app associated with the task
+         * @property taskHeight height of the task in dp
+         * @property taskWidth width of the task in dp
+         * @property displayArea the display size of the screen in dp
+         */
+        data class TaskSizeUpdate(
+            val resizeTrigger: ResizeTrigger? = null,
+            val inputMethod: InputMethod? = null,
+            val instanceId: Int,
+            val uid: Int,
+            val taskHeight: Int,
+            val taskWidth: Int,
+            val displayArea: Int,
+        )
+
         // Default value used when the task was not minimized.
         @VisibleForTesting
         const val UNSET_MINIMIZE_REASON =
             FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__UNSET_MINIMIZE
 
         /** The reason a task was minimized. */
-        enum class MinimizeReason (val reason: Int) {
+        enum class MinimizeReason(val reason: Int) {
             TASK_LIMIT(
                 FrameworkStatsLog
                     .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_TASK_LIMIT
@@ -211,7 +303,7 @@
             FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNSET_UNMINIMIZE
 
         /** The reason a task was unminimized. */
-        enum class UnminimizeReason (val reason: Int) {
+        enum class UnminimizeReason(val reason: Int) {
             UNKNOWN(
                 FrameworkStatsLog
                     .DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_UNKNOWN
@@ -275,8 +367,88 @@
             SCREEN_OFF(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__SCREEN_OFF)
         }
 
+        /**
+         * Enum ResizeTrigger mapped to the ResizeTrigger definition in
+         * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto
+         */
+        enum class ResizeTrigger(val trigger: Int) {
+            UNKNOWN_RESIZE_TRIGGER(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER
+            ),
+            CORNER(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER
+            ),
+            EDGE(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__EDGE_RESIZE_TRIGGER
+            ),
+            TILING_DIVIDER(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__TILING_DIVIDER_RESIZE_TRIGGER
+            ),
+            MAXIMIZE_BUTTON(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__MAXIMIZE_BUTTON_RESIZE_TRIGGER
+            ),
+            DOUBLE_TAP_APP_HEADER(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DOUBLE_TAP_APP_HEADER_RESIZE_TRIGGER
+            ),
+            DRAG_LEFT(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DRAG_LEFT_RESIZE_TRIGGER
+            ),
+            DRAG_RIGHT(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DRAG_RIGHT_RESIZE_TRIGGER
+            ),
+            SNAP_LEFT_MENU(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_LEFT_MENU_RESIZE_TRIGGER
+            ),
+            SNAP_RIGHT_MENU(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_RIGHT_MENU_RESIZE_TRIGGER
+            ),
+        }
+
+        /**
+         * Enum InputMethod mapped to the InputMethod definition in
+         * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto
+         */
+        enum class InputMethod(val method: Int) {
+            UNKNOWN_INPUT_METHOD(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD
+            ),
+            TOUCH(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__TOUCH_INPUT_METHOD
+            ),
+            STYLUS(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__STYLUS_INPUT_METHOD
+            ),
+            MOUSE(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__MOUSE_INPUT_METHOD
+            ),
+            TOUCHPAD(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__TOUCHPAD_INPUT_METHOD
+            ),
+            KEYBOARD(
+                FrameworkStatsLog
+                    .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__KEYBOARD_INPUT_METHOD
+            ),
+        }
+
         private const val DESKTOP_MODE_ATOM_ID = FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED
         private const val DESKTOP_MODE_TASK_UPDATE_ATOM_ID =
             FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE
+        private const val DESKTOP_MODE_TASK_SIZE_UPDATED_ATOM_ID =
+            FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index b8bb73b..fcd2f8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -406,7 +406,7 @@
         interactionJankMonitor.begin(taskSurface, context, handler,
             CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD)
         dragToDesktopTransitionHandler.startDragToDesktopTransition(
-            taskInfo.taskId,
+            taskInfo,
             dragToDesktopValueAnimator
         )
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index 2bc01b2..8e264b2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -109,8 +109,8 @@
      * after one of the "end" or "cancel" transitions is merged into this transition.
      */
     fun startDragToDesktopTransition(
-        taskId: Int,
-        dragToDesktopAnimator: MoveToDesktopAnimator,
+        taskInfo: RunningTaskInfo,
+        dragToDesktopAnimator: MoveToDesktopAnimator
     ) {
         if (inProgress) {
             ProtoLog.v(
@@ -137,23 +137,26 @@
             )
         val wct = WindowContainerTransaction()
         wct.sendPendingIntent(pendingIntent, launchHomeIntent, Bundle())
+        // The home launch done above will result in an attempt to move the task to pip if
+        // applicable, resulting in a broken state. Prevent that here.
+        wct.setDoNotPip(taskInfo.token)
         val startTransitionToken =
             transitions.startTransition(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP, wct, this)
 
         transitionState =
-            if (isSplitTask(taskId)) {
+            if (isSplitTask(taskInfo.taskId)) {
                 val otherTask =
-                    getOtherSplitTask(taskId)
+                    getOtherSplitTask(taskInfo.taskId)
                         ?: throw IllegalStateException("Expected split task to have a counterpart.")
                 TransitionState.FromSplit(
-                    draggedTaskId = taskId,
+                    draggedTaskId = taskInfo.taskId,
                     dragAnimator = dragToDesktopAnimator,
                     startTransitionToken = startTransitionToken,
                     otherSplitTask = otherTask
                 )
             } else {
                 TransitionState.FromFullscreen(
-                    draggedTaskId = taskId,
+                    draggedTaskId = taskInfo.taskId,
                     dragAnimator = dragToDesktopAnimator,
                     startTransitionToken = startTransitionToken
                 )
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 03ff1aa..c9c0873 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
+import android.graphics.Point;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -46,6 +47,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.protolog.ProtoLog;
+import com.android.window.flags.Flags;
 import com.android.wm.shell.common.ExternalInterfaceBinder;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
@@ -421,6 +423,16 @@
                 if (mostRecentFreeformTaskIndex == Integer.MAX_VALUE) {
                     mostRecentFreeformTaskIndex = recentTasks.size();
                 }
+                // If task has their app bounds set to null which happens after reboot, set the
+                // app bounds to persisted lastFullscreenBounds. Also set the position in parent
+                // to the top left of the bounds.
+                if (Flags.enableDesktopWindowingPersistence()
+                        && taskInfo.configuration.windowConfiguration.getAppBounds() == null) {
+                    taskInfo.configuration.windowConfiguration.setAppBounds(
+                            taskInfo.lastNonFullscreenBounds);
+                    taskInfo.positionInParent = new Point(taskInfo.lastNonFullscreenBounds.left,
+                            taskInfo.lastNonFullscreenBounds.top);
+                }
                 freeformTasks.add(taskInfo);
                 if (mDesktopModeTaskRepository.get().isMinimizedTask(taskInfo.taskId)) {
                     minimizedFreeformTasks.add(taskInfo.taskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 5daa3ee..ada1e0b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -824,6 +824,7 @@
                         WindowInsets.Type.systemBars() & ~WindowInsets.Type.captionBar(),
                         false /* ignoreVisibility */);
                 relayoutParams.mCaptionTopPadding = systemBarInsets.top;
+                relayoutParams.mIsInsetSource = false;
             }
             // Report occluding elements as bounding rects to the insets system so that apps can
             // draw in the empty space in the center:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 000beba1..f8aed41 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -346,7 +346,7 @@
 
     private void updateCaptionInsets(RelayoutParams params, WindowContainerTransaction wct,
             RelayoutResult<T> outResult, Rect taskBounds) {
-        if (!mIsCaptionVisible) {
+        if (!mIsCaptionVisible || !params.mIsInsetSource) {
             if (mWindowDecorationInsets != null) {
                 mWindowDecorationInsets.remove(wct);
                 mWindowDecorationInsets = null;
@@ -724,6 +724,7 @@
         int mCaptionWidthId;
         final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
         int mInputFeatures;
+        boolean mIsInsetSource = true;
         @InsetsSource.Flags int mInsetSourceFlags;
 
         int mShadowRadiusId;
@@ -743,6 +744,7 @@
             mCaptionWidthId = Resources.ID_NULL;
             mOccludingCaptionElements.clear();
             mInputFeatures = 0;
+            mIsInsetSource = true;
             mInsetSourceFlags = 0;
 
             mShadowRadiusId = Resources.ID_NULL;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
index 6a5719b..d7a132d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
@@ -16,15 +16,22 @@
 
 package com.android.wm.shell.desktopmode
 
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
 import com.android.dx.mockito.inline.extended.ExtendedMockito.verify
 import com.android.internal.util.FrameworkStatsLog
 import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.android.window.flags.Flags
 import com.android.wm.shell.EventLogTags
 import com.android.wm.shell.ShellTestCase
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskSizeUpdate
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_MINIMIZE_REASON
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON
@@ -41,11 +48,15 @@
     private val desktopModeEventLogger = DesktopModeEventLogger()
 
     @JvmField
-    @Rule
+    @Rule(order = 0)
     val extendedMockitoRule = ExtendedMockitoRule.Builder(this)
             .mockStatic(FrameworkStatsLog::class.java)
             .mockStatic(EventLogTags::class.java).build()!!
 
+    @JvmField
+    @Rule(order = 1)
+    val setFlagsRule = SetFlagsRule()
+
     @Test
     fun logSessionEnter_enterReason() = runBlocking {
         desktopModeEventLogger.logSessionEnter(sessionId = SESSION_ID, EnterReason.UNKNOWN_ENTER)
@@ -328,7 +339,65 @@
         }
     }
 
-    companion object {
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_RESIZING_METRICS)
+    fun logTaskResizingStarted_logsTaskSizeUpdatedWithStartResizingStage() = runBlocking {
+        desktopModeEventLogger.logTaskResizingStarted(sessionId = SESSION_ID, createTaskSizeUpdate())
+
+        verify {
+            FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED),
+                /* resize_trigger */
+                eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER),
+                /* resizing_stage */
+                eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE),
+                /* input_method */
+                eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD),
+                /* desktop_mode_session_id */
+                eq(SESSION_ID),
+                /* instance_id */
+                eq(TASK_SIZE_UPDATE.instanceId),
+                /* uid */
+                eq(TASK_SIZE_UPDATE.uid),
+                /* task_height */
+                eq(TASK_SIZE_UPDATE.taskHeight),
+                /* task_width */
+                eq(TASK_SIZE_UPDATE.taskWidth),
+                /* display_area */
+                eq(TASK_SIZE_UPDATE.displayArea),
+            )
+        }
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_RESIZING_METRICS)
+    fun logTaskResizingEnded_logsTaskSizeUpdatedWithEndResizingStage() = runBlocking {
+        desktopModeEventLogger.logTaskResizingEnded(sessionId = SESSION_ID, createTaskSizeUpdate())
+
+        verify {
+            FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED),
+                /* resize_trigger */
+                eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER),
+                /* resizing_stage */
+                eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE),
+                /* input_method */
+                eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD),
+                /* desktop_mode_session_id */
+                eq(SESSION_ID),
+                /* instance_id */
+                eq(TASK_SIZE_UPDATE.instanceId),
+                /* uid */
+                eq(TASK_SIZE_UPDATE.uid),
+                /* task_height */
+                eq(TASK_SIZE_UPDATE.taskHeight),
+                /* task_width */
+                eq(TASK_SIZE_UPDATE.taskWidth),
+                /* display_area */
+                eq(TASK_SIZE_UPDATE.displayArea),
+            )
+        }
+    }
+
+    private companion object {
         private const val SESSION_ID = 1
         private const val TASK_ID = 1
         private const val TASK_UID = 1
@@ -337,12 +406,36 @@
         private const val TASK_HEIGHT = 100
         private const val TASK_WIDTH = 100
         private const val TASK_COUNT = 1
+        private const val DISPLAY_AREA = 1000
 
         private val TASK_UPDATE = TaskUpdate(
             TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y,
             visibleTaskCount = TASK_COUNT,
         )
 
+        private val TASK_SIZE_UPDATE = TaskSizeUpdate(
+            resizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER,
+            inputMethod = InputMethod.UNKNOWN_INPUT_METHOD,
+            TASK_ID,
+            TASK_UID,
+            TASK_HEIGHT,
+            TASK_WIDTH,
+            DISPLAY_AREA,
+        )
+
+        private fun createTaskSizeUpdate(
+            resizeTrigger: ResizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER,
+            inputMethod: InputMethod = InputMethod.UNKNOWN_INPUT_METHOD,
+        ) = TaskSizeUpdate(
+            resizeTrigger,
+            inputMethod,
+            TASK_ID,
+            TASK_UID,
+            TASK_HEIGHT,
+            TASK_WIDTH,
+            DISPLAY_AREA,
+        )
+
         private fun createTaskUpdate(
             minimizeReason: MinimizeReason? = null,
             unminimizeReason: UnminimizeReason? = null,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
index d9387d2..230f7e6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
@@ -581,7 +581,7 @@
                 )
             )
             .thenReturn(token)
-        handler.startDragToDesktopTransition(task.taskId, dragAnimator)
+        handler.startDragToDesktopTransition(task, dragAnimator)
         return token
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 753d4cd..0364b51 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -22,6 +22,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE;
 import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
 
 import static org.junit.Assert.assertEquals;
@@ -50,6 +51,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.platform.test.annotations.DisableFlags;
@@ -441,6 +443,40 @@
     }
 
     @Test
+    @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE)
+    public void testGetRecentTasks_hasDesktopTasks_persistenceEnabled_freeformTaskHaveBoundsSet() {
+        ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
+        ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
+
+        t1.lastNonFullscreenBounds = new Rect(100, 200, 300, 400);
+        t2.lastNonFullscreenBounds = new Rect(150, 250, 350, 450);
+        setRawList(t1, t2);
+
+        when(mDesktopModeTaskRepository.isActiveTask(1)).thenReturn(true);
+        when(mDesktopModeTaskRepository.isActiveTask(2)).thenReturn(true);
+
+        ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks(
+                MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
+
+        assertEquals(1, recentTasks.size());
+        GroupedRecentTaskInfo freeformGroup = recentTasks.get(0);
+
+        // Check bounds
+        assertEquals(t1.lastNonFullscreenBounds, freeformGroup.getTaskInfoList().get(
+                0).configuration.windowConfiguration.getAppBounds());
+        assertEquals(t2.lastNonFullscreenBounds, freeformGroup.getTaskInfoList().get(
+                1).configuration.windowConfiguration.getAppBounds());
+
+        // Check position in parent
+        assertEquals(new Point(t1.lastNonFullscreenBounds.left,
+                        t1.lastNonFullscreenBounds.top),
+                freeformGroup.getTaskInfoList().get(0).positionInParent);
+        assertEquals(new Point(t2.lastNonFullscreenBounds.left,
+                        t2.lastNonFullscreenBounds.top),
+                freeformGroup.getTaskInfoList().get(1).positionInParent);
+    }
+
+    @Test
     public void testRemovedTaskRemovesSplit() {
         ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
         ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
@@ -623,6 +659,7 @@
     private ActivityManager.RecentTaskInfo makeTaskInfo(int taskId) {
         ActivityManager.RecentTaskInfo info = new ActivityManager.RecentTaskInfo();
         info.taskId = taskId;
+        info.lastNonFullscreenBounds = new Rect();
         return info;
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 3e7f3bd..ed752fd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -619,6 +619,27 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
+    public void updateRelayoutParams_header_notAnInsetsSourceInFullyImmersive() {
+        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        final RelayoutParams relayoutParams = new RelayoutParams();
+
+        DesktopModeWindowDecoration.updateRelayoutParams(
+                relayoutParams,
+                mTestableContext,
+                taskInfo,
+                /* applyStartTransactionOnDraw= */ true,
+                /* shouldSetTaskPositionAndCrop */ false,
+                /* isStatusBarVisible */ true,
+                /* isKeyguardVisibleAndOccluded */ false,
+                /* inFullImmersiveMode */ true,
+                new InsetsState());
+
+        assertThat(relayoutParams.mIsInsetSource).isFalse();
+    }
+
+    @Test
     @DisableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
     public void updateRelayoutParams_header_statusBarInvisible_captionVisible() {
         final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 94cabc4..54dd15ba 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -650,6 +650,57 @@
     }
 
     @Test
+    public void testRelayout_notAnInsetsSource_doesNotAddInsets() {
+        final Display defaultDisplay = mock(Display.class);
+        doReturn(defaultDisplay).when(mMockDisplayController)
+                .getDisplay(Display.DEFAULT_DISPLAY);
+
+        final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+                .setDisplayId(Display.DEFAULT_DISPLAY)
+                .setVisible(true)
+                .setBounds(new Rect(0, 0, 1000, 1000))
+                .build();
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+        mRelayoutParams.mIsInsetSource = false;
+        windowDecor.relayout(taskInfo);
+
+        // Never added.
+        verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
+                eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
+        verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
+                eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
+    }
+
+    @Test
+    public void testRelayout_notAnInsetsSource_hadInsetsBefore_removesInsets() {
+        final Display defaultDisplay = mock(Display.class);
+        doReturn(defaultDisplay).when(mMockDisplayController)
+                .getDisplay(Display.DEFAULT_DISPLAY);
+
+        final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+                .setDisplayId(Display.DEFAULT_DISPLAY)
+                .setVisible(true)
+                .setBounds(new Rect(0, 0, 1000, 1000))
+                .build();
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+
+        mRelayoutParams.mIsCaptionVisible = true;
+        mRelayoutParams.mIsInsetSource = true;
+        windowDecor.relayout(taskInfo);
+
+        mRelayoutParams.mIsCaptionVisible = true;
+        mRelayoutParams.mIsInsetSource = false;
+        windowDecor.relayout(taskInfo);
+
+        // Insets should be removed.
+        verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
+                eq(0) /* index */, eq(captionBar()));
+        verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(),
+                eq(0) /* index */, eq(mandatorySystemGestures()));
+    }
+
+    @Test
     public void testClose_withExistingInsets_insetsRemoved() {
         final Display defaultDisplay = mock(Display.class);
         doReturn(defaultDisplay).when(mMockDisplayController)
diff --git a/libs/appfunctions/api/current.txt b/libs/appfunctions/api/current.txt
index bb0fc41..bc269fe 100644
--- a/libs/appfunctions/api/current.txt
+++ b/libs/appfunctions/api/current.txt
@@ -16,7 +16,7 @@
     ctor public AppFunctionService();
     method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
     method @MainThread public void onExecuteFunction(@NonNull com.google.android.appfunctions.sidecar.ExecuteAppFunctionRequest, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse>);
-    method @Deprecated @MainThread public abstract void onExecuteFunction(@NonNull com.google.android.appfunctions.sidecar.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse>);
+    method @Deprecated @MainThread public void onExecuteFunction(@NonNull com.google.android.appfunctions.sidecar.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse>);
     field @NonNull public static final String BIND_APP_FUNCTION_SERVICE = "android.permission.BIND_APP_FUNCTION_SERVICE";
     field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
   }
@@ -45,12 +45,12 @@
     method @NonNull public static com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse newSuccess(@NonNull android.app.appsearch.GenericDocument, @Nullable android.os.Bundle);
     field public static final String PROPERTY_RETURN_VALUE = "returnValue";
     field public static final int RESULT_APP_UNKNOWN_ERROR = 2; // 0x2
+    field public static final int RESULT_CANCELLED = 6; // 0x6
     field public static final int RESULT_DENIED = 1; // 0x1
-    field public static final int RESULT_DISABLED = 6; // 0x6
+    field public static final int RESULT_DISABLED = 5; // 0x5
     field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3
     field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4
     field public static final int RESULT_OK = 0; // 0x0
-    field public static final int RESULT_TIMED_OUT = 5; // 0x5
   }
 
 }
diff --git a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java
index 6023c97..6e91de6 100644
--- a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java
+++ b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java
@@ -26,6 +26,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.CancellationSignal;
+import android.util.Log;
 
 import java.util.function.Consumer;
 
@@ -143,7 +144,11 @@
      */
     @MainThread
     @Deprecated
-    public abstract void onExecuteFunction(
+    public void onExecuteFunction(
             @NonNull ExecuteAppFunctionRequest request,
-            @NonNull Consumer<ExecuteAppFunctionResponse> callback);
+            @NonNull Consumer<ExecuteAppFunctionResponse> callback) {
+        Log.w(
+                "AppFunctionService",
+                "Calling deprecated default implementation of onExecuteFunction");
+    }
 }
diff --git a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java
index c7ce95b..d87fec79 100644
--- a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java
+++ b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java
@@ -73,11 +73,14 @@
      */
     public static final int RESULT_INVALID_ARGUMENT = 4;
 
-    /** The operation was timed out. */
-    public static final int RESULT_TIMED_OUT = 5;
-
     /** The caller tried to execute a disabled app function. */
-    public static final int RESULT_DISABLED = 6;
+    public static final int RESULT_DISABLED = 5;
+
+    /**
+     * The operation was cancelled. Use this error code to report that a cancellation is done after
+     * receiving a cancellation signal.
+     */
+    public static final int RESULT_CANCELLED = 6;
 
     /** The result code of the app function execution. */
     @ResultCode private final int mResultCode;
@@ -236,7 +239,6 @@
                     RESULT_APP_UNKNOWN_ERROR,
                     RESULT_INTERNAL_ERROR,
                     RESULT_INVALID_ARGUMENT,
-                    RESULT_TIMED_OUT,
                     RESULT_DISABLED
             })
     @Retention(RetentionPolicy.SOURCE)
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index 27add35..4305196 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -141,6 +141,13 @@
         return;
     }
 
+    if (!RenderThread::isCurrent()) {
+        // releaseQueueOwnership needs to run on RenderThread to prevent multithread calling
+        // setBackendTextureState will operate skia resource cache which need single owner
+        RenderThread::getInstance().queue().post([this, context]() { releaseQueueOwnership(context); });
+        return;
+    }
+
     LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
     if (mBackendTexture.isValid()) {
         // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout.
diff --git a/libs/hwui/Gainmap.cpp b/libs/hwui/Gainmap.cpp
index 30f401e..ea955e2 100644
--- a/libs/hwui/Gainmap.cpp
+++ b/libs/hwui/Gainmap.cpp
@@ -15,12 +15,37 @@
  */
 #include "Gainmap.h"
 
+#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkColorFilter.h>
+#include <SkImagePriv.h>
+#include <SkPaint.h>
+
+#include "HardwareBitmapUploader.h"
+
 namespace android::uirenderer {
 
 sp<Gainmap> Gainmap::allocateHardwareGainmap(const sp<Gainmap>& srcGainmap) {
     auto gainmap = sp<Gainmap>::make();
     gainmap->info = srcGainmap->info;
-    const SkBitmap skSrcBitmap = srcGainmap->bitmap->getSkBitmap();
+    SkBitmap skSrcBitmap = srcGainmap->bitmap->getSkBitmap();
+    if (skSrcBitmap.info().colorType() == kAlpha_8_SkColorType &&
+        !HardwareBitmapUploader::hasAlpha8Support()) {
+        // The regular Bitmap::allocateHardwareBitmap will do a conversion that preserves channels,
+        // so alpha8 maps to the alpha channel of rgba. However, for gainmaps we will interpret
+        // the data of an rgba buffer differently as we'll only look at the rgb channels
+        // So we need to map alpha8 to rgbx_8888 essentially
+        SkBitmap bitmap;
+        bitmap.allocPixels(skSrcBitmap.info().makeColorType(kN32_SkColorType));
+        SkCanvas canvas(bitmap);
+        SkPaint paint;
+        const float alphaToOpaque[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
+                                       0, 0, 0, 1, 0, 0, 0, 0, 0, 255};
+        paint.setColorFilter(SkColorFilters::Matrix(alphaToOpaque, SkColorFilters::Clamp::kNo));
+        canvas.drawImage(SkMakeImageFromRasterBitmap(skSrcBitmap, kNever_SkCopyPixelsMode), 0, 0,
+                         SkSamplingOptions{}, &paint);
+        skSrcBitmap = bitmap;
+    }
     sk_sp<Bitmap> skBitmap(Bitmap::allocateHardwareBitmap(skSrcBitmap));
     if (!skBitmap.get()) {
         return nullptr;
diff --git a/libs/hwui/jni/graphics_jni_helpers.h b/libs/hwui/jni/graphics_jni_helpers.h
index 78db54a..91db134 100644
--- a/libs/hwui/jni/graphics_jni_helpers.h
+++ b/libs/hwui/jni/graphics_jni_helpers.h
@@ -80,9 +80,52 @@
     return static_cast<T>(res);
 }
 
+//  Inline variable that specifies the method binding format.
+//  The expected format is 'XX${method}XX', where ${method} represents the original method name.
+//  This variable is shared across all translation units. This is treated as a global variable as
+//  per C++ 17.
+inline std::string jniMethodFormat;
+
+inline static void setJniMethodFormat(std::string value) {
+    jniMethodFormat = value;
+}
+
+// Register the native methods, potenially applying the jniMethodFormat if it has been set.
+static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className,
+                                                       const JNINativeMethod* gMethods,
+                                                       int numMethods) {
+    if (jniMethodFormat.empty()) {
+        return jniRegisterNativeMethods(env, className, gMethods, numMethods);
+    }
+
+    // Make a copy of gMethods with reformatted method names.
+    JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods];
+    LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods");
+
+    size_t methodNamePos = jniMethodFormat.find("${method}");
+    LOG_ALWAYS_FATAL_IF(methodNamePos == std::string::npos,
+                        "Invalid jniMethodFormat: could not find '${method}' in pattern");
+
+    for (int i = 0; i < numMethods; i++) {
+        modifiedMethods[i] = gMethods[i];
+        std::string modifiedName = jniMethodFormat;
+        modifiedName.replace(methodNamePos, 9, gMethods[i].name);
+        char* modifiedNameChars = new char[modifiedName.length() + 1];
+        LOG_ALWAYS_FATAL_IF(!modifiedNameChars, "Failed to allocate the new method name");
+        std::strcpy(modifiedNameChars, modifiedName.c_str());
+        modifiedMethods[i].name = modifiedNameChars;
+    }
+    int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods);
+    for (int i = 0; i < numMethods; i++) {
+        delete[] modifiedMethods[i].name;
+    }
+    delete[] modifiedMethods;
+    return res;
+}
+
 static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
                                        const JNINativeMethod* gMethods, int numMethods) {
-    int res = jniRegisterNativeMethods(env, className, gMethods, numMethods);
+    int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods);
     LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
     return res;
 }
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index bc5b691..b266912 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -50,13 +50,13 @@
     <!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
 
     <!-- Confirmation for associating an application with a companion device of APP_STREAMING profile (type) [CHAR LIMIT=NONE] -->
-    <string name="title_app_streaming">Allow &lt;strong&gt;<xliff:g id="app_name" example="Exo">%1$s</xliff:g>&lt;/strong&gt; to stream apps and system features between your <xliff:g id="device_type" example="phone">%2$s</xliff:g> and &lt;strong&gt;<xliff:g id="device_name" example="Chromebook">%3$s</xliff:g>&lt;/strong&gt;?</string>
+    <string name="title_app_streaming">Allow &lt;strong&gt;<xliff:g id="app_name" example="Exo">%1$s</xliff:g>&lt;/strong&gt; to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps and system features to &lt;strong&gt;<xliff:g id="device_name" example="Chromebook">%3$s</xliff:g>&lt;/strong&gt;?</string>
 
     <!-- Summary for associating an application with a companion device of APP_STREAMING profile [CHAR LIMIT=NONE] -->
-    <string name="summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, payment info, passwords and messages.&lt;br/>&lt;br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string>
+    <string name="summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.&lt;br/>&lt;br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string>
 
     <!-- Description of the helper dialog for APP_STREAMING profile. [CHAR LIMIT=NONE] -->
-    <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to stream apps and system features between your devices</string>
+    <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to stream apps and system features from your <xliff:g id="device_type" example="phone">%3$s</xliff:g></string>
 
     <!-- ================= DEVICE_PROFILE_AUTOMOTIVE_PROJECTION ================= -->
 
@@ -83,7 +83,7 @@
     <string name="title_nearby_device_streaming">Allow &lt;strong&gt;<xliff:g id="app_name" example="Exo">%1$s</xliff:g>&lt;/strong&gt; to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps to &lt;strong&gt;<xliff:g id="device_name" example="Chromebook">%3$s</xliff:g>&lt;/strong&gt;?</string>
 
     <!-- Summary for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile [CHAR LIMIT=NONE] -->
-    <string name="summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g>, including audio, photos, payment info, passwords and messages.&lt;br/>&lt;br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string>
+    <string name="summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g>, including audio, photos, payment info, passwords, and messages.&lt;br/>&lt;br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string>
 
     <!-- Description of the helper dialog for NEARBY_DEVICE_STREAMING profile. [CHAR LIMIT=NONE] -->
     <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to stream apps from your <xliff:g id="device_type" example="phone">%3$s</xliff:g></string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 9d56c77..744e97e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -30,9 +30,10 @@
 import android.icu.text.NumberFormat;
 import android.location.LocationManager;
 import android.media.AudioManager;
+import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
 import android.net.TetheringManager;
-import android.net.vcn.VcnTransportInfo;
+import android.net.vcn.VcnUtils;
 import android.net.wifi.WifiInfo;
 import android.os.BatteryManager;
 import android.os.Build;
@@ -737,14 +738,9 @@
      * @param networkCapabilities NetworkCapabilities of the network.
      */
     @Nullable
-    public static WifiInfo tryGetWifiInfoForVcn(NetworkCapabilities networkCapabilities) {
-        if (networkCapabilities.getTransportInfo() == null
-                || !(networkCapabilities.getTransportInfo() instanceof VcnTransportInfo)) {
-            return null;
-        }
-        VcnTransportInfo vcnTransportInfo =
-                (VcnTransportInfo) networkCapabilities.getTransportInfo();
-        return vcnTransportInfo.getWifiInfo();
+    public static WifiInfo tryGetWifiInfoForVcn(
+            ConnectivityManager connectivityMgr, NetworkCapabilities networkCapabilities) {
+        return VcnUtils.getWifiInfoFromVcnCaps(connectivityMgr, networkCapabilities);
     }
 
     /** Whether there is any incompatible chargers in the current UsbPort? */
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 015356e..cea3d17 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -30,6 +30,7 @@
 import android.net.ScoredNetwork;
 import android.net.TransportInfo;
 import android.net.vcn.VcnTransportInfo;
+import android.net.vcn.VcnUtils;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkScoreCache;
@@ -394,10 +395,7 @@
 
         TransportInfo transportInfo = networkCapabilities.getTransportInfo();
         if (transportInfo instanceof VcnTransportInfo) {
-            // This VcnTransportInfo logic is copied from
-            // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
-            // re-used because it makes the logic here clearer.
-            return ((VcnTransportInfo) transportInfo).getWifiInfo();
+            return VcnUtils.getWifiInfoFromVcnCaps(mConnectivityManager, networkCapabilities);
         } else if (transportInfo instanceof WifiInfo) {
             return (WifiInfo) transportInfo;
         } else {
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 5e31da4..4dc8424 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -168,10 +168,6 @@
         Settings.Secure.SHOW_NOTIFICATION_SNOOZE,
         Settings.Secure.NOTIFICATION_HISTORY_ENABLED,
         Settings.Secure.ZEN_DURATION,
-        Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION,
-        Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION,
-        Settings.Secure.ZEN_SETTINGS_UPDATED,
-        Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED,
         Settings.Secure.CHARGING_SOUNDS_ENABLED,
         Settings.Secure.CHARGING_VIBRATION_ENABLED,
         Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index b3f7374..688676d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -247,10 +247,6 @@
         VALIDATORS.put(Secure.SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.NOTIFICATION_HISTORY_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ZEN_DURATION, ANY_INTEGER_VALIDATOR);
-        VALIDATORS.put(Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Secure.SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Secure.ZEN_SETTINGS_UPDATED, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3c24f5c..2034f36 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2734,18 +2734,6 @@
                 Settings.Secure.ZEN_DURATION,
                 SecureSettingsProto.Zen.DURATION);
         dumpSetting(s, p,
-                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION,
-                SecureSettingsProto.Zen.SHOW_ZEN_UPGRADE_NOTIFICATION);
-        dumpSetting(s, p,
-                Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION,
-                SecureSettingsProto.Zen.SHOW_ZEN_SETTINGS_SUGGESTION);
-        dumpSetting(s, p,
-                Settings.Secure.ZEN_SETTINGS_UPDATED,
-                SecureSettingsProto.Zen.SETTINGS_UPDATED);
-        dumpSetting(s, p,
-                Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED,
-                SecureSettingsProto.Zen.SETTINGS_SUGGESTION_VIEWED);
-        dumpSetting(s, p,
                 Settings.Secure.CHARGE_OPTIMIZATION_MODE,
                 SecureSettingsProto.CHARGE_OPTIMIZATION_MODE);
         p.end(zenToken);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 749ad0a..a8af43f5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4771,9 +4771,9 @@
                 }
 
                 if (currentVersion == 169) {
-                    // Version 169: Set the default value for Secure Settings ZEN_DURATION,
-                    // SHOW_ZEN_SETTINGS_SUGGESTION, ZEN_SETTINGS_UPDATE and
-                    // ZEN_SETTINGS_SUGGESTION_VIEWED
+                    // Version 169: Set the default value for Secure Settings ZEN_DURATION.
+                    // Also used to update SHOW_ZEN_SETTINGS_SUGGESTION, ZEN_SETTINGS_UPDATE and
+                    // ZEN_SETTINGS_SUGGESTION_VIEWED, but those properties are gone now.
 
                     final SettingsState globalSettings = getGlobalSettingsLocked();
                     final Setting globalZenDuration = globalSettings.getSettingLocked(
@@ -4801,33 +4801,6 @@
                                 SettingsState.SYSTEM_PACKAGE_NAME);
                     }
 
-                    // SHOW_ZEN_SETTINGS_SUGGESTION
-                    final Setting currentShowZenSettingSuggestion = secureSettings.getSettingLocked(
-                            Secure.SHOW_ZEN_SETTINGS_SUGGESTION);
-                    if (currentShowZenSettingSuggestion.isNull()) {
-                        secureSettings.insertSettingOverrideableByRestoreLocked(
-                                Secure.SHOW_ZEN_SETTINGS_SUGGESTION, "1",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
-                    // ZEN_SETTINGS_UPDATED
-                    final Setting currentUpdatedSetting = secureSettings.getSettingLocked(
-                            Secure.ZEN_SETTINGS_UPDATED);
-                    if (currentUpdatedSetting.isNull()) {
-                        secureSettings.insertSettingOverrideableByRestoreLocked(
-                                Secure.ZEN_SETTINGS_UPDATED, "0",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
-                    // ZEN_SETTINGS_SUGGESTION_VIEWED
-                    final Setting currentSettingSuggestionViewed = secureSettings.getSettingLocked(
-                            Secure.ZEN_SETTINGS_SUGGESTION_VIEWED);
-                    if (currentSettingSuggestionViewed.isNull()) {
-                        secureSettings.insertSettingOverrideableByRestoreLocked(
-                                Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, "0",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
                     currentVersion = 170;
                 }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 3c634f0..011ffbc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -610,7 +610,7 @@
                                 flag.getPackageName(),
                                 flag.getFlagName(),
                                 flag.getServerFlagValue(),
-                                false);
+                                StorageRequestMessage.SERVER_ON_REBOOT);
                     }
 
                     if (flag.getHasLocalOverride()) {
@@ -619,7 +619,7 @@
                                 flag.getPackageName(),
                                 flag.getFlagName(),
                                 flag.getLocalFlagValue(),
-                                true);
+                                StorageRequestMessage.LOCAL_ON_REBOOT);
                     }
                 }
 
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index ec7012e..6c3ba68 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1081,6 +1081,16 @@
 }
 
 flag {
+    name: "dream_overlay_updated_font"
+    namespace: "systemui"
+    description: "Flag to enable updated font settings for dream overlay"
+    bug: "349656117"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
   name: "app_clips_backlinks"
   namespace: "systemui"
   description: "Enables Backlinks improvement feature in App Clips"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index ac58ab5..340ac32 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -1,5 +1,6 @@
 package com.android.systemui.scene.ui.composable
 
+import androidx.compose.animation.core.spring
 import androidx.compose.foundation.gestures.Orientation
 import com.android.compose.animation.scene.ProgressConverter
 import com.android.compose.animation.scene.TransitionKey
@@ -12,6 +13,8 @@
 import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
 import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition
 import com.android.systemui.scene.ui.composable.transitions.bouncerToLockscreenPreview
+import com.android.systemui.scene.ui.composable.transitions.communalToBouncerTransition
+import com.android.systemui.scene.ui.composable.transitions.communalToShadeTransition
 import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition
 import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition
 import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition
@@ -44,6 +47,7 @@
 
     // Overscroll progress starts linearly with some resistance (3f) and slowly approaches 0.2f
     defaultOverscrollProgressConverter = ProgressConverter.tanh(maxProgress = 0.2f, tilt = 3f)
+    defaultSwipeSpec = spring(stiffness = 300f, dampingRatio = 0.8f, visibilityThreshold = 0.5f)
 
     // Scene transitions
 
@@ -87,6 +91,8 @@
         sharedElement(Notifications.Elements.NotificationStackPlaceholder, enabled = false)
         sharedElement(Notifications.Elements.HeadsUpNotificationPlaceholder, enabled = false)
     }
+    from(Scenes.Communal, to = Scenes.Shade) { communalToShadeTransition() }
+    from(Scenes.Communal, to = Scenes.Bouncer) { communalToBouncerTransition() }
 
     // Overlay transitions
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt
similarity index 65%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
rename to packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt
index 15ed1b3..d7173fd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.scene.data.repository
+package com.android.systemui.scene.ui.composable.transitions
 
-import android.view.windowManagerService
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.compose.animation.scene.TransitionBuilder
 
-val Kosmos.systemGestureExclusionRepository by Fixture {
-    SystemGestureExclusionRepository(windowManager = windowManagerService)
+fun TransitionBuilder.communalToBouncerTransition() {
+    toBouncerTransition()
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt
similarity index 65%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
copy to packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt
index 15ed1b3..ba920ac 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.scene.data.repository
+package com.android.systemui.scene.ui.composable.transitions
 
-import android.view.windowManagerService
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.compose.animation.scene.TransitionBuilder
 
-val Kosmos.systemGestureExclusionRepository by Fixture {
-    SystemGestureExclusionRepository(windowManager = windowManagerService)
+fun TransitionBuilder.communalToShadeTransition() {
+    toShadeTransition()
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
index 4c0efd2..dd37b53 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
@@ -1,29 +1,11 @@
 package com.android.systemui.scene.ui.composable.transitions
 
 import androidx.compose.animation.core.CubicBezierEasing
-import androidx.compose.animation.core.tween
-import androidx.compose.ui.unit.dp
 import com.android.compose.animation.scene.TransitionBuilder
-import com.android.compose.animation.scene.UserActionDistance
 import com.android.systemui.bouncer.ui.composable.Bouncer
 
-const val FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION = 0.5f
-const val FROM_LOCK_SCREEN_TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f
-
 fun TransitionBuilder.lockscreenToBouncerTransition() {
-    spec = tween(durationMillis = 500)
-
-    distance = UserActionDistance { fromSceneSize, _ ->
-        fromSceneSize.height * FROM_LOCK_SCREEN_TO_BOUNCER_SWIPE_DISTANCE_FRACTION
-    }
-
-    translate(Bouncer.Elements.Content, y = 300.dp)
-    fractionRange(end = FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION) {
-        fade(Bouncer.Elements.Background)
-    }
-    fractionRange(start = FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION) {
-        fade(Bouncer.Elements.Content)
-    }
+    toBouncerTransition()
 }
 
 fun TransitionBuilder.bouncerToLockscreenPreview() {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
new file mode 100644
index 0000000..de76f70
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.ui.composable.transitions
+
+import androidx.compose.animation.core.tween
+import androidx.compose.ui.unit.dp
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.compose.animation.scene.UserActionDistance
+import com.android.systemui.bouncer.ui.composable.Bouncer
+
+const val TO_BOUNCER_FADE_FRACTION = 0.5f
+private const val TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f
+
+fun TransitionBuilder.toBouncerTransition() {
+    spec = tween(durationMillis = 500)
+
+    distance = UserActionDistance { fromSceneSize, _ ->
+        fromSceneSize.height * TO_BOUNCER_SWIPE_DISTANCE_FRACTION
+    }
+
+    translate(Bouncer.Elements.Content, y = 300.dp)
+    fractionRange(end = TO_BOUNCER_FADE_FRACTION) { fade(Bouncer.Elements.Background) }
+    fractionRange(start = TO_BOUNCER_FADE_FRACTION) { fade(Bouncer.Elements.Content) }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 5fa5db8..085157a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -226,7 +226,6 @@
         val fromSource = resolveSwipeSource(startedPosition)
         val upOrLeft = resolveSwipe(pointersDown, fromSource, isUpOrLeft = true)
         val downOrRight = resolveSwipe(pointersDown, fromSource, isUpOrLeft = false)
-
         return if (fromSource == null) {
             Swipes(
                 upOrLeft = null,
@@ -366,10 +365,18 @@
             return 0f
         }
 
+        val currentTransitionIrreversible =
+            if (swipeAnimation.isUpOrLeft) {
+                swipes.upOrLeftResult?.isIrreversible ?: false
+            } else {
+                swipes.downOrRightResult?.isIrreversible ?: false
+            }
+
         val needNewTransition =
-            hasReachedToContent ||
-                result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
-                result.transitionKey != swipeAnimation.contentTransition.key
+            !currentTransitionIrreversible &&
+                (hasReachedToContent ||
+                    result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
+                    result.transitionKey != swipeAnimation.contentTransition.key)
 
         if (needNewTransition) {
             // Make sure the current transition will finish to the right current scene.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 5ddc284..dc3135d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -42,8 +42,10 @@
 import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
 import androidx.compose.ui.node.DelegatingNode
 import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.ObserverModifierNode
 import androidx.compose.ui.node.PointerInputModifierNode
 import androidx.compose.ui.node.currentValueOf
+import androidx.compose.ui.node.observeReads
 import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.Velocity
@@ -77,6 +79,7 @@
 @Stable
 internal fun Modifier.multiPointerDraggable(
     orientation: Orientation,
+    enabled: () -> Boolean,
     startDragImmediately: (startedPosition: Offset) -> Boolean,
     onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController,
     onFirstPointerDown: () -> Unit = {},
@@ -86,6 +89,7 @@
     this.then(
         MultiPointerDraggableElement(
             orientation,
+            enabled,
             startDragImmediately,
             onDragStarted,
             onFirstPointerDown,
@@ -96,6 +100,7 @@
 
 private data class MultiPointerDraggableElement(
     private val orientation: Orientation,
+    private val enabled: () -> Boolean,
     private val startDragImmediately: (startedPosition: Offset) -> Boolean,
     private val onDragStarted:
         (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController,
@@ -106,6 +111,7 @@
     override fun create(): MultiPointerDraggableNode =
         MultiPointerDraggableNode(
             orientation = orientation,
+            enabled = enabled,
             startDragImmediately = startDragImmediately,
             onDragStarted = onDragStarted,
             onFirstPointerDown = onFirstPointerDown,
@@ -115,6 +121,7 @@
 
     override fun update(node: MultiPointerDraggableNode) {
         node.orientation = orientation
+        node.enabled = enabled
         node.startDragImmediately = startDragImmediately
         node.onDragStarted = onDragStarted
         node.onFirstPointerDown = onFirstPointerDown
@@ -124,6 +131,7 @@
 
 internal class MultiPointerDraggableNode(
     orientation: Orientation,
+    enabled: () -> Boolean,
     var startDragImmediately: (startedPosition: Offset) -> Boolean,
     var onDragStarted:
         (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController,
@@ -134,10 +142,21 @@
     DelegatingNode(),
     PointerInputModifierNode,
     CompositionLocalConsumerModifierNode,
+    ObserverModifierNode,
     SpaceVectorConverter {
     private val pointerTracker = delegate(SuspendingPointerInputModifierNode { pointerTracker() })
     private val pointerInput = delegate(SuspendingPointerInputModifierNode { pointerInput() })
     private val velocityTracker = VelocityTracker()
+    private var previousEnabled: Boolean = false
+
+    var enabled: () -> Boolean = enabled
+        set(value) {
+            // Reset the pointer input whenever enabled changed.
+            if (value != field) {
+                field = value
+                pointerInput.resetPointerInputHandler()
+            }
+        }
 
     private var converter = SpaceVectorConverter(orientation)
 
@@ -159,6 +178,21 @@
             }
         }
 
+    override fun onAttach() {
+        previousEnabled = enabled()
+        onObservedReadsChanged()
+    }
+
+    override fun onObservedReadsChanged() {
+        observeReads {
+            val newEnabled = enabled()
+            if (newEnabled != previousEnabled) {
+                pointerInput.resetPointerInputHandler()
+            }
+            previousEnabled = newEnabled
+        }
+    }
+
     override fun onCancelPointerInput() {
         pointerTracker.onCancelPointerInput()
         pointerInput.onCancelPointerInput()
@@ -220,7 +254,9 @@
                         velocityTracker.resetTracking()
                         velocityTracker.addPointerInputChange(firstPointerDown)
                         startedPosition = firstPointerDown.position
-                        onFirstPointerDown()
+                        if (enabled()) {
+                            onFirstPointerDown()
+                        }
                     }
 
                     // Changes with at least one pointer
@@ -259,6 +295,10 @@
     }
 
     private suspend fun PointerInputScope.pointerInput() {
+        if (!enabled()) {
+            return
+        }
+
         val currentContext = currentCoroutineContext()
         awaitPointerEventScope {
             while (currentContext.isActive) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index cec8883..c9a4d58 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -498,6 +498,12 @@
      * bigger than 100% when the user released their finger. `
      */
     open val requiresFullDistanceSwipe: Boolean,
+
+    /**
+     * Whether swiping back in the opposite direction past the origin point of the swipe can replace
+     * the action with the action for the opposite direction.
+     */
+    open val isIrreversible: Boolean = false,
 ) {
     internal abstract fun toContent(currentScene: SceneKey): ContentKey
 
@@ -507,6 +513,7 @@
         val toScene: SceneKey,
         override val transitionKey: TransitionKey? = null,
         override val requiresFullDistanceSwipe: Boolean = false,
+        override val isIrreversible: Boolean = false,
     ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
         override fun toContent(currentScene: SceneKey): ContentKey = toScene
     }
@@ -516,6 +523,7 @@
         val overlay: OverlayKey,
         override val transitionKey: TransitionKey? = null,
         override val requiresFullDistanceSwipe: Boolean = false,
+        override val isIrreversible: Boolean = false,
     ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) {
         override fun toContent(currentScene: SceneKey): ContentKey = overlay
     }
@@ -558,7 +566,14 @@
              * the user released their finger.
              */
             requiresFullDistanceSwipe: Boolean = false,
-        ): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)
+
+            /**
+             * Whether swiping back in the opposite direction past the origin point of the swipe can
+             * replace the action with the action for the opposite direction.
+             */
+            isIrreversible: Boolean = false,
+        ): UserActionResult =
+            ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe, isIrreversible)
 
         /** A [UserActionResult] that shows [toOverlay]. */
         operator fun invoke(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index b358faf..879dc54 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -152,6 +152,7 @@
         internal val DefaultSwipeSpec =
             spring(
                 stiffness = Spring.StiffnessMediumLow,
+                dampingRatio = Spring.DampingRatioLowBouncy,
                 visibilityThreshold = OffsetVisibilityThreshold,
             )
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index d201be9..98d4aaa 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -41,28 +41,7 @@
     draggableHandler: DraggableHandlerImpl,
     swipeDetector: SwipeDetector,
 ): Modifier {
-    return if (draggableHandler.enabled()) {
-        this.then(SwipeToSceneElement(draggableHandler, swipeDetector))
-    } else {
-        this
-    }
-}
-
-private fun DraggableHandlerImpl.enabled(): Boolean {
-    return isDrivingTransition || contentForSwipes().shouldEnableSwipes(orientation)
-}
-
-private fun DraggableHandlerImpl.contentForSwipes(): Content {
-    return layoutImpl.contentForUserActions()
-}
-
-/** Whether swipe should be enabled in the given [orientation]. */
-private fun Content.shouldEnableSwipes(orientation: Orientation): Boolean {
-    if (userActions.isEmpty()) {
-        return false
-    }
-
-    return userActions.keys.any { it is Swipe.Resolved && it.direction.orientation == orientation }
+    return this.then(SwipeToSceneElement(draggableHandler, swipeDetector))
 }
 
 private data class SwipeToSceneElement(
@@ -85,6 +64,7 @@
         delegate(
             MultiPointerDraggableNode(
                 orientation = draggableHandler.orientation,
+                enabled = ::enabled,
                 startDragImmediately = ::startDragImmediately,
                 onDragStarted = draggableHandler::onDragStarted,
                 onFirstPointerDown = ::onFirstPointerDown,
@@ -144,6 +124,22 @@
 
     override fun onCancelPointerInput() = multiPointerDraggableNode.onCancelPointerInput()
 
+    private fun enabled(): Boolean {
+        return draggableHandler.isDrivingTransition ||
+            contentForSwipes().shouldEnableSwipes(multiPointerDraggableNode.orientation)
+    }
+
+    private fun contentForSwipes(): Content {
+        return draggableHandler.layoutImpl.contentForUserActions()
+    }
+
+    /** Whether swipe should be enabled in the given [orientation]. */
+    private fun Content.shouldEnableSwipes(orientation: Orientation): Boolean {
+        return userActions.keys.any {
+            it is Swipe.Resolved && it.direction.orientation == orientation
+        }
+    }
+
     private fun startDragImmediately(startedPosition: Offset): Boolean {
         // Immediately start the drag if the user can't swipe in the other direction and the gesture
         // handler can intercept it.
@@ -156,7 +152,7 @@
                 Orientation.Vertical -> Orientation.Horizontal
                 Orientation.Horizontal -> Orientation.Vertical
             }
-        return draggableHandler.contentForSwipes().shouldEnableSwipes(oppositeOrientation)
+        return contentForSwipes().shouldEnableSwipes(oppositeOrientation)
     }
 }
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
index a6ebb0e..a3641e6 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
@@ -34,71 +34,76 @@
  * Note: Call [reset] before destroying this object to make sure you always get a call to [onStop]
  * after [onStart].
  *
- * @sample com.android.compose.animation.scene.rememberSwipeToSceneNestedScrollConnection
+ * @sample LargeTopAppBarNestedScrollConnection
+ * @sample com.android.compose.animation.scene.NestedScrollHandlerImpl.nestedScrollConnection
  */
 class PriorityNestedScrollConnection(
-    private val canStartPreScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean,
-    private val canStartPostScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean,
-    private val canStartPostFling: (velocityAvailable: Velocity) -> Boolean,
+    orientation: Orientation,
+    private val canStartPreScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
+    private val canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
+    private val canStartPostFling: (velocityAvailable: Float) -> Boolean,
     private val canContinueScroll: (source: NestedScrollSource) -> Boolean,
     private val canScrollOnFling: Boolean,
-    private val onStart: (offsetAvailable: Offset) -> Unit,
-    private val onScroll: (offsetAvailable: Offset) -> Offset,
-    private val onStop: (velocityAvailable: Velocity) -> SuspendedValue<Velocity>,
-) : NestedScrollConnection {
+    private val onStart: (offsetAvailable: Float) -> Unit,
+    private val onScroll: (offsetAvailable: Float) -> Float,
+    private val onStop: (velocityAvailable: Float) -> SuspendedValue<Float>,
+) : NestedScrollConnection, SpaceVectorConverter by SpaceVectorConverter(orientation) {
 
     /** In priority mode [onPreScroll] events are first consumed by the parent, via [onScroll]. */
     private var isPriorityMode = false
 
-    private var offsetScrolledBeforePriorityMode = Offset.Zero
+    private var offsetScrolledBeforePriorityMode = 0f
 
     override fun onPostScroll(
         consumed: Offset,
         available: Offset,
         source: NestedScrollSource,
     ): Offset {
+        val availableFloat = available.toFloat()
         // The offset before the start takes into account the up and down movements, starting from
         // the beginning or from the last fling gesture.
-        val offsetBeforeStart = offsetScrolledBeforePriorityMode - available
+        val offsetBeforeStart = offsetScrolledBeforePriorityMode - availableFloat
 
         if (
             isPriorityMode ||
                 (source == NestedScrollSource.SideEffect && !canScrollOnFling) ||
-                !canStartPostScroll(available, offsetBeforeStart)
+                !canStartPostScroll(availableFloat, offsetBeforeStart)
         ) {
             // The priority mode cannot start so we won't consume the available offset.
             return Offset.Zero
         }
 
-        return onPriorityStart(available)
+        return onPriorityStart(availableFloat).toOffset()
     }
 
     override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
         if (!isPriorityMode) {
             if (source == NestedScrollSource.UserInput || canScrollOnFling) {
-                if (canStartPreScroll(available, offsetScrolledBeforePriorityMode)) {
-                    return onPriorityStart(available)
+                val availableFloat = available.toFloat()
+                if (canStartPreScroll(availableFloat, offsetScrolledBeforePriorityMode)) {
+                    return onPriorityStart(availableFloat).toOffset()
                 }
                 // We want to track the amount of offset consumed before entering priority mode
-                offsetScrolledBeforePriorityMode += available
+                offsetScrolledBeforePriorityMode += availableFloat
             }
 
             return Offset.Zero
         }
 
+        val availableFloat = available.toFloat()
         if (!canContinueScroll(source)) {
             // Step 3a: We have lost priority and we no longer need to intercept scroll events.
-            onPriorityStop(velocity = Velocity.Zero)
+            onPriorityStop(velocity = 0f)
 
-            // We've just reset offsetScrolledBeforePriorityMode to Offset.Zero
+            // We've just reset offsetScrolledBeforePriorityMode to 0f
             // We want to track the amount of offset consumed before entering priority mode
-            offsetScrolledBeforePriorityMode += available
+            offsetScrolledBeforePriorityMode += availableFloat
 
             return Offset.Zero
         }
 
         // Step 2: We have the priority and can consume the scroll events.
-        return onScroll(available)
+        return onScroll(availableFloat).toOffset()
     }
 
     override suspend fun onPreFling(available: Velocity): Velocity {
@@ -108,15 +113,16 @@
         }
         // Step 3b: The finger is lifted, we can stop intercepting scroll events and use the speed
         // of the fling gesture.
-        return onPriorityStop(velocity = available).invoke()
+        return onPriorityStop(velocity = available.toFloat()).invoke().toVelocity()
     }
 
     override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+        val availableFloat = available.toFloat()
         if (isPriorityMode) {
-            return onPriorityStop(velocity = available).invoke()
+            return onPriorityStop(velocity = availableFloat).invoke().toVelocity()
         }
 
-        if (!canStartPostFling(available)) {
+        if (!canStartPostFling(availableFloat)) {
             return Velocity.Zero
         }
 
@@ -124,11 +130,11 @@
         // given the available velocity.
         // TODO(b/291053278): Remove canStartPostFling() and instead make it possible to define the
         // overscroll behavior on the Scene level.
-        val smallOffset = Offset(available.x.sign, available.y.sign)
-        onPriorityStart(available = smallOffset)
+        val smallOffset = availableFloat.sign
+        onPriorityStart(availableOffset = smallOffset)
 
         // This is the last event of a scroll gesture.
-        return onPriorityStop(available).invoke()
+        return onPriorityStop(availableFloat).invoke().toVelocity()
     }
 
     /**
@@ -138,10 +144,10 @@
      */
     fun reset() {
         // Step 3c: To ensure that an onStop is always called for every onStart.
-        onPriorityStop(velocity = Velocity.Zero)
+        onPriorityStop(velocity = 0f)
     }
 
-    private fun onPriorityStart(available: Offset): Offset {
+    private fun onPriorityStart(availableOffset: Float): Float {
         if (isPriorityMode) {
             error("This should never happen, onPriorityStart() was called when isPriorityMode")
         }
@@ -152,17 +158,17 @@
 
         // Note: onStop will be called if we cannot continue to scroll (step 3a), or the finger is
         // lifted (step 3b), or this object has been destroyed (step 3c).
-        onStart(available)
+        onStart(availableOffset)
 
-        return onScroll(available)
+        return onScroll(availableOffset)
     }
 
-    private fun onPriorityStop(velocity: Velocity): SuspendedValue<Velocity> {
+    private fun onPriorityStop(velocity: Float): SuspendedValue<Float> {
         // We can restart tracking the consumed offsets from scratch.
-        offsetScrolledBeforePriorityMode = Offset.Zero
+        offsetScrolledBeforePriorityMode = 0f
 
         if (!isPriorityMode) {
-            return { Velocity.Zero }
+            return { 0f }
         }
 
         isPriorityMode = false
@@ -170,38 +176,3 @@
         return onStop(velocity)
     }
 }
-
-fun PriorityNestedScrollConnection(
-    orientation: Orientation,
-    canStartPreScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
-    canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
-    canStartPostFling: (velocityAvailable: Float) -> Boolean,
-    canContinueScroll: (source: NestedScrollSource) -> Boolean,
-    canScrollOnFling: Boolean,
-    onStart: (offsetAvailable: Float) -> Unit,
-    onScroll: (offsetAvailable: Float) -> Float,
-    onStop: (velocityAvailable: Float) -> SuspendedValue<Float>,
-) =
-    with(SpaceVectorConverter(orientation)) {
-        PriorityNestedScrollConnection(
-            canStartPreScroll = { offsetAvailable: Offset, offsetBeforeStart: Offset ->
-                canStartPreScroll(offsetAvailable.toFloat(), offsetBeforeStart.toFloat())
-            },
-            canStartPostScroll = { offsetAvailable: Offset, offsetBeforeStart: Offset ->
-                canStartPostScroll(offsetAvailable.toFloat(), offsetBeforeStart.toFloat())
-            },
-            canStartPostFling = { velocityAvailable: Velocity ->
-                canStartPostFling(velocityAvailable.toFloat())
-            },
-            canContinueScroll = canContinueScroll,
-            canScrollOnFling = canScrollOnFling,
-            onStart = { offsetAvailable -> onStart(offsetAvailable.toFloat()) },
-            onScroll = { offsetAvailable: Offset ->
-                onScroll(offsetAvailable.toFloat()).toOffset()
-            },
-            onStop = { velocityAvailable: Velocity ->
-                val consumedVelocity = onStop(velocityAvailable.toFloat())
-                suspend { consumedVelocity.invoke().toVelocity() }
-            },
-        )
-    }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index dd4f99f..ecef6be 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -507,6 +507,54 @@
     }
 
     @Test
+    fun onDragWithActionsInBothDirections_dragToOppositeDirectionReplacesAction() = runGestureTest {
+        // We are on SceneA. UP -> B, DOWN-> C.
+        val dragController = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneB,
+            progress = 0.2f,
+        )
+
+        // Reverse drag direction, it will replace the previous transition
+        dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneC,
+            progress = 0.3f,
+        )
+    }
+
+    @Test
+    fun onDragWithActionsInBothDirections_dragToOppositeDirectionNotReplaceable() = runGestureTest {
+        // We are on SceneA. UP -> B, DOWN-> C. The up swipe is not replaceable though.
+        mutableUserActionsA =
+            mapOf(Swipe.Up to UserActionResult(SceneB, isIrreversible = true), Swipe.Down to SceneC)
+        val dragController =
+            onDragStarted(
+                startedPosition = Offset(SCREEN_SIZE * 0.5f, SCREEN_SIZE * 0.5f),
+                overSlop = up(fractionOfScreen = 0.2f),
+            )
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneB,
+            progress = 0.2f,
+        )
+
+        // Reverse drag direction, it cannot replace the previous transition
+        dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneB,
+            progress = -0.3f,
+        )
+    }
+
+    @Test
     fun onDragFromEdge_startTransitionToEdgeAction() = runGestureTest {
         navigateToSceneC()
 
@@ -1241,7 +1289,8 @@
     fun overscroll_releaseBetween0And100Percent_up() = runGestureTest {
         // Make scene B overscrollable.
         layoutState.transitions = transitions {
-            from(SceneA, to = SceneB) { spec = spring(dampingRatio = Spring.DampingRatioNoBouncy) }
+            defaultSwipeSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy)
+            from(SceneA, to = SceneB) {}
             overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
         }
 
@@ -1272,7 +1321,8 @@
     fun overscroll_releaseBetween0And100Percent_down() = runGestureTest {
         // Make scene C overscrollable.
         layoutState.transitions = transitions {
-            from(SceneA, to = SceneC) { spec = spring(dampingRatio = Spring.DampingRatioNoBouncy) }
+            defaultSwipeSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy)
+            from(SceneA, to = SceneC) {}
             overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) }
         }
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
index c8f6e6d..493f3a1 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
@@ -45,7 +45,6 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Velocity
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.compose.modifiers.thenIf
 import com.android.compose.nestedscroll.SuspendedValue
 import com.google.common.truth.Truth.assertThat
 import kotlin.properties.Delegates
@@ -95,20 +94,19 @@
             Box(
                 Modifier.size(with(LocalDensity.current) { Size(size, size).toDpSize() })
                     .nestedScrollDispatcher()
-                    .thenIf(enabled) {
-                        Modifier.multiPointerDraggable(
-                            orientation = Orientation.Vertical,
-                            startDragImmediately = { false },
-                            onDragStarted = { _, _, _ ->
-                                started = true
-                                SimpleDragController(
-                                    onDrag = { dragged = true },
-                                    onStop = { stopped = true },
-                                )
-                            },
-                            dispatcher = defaultDispatcher,
-                        )
-                    }
+                    .multiPointerDraggable(
+                        orientation = Orientation.Vertical,
+                        enabled = { enabled },
+                        startDragImmediately = { false },
+                        onDragStarted = { _, _, _ ->
+                            started = true
+                            SimpleDragController(
+                                onDrag = { dragged = true },
+                                onStop = { stopped = true },
+                            )
+                        },
+                        dispatcher = defaultDispatcher,
+                    )
             )
         }
 
@@ -166,6 +164,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         // We want to start a drag gesture immediately
                         startDragImmediately = { true },
                         onDragStarted = { _, _, _ ->
@@ -239,6 +238,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         startDragImmediately = { false },
                         onDragStarted = { _, _, _ ->
                             started = true
@@ -358,6 +358,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         startDragImmediately = { false },
                         onDragStarted = { _, _, _ ->
                             started = true
@@ -463,6 +464,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         startDragImmediately = { false },
                         onDragStarted = { _, _, _ ->
                             verticalStarted = true
@@ -475,6 +477,7 @@
                     )
                     .multiPointerDraggable(
                         orientation = Orientation.Horizontal,
+                        enabled = { true },
                         startDragImmediately = { false },
                         onDragStarted = { _, _, _ ->
                             horizontalStarted = true
@@ -567,6 +570,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         startDragImmediately = { false },
                         swipeDetector =
                             object : SwipeDetector {
@@ -668,6 +672,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         startDragImmediately = { false },
                         onDragStarted = { _, _, _ ->
                             SimpleDragController(
@@ -739,6 +744,7 @@
                     .nestedScrollDispatcher()
                     .multiPointerDraggable(
                         orientation = Orientation.Vertical,
+                        enabled = { true },
                         startDragImmediately = { false },
                         onDragStarted = { _, _, _ ->
                             SimpleDragController(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index ce64628..25e8713 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -22,15 +22,11 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.size
-import androidx.compose.material3.Button
-import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
@@ -40,11 +36,8 @@
 import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertPositionInRootIsEqualTo
-import androidx.compose.ui.test.assertTextEquals
 import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onRoot
-import androidx.compose.ui.test.performClick
 import androidx.compose.ui.test.performTouchInput
 import androidx.compose.ui.test.swipeWithVelocity
 import androidx.compose.ui.unit.Density
@@ -851,29 +844,4 @@
         assertThat(transition.progress).isEqualTo(1f)
         assertThat(availableOnPostScroll).isEqualTo(ovescrollPx)
     }
-
-    @Test
-    fun sceneWithoutSwipesDoesNotConsumeGestures() {
-        val buttonTag = "button"
-
-        rule.setContent {
-            Box {
-                var count by remember { mutableStateOf(0) }
-                Button(onClick = { count++ }, Modifier.testTag(buttonTag).align(Alignment.Center)) {
-                    Text("Count: $count")
-                }
-
-                SceneTransitionLayout(remember { MutableSceneTransitionLayoutState(SceneA) }) {
-                    scene(SceneA) { Box(Modifier.fillMaxSize()) }
-                }
-            }
-        }
-
-        rule.onNodeWithTag(buttonTag).assertTextEquals("Count: 0")
-
-        // Click on the root at its center, where the button is located. Clicks should go through
-        // the STL and reach the button given that there is no swipes for the current scene.
-        repeat(3) { rule.onRoot().performClick() }
-        rule.onNodeWithTag(buttonTag).assertTextEquals("Count: 3")
-    }
 }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
index bde7699..badc43b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
@@ -18,8 +18,9 @@
 
 package com.android.compose.nestedscroll
 
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource.Companion.UserInput
 import androidx.compose.ui.unit.Velocity
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
@@ -35,13 +36,14 @@
     private var canStartPostFling = false
     private var canContinueScroll = false
     private var isStarted = false
-    private var lastScroll: Offset? = null
-    private var returnOnScroll = Offset.Zero
-    private var lastStop: Velocity? = null
-    private var returnOnStop = Velocity.Zero
+    private var lastScroll: Float? = null
+    private var returnOnScroll = 0f
+    private var lastStop: Float? = null
+    private var returnOnStop = 0f
 
     private val scrollConnection =
         PriorityNestedScrollConnection(
+            orientation = Orientation.Vertical,
             canStartPreScroll = { _, _ -> canStartPreScroll },
             canStartPostScroll = { _, _ -> canStartPostScroll },
             canStartPostFling = { canStartPostFling },
@@ -58,11 +60,6 @@
             },
         )
 
-    private val offset1 = Offset(1f, 1f)
-    private val offset2 = Offset(2f, 2f)
-    private val velocity1 = Velocity(1f, 1f)
-    private val velocity2 = Velocity(2f, 2f)
-
     @Test
     fun step1_priorityModeShouldStartOnlyOnPreScroll() = runTest {
         canStartPreScroll = true
@@ -70,7 +67,7 @@
         scrollConnection.onPostScroll(
             consumed = Offset.Zero,
             available = Offset.Zero,
-            source = NestedScrollSource.Drag,
+            source = UserInput,
         )
         assertThat(isStarted).isEqualTo(false)
 
@@ -80,7 +77,7 @@
         scrollConnection.onPostFling(consumed = Velocity.Zero, available = Velocity.Zero)
         assertThat(isStarted).isEqualTo(false)
 
-        scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
+        scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput)
         assertThat(isStarted).isEqualTo(true)
     }
 
@@ -89,7 +86,7 @@
         scrollConnection.onPostScroll(
             consumed = Offset.Zero,
             available = Offset.Zero,
-            source = NestedScrollSource.Drag,
+            source = UserInput,
         )
     }
 
@@ -97,7 +94,7 @@
     fun step1_priorityModeShouldStartOnlyOnPostScroll() = runTest {
         canStartPostScroll = true
 
-        scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
+        scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput)
         assertThat(isStarted).isEqualTo(false)
 
         scrollConnection.onPreFling(available = Velocity.Zero)
@@ -115,7 +112,7 @@
         scrollConnection.onPostScroll(
             consumed = Offset.Zero,
             available = Offset.Zero,
-            source = NestedScrollSource.Drag,
+            source = UserInput,
         )
         assertThat(isStarted).isEqualTo(false)
 
@@ -128,12 +125,12 @@
         canStartPostScroll = true
 
         scrollConnection.onPostScroll(
-            consumed = offset1,
-            available = offset2,
-            source = NestedScrollSource.Drag,
+            consumed = Offset(1f, 1f),
+            available = Offset(2f, 2f),
+            source = UserInput,
         )
 
-        assertThat(lastScroll).isEqualTo(offset2)
+        assertThat(lastScroll).isEqualTo(2f)
     }
 
     @Test
@@ -141,13 +138,13 @@
         startPriorityModePostScroll()
         canContinueScroll = true
 
-        scrollConnection.onPreScroll(available = offset1, source = NestedScrollSource.Drag)
-        assertThat(lastScroll).isEqualTo(offset1)
+        scrollConnection.onPreScroll(available = Offset(1f, 1f), source = UserInput)
+        assertThat(lastScroll).isEqualTo(1f)
 
         canContinueScroll = false
-        scrollConnection.onPreScroll(available = offset2, source = NestedScrollSource.Drag)
-        assertThat(lastScroll).isNotEqualTo(offset2)
-        assertThat(lastScroll).isEqualTo(offset1)
+        scrollConnection.onPreScroll(available = Offset(2f, 2f), source = UserInput)
+        assertThat(lastScroll).isNotEqualTo(2f)
+        assertThat(lastScroll).isEqualTo(1f)
     }
 
     @Test
@@ -155,7 +152,7 @@
         startPriorityModePostScroll()
         canContinueScroll = false
 
-        scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
+        scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput)
 
         assertThat(lastStop).isNotNull()
     }
@@ -184,22 +181,22 @@
     fun receive_onPostFling() = runTest {
         canStartPostFling = true
 
-        scrollConnection.onPostFling(consumed = velocity1, available = velocity2)
+        scrollConnection.onPostFling(consumed = Velocity(1f, 1f), available = Velocity(2f, 2f))
 
-        assertThat(lastStop).isEqualTo(velocity2)
+        assertThat(lastStop).isEqualTo(2f)
     }
 
     @Test
     fun step1_priorityModeShouldStartOnlyOnPostFling() = runTest {
         canStartPostFling = true
 
-        scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag)
+        scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput)
         assertThat(isStarted).isEqualTo(false)
 
         scrollConnection.onPostScroll(
             consumed = Offset.Zero,
             available = Offset.Zero,
-            source = NestedScrollSource.Drag,
+            source = UserInput,
         )
         assertThat(isStarted).isEqualTo(false)
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable
index 0d369a3..97f2e56 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable
@@ -67,7 +67,6 @@
 import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
 import com.android.systemui.scene.ui.composable.Scene
 import com.android.systemui.scene.ui.composable.SceneContainer
-import com.android.systemui.settings.displayTracker
 import com.android.systemui.testKosmos
 import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.awaitCancellation
@@ -127,7 +126,7 @@
 
     private val sceneContainerViewModel by lazy {
         kosmos.sceneContainerViewModelFactory
-            .create(view, kosmos.displayTracker.defaultDisplayId, {})
+            .create(view) {}
             .apply { setTransitionState(transitionState) }
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
index 58b59ff..755c4eb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt
@@ -85,7 +85,8 @@
             assertThat(actions).isNotEmpty()
             assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
-            assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
+            assertThat(actions?.get(Swipe.Down))
+                .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
 
             setUpState(
                 isShadeTouchable = false,
@@ -102,7 +103,8 @@
             assertThat(actions).isNotEmpty()
             assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
-            assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade))
+            assertThat(actions?.get(Swipe.Down))
+                .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true))
         }
 
     @Test
@@ -120,7 +122,7 @@
             assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
             assertThat(actions?.get(Swipe.Down))
-                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
 
             setUpState(
                 isShadeTouchable = false,
@@ -138,7 +140,7 @@
             assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
             assertThat(actions?.get(Swipe.Down))
-                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
         }
 
     @Test
@@ -156,7 +158,9 @@
             assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer))
             assertThat(actions?.get(Swipe.Down))
-                .isEqualTo(UserActionResult(Overlays.NotificationsShade))
+                .isEqualTo(
+                    UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+                )
 
             setUpState(
                 isShadeTouchable = false,
@@ -170,7 +174,9 @@
             assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home))
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone))
             assertThat(actions?.get(Swipe.Down))
-                .isEqualTo(UserActionResult(Overlays.NotificationsShade))
+                .isEqualTo(
+                    UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+                )
         }
 
     private fun TestScope.setUpState(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index fb1bf28..6397979 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -303,7 +303,8 @@
                 // Top edge is not applicable in dual shade, as well as two-finger swipe.
                 assertThat(downDestination).isNull()
             } else {
-                assertThat(downDestination).isEqualTo(ShowOverlay(Overlays.NotificationsShade))
+                assertThat(downDestination)
+                    .isEqualTo(ShowOverlay(Overlays.NotificationsShade, isIrreversible = true))
                 assertThat(downDestination?.transitionKey).isNull()
             }
 
@@ -320,7 +321,7 @@
                 downWithTwoPointers -> assertThat(downFromTopRightDestination).isNull()
                 else -> {
                     assertThat(downFromTopRightDestination)
-                        .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade))
+                        .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true))
                     assertThat(downFromTopRightDestination?.transitionKey).isNull()
                 }
             }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index 5c47f55..47fae9f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -106,7 +106,7 @@
             runCurrent()
 
             assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
-                .isEqualTo(UserActionResult(Scenes.QuickSettings))
+                .isEqualTo(UserActionResult(Scenes.QuickSettings, isIrreversible = true))
         }
 
     @Test
@@ -118,7 +118,7 @@
             runCurrent()
 
             assertThat(userActions?.get(swipeDownFromTopWithTwoFingers()))
-                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade))
+                .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true))
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt
deleted file mode 100644
index efde1ec..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.scene.ui.viewmodel
-
-import android.graphics.Region
-import android.view.setSystemGestureExclusionRegion
-import androidx.compose.ui.geometry.Offset
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.lifecycle.activateIn
-import com.android.systemui.scene.sceneContainerGestureFilterFactory
-import com.android.systemui.settings.displayTracker
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SceneContainerGestureFilterTest : SysuiTestCase() {
-
-    private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
-    private val displayId = kosmos.displayTracker.defaultDisplayId
-
-    private val underTest = kosmos.sceneContainerGestureFilterFactory.create(displayId)
-    private val activationJob = Job()
-
-    @Test
-    fun shouldFilterGesture_whenNoRegion_returnsFalse() =
-        testScope.runTest {
-            activate()
-            setSystemGestureExclusionRegion(displayId, null)
-            runCurrent()
-
-            assertThat(underTest.shouldFilterGesture(Offset(100f, 100f))).isFalse()
-        }
-
-    @Test
-    fun shouldFilterGesture_whenOutsideRegion_returnsFalse() =
-        testScope.runTest {
-            activate()
-            setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
-            runCurrent()
-
-            assertThat(underTest.shouldFilterGesture(Offset(300f, 100f))).isFalse()
-        }
-
-    @Test
-    fun shouldFilterGesture_whenInsideRegion_returnsTrue() =
-        testScope.runTest {
-            activate()
-            setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
-            runCurrent()
-
-            assertThat(underTest.shouldFilterGesture(Offset(100f, 100f))).isTrue()
-        }
-
-    @Test(expected = IllegalStateException::class)
-    fun shouldFilterGesture_beforeActivation_throws() =
-        testScope.runTest {
-            setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
-            runCurrent()
-
-            underTest.shouldFilterGesture(Offset(100f, 100f))
-        }
-
-    @Test(expected = IllegalStateException::class)
-    fun shouldFilterGesture_afterCancellation_throws() =
-        testScope.runTest {
-            activate()
-            setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200))
-            runCurrent()
-
-            cancel()
-
-            underTest.shouldFilterGesture(Offset(100f, 100f))
-        }
-
-    private fun TestScope.activate() {
-        underTest.activateIn(testScope, activationJob)
-        runCurrent()
-    }
-
-    private fun TestScope.cancel() {
-        activationJob.cancel()
-        runCurrent()
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index a37f511..4ec0802 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -39,7 +39,6 @@
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.settings.displayTracker
 import com.android.systemui.shade.data.repository.fakeShadeRepository
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shade.shared.flag.DualShade
@@ -82,7 +81,6 @@
         underTest =
             kosmos.sceneContainerViewModelFactory.create(
                 view,
-                kosmos.displayTracker.defaultDisplayId,
                 { motionEventHandler ->
                     this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler
                 },
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
index 15d6881..fcb366b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.EnableSceneContainer
@@ -50,6 +51,7 @@
 import com.android.systemui.shade.shared.flag.DualShade
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.TestScope
@@ -248,6 +250,27 @@
             assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Communal))
         }
 
+    @Test
+    fun upTransitionSceneKey_neverGoesBackToShadeScene() =
+        testScope.runTest {
+            val actions by collectValues(underTest.actions)
+            val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
+            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            kosmos.sceneInteractor.changeScene(Scenes.Shade, "")
+            assertThat(currentScene).isEqualTo(Scenes.Shade)
+
+            kosmos.sceneInteractor.changeScene(Scenes.QuickSettings, "")
+            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+
+            actions.forEachIndexed { index, map ->
+                assertWithMessage(
+                        "Actions on index $index is incorrectly mapping back to the Shade scene!"
+                    )
+                    .that((map[Swipe.Up] as? UserActionResult.ChangeScene)?.toScene)
+                    .isNotEqualTo(Scenes.Shade)
+            }
+        }
+
     private fun TestScope.setDeviceEntered(isEntered: Boolean) {
         if (isEntered) {
             // Unlock the device marking the device has entered.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
index a0f6431..9d93a9c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
@@ -61,7 +61,7 @@
             interactor,
             kosmos.testDispatcher,
             mockDialogDelegate,
-            mockDialogEventLogger
+            mockDialogEventLogger,
         )
 
     @Test
@@ -97,7 +97,7 @@
             assertThat(tiles?.size).isEqualTo(3)
             with(tiles?.elementAt(0)!!) {
                 assertThat(this.text).isEqualTo("Disabled by other")
-                assertThat(this.subtext).isEqualTo("Set up")
+                assertThat(this.subtext).isEqualTo("Not set")
                 assertThat(this.enabled).isEqualTo(false)
             }
             with(tiles?.elementAt(1)!!) {
@@ -323,10 +323,10 @@
             assertThat(tiles!!).hasSize(6)
             assertThat(tiles!![0].subtext).isEqualTo("When the going gets tough")
             assertThat(tiles!![1].subtext).isEqualTo("On • When in Rome")
-            assertThat(tiles!![2].subtext).isEqualTo("Set up")
+            assertThat(tiles!![2].subtext).isEqualTo("Not set")
             assertThat(tiles!![3].subtext).isEqualTo("Off")
             assertThat(tiles!![4].subtext).isEqualTo("On")
-            assertThat(tiles!![5].subtext).isEqualTo("Set up")
+            assertThat(tiles!![5].subtext).isEqualTo("Not set")
         }
 
     @Test
@@ -387,7 +387,7 @@
             }
             with(tiles?.elementAt(2)!!) {
                 assertThat(this.stateDescription).isEqualTo("Off")
-                assertThat(this.subtextDescription).isEqualTo("Set up")
+                assertThat(this.subtextDescription).isEqualTo("Not set")
             }
             with(tiles?.elementAt(3)!!) {
                 assertThat(this.stateDescription).isEqualTo("Off")
@@ -399,7 +399,7 @@
             }
             with(tiles?.elementAt(5)!!) {
                 assertThat(this.stateDescription).isEqualTo("Off")
-                assertThat(this.subtextDescription).isEqualTo("Set up")
+                assertThat(this.subtextDescription).isEqualTo("Not set")
             }
 
             // All tiles have the same long click info
@@ -451,7 +451,7 @@
                         .setName("Active without manual")
                         .setActive(true)
                         .setManualInvocationAllowed(false)
-                        .build(),
+                        .build()
                 )
             )
             runCurrent()
@@ -492,7 +492,7 @@
                         .setId("ID")
                         .setName("Disabled by other")
                         .setEnabled(false, /* byUser= */ false)
-                        .build(),
+                        .build()
                 )
             )
             runCurrent()
@@ -500,7 +500,7 @@
             assertThat(tiles?.size).isEqualTo(1)
             with(tiles?.elementAt(0)!!) {
                 assertThat(this.text).isEqualTo("Disabled by other")
-                assertThat(this.subtext).isEqualTo("Set up")
+                assertThat(this.subtext).isEqualTo("Not set")
                 assertThat(this.enabled).isEqualTo(false)
 
                 // Click the tile
@@ -519,7 +519,7 @@
             // Check that nothing happened to the tile
             with(tiles?.elementAt(0)!!) {
                 assertThat(this.text).isEqualTo("Disabled by other")
-                assertThat(this.subtext).isEqualTo("Set up")
+                assertThat(this.subtext).isEqualTo("Not set")
                 assertThat(this.enabled).isEqualTo(false)
             }
         }
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c76b35f..2ddaa56 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1120,7 +1120,7 @@
     <string name="zen_mode_off">Off</string>
 
     <!-- Modes: label for a mode that needs to be set up [CHAR LIMIT=35] -->
-    <string name="zen_mode_set_up">Set up</string>
+    <string name="zen_mode_set_up">Not set</string>
 
     <!-- Modes: label for a mode that cannot be manually turned on [CHAR LIMIT=35] -->
     <string name="zen_mode_no_manual_invocation">Manage in settings</string>
@@ -1827,6 +1827,12 @@
     <!-- Name of the alarm status bar icon. -->
     <string name="status_bar_alarm">Alarm</string>
 
+    <!-- Format string for the content description of the icon that indicates that a Mode is on.
+       For example, if the mode name is Bedtime, this will be "Bedtime is on". This content
+       description will be associated to the mode icon in status bar, smartspace, and everyone else
+       where it might be displayed without text. [CHAR LIMIT=NONE] -->
+    <string name="active_mode_content_description"><xliff:g id="modeName" example="Do Not Disturb">%1$s</xliff:g> is on</string>
+
     <!-- Wallet strings -->
     <!-- Wallet empty state, title [CHAR LIMIT=32] -->
     <string name="wallet_title">Wallet</string>
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt
index 099e3fc..4b9ac1d 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt
@@ -21,9 +21,10 @@
 import android.view.View
 import android.widget.TextClock
 import com.android.internal.util.Preconditions
-import com.android.systemui.res.R
+import com.android.systemui.Flags
 import com.android.systemui.complication.DreamClockTimeComplication
 import com.android.systemui.complication.DreamClockTimeComplication.DreamClockTimeViewHolder
+import com.android.systemui.res.R
 import dagger.Module
 import dagger.Provides
 import dagger.Subcomponent
@@ -71,9 +72,13 @@
                             /* root = */ null,
                             /* attachToRoot = */ false,
                         ) as TextClock,
-                        "R.layout.dream_overlay_complication_clock_time did not properly inflate"
+                        "R.layout.dream_overlay_complication_clock_time did not properly inflate",
                     )
-                view.setFontVariationSettings(TAG_WEIGHT + WEIGHT)
+                if (Flags.dreamOverlayUpdatedFont()) {
+                    view.setFontVariationSettings("'wght' 600, 'opsz' 96")
+                } else {
+                    view.setFontVariationSettings(TAG_WEIGHT + WEIGHT)
+                }
                 return view
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
index c0b9efaa..914730e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.composable.transitions.FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION
+import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -49,14 +49,12 @@
                 duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
                 edge = Edge.create(from = LOCKSCREEN, to = Scenes.Bouncer),
             )
-            .setupWithoutSceneContainer(
-                edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER),
-            )
+            .setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER))
 
     private val alphaForAnimationStep: (Float) -> Float =
         when {
             SceneContainerFlag.isEnabled -> { step ->
-                    1f - Math.min((step / FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION), 1f)
+                    1f - Math.min((step / TO_BOUNCER_FADE_FRACTION), 1f)
                 }
             else -> { step -> 1f - step }
         }
@@ -64,7 +62,7 @@
     val shortcutsAlpha: Flow<Float> =
         transitionAnimation.sharedFlow(
             duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
-            onStep = alphaForAnimationStep
+            onStep = alphaForAnimationStep,
         )
 
     val lockscreenAlpha: Flow<Float> = shortcutsAlpha
@@ -76,8 +74,8 @@
                     duration = 250.milliseconds,
                     onStep = { 1f - it },
                     onCancel = { 0f },
-                    onFinish = { 0f }
+                    onFinish = { 0f },
                 ),
-            flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f)
+            flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f),
         )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index a4fe4e3..ad76b4f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -169,50 +169,34 @@
 
     private void enableZenMode(@Nullable Expandable expandable) {
         int zenDuration = mSettingZenDuration.getValue();
-        boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
-                && Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
-        if (showOnboarding) {
-            // don't show on-boarding again or notification ever
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
-            // turn on DND
-            mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
-            // show on-boarding screen
-            Intent intent = new Intent(Settings.ZEN_MODE_ONBOARDING);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-            mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
-        } else {
-            switch (zenDuration) {
-                case Settings.Secure.ZEN_DURATION_PROMPT:
-                    mUiHandler.post(() -> {
-                        Dialog dialog = makeZenModeDialog();
-                        if (expandable != null) {
-                            DialogTransitionAnimator.Controller controller =
-                                    expandable.dialogTransitionController(new DialogCuj(
-                                            InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
-                                            INTERACTION_JANK_TAG));
-                            if (controller != null) {
-                                mDialogTransitionAnimator.show(dialog,
-                                        controller, /* animateBackgroundBoundsChange= */ false);
-                            } else {
-                                dialog.show();
-                            }
+        switch (zenDuration) {
+            case Settings.Secure.ZEN_DURATION_PROMPT:
+                mUiHandler.post(() -> {
+                    Dialog dialog = makeZenModeDialog();
+                    if (expandable != null) {
+                        DialogTransitionAnimator.Controller controller =
+                                expandable.dialogTransitionController(new DialogCuj(
+                                        InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+                                        INTERACTION_JANK_TAG));
+                        if (controller != null) {
+                            mDialogTransitionAnimator.show(dialog,
+                                    controller, /* animateBackgroundBoundsChange= */ false);
                         } else {
                             dialog.show();
                         }
-                    });
-                    break;
-                case Settings.Secure.ZEN_DURATION_FOREVER:
-                    mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
-                    break;
-                default:
-                    Uri conditionId = ZenModeConfig.toTimeCondition(mContext, zenDuration,
-                            mHost.getUserId(), true).id;
-                    mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
-                            conditionId, TAG);
-            }
+                    } else {
+                        dialog.show();
+                    }
+                });
+                break;
+            case Settings.Secure.ZEN_DURATION_FOREVER:
+                mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG);
+                break;
+            default:
+                Uri conditionId = ZenModeConfig.toTimeCondition(mContext, zenDuration,
+                        mHost.getUserId(), true).id;
+                mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                        conditionId, TAG);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt
deleted file mode 100644
index a8d0777..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.data.repository
-
-import android.graphics.Region
-import android.view.ISystemGestureExclusionListener
-import android.view.IWindowManager
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
-import javax.inject.Inject
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-
-@SysUISingleton
-class SystemGestureExclusionRepository
-@Inject
-constructor(private val windowManager: IWindowManager) {
-
-    /**
-     * Returns [Flow] of the [Region] in which system gestures should be excluded on the display
-     * identified with [displayId].
-     */
-    fun exclusionRegion(displayId: Int): Flow<Region?> {
-        return conflatedCallbackFlow {
-            val listener =
-                object : ISystemGestureExclusionListener.Stub() {
-                    override fun onSystemGestureExclusionChanged(
-                        displayId: Int,
-                        restrictedRegion: Region?,
-                        unrestrictedRegion: Region?,
-                    ) {
-                        trySend(restrictedRegion)
-                    }
-                }
-            windowManager.registerSystemGestureExclusionListener(listener, displayId)
-
-            awaitClose {
-                windowManager.unregisterSystemGestureExclusionListener(listener, displayId)
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt
deleted file mode 100644
index 4cee874..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.domain.interactor
-
-import android.graphics.Region
-import com.android.systemui.scene.data.repository.SystemGestureExclusionRepository
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-
-class SystemGestureExclusionInteractor
-@Inject
-constructor(private val repository: SystemGestureExclusionRepository) {
-
-    /**
-     * Returns [Flow] of the [Region] in which system gestures should be excluded on the display
-     * identified with [displayId].
-     */
-    fun exclusionRegion(displayId: Int): Flow<Region?> {
-        return repository.exclusionRegion(displayId)
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index a8be580..38f4e73 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -107,13 +107,7 @@
             view.viewModel(
                 traceName = "SceneWindowRootViewBinder",
                 minWindowLifecycleState = WindowLifecycleState.ATTACHED,
-                factory = {
-                    viewModelFactory.create(
-                        view,
-                        view.context.displayId,
-                        motionEventHandlerReceiver,
-                    )
-                },
+                factory = { viewModelFactory.create(view, motionEventHandlerReceiver) },
             ) { viewModel ->
                 try {
                     view.setViewTreeOnBackPressedDispatcherOwner(
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt
deleted file mode 100644
index a1d915a..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.ui.viewmodel
-
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.geometry.Offset
-import com.android.systemui.lifecycle.ExclusiveActivatable
-import com.android.systemui.lifecycle.Hydrator
-import com.android.systemui.scene.domain.interactor.SystemGestureExclusionInteractor
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import kotlin.math.roundToInt
-
-/** Decides whether drag gestures should be filtered out in the scene container framework. */
-class SceneContainerGestureFilter
-@AssistedInject
-constructor(interactor: SystemGestureExclusionInteractor, @Assisted displayId: Int) :
-    ExclusiveActivatable() {
-
-    private val hydrator = Hydrator("SceneContainerGestureFilter.hydrator")
-    private val exclusionRegion by
-        hydrator.hydratedStateOf(
-            traceName = "exclusionRegion",
-            initialValue = null,
-            source = interactor.exclusionRegion(displayId),
-        )
-
-    override suspend fun onActivated(): Nothing {
-        hydrator.activate()
-    }
-
-    /**
-     * Returns `true` if a drag gesture starting at [startPosition] should be filtered out (e.g.
-     * ignored, `false` otherwise.
-     *
-     * Invoke this and pass in the position of the `ACTION_DOWN` pointer event that began the
-     * gesture.
-     */
-    fun shouldFilterGesture(startPosition: Offset): Boolean {
-        check(isActive) { "Must be activated to use!" }
-
-        return exclusionRegion?.contains(startPosition.x.roundToInt(), startPosition.y.roundToInt())
-            ?: false
-    }
-
-    @AssistedFactory
-    interface Factory {
-        fun create(displayId: Int): SceneContainerGestureFilter
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index f505385..889380a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -19,7 +19,6 @@
 import android.view.MotionEvent
 import android.view.View
 import androidx.compose.runtime.getValue
-import androidx.compose.ui.geometry.Offset
 import com.android.app.tracing.coroutines.launch
 import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.DefaultEdgeDetector
@@ -61,10 +60,8 @@
     shadeInteractor: ShadeInteractor,
     private val splitEdgeDetector: SplitEdgeDetector,
     private val logger: SceneLogger,
-    gestureFilterFactory: SceneContainerGestureFilter.Factory,
     hapticsViewModelFactory: SceneContainerHapticsViewModel.Factory,
     @Assisted view: View,
-    @Assisted displayId: Int,
     @Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
 ) : ExclusiveActivatable() {
 
@@ -92,8 +89,6 @@
                 },
         )
 
-    private val gestureFilter: SceneContainerGestureFilter = gestureFilterFactory.create(displayId)
-
     override suspend fun onActivated(): Nothing {
         try {
             // Sends a MotionEventHandler to the owner of the view-model so they can report
@@ -112,7 +107,6 @@
 
             coroutineScope {
                 launch { hydrator.activate() }
-                launch { gestureFilter.activate() }
                 launch("SceneContainerHapticsViewModel") { hapticsViewModel.activate() }
             }
             awaitCancellation()
@@ -262,17 +256,6 @@
         }
     }
 
-    /**
-     * Returns `true` if a drag gesture starting at [startPosition] should be filtered out (e.g.
-     * ignored, `false` otherwise.
-     *
-     * Invoke this and pass in the position of the `ACTION_DOWN` pointer event that began the
-     * gesture.
-     */
-    fun shouldFilterGesture(startPosition: Offset): Boolean {
-        return gestureFilter.shouldFilterGesture(startPosition)
-    }
-
     /** Defines interface for classes that can handle externally-reported [MotionEvent]s. */
     interface MotionEventHandler {
         /** Notifies that a [MotionEvent] has occurred. */
@@ -289,7 +272,6 @@
     interface Factory {
         fun create(
             view: View,
-            displayId: Int,
             motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
         ): SceneContainerViewModel
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
index 65b6231..e5f6846 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt
@@ -30,41 +30,47 @@
 fun singleShadeActions(
     requireTwoPointersForTopEdgeForQs: Boolean = false
 ): Array<Pair<UserAction, UserActionResult>> {
+    val shadeUserActionResult = UserActionResult(Scenes.Shade, isIrreversible = true)
+    val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings, isIrreversible = true)
     return arrayOf(
         // Swiping down, not from the edge, always goes to shade.
-        Swipe.Down to Scenes.Shade,
-        swipeDown(pointerCount = 2) to Scenes.Shade,
+        Swipe.Down to shadeUserActionResult,
+        swipeDown(pointerCount = 2) to shadeUserActionResult,
 
         // Swiping down from the top edge.
         swipeDownFromTop(pointerCount = 1) to
             if (requireTwoPointersForTopEdgeForQs) {
-                Scenes.Shade
+                shadeUserActionResult
             } else {
-                Scenes.QuickSettings
+                qsSceneUserActionResult
             },
-        swipeDownFromTop(pointerCount = 2) to Scenes.QuickSettings,
+        swipeDownFromTop(pointerCount = 2) to qsSceneUserActionResult,
     )
 }
 
 /** Returns collection of [UserAction] to [UserActionResult] pairs for opening the split shade. */
 fun splitShadeActions(): Array<Pair<UserAction, UserActionResult>> {
-    val splitShadeSceneKey = UserActionResult(Scenes.Shade, ToSplitShade)
+    val shadeUserActionResult = UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)
     return arrayOf(
         // Swiping down, not from the edge, always goes to shade.
-        Swipe.Down to splitShadeSceneKey,
-        swipeDown(pointerCount = 2) to splitShadeSceneKey,
+        Swipe.Down to shadeUserActionResult,
+        swipeDown(pointerCount = 2) to shadeUserActionResult,
         // Swiping down from the top edge goes to QS.
-        swipeDownFromTop(pointerCount = 1) to splitShadeSceneKey,
-        swipeDownFromTop(pointerCount = 2) to splitShadeSceneKey,
+        swipeDownFromTop(pointerCount = 1) to shadeUserActionResult,
+        swipeDownFromTop(pointerCount = 2) to shadeUserActionResult,
     )
 }
 
 /** Returns collection of [UserAction] to [UserActionResult] pairs for opening the dual shade. */
 fun dualShadeActions(): Array<Pair<UserAction, UserActionResult>> {
+    val notifShadeUserActionResult =
+        UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)
+    val qsShadeuserActionResult =
+        UserActionResult.ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true)
     return arrayOf(
-        Swipe.Down to Overlays.NotificationsShade,
+        Swipe.Down to notifShadeUserActionResult,
         Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to
-            Overlays.QuickSettingsShade,
+            qsShadeuserActionResult,
     )
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
index cc6e8c2..3113dc4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
@@ -32,6 +32,7 @@
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
 
 /**
  * Models the UI state for the user actions that the user can perform to navigate to other scenes.
@@ -50,7 +51,9 @@
         combine(
                 shadeInteractor.shadeMode,
                 qsSceneAdapter.isCustomizerShowing,
-                sceneBackInteractor.backScene.map { it ?: SceneFamilies.Home },
+                sceneBackInteractor.backScene
+                    .filter { it != Scenes.Shade }
+                    .map { it ?: SceneFamilies.Home },
             ) { shadeMode, isCustomizerShowing, backScene ->
                 buildMap<UserAction, UserActionResult> {
                     if (!isCustomizerShowing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index e3c47a4..321593b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -596,7 +596,8 @@
             // NetworkCapabilities, but we need to convert it into TRANSPORT_WIFI in order to
             // distinguish it from VCN over Cellular.
             if (transportTypes[i] == NetworkCapabilities.TRANSPORT_CELLULAR
-                    && Utils.tryGetWifiInfoForVcn(networkCapabilities) != null) {
+                    && Utils.tryGetWifiInfoForVcn(mConnectivityManager, networkCapabilities)
+                            != null) {
                 transportTypes[i] = NetworkCapabilities.TRANSPORT_WIFI;
                 break;
             }
@@ -1112,7 +1113,9 @@
                     continue;
                 }
                 if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR
-                        && Utils.tryGetWifiInfoForVcn(mLastDefaultNetworkCapabilities) != null) {
+                        && Utils.tryGetWifiInfoForVcn(
+                                        mConnectivityManager, mLastDefaultNetworkCapabilities)
+                                != null) {
                     mConnectedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
                     if (mLastDefaultNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
                         mValidatedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 8c03538..f8eae36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -411,7 +411,8 @@
                     mainActiveMode.getIcon().key().resPackage(),
                     mainActiveMode.getIcon().key().resId(),
                     mainActiveMode.getIcon().drawable(),
-                    mainActiveMode.getName(),
+                    mResources.getString(R.string.active_mode_content_description,
+                            mainActiveMode.getName()),
                     StatusBarIcon.Shape.FIXED_SPACE);
         }
         if (visible != mZenVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
index 6764839c..4f595ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
@@ -76,7 +76,7 @@
                         // can be manually toggled on
                         mode.rule.isEnabled -> mode.isActive || mode.rule.isManualInvocationAllowed
                         // Mode was created as disabled, or disabled by the app that owns it ->
-                        // will be shown with a "Set up" text
+                        // will be shown with a "Not set" text
                         !mode.rule.isEnabled -> mode.status == ZenMode.Status.DISABLED_BY_OTHER
                         else -> false
                     }
@@ -120,7 +120,7 @@
                         },
                         onLongClick = { openSettings(mode) },
                         onLongClickLabel =
-                            context.resources.getString(R.string.accessibility_long_click_tile)
+                            context.resources.getString(R.string.accessibility_long_click_tile),
                     )
                 }
             }
@@ -137,10 +137,10 @@
 
     /**
      * Returns a description of the mode, which is:
-     *   * a prompt to set up the mode if it is not enabled
-     *   * if it cannot be manually activated, text that says so
-     *   * otherwise, the trigger description of the mode if it exists...
-     *   * ...or null if it doesn't
+     * * a prompt to set up the mode if it is not enabled
+     * * if it cannot be manually activated, text that says so
+     * * otherwise, the trigger description of the mode if it exists...
+     * * ...or null if it doesn't
      *
      * This description is used directly for the content description of a mode tile for screen
      * readers, and for the tile subtext will be augmented with the current status of the mode.
@@ -174,7 +174,7 @@
                     context,
                     R.style.Theme_SystemUI_Dialog,
                     /* cancelIsNeutral= */ true,
-                    zenDialogMetricsLogger
+                    zenDialogMetricsLogger,
                 )
                 .createDialog()
         SystemUIDialog.applyFlags(dialog)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 98315d0c..83dbfa0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -95,6 +95,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class NetworkControllerBaseTest extends SysuiTestCase {
@@ -332,10 +333,15 @@
     }
 
     public void setConnectivityViaCallbackInNetworkControllerForVcn(
-            int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
+            int networkType,
+            boolean validated,
+            boolean isConnected,
+            VcnTransportInfo info,
+            Network underlyingNetwork) {
         final NetworkCapabilities.Builder builder =
                 new NetworkCapabilities.Builder(mNetCapabilities);
-        builder.setTransportInfo(info);
+        builder.setTransportInfo(info)
+                .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork));
         setConnectivityCommon(builder, networkType, validated, isConnected);
         mDefaultCallbackInNetworkController.onCapabilitiesChanged(
                 mock(Network.class), builder.build());
@@ -385,10 +391,15 @@
     }
 
     public void setConnectivityViaCallbackInWifiTrackerForVcn(
-            int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
+            int networkType,
+            boolean validated,
+            boolean isConnected,
+            VcnTransportInfo info,
+            Network underlyingNetwork) {
         final NetworkCapabilities.Builder builder =
                 new NetworkCapabilities.Builder(mNetCapabilities);
-        builder.setTransportInfo(info);
+        builder.setTransportInfo(info)
+                .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork));
         setConnectivityCommon(builder, networkType, validated, isConnected);
         if (networkType == NetworkCapabilities.TRANSPORT_CELLULAR) {
             if (isConnected) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
index 6c80a97..6febb91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
 import static junit.framework.Assert.assertEquals;
 
@@ -250,6 +251,17 @@
         assertEquals(testSsid, mNetworkController.mWifiSignalController.mCurrentState.ssid);
     }
 
+    private Network newWifiNetwork(WifiInfo wifiInfo) {
+        final Network network = mock(Network.class);
+        final NetworkCapabilities wifiCaps =
+                new NetworkCapabilities.Builder()
+                        .addTransportType(TRANSPORT_WIFI)
+                        .setTransportInfo(wifiInfo)
+                        .build();
+        when(mMockCm.getNetworkCapabilities(network)).thenReturn(wifiCaps);
+        return network;
+    }
+
     @Test
     public void testVcnWithUnderlyingWifi() {
         String testSsid = "Test VCN SSID";
@@ -266,11 +278,19 @@
             setWifiLevelForVcn(testLevel);
 
             setConnectivityViaCallbackInNetworkControllerForVcn(
-                    NetworkCapabilities.TRANSPORT_CELLULAR, true, true, mVcnTransportInfo);
+                    NetworkCapabilities.TRANSPORT_CELLULAR,
+                    true,
+                    true,
+                    mVcnTransportInfo,
+                    newWifiNetwork(mWifiInfo));
             verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, true);
 
             setConnectivityViaCallbackInNetworkControllerForVcn(
-                    NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
+                    NetworkCapabilities.TRANSPORT_CELLULAR,
+                    false,
+                    true,
+                    mVcnTransportInfo,
+                    newWifiNetwork(mWifiInfo));
             verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, false);
         }
     }
@@ -391,13 +411,15 @@
     }
 
     protected void setWifiLevelForVcn(int level) {
-        when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
-        when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
         when(mWifiInfo.getRssi()).thenReturn(calculateRssiForLevel(level));
         when(mWifiInfo.isCarrierMerged()).thenReturn(true);
         when(mWifiInfo.getSubscriptionId()).thenReturn(1);
         setConnectivityViaCallbackInWifiTrackerForVcn(
-                NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
+                NetworkCapabilities.TRANSPORT_CELLULAR,
+                false,
+                true,
+                mVcnTransportInfo,
+                newWifiNetwork(mWifiInfo));
     }
 
     private int calculateRssiForLevel(int level) {
@@ -409,13 +431,15 @@
     }
 
     protected void setWifiStateForVcn(boolean connected, String ssid) {
-        when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
-        when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
         when(mWifiInfo.getSSID()).thenReturn(ssid);
         when(mWifiInfo.isCarrierMerged()).thenReturn(true);
         when(mWifiInfo.getSubscriptionId()).thenReturn(1);
         setConnectivityViaCallbackInWifiTrackerForVcn(
-                NetworkCapabilities.TRANSPORT_CELLULAR, false, connected, mVcnTransportInfo);
+                NetworkCapabilities.TRANSPORT_CELLULAR,
+                false,
+                connected,
+                mVcnTransportInfo,
+                newWifiNetwork(mWifiInfo));
     }
 
     protected void verifyLastQsDataDirection(boolean in, boolean out) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 2ed3473..8360042 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -160,11 +160,11 @@
         testableLooper = TestableLooper.get(this)
         context.orCreateTestableResources.addOverride(
             com.android.internal.R.string.status_bar_alarm_clock,
-            ALARM_SLOT
+            ALARM_SLOT,
         )
         context.orCreateTestableResources.addOverride(
             com.android.internal.R.string.status_bar_managed_profile,
-            MANAGED_PROFILE_SLOT
+            MANAGED_PROFILE_SLOT,
         )
         whenever(devicePolicyManager.resources).thenReturn(devicePolicyManagerResources)
         whenever(devicePolicyManagerResources.getString(anyString(), any())).thenReturn("")
@@ -430,8 +430,8 @@
                     eq(mContext.packageName),
                     eq(android.R.drawable.ic_lock_lock),
                     any(), // non-null
-                    eq("Bedtime Mode"),
-                    eq(StatusBarIcon.Shape.FIXED_SPACE)
+                    eq("Bedtime Mode is on"),
+                    eq(StatusBarIcon.Shape.FIXED_SPACE),
                 )
 
             zenModeRepository.deactivateMode("bedtime")
@@ -443,8 +443,8 @@
                     eq(null),
                     eq(android.R.drawable.ic_media_play),
                     any(), // non-null
-                    eq("Other Mode"),
-                    eq(StatusBarIcon.Shape.FIXED_SPACE)
+                    eq("Other Mode is on"),
+                    eq(StatusBarIcon.Shape.FIXED_SPACE),
                 )
 
             zenModeRepository.deactivateMode("other")
@@ -538,7 +538,7 @@
             privacyLogger,
             fakeConnectedDisplayStateProvider,
             kosmos.zenModeInteractor,
-            JavaAdapter(testScope.backgroundScope)
+            JavaAdapter(testScope.backgroundScope),
         )
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index f842db4..020f0a6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -8,17 +8,14 @@
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.scene.domain.interactor.systemGestureExclusionInteractor
 import com.android.systemui.scene.shared.logger.sceneLogger
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.FakeOverlay
-import com.android.systemui.scene.ui.viewmodel.SceneContainerGestureFilter
 import com.android.systemui.scene.ui.viewmodel.SceneContainerHapticsViewModel
 import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
 import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
-import com.android.systemui.settings.displayTracker
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import kotlinx.coroutines.flow.MutableStateFlow
 import org.mockito.kotlin.mock
@@ -72,16 +69,15 @@
 }
 
 val Kosmos.sceneContainerViewModel by Fixture {
-    sceneContainerViewModelFactory.create(mock<View>(), displayTracker.defaultDisplayId, {}).apply {
-        setTransitionState(transitionState)
-    }
+    sceneContainerViewModelFactory
+        .create(mock<View>()) {}
+        .apply { setTransitionState(transitionState) }
 }
 
 val Kosmos.sceneContainerViewModelFactory by Fixture {
     object : SceneContainerViewModel.Factory {
         override fun create(
             view: View,
-            displayId: Int,
             motionEventHandlerReceiver: (SceneContainerViewModel.MotionEventHandler?) -> Unit,
         ): SceneContainerViewModel =
             SceneContainerViewModel(
@@ -91,26 +87,13 @@
                 shadeInteractor = shadeInteractor,
                 splitEdgeDetector = splitEdgeDetector,
                 logger = sceneLogger,
-                gestureFilterFactory = sceneContainerGestureFilterFactory,
                 hapticsViewModelFactory = sceneContainerHapticsViewModelFactory,
                 view = view,
-                displayId = displayId,
                 motionEventHandlerReceiver = motionEventHandlerReceiver,
             )
     }
 }
 
-val Kosmos.sceneContainerGestureFilterFactory by Fixture {
-    object : SceneContainerGestureFilter.Factory {
-        override fun create(displayId: Int): SceneContainerGestureFilter {
-            return SceneContainerGestureFilter(
-                interactor = systemGestureExclusionInteractor,
-                displayId = displayId,
-            )
-        }
-    }
-}
-
 val Kosmos.sceneContainerHapticsViewModelFactory by Fixture {
     object : SceneContainerHapticsViewModel.Factory {
         override fun create(view: View): SceneContainerHapticsViewModel {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt
deleted file mode 100644
index 3e46c3f..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.domain.interactor
-
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.scene.data.repository.systemGestureExclusionRepository
-
-val Kosmos.systemGestureExclusionInteractor by Fixture {
-    SystemGestureExclusionInteractor(repository = systemGestureExclusionRepository)
-}
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 994bdb5..6489905 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -206,7 +206,7 @@
 
     // Inform that DND settings have changed on OS upgrade
     // Package: android
-    NOTE_ZEN_UPGRADE = 48;
+    NOTE_ZEN_UPGRADE = 48  [deprecated = true];
 
     // Notification to suggest automatic battery saver.
     // Package: android
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index ab9cc20..d0c3daf 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -438,62 +438,17 @@
                         targetUser,
                         mServiceConfig.getExecuteAppFunctionCancellationTimeoutMillis(),
                         cancellationSignal,
-                        new RunServiceCallCallback<IAppFunctionService>() {
-                            @Override
-                            public void onServiceConnected(
-                                    @NonNull IAppFunctionService service,
-                                    @NonNull
-                                            ServiceUsageCompleteListener
-                                                    serviceUsageCompleteListener) {
-                                try {
-                                    service.executeAppFunction(
-                                            requestInternal.getClientRequest(),
-                                            cancellationCallback,
-                                            new IExecuteAppFunctionCallback.Stub() {
-                                                @Override
-                                                public void onResult(
-                                                        ExecuteAppFunctionResponse response) {
-                                                    safeExecuteAppFunctionCallback.onResult(
-                                                            response);
-                                                    serviceUsageCompleteListener.onCompleted();
-                                                }
-                                            });
-                                } catch (Exception e) {
-                                    safeExecuteAppFunctionCallback.onResult(
-                                            ExecuteAppFunctionResponse.newFailure(
-                                                    ExecuteAppFunctionResponse
-                                                            .RESULT_APP_UNKNOWN_ERROR,
-                                                    e.getMessage(),
-                                                    /* extras= */ null));
-                                    serviceUsageCompleteListener.onCompleted();
-                                }
-                            }
-
-                            @Override
-                            public void onFailedToConnect() {
-                                Slog.e(TAG, "Failed to connect to service");
-                                safeExecuteAppFunctionCallback.onResult(
-                                        ExecuteAppFunctionResponse.newFailure(
-                                                ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
-                                                "Failed to connect to AppFunctionService",
-                                                /* extras= */ null));
-                            }
-
-                            @Override
-                            public void onCancelled() {
-                                // Do not forward the result back to the caller once it has been
-                                // canceled. The caller does not need a notification and should
-                                // proceed after initiating a cancellation.
-                                safeExecuteAppFunctionCallback.disable();
-                            }
-                        },
+                        RunAppFunctionServiceCallback.create(
+                                requestInternal,
+                                cancellationCallback,
+                                safeExecuteAppFunctionCallback),
                         callerBinder);
 
         if (!bindServiceResult) {
             Slog.e(TAG, "Failed to bind to the AppFunctionService");
             safeExecuteAppFunctionCallback.onResult(
                     ExecuteAppFunctionResponse.newFailure(
-                            ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
+                            ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
                             "Failed to bind the AppFunctionService.",
                             /* extras= */ null));
         }
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
new file mode 100644
index 0000000..7820390
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.appfunctions;
+
+import android.annotation.NonNull;
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
+import android.app.appfunctions.ExecuteAppFunctionResponse;
+import android.app.appfunctions.IAppFunctionService;
+import android.app.appfunctions.ICancellationCallback;
+import android.app.appfunctions.IExecuteAppFunctionCallback;
+import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback;
+import android.util.Slog;
+
+import com.android.server.appfunctions.RemoteServiceCaller.RunServiceCallCallback;
+import com.android.server.appfunctions.RemoteServiceCaller.ServiceUsageCompleteListener;
+
+
+/**
+ * A callback to forward a request to the {@link IAppFunctionService} and report back the result.
+ */
+public class RunAppFunctionServiceCallback implements RunServiceCallCallback<IAppFunctionService> {
+
+    private final ExecuteAppFunctionAidlRequest mRequestInternal;
+    private final SafeOneTimeExecuteAppFunctionCallback mSafeExecuteAppFunctionCallback;
+    private final ICancellationCallback mCancellationCallback;
+
+    private RunAppFunctionServiceCallback(
+            ExecuteAppFunctionAidlRequest requestInternal,
+            ICancellationCallback cancellationCallback,
+            SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) {
+        this.mRequestInternal = requestInternal;
+        this.mSafeExecuteAppFunctionCallback = safeExecuteAppFunctionCallback;
+        this.mCancellationCallback = cancellationCallback;
+    }
+
+    /**
+     * Creates a new instance of {@link RunAppFunctionServiceCallback}.
+     *
+     * @param requestInternal a request to send to the service.
+     * @param cancellationCallback a callback to forward cancellation signal to the service.
+     * @param safeExecuteAppFunctionCallback a callback to report back the result of the operation.
+     */
+    public static RunAppFunctionServiceCallback create(
+            ExecuteAppFunctionAidlRequest requestInternal,
+            ICancellationCallback cancellationCallback,
+            SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) {
+        return new RunAppFunctionServiceCallback(
+                requestInternal, cancellationCallback, safeExecuteAppFunctionCallback);
+    }
+
+    @Override
+    public void onServiceConnected(
+            @NonNull IAppFunctionService service,
+            @NonNull ServiceUsageCompleteListener serviceUsageCompleteListener) {
+        try {
+            service.executeAppFunction(
+                    mRequestInternal.getClientRequest(),
+                    mCancellationCallback,
+                    new IExecuteAppFunctionCallback.Stub() {
+                        @Override
+                        public void onResult(ExecuteAppFunctionResponse response) {
+                            mSafeExecuteAppFunctionCallback.onResult(response);
+                            serviceUsageCompleteListener.onCompleted();
+                        }
+                    });
+        } catch (Exception e) {
+            mSafeExecuteAppFunctionCallback.onResult(
+                    ExecuteAppFunctionResponse.newFailure(
+                            ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
+                            e.getMessage(),
+                            /* extras= */ null));
+            serviceUsageCompleteListener.onCompleted();
+        }
+    }
+
+    @Override
+    public void onFailedToConnect() {
+        Slog.e("AppFunctionManagerServiceImpl", "Failed to connect to service");
+        mSafeExecuteAppFunctionCallback.onResult(
+                ExecuteAppFunctionResponse.newFailure(
+                        ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
+                        "Failed to connect to AppFunctionService",
+                        /* extras= */ null));
+    }
+
+    @Override
+    public void onCancelled() {
+        mSafeExecuteAppFunctionCallback.disable();
+    }
+}
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 9060250..2acedd5 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -47,6 +47,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
+import android.util.EventLog;
 import android.util.IndentingPrintWriter;
 import android.util.LongArrayQueue;
 import android.util.Slog;
@@ -200,6 +201,13 @@
     // aborted.
     private static final String METADATA_FILE = "/metadata/watchdog/mitigation_count.txt";
 
+    /**
+     * EventLog tags used when logging into the event log. Note the values must be sync with
+     * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct
+     * name translation.
+     */
+    private static final int LOG_TAG_RESCUE_NOTE = 2900;
+
     private static final Object sPackageWatchdogLock = new Object();
     @GuardedBy("sPackageWatchdogLock")
     private static PackageWatchdog sPackageWatchdog;
@@ -2024,7 +2032,7 @@
             } else {
                 int count = getCount() + 1;
                 setCount(count);
-                EventLogTags.writeRescueNote(Process.ROOT_UID, count, window);
+                EventLog.writeEvent(LOG_TAG_RESCUE_NOTE, Process.ROOT_UID, count, window);
                 if (Flags.recoverabilityDetection()) {
                     // After a reboot (e.g. by WARM_REBOOT or mainline rollback) we apply
                     // mitigations without waiting for DEFAULT_BOOT_LOOP_TRIGGER_COUNT.
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index ada1953..feb5775 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -42,6 +42,7 @@
 import android.sysprop.CrashRecoveryProperties;
 import android.text.TextUtils;
 import android.util.ArraySet;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
 
@@ -154,6 +155,14 @@
     private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
             | ApplicationInfo.FLAG_SYSTEM;
 
+    /**
+     * EventLog tags used when logging into the event log. Note the values must be sync with
+     * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct
+     * name translation.
+     */
+    private static final int LOG_TAG_RESCUE_SUCCESS = 2902;
+    private static final int LOG_TAG_RESCUE_FAILURE = 2903;
+
     /** Register the Rescue Party observer as a Package Watchdog health observer */
     public static void registerHealthObserver(Context context) {
         PackageWatchdog.getInstance(context).registerHealthObserver(
@@ -523,7 +532,7 @@
         Slog.w(TAG, "Attempting rescue level " + levelToString(level));
         try {
             executeRescueLevelInternal(context, level, failedPackage);
-            EventLogTags.writeRescueSuccess(level);
+            EventLog.writeEvent(LOG_TAG_RESCUE_SUCCESS, level);
             String successMsg = "Finished rescue level " + levelToString(level);
             if (!TextUtils.isEmpty(failedPackage)) {
                 successMsg += " for package " + failedPackage;
@@ -704,7 +713,7 @@
     private static void logRescueException(int level, @Nullable String failedPackageName,
             Throwable t) {
         final String msg = getCompleteMessage(t);
-        EventLogTags.writeRescueFailure(level, msg);
+        EventLog.writeEvent(LOG_TAG_RESCUE_FAILURE, level, msg);
         String failureMsg = "Failed rescue level " + levelToString(level);
         if (!TextUtils.isEmpty(failedPackageName)) {
             failureMsg += " for package " + failedPackageName;
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index a459ea9..ce66dc3 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -114,6 +114,9 @@
             "options": [
                 {
                     "include-filter": "android.os.storage.cts.StorageManagerTest"
+                },
+                {
+                    "include-filter": "android.os.storage.cts.StorageStatsManagerTest"
                 }
             ]
         }
@@ -173,15 +176,6 @@
                     "include-filter": "com.android.server.wm.BackgroundActivityStart*"
                 }
             ]
-        },
-        {
-            "name": "CtsOsTestCases",
-            "file_patterns": ["StorageManagerService\\.java"],
-            "options": [
-                {
-                    "include-filter": "android.os.storage.cts.StorageStatsManagerTest"
-                }
-            ]
         }
    ]
 }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 78a0a11..796de19 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -458,7 +458,13 @@
         }
 
         void setThreadPriority(int tid, int priority) {
-            Process.setThreadPriority(tid, priority);
+            if (Flags.resetOnForkEnabled()) {
+                Process.setThreadScheduler(tid,
+                    Process.SCHED_OTHER | Process.SCHED_RESET_ON_FORK,
+                    priority);
+            } else {
+                 Process.setThreadPriority(tid, priority);
+            }
         }
 
     }
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 4f6da3b..cc66378 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -214,3 +214,10 @@
     description: "Defer submitting display events to frozen processes."
     bug: "326315985"
 }
+
+flag {
+    name: "reset_on_fork_enabled"
+    namespace: "system_performance"
+    description: "Set reset_on_fork flag."
+    bug: "370988407"
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c2e62d0..e0cf96f 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -540,11 +540,11 @@
             this.uid = uid;
         }
 
-        @SuppressWarnings("GuardedBy")
         public void clear() {
             mAppOpsCheckingService.removeUid(uid);
             for (int i = 0; i < pkgOps.size(); i++) {
-                packageRemovedLocked(uid, pkgOps.keyAt(i));
+                String packageName = pkgOps.keyAt(i);
+                mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid));
             }
         }
 
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 87504154..0475b94 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -384,11 +384,12 @@
     /**
      * Indicates if a Bluetooth SCO activation request owner is controlling
      * the SCO audio state itself or not.
-     * @param uid the UI of the SOC request owner app
+     * @param uid the UID of the SOC request owner app
      * @return true if we should control SCO audio state, false otherwise
      */
     private boolean shouldStartScoForUid(int uid) {
-        return !(uid == Process.BLUETOOTH_UID || uid == Process.PHONE_UID);
+        return !(UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)
+                || UserHandle.isSameApp(uid, Process.PHONE_UID));
     }
 
     @GuardedBy("mDeviceStateLock")
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 5fd12c2..09de894 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -385,11 +385,6 @@
                     || !updatedDevice.getDeviceAddress().equals(ads.getDeviceAddress())) {
                 continue;
             }
-            if (mDeviceBroker.isSADevice(updatedDevice) == mDeviceBroker.isSADevice(ads)) {
-                ads.setHasHeadTracker(updatedDevice.hasHeadTracker());
-                ads.setHeadTrackerEnabled(updatedDevice.isHeadTrackerEnabled());
-                ads.setSAEnabled(updatedDevice.isSAEnabled());
-            }
             ads.setAudioDeviceCategory(updatedDevice.getAudioDeviceCategory());
 
             mDeviceBroker.postUpdatedAdiDeviceState(ads, false /*initSA*/);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f9e8392..c37d471 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -10100,9 +10100,6 @@
 
                 case MSG_INIT_SPATIALIZER:
                     onInitSpatializer();
-                    // the device inventory can only be synchronized after the
-                    // spatializer has been initialized
-                    mDeviceBroker.postSynchronizeAdiDevicesInInventory(null);
                     mAudioEventWakeLock.release();
                     break;
 
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index af9c9ac..8d96ba9 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -377,6 +377,7 @@
  *              </point>
  *            </map>
  *          </luxToBrightnessMapping>
+ *          <idleStylusTimeoutMillis>10000</idleStylusTimeoutMillis>
  *      </autoBrightness>
  *
  *      <screenBrightnessRampFastDecrease>0.01</screenBrightnessRampFastDecrease>
@@ -708,6 +709,10 @@
 
     private static final int KEEP_CURRENT_BRIGHTNESS = -1;
 
+    // The default value to 0 which will signify that the stylus usage immediately stopped
+    // after it was started. This will make the system behave as if the stylus was never used
+    private static final int DEFAULT_IDLE_STYLUS_TIMEOUT_MILLIS = 0;
+
     private final Context mContext;
 
     // The details of the ambient light sensor associated with this display.
@@ -754,6 +759,9 @@
     @Nullable
     private DisplayBrightnessMappingConfig mDisplayBrightnessMapping;
 
+    private int mIdleStylusTimeoutMillis =
+            DEFAULT_IDLE_STYLUS_TIMEOUT_MILLIS;
+
     private float mBacklightMinimum = Float.NaN;
     private float mBacklightMaximum = Float.NaN;
     private float mBrightnessDefault = Float.NaN;
@@ -1730,6 +1738,7 @@
                 + ", mDisplayBrightnessMapping= " + mDisplayBrightnessMapping
                 + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable
                 + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable
+                + ", mIdleStylusTimeoutMillis= " + mIdleStylusTimeoutMillis
                 + "\n"
                 + "mDefaultLowBlockingZoneRefreshRate= " + mDefaultLowBlockingZoneRefreshRate
                 + ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate
@@ -2389,10 +2398,19 @@
         loadAutoBrightnessDarkeningLightDebounceIdle(autoBrightness);
         mDisplayBrightnessMapping = new DisplayBrightnessMappingConfig(mContext, mFlags,
                 autoBrightness, getBacklightToBrightnessSpline());
+        loadIdleStylusTimeoutMillis(autoBrightness);
         loadEnableAutoBrightness(autoBrightness);
     }
 
     /**
+     * Gets the timeout post the stylus usage after which the automatic brightness will be enabled
+     * again
+     */
+    public int getIdleStylusTimeoutMillis() {
+        return mIdleStylusTimeoutMillis;
+    }
+
+    /**
      * Loads the auto-brightness brightening light debounce. Internally, this takes care of loading
      * the value from the display config, and if not present, falls back to config.xml.
      */
@@ -2923,6 +2941,16 @@
         return levels;
     }
 
+    private void loadIdleStylusTimeoutMillis(AutoBrightness autoBrightness) {
+        if (autoBrightness == null) {
+            return;
+        }
+        BigInteger idleStylusTimeoutMillis = autoBrightness.getIdleStylusTimeoutMillis();
+        if (idleStylusTimeoutMillis != null) {
+            mIdleStylusTimeoutMillis = idleStylusTimeoutMillis.intValue();
+        }
+    }
+
     private void loadEnableAutoBrightness(AutoBrightness autobrightness) {
         // mDdcAutoBrightnessAvailable is initialised to true, so that we fallback to using the
         // config.xml values if the autobrightness tag is not defined in the ddc file.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 99a7743..bb503aa 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -5646,6 +5646,21 @@
         public void onPresentation(int displayId, boolean isShown) {
             mExternalDisplayPolicy.onPresentation(displayId, isShown);
         }
+
+        @Override
+        public void stylusGestureStarted(long eventTime) {
+            if (mFlags.isBlockAutobrightnessChangesOnStylusUsage()) {
+                DisplayPowerController displayPowerController;
+                synchronized (mSyncRoot) {
+                    displayPowerController = mDisplayPowerControllers.get(
+                            Display.DEFAULT_DISPLAY);
+                }
+                // We assume that the stylus is being used on the default display. This should
+                // be changed to the displayId on which it is being used once we start getting this
+                // information from the input manager service
+                displayPowerController.stylusGestureStarted(eventTime);
+            }
+        }
     }
 
     class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 03fec011..8f07bb3 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -167,12 +167,11 @@
     private static final int MSG_SET_DWBC_LOGGING_ENABLED = 16;
     private static final int MSG_SET_BRIGHTNESS_FROM_OFFLOAD = 17;
     private static final int MSG_OFFLOADING_SCREEN_ON_UNBLOCKED = 18;
-
-
+    private static final int MSG_SET_STYLUS_BEING_USED = 19;
+    private static final int MSG_SET_STYLUS_USE_ENDED = 20;
 
     private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
 
-
     // State machine constants for tracking initial brightness ramp skipping when enabled.
     private static final int RAMP_STATE_SKIP_NONE = 0;
     private static final int RAMP_STATE_SKIP_INITIAL = 1;
@@ -191,6 +190,10 @@
         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
         90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
         1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
+
+    private static final int STYLUS_USAGE_DEBOUNCE_TIME  = 1000;
+    private static final int NANO_SECONDS_TO_MILLI_SECONDS_RATIO  = 1_000_000;
+
     private static final int[] BRIGHTNESS_RANGE_INDEX = {
         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN,
         FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1,
@@ -498,6 +501,11 @@
     @GuardedBy("mLock")
     private int mPendingOverrideDozeScreenStateLocked;
 
+    private long mLastStylusUsageEventTime = -1;
+
+    // The time of inactivity after which the stylus can be assumed to be no longer in use.
+    private long mIdleStylusTimeoutMillisConfig = 0;
+
     /**
      * Creates the display power controller.
      */
@@ -518,6 +526,7 @@
         mSensorManager = sensorManager;
         mHandler = new DisplayControllerHandler(handler.getLooper());
         mDisplayDeviceConfig = mDisplayDevice.getDisplayDeviceConfig();
+        mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis();
         mIsEnabled = logicalDisplay.isEnabledLocked();
         mIsInTransition = logicalDisplay.isInTransitionLocked();
         mIsDisplayInternal = displayDeviceInfo.type == Display.TYPE_INTERNAL;
@@ -893,6 +902,7 @@
                 mPhysicalDisplayName = displayName;
                 mDisplayStatsId = mUniqueDisplayId.hashCode();
                 mDisplayDeviceConfig = config;
+                mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis();
                 mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
                 loadFromDisplayDeviceConfig(token, info, hbmMetadata);
                 mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
@@ -2971,6 +2981,18 @@
         return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
     }
 
+    public void stylusGestureStarted(long eventTimeNanoSeconds) {
+        long eventTimeMs = eventTimeNanoSeconds / NANO_SECONDS_TO_MILLI_SECONDS_RATIO;
+        if (mLastStylusUsageEventTime == -1
+                || eventTimeMs > mLastStylusUsageEventTime + STYLUS_USAGE_DEBOUNCE_TIME) {
+            synchronized (mLock) {
+                // Add a message to notify the stylus usage has started
+                mHandler.sendEmptyMessageAtTime(MSG_SET_STYLUS_BEING_USED, mClock.uptimeMillis());
+            }
+            mLastStylusUsageEventTime = eventTimeMs;
+        }
+    }
+
     private final class DisplayControllerHandler extends Handler {
         DisplayControllerHandler(Looper looper) {
             super(looper, null, true /*async*/);
@@ -3087,6 +3109,20 @@
                         updatePowerState();
                     }
                     break;
+                case MSG_SET_STYLUS_BEING_USED:
+                    // Remove any MSG_SET_STYLUS_USE_ENDED message from the handler queue and
+                    // post a delayed MSG_SET_STYLUS_USE_ENDED message to delay the stylus
+                    // usage ended event processing
+                    mHandler.removeMessages(MSG_SET_STYLUS_USE_ENDED);
+                    Message message = mHandler.obtainMessage(MSG_SET_STYLUS_USE_ENDED);
+                    mHandler.sendMessageAtTime(message,
+                            mClock.uptimeMillis() + mIdleStylusTimeoutMillisConfig);
+                    mDisplayBrightnessController.setStylusBeingUsed(true);
+                    break;
+                case MSG_SET_STYLUS_USE_ENDED:
+                    mDisplayBrightnessController.setStylusBeingUsed(false);
+                    updatePowerState();
+                    break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 72a91d5..71fdaf3 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -501,6 +501,13 @@
         return true;
     }
 
+    /**
+     * Notifies if the stylus is currently being used or not.
+     */
+    public void setStylusBeingUsed(boolean isEnabled) {
+        // Todo(b/369977976) - Disable the auto-brightness strategy
+    }
+
     @VisibleForTesting
     static class Injector {
         DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(Context context,
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index df66893..5284d1c 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -203,6 +203,10 @@
             Flags.FLAG_NORMAL_BRIGHTNESS_FOR_DOZE_PARAMETER,
             Flags::normalBrightnessForDozeParameter
     );
+    private final FlagState mBlockAutobrightnessChangesOnStylusUsage = new FlagState(
+            Flags.FLAG_BLOCK_AUTOBRIGHTNESS_CHANGES_ON_STYLUS_USAGE,
+            Flags::blockAutobrightnessChangesOnStylusUsage
+    );
 
     private final FlagState mEnableBatteryStatsForAllDisplays = new FlagState(
             Flags.FLAG_ENABLE_BATTERY_STATS_FOR_ALL_DISPLAYS,
@@ -436,6 +440,13 @@
     }
 
     /**
+     * @return {@code true} if autobrightness is to be blocked when stylus is being used
+     */
+    public boolean isBlockAutobrightnessChangesOnStylusUsage() {
+        return mBlockAutobrightnessChangesOnStylusUsage.isEnabled();
+    }
+
+    /**
      * dumps all flagstates
      * @param pw printWriter
      */
@@ -479,6 +490,7 @@
         pw.println(" " + mNormalBrightnessForDozeParameter);
         pw.println(" " + mIdleScreenConfigInSubscribingLightSensor);
         pw.println(" " + mEnableBatteryStatsForAllDisplays);
+        pw.println(" " + mBlockAutobrightnessChangesOnStylusUsage);
     }
 
     private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index e3ebe5b..252ed09 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -364,4 +364,12 @@
     description: "Flag to enable battery stats for all displays."
     bug: "366112793"
     is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+    name: "block_autobrightness_changes_on_stylus_usage"
+    namespace: "display_manager"
+    description: "Block the usage of ALS to control the display brightness when stylus is being used"
+    bug: "352411468"
+    is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f045576..8acf583 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2694,6 +2694,9 @@
     @SuppressWarnings("unused")
     private void notifyStylusGestureStarted(int deviceId, long eventTime) {
         mBatteryController.notifyStylusGestureStarted(deviceId, eventTime);
+        if (mDisplayManagerInternal != null) {
+            mDisplayManagerInternal.stylusGestureStarted(eventTime);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 47f579d..e7e519e 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -42,6 +42,8 @@
 import android.app.IProcessObserver;
 import android.app.KeyguardManager;
 import android.app.compat.CompatChanges;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
@@ -94,7 +96,7 @@
 
 /**
  * Manages MediaProjection sessions.
- *
+ * <p>
  * The {@link MediaProjectionManagerService} manages the creation and lifetime of MediaProjections,
  * as well as the capabilities they grant. Any service using MediaProjection tokens as permission
  * grants <b>must</b> validate the token before use by calling {@link
@@ -137,6 +139,7 @@
     private final PackageManager mPackageManager;
     private final WindowManagerInternal mWmInternal;
     private final KeyguardManager mKeyguardManager;
+    private final RoleManager mRoleManager;
 
     private final MediaRouter mMediaRouter;
     private final MediaRouterCallback mMediaRouterCallback;
@@ -173,6 +176,7 @@
         mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
         mKeyguardManager.addKeyguardLockedStateListener(
                 mContext.getMainExecutor(), this::onKeyguardLockedStateChanged);
+        mRoleManager = mContext.getSystemService(RoleManager.class);
         Watchdog.getInstance().addMonitor(this);
     }
 
@@ -182,6 +186,7 @@
      *   - be one of the bugreport allowlisted packages, or
      *   - hold the OP_PROJECT_MEDIA AppOp.
      */
+    @SuppressWarnings("BooleanMethodIsAlwaysInverted")
     private boolean canCaptureKeyguard() {
         if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) {
             return true;
@@ -193,6 +198,9 @@
             if (mPackageManager.checkPermission(RECORD_SENSITIVE_CONTENT,
                     mProjectionGrant.packageName)
                     == PackageManager.PERMISSION_GRANTED) {
+                Slog.v(TAG,
+                        "Allowing keyguard capture for package with RECORD_SENSITIVE_CONTENT "
+                                + "permission");
                 return true;
             }
             if (AppOpsManager.MODE_ALLOWED == mAppOps.noteOpNoThrow(AppOpsManager.OP_PROJECT_MEDIA,
@@ -200,6 +208,13 @@
                     "recording lockscreen")) {
                 // Some tools use media projection by granting the OP_PROJECT_MEDIA app
                 // op via a shell command. Those tools can be granted keyguard capture
+                Slog.v(TAG,
+                        "Allowing keyguard capture for package with OP_PROJECT_MEDIA AppOp ");
+                return true;
+            }
+            if (isProjectionAppHoldingAppStreamingRoleLocked()) {
+                Slog.v(TAG,
+                        "Allowing keyguard capture for package holding app streaming role.");
                 return true;
             }
             return SystemConfig.getInstance().getBugreportWhitelistedPackages()
@@ -698,6 +713,20 @@
         }
     }
 
+    /**
+     * Application holding the app streaming role
+     * ({@value AssociationRequest#DEVICE_PROFILE_APP_STREAMING}) are allowed to record the
+     * lockscreen.
+     *
+     * @return true if the is held by the recording application.
+     */
+    @GuardedBy("mLock")
+    private boolean isProjectionAppHoldingAppStreamingRoleLocked() {
+        return mRoleManager.getRoleHoldersAsUser(AssociationRequest.DEVICE_PROFILE_APP_STREAMING,
+                        mContext.getUser())
+                .contains(mProjectionGrant.packageName);
+    }
+
     private void dump(final PrintWriter pw) {
         pw.println("MEDIA PROJECTION MANAGER (dumpsys media_projection)");
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index ff263d1..bdca555 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -37,7 +37,6 @@
 import android.util.ArraySet;
 import android.util.Slog;
 
-import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.util.NotificationMessagingUtil;
 
 import java.io.PrintWriter;
@@ -173,13 +172,6 @@
             maybeLogInterceptDecision(record, false, "criticalNotification");
             return false;
         }
-        // Make an exception to policy for the notification saying that policy has changed
-        if (NotificationManager.Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)
-                && "android".equals(record.getSbn().getPackageName())
-                && SystemMessageProto.SystemMessage.NOTE_ZEN_UPGRADE == record.getSbn().getId()) {
-            maybeLogInterceptDecision(record, false, "systemDndChangedNotification");
-            return false;
-        }
         switch (zen) {
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
                 // #notevenalarms
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 626c3dd..ea211a9 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -54,10 +54,8 @@
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
 import android.app.Flags;
-import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
-import android.app.PendingIntent;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
@@ -74,7 +72,6 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
-import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
@@ -90,7 +87,6 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.Condition;
 import android.service.notification.ConditionProviderService;
@@ -117,8 +113,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
@@ -309,7 +303,6 @@
         mHandler.postMetricsTimer();
         cleanUpZenRules();
         mIsSystemServicesReady = true;
-        showZenUpgradeNotification(mZenMode);
     }
 
     /**
@@ -485,7 +478,7 @@
             populateZenRule(pkg, automaticZenRule, rule, origin, /* isNew= */ true);
             rule = maybeRestoreRemovedRule(newConfig, pkg, rule, automaticZenRule, origin);
             newConfig.automaticRules.put(rule.id, rule);
-            maybeReplaceDefaultRule(newConfig, automaticZenRule);
+            maybeReplaceDefaultRule(newConfig, null, automaticZenRule);
 
             if (setConfigLocked(newConfig, origin, reason, rule.component, true, callingUid)) {
                 return rule.id;
@@ -535,13 +528,24 @@
         return ruleToRestore;
     }
 
-    private static void maybeReplaceDefaultRule(ZenModeConfig config, AutomaticZenRule addedRule) {
+    /**
+     * Possibly delete built-in rules if a more suitable rule is added or updated.
+     *
+     * <p>Today, this is done in one case: delete a disabled "Sleeping" rule if a Bedtime Mode is
+     * added (or an existing mode is turned into {@link AutomaticZenRule#TYPE_BEDTIME}, when
+     * upgrading). Because only the {@code config_systemWellbeing} package is allowed to use rules
+     * of this type, this will not trigger wantonly.
+     *
+     * @param oldRule If non-null, {@code rule} is updating {@code oldRule}. Otherwise,
+     *                {@code rule} is being added.
+     */
+    private static void maybeReplaceDefaultRule(ZenModeConfig config, @Nullable ZenRule oldRule,
+            AutomaticZenRule rule) {
         if (!Flags.modesApi()) {
             return;
         }
-        if (addedRule.getType() == AutomaticZenRule.TYPE_BEDTIME) {
-            // Delete a built-in disabled "Sleeping" rule when a BEDTIME rule is added; it may have
-            // smarter triggers and it will prevent confusion about which one to use.
+        if (rule.getType() == AutomaticZenRule.TYPE_BEDTIME
+                && (oldRule == null || oldRule.type != rule.getType())) {
             // Note: we must not verify canManageAutomaticZenRule here, since most likely they
             // won't have the same owner (sleeping - system; bedtime - DWB).
             ZenRule sleepingRule = config.automaticRules.get(
@@ -589,6 +593,10 @@
                 // condition) when no changes happen.
                 return true;
             }
+
+            if (Flags.modesUi()) {
+                maybeReplaceDefaultRule(newConfig, oldRule, automaticZenRule);
+            }
             return setConfigLocked(newConfig, origin, reason,
                     newRule.component, true, callingUid);
         }
@@ -1584,8 +1592,6 @@
             String reason, @Nullable String caller, int callingUid) {
         setManualZenMode(zenMode, conditionId, origin, reason, caller, true /*setRingerMode*/,
                 callingUid);
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
     }
 
     private void setManualZenMode(int zenMode, Uri conditionId, @ConfigOrigin int origin,
@@ -1783,17 +1789,6 @@
                 SystemZenRules.maybeUpgradeRules(mContext, config);
             }
 
-            // Resolve user id for settings.
-            userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
-            if (config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE) {
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId);
-            } else {
-                // devices not restoring/upgrading already have updated zen settings
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId);
-            }
-
             if (Flags.modesApi() && forRestore) {
                 // Note: forBackup doesn't write deletedRules, but just in case.
                 config.deletedRules.clear();
@@ -2062,7 +2057,6 @@
         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
         ZenLog.traceSetZenMode(Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, -1),
                 "updated setting");
-        showZenUpgradeNotification(zen);
     }
 
     private int getPreviousRingerModeSetting() {
@@ -2117,12 +2111,6 @@
             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
                 if (automaticRule.isActive()) {
                     if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
-                        // automatic rule triggered dnd and user hasn't seen update dnd dialog
-                        if (Settings.Secure.getInt(mContext.getContentResolver(),
-                                Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
-                            Settings.Secure.putInt(mContext.getContentResolver(),
-                                    Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
-                        }
                         zen = automaticRule.zenMode;
                     }
                 }
@@ -2702,62 +2690,6 @@
         }
     }
 
-    private void showZenUpgradeNotification(int zen) {
-        final boolean isWatch = mContext.getPackageManager().hasSystemFeature(
-            PackageManager.FEATURE_WATCH);
-        final boolean showNotification = mIsSystemServicesReady
-                && zen != Global.ZEN_MODE_OFF
-                && !isWatch
-                && Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
-                && Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
-
-        if (isWatch) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
-        }
-
-        if (showNotification) {
-            mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
-                    createZenUpgradeNotification());
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
-        }
-    }
-
-    @VisibleForTesting
-    protected Notification createZenUpgradeNotification() {
-        final Bundle extras = new Bundle();
-        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
-                mContext.getResources().getString(R.string.global_action_settings));
-        int title = R.string.zen_upgrade_notification_title;
-        int content = R.string.zen_upgrade_notification_content;
-        int drawable = R.drawable.ic_zen_24dp;
-        if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
-                getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
-            title = R.string.zen_upgrade_notification_visd_title;
-            content = R.string.zen_upgrade_notification_visd_content;
-            drawable = R.drawable.ic_dnd_block_notifications;
-        }
-
-        Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
-        onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
-                .setAutoCancel(true)
-                .setSmallIcon(R.drawable.ic_settings_24dp)
-                .setLargeIcon(Icon.createWithResource(mContext, drawable))
-                .setContentTitle(mContext.getResources().getString(title))
-                .setContentText(mContext.getResources().getString(content))
-                .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
-                .setAutoCancel(true)
-                .setLocalOnly(true)
-                .addExtras(extras)
-                .setStyle(new Notification.BigTextStyle())
-                .build();
-    }
-
     private int drawableResNameToResId(String packageName, String resourceName) {
         if (TextUtils.isEmpty(resourceName)) {
             return 0;
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 89ced12..4665a72 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -2208,10 +2208,10 @@
             return true;
         }
         boolean permissionGranted = requireFullPermission ? hasPermission(
-                Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
+                Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                 : (hasPermission(
-                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
-                        || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS, callingUid));
+                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                        || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS));
         if (!permissionGranted) {
             if (Process.isIsolatedUid(callingUid) && isKnownIsolatedComputeApp(callingUid)) {
                 return checkIsolatedOwnerHasPermission(callingUid, requireFullPermission);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 8657de2..5653da0 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -716,7 +716,7 @@
                     visiblePackages.add(info.getActivityInfo().packageName);
                 }
                 final List<ApplicationInfo> installedPackages =
-                        mPackageManagerInternal.getInstalledApplicationsCrossUser(
+                        mPackageManagerInternal.getInstalledApplications(
                                 /* flags= */ 0, user.getIdentifier(), callingUid);
                 for (ApplicationInfo applicationInfo : installedPackages) {
                     if (!visiblePackages.contains(applicationInfo.packageName)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e47b4c2..68e781f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1141,9 +1141,9 @@
                         + mShortPressOnPowerBehavior);
 
         if (count == 2) {
-            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
+            powerMultiPressAction(displayId, eventTime, interactive, mDoublePressOnPowerBehavior);
         } else if (count == 3) {
-            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
+            powerMultiPressAction(displayId, eventTime, interactive, mTriplePressOnPowerBehavior);
         } else if (count > 3 && count <= getMaxMultiPressPowerCount()) {
             Slog.d(TAG, "No behavior defined for power press count " + count);
         } else if (count == 1 && shouldHandleShortPressPowerAction(interactive, eventTime)) {
@@ -1307,7 +1307,8 @@
         }
     }
 
-    private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
+    private void powerMultiPressAction(int displayId, long eventTime, boolean interactive,
+            int behavior) {
         switch (behavior) {
             case MULTI_PRESS_POWER_NOTHING:
                 break;
@@ -1322,7 +1323,7 @@
                     Settings.Global.putInt(mContext.getContentResolver(),
                             Settings.Global.THEATER_MODE_ON, 0);
                     if (!interactive) {
-                        wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
+                        wakeUpFromWakeKey(displayId, eventTime, KEYCODE_POWER, /* isDown= */ false);
                     }
                 } else {
                     Slog.i(TAG, "Toggling theater mode on.");
@@ -1338,7 +1339,7 @@
             case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
                 Slog.i(TAG, "Starting brightness boost.");
                 if (!interactive) {
-                    wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
+                    wakeUpFromWakeKey(displayId, eventTime, KEYCODE_POWER, /* isDown= */ false);
                 }
                 mPowerManager.boostScreenBrightness(eventTime);
                 break;
@@ -5546,7 +5547,7 @@
         if (mRequestedOrSleepingDefaultDisplay) {
             mCameraGestureTriggeredDuringGoingToSleep = true;
             // Wake device up early to prevent display doing redundant turning off/on stuff.
-            mWindowWakeUpPolicy.wakeUpFromPowerKeyCameraGesture();
+            mWindowWakeUpPolicy.wakeUpFromPowerKeyCameraGesture(event.getDisplayId());
         }
         return true;
     }
@@ -5644,8 +5645,8 @@
     public int interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action,
             long whenNanos, int policyFlags) {
         if ((policyFlags & FLAG_WAKE) != 0) {
-            if (mWindowWakeUpPolicy.wakeUpFromMotion(
-                        whenNanos / 1000000, source, action == MotionEvent.ACTION_DOWN)) {
+            if (mWindowWakeUpPolicy.wakeUpFromMotion(displayId, whenNanos / 1000000, source,
+                    action == MotionEvent.ACTION_DOWN)) {
                 // Woke up. Pass motion events to user.
                 return ACTION_PASS_TO_USER;
             }
@@ -5659,8 +5660,8 @@
         // there will be no dream to intercept the touch and wake into ambient.  The device should
         // wake up in this case.
         if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
-            if (mWindowWakeUpPolicy.wakeUpFromMotion(
-                        whenNanos / 1000000, source, action == MotionEvent.ACTION_DOWN)) {
+            if (mWindowWakeUpPolicy.wakeUpFromMotion(displayId, whenNanos / 1000000, source,
+                    action == MotionEvent.ACTION_DOWN)) {
                 // Woke up. Pass motion events to user.
                 return ACTION_PASS_TO_USER;
             }
@@ -6002,13 +6003,14 @@
             return;
         }
         wakeUpFromWakeKey(
+                event.getDisplayId(),
                 event.getEventTime(),
                 event.getKeyCode(),
                 event.getAction() == KeyEvent.ACTION_DOWN);
     }
 
-    private void wakeUpFromWakeKey(long eventTime, int keyCode, boolean isDown) {
-        if (mWindowWakeUpPolicy.wakeUpFromKey(eventTime, keyCode, isDown)) {
+    private void wakeUpFromWakeKey(int displayId, long eventTime, int keyCode, boolean isDown) {
+        if (mWindowWakeUpPolicy.wakeUpFromKey(displayId, eventTime, keyCode, isDown)) {
             final boolean keyCanLaunchHome = keyCode == KEYCODE_HOME || keyCode == KEYCODE_POWER;
             // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
             if (shouldWakeUpWithHomeIntent() &&  keyCanLaunchHome) {
diff --git a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
index af1ad13..966d84f4 100644
--- a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
@@ -25,6 +25,7 @@
 import static android.view.KeyEvent.KEYCODE_POWER;
 
 import static com.android.server.policy.Flags.supportInputWakeupDelegate;
+import static com.android.server.power.feature.flags.Flags.perDisplayWakeByTouch;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -107,13 +108,14 @@
     /**
      * Wakes up from a key event.
      *
+     * @param displayId the id of the display to wake.
      * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
      * @param keyCode the {@link android.view.KeyEvent} key code of the key event.
      * @param isDown {@code true} if the event's action is {@link KeyEvent#ACTION_DOWN}.
      * @return {@code true} if the policy allows the requested wake up and the request has been
      *      executed; {@code false} otherwise.
      */
-    boolean wakeUpFromKey(long eventTime, int keyCode, boolean isDown) {
+    boolean wakeUpFromKey(int displayId, long eventTime, int keyCode, boolean isDown) {
         final boolean wakeAllowedDuringTheaterMode =
                 keyCode == KEYCODE_POWER
                         ? mAllowTheaterModeWakeFromPowerKey
@@ -127,6 +129,7 @@
             return true;
         }
         wakeUp(
+                displayId,
                 eventTime,
                 keyCode == KEYCODE_POWER ? WAKE_REASON_POWER_BUTTON : WAKE_REASON_WAKE_KEY,
                 keyCode == KEYCODE_POWER ? "POWER" : "KEY");
@@ -136,12 +139,13 @@
     /**
      * Wakes up from a motion event.
      *
+     * @param displayId the id of the display to wake.
      * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
      * @param isDown {@code true} if the event's action is {@link MotionEvent#ACTION_DOWN}.
      * @return {@code true} if the policy allows the requested wake up and the request has been
      *      executed; {@code false} otherwise.
      */
-    boolean wakeUpFromMotion(long eventTime, int source, boolean isDown) {
+    boolean wakeUpFromMotion(int displayId, long eventTime, int source, boolean isDown) {
         if (!canWakeUp(mAllowTheaterModeWakeFromMotion)) {
             if (DEBUG) Slog.d(TAG, "Unable to wake up from motion.");
             return false;
@@ -150,7 +154,7 @@
                 && mInputWakeUpDelegate.wakeUpFromMotion(eventTime, source, isDown)) {
             return true;
         }
-        wakeUp(eventTime, WAKE_REASON_WAKE_MOTION, "MOTION");
+        wakeUp(displayId, eventTime, WAKE_REASON_WAKE_MOTION, "MOTION");
         return true;
     }
 
@@ -166,7 +170,7 @@
             if (DEBUG) Slog.d(TAG, "Unable to wake up from camera cover.");
             return false;
         }
-        wakeUp(eventTime, WAKE_REASON_CAMERA_LAUNCH, "CAMERA_COVER");
+        wakeUp(Display.DEFAULT_DISPLAY, eventTime, WAKE_REASON_CAMERA_LAUNCH, "CAMERA_COVER");
         return true;
     }
 
@@ -181,22 +185,24 @@
             if (DEBUG) Slog.d(TAG, "Unable to wake up from lid.");
             return false;
         }
-        wakeUp(mClock.uptimeMillis(), WAKE_REASON_LID, "LID");
+        wakeUp(Display.DEFAULT_DISPLAY, mClock.uptimeMillis(), WAKE_REASON_LID, "LID");
         return true;
     }
 
     /**
      * Wakes up to prevent sleeping when opening camera through power button.
      *
+     * @param displayId the id of the display to wake.
      * @return {@code true} if the policy allows the requested wake up and the request has been
      *      executed; {@code false} otherwise.
      */
-    boolean wakeUpFromPowerKeyCameraGesture() {
+    boolean wakeUpFromPowerKeyCameraGesture(int displayId) {
         if (!canWakeUp(mAllowTheaterModeWakeFromPowerKey)) {
             if (DEBUG) Slog.d(TAG, "Unable to wake up from power key camera gesture.");
             return false;
         }
-        wakeUp(mClock.uptimeMillis(), WAKE_REASON_CAMERA_LAUNCH, "CAMERA_GESTURE_PREVENT_LOCK");
+        wakeUp(displayId, mClock.uptimeMillis(), WAKE_REASON_CAMERA_LAUNCH,
+                "CAMERA_GESTURE_PREVENT_LOCK");
         return true;
     }
 
@@ -211,7 +217,7 @@
             if (DEBUG) Slog.d(TAG, "Unable to wake up from gesture.");
             return false;
         }
-        wakeUp(mClock.uptimeMillis(), WAKE_REASON_GESTURE, "GESTURE");
+        wakeUp(Display.DEFAULT_DISPLAY, mClock.uptimeMillis(), WAKE_REASON_GESTURE, "GESTURE");
         return true;
     }
 
@@ -234,7 +240,11 @@
     }
 
     /** Wakes up {@link PowerManager}. */
-    private void wakeUp(long wakeTime, @WakeReason int reason, String details) {
-        mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
+    private void wakeUp(int displayId, long wakeTime, @WakeReason int reason, String details) {
+        if (perDisplayWakeByTouch()) {
+            mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details, displayId);
+        } else {
+            mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index dc48242..c969eff 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -21,6 +21,7 @@
 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
 import static com.android.server.power.hint.Flags.adpfSessionTag;
 import static com.android.server.power.hint.Flags.powerhintThreadCleanup;
+import static com.android.server.power.hint.Flags.resetOnForkEnabled;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1057,6 +1058,11 @@
                     Slogf.w(TAG, errMsg);
                     throw new SecurityException(errMsg);
                 }
+                if (resetOnForkEnabled()){
+                    for (int tid : tids) {
+                        Process.setThreadScheduler(tid, Process.SCHED_RESET_ON_FORK, 0);
+                    }
+                }
 
                 if (adpfSessionTag() && tag == SessionTag.APP) {
                     // If the category of the app is a game,
@@ -1447,6 +1453,11 @@
                             Slogf.w(TAG, errMsg);
                             throw new SecurityException(errMsg);
                         }
+                        if (resetOnForkEnabled()){
+                            for (int tid : tids) {
+                                Process.setThreadScheduler(tid, Process.SCHED_RESET_ON_FORK, 0);
+                            }
+                        }
                         if (powerhintThreadCleanup()) {
                             synchronized (mNonIsolatedTidsLock) {
                                 for (int i = nonIsolated.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/power/hint/flags.aconfig b/services/core/java/com/android/server/power/hint/flags.aconfig
index 55afa05..e56b68c 100644
--- a/services/core/java/com/android/server/power/hint/flags.aconfig
+++ b/services/core/java/com/android/server/power/hint/flags.aconfig
@@ -14,3 +14,10 @@
     description: "Feature flag for adding session tag to hint session atom"
     bug: "345011125"
 }
+
+flag {
+    name: "reset_on_fork_enabled"
+    namespace: "game"
+    description: "Set reset_on_fork flag."
+    bug: "370988407"
+}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index a07facf..776de2e 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -712,6 +712,12 @@
                         minOccurs="0" maxOccurs="unbounded">
                 <xs:annotation name="final"/>
             </xs:element>
+            <!-- The time after which the stylus is to be assumed to be not under use. This will
+             enable the logic of changing the brightness with ambient light changes -->
+            <xs:element name="idleStylusTimeoutMillis" type="xs:nonNegativeInteger"
+                minOccurs="0" maxOccurs="1">
+                <xs:annotation name="final"/>
+            </xs:element>
         </xs:sequence>
     </xs:complexType>
 
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 5309263..110a5a2 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -8,12 +8,14 @@
     method public final java.math.BigInteger getDarkeningLightDebounceIdleMillis();
     method public final java.math.BigInteger getDarkeningLightDebounceMillis();
     method public boolean getEnabled();
+    method public final java.math.BigInteger getIdleStylusTimeoutMillis();
     method public final java.util.List<com.android.server.display.config.LuxToBrightnessMapping> getLuxToBrightnessMapping();
     method public final void setBrighteningLightDebounceIdleMillis(java.math.BigInteger);
     method public final void setBrighteningLightDebounceMillis(java.math.BigInteger);
     method public final void setDarkeningLightDebounceIdleMillis(java.math.BigInteger);
     method public final void setDarkeningLightDebounceMillis(java.math.BigInteger);
     method public void setEnabled(boolean);
+    method public final void setIdleStylusTimeoutMillis(java.math.BigInteger);
   }
 
   public enum AutoBrightnessModeName {
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 7d5532f..5c4716d 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -57,7 +57,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
-import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.doReturn
@@ -384,10 +383,6 @@
                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
                 PackageManager.PERMISSION_GRANTED
             }
-            whenever(this.checkPermission(
-                eq(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL), anyInt(), anyInt())) {
-                PackageManager.PERMISSION_GRANTED
-            }
         }
         val mockSharedLibrariesImpl: SharedLibrariesImpl = mock {
             whenever(this.snapshot()) { this@mock }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 8e1be9a..3976ea4 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -157,6 +157,7 @@
                 .getIdleScreenRefreshRateTimeoutLuxThresholdPoint());
         assertNull(mDisplayDeviceConfig.getTempSensor().name);
         assertTrue(mDisplayDeviceConfig.isAutoBrightnessAvailable());
+        assertEquals(0, mDisplayDeviceConfig.getIdleStylusTimeoutMillis());
     }
 
     @Test
@@ -253,6 +254,7 @@
                 .getLux().intValue());
         assertEquals(800, idleScreenRefreshRateTimeoutLuxThresholdPoints.get(1)
                 .getTimeout().intValue());
+        assertEquals(1000, mDisplayDeviceConfig.getIdleStylusTimeoutMillis());
     }
 
     @Test
@@ -1479,6 +1481,7 @@
                 +               "</point>\n"
                 +           "</map>\n"
                 +       "</luxToBrightnessMapping>\n"
+                +       "<idleStylusTimeoutMillis>1000</idleStylusTimeoutMillis>\n"
                 +   "</autoBrightness>\n"
                 +  getPowerThrottlingConfig()
                 +   "<highBrightnessMode enabled=\"true\">\n"
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index ee63d5d..425bb15 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -33,6 +33,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -51,11 +52,15 @@
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertThrows;
 
+import android.Manifest;
 import android.annotation.SuppressLint;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions.LaunchCookie;
 import android.app.AppOpsManager;
+import android.app.Instrumentation;
 import android.app.KeyguardManager;
+import android.app.role.RoleManager;
+import android.companion.AssociationRequest;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -68,6 +73,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.test.TestLooper;
@@ -88,6 +94,7 @@
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -98,6 +105,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -312,7 +320,6 @@
         assertThat(mService.getActiveProjectionInfo()).isNotNull();
     }
 
-    @SuppressLint("MissingPermission")
     @EnableFlags(android.companion.virtualdevice.flags
             .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
     @Test
@@ -335,6 +342,36 @@
         assertThat(mService.getActiveProjectionInfo()).isNotNull();
     }
 
+    @EnableFlags(android.companion.virtualdevice.flags
+            .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS)
+    @Test
+    public void testCreateProjection_keyguardLocked_RoleHeld() {
+        runWithRole(AssociationRequest.DEVICE_PROFILE_APP_STREAMING, () -> {
+            try {
+                mAppInfo.privateFlags |= PRIVATE_FLAG_PRIVILEGED;
+                doReturn(mAppInfo).when(mPackageManager).getApplicationInfoAsUser(anyString(),
+                        any(ApplicationInfoFlags.class), any(UserHandle.class));
+                MediaProjectionManagerService.MediaProjection projection =
+                        mService.createProjectionInternal(Process.myUid(),
+                                mContext.getPackageName(),
+                                TYPE_MIRRORING, /* isPermanentGrant= */ false, UserHandle.CURRENT);
+                doReturn(true).when(mKeyguardManager).isKeyguardLocked();
+                doReturn(PackageManager.PERMISSION_DENIED).when(
+                        mPackageManager).checkPermission(
+                        RECORD_SENSITIVE_CONTENT, projection.packageName);
+
+                projection.start(mIMediaProjectionCallback);
+                projection.notifyVirtualDisplayCreated(10);
+
+                // The projection was started because it was allowed to capture the keyguard.
+                assertWithMessage("Failed to run projection")
+                        .that(mService.getActiveProjectionInfo()).isNotNull();
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
     @Test
     public void testCreateProjection_attemptReuse_noPriorProjectionGrant()
             throws NameNotFoundException {
@@ -1202,6 +1239,47 @@
         return mService.getProjectionInternal(UID, PACKAGE_NAME);
     }
 
+    /**
+     * Run the provided block giving the current context's package the provided role.
+     */
+    @SuppressWarnings("SameParameterValue")
+    private void runWithRole(String role, Runnable block) {
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        String packageName = mContext.getPackageName();
+        UserHandle user = instrumentation.getTargetContext().getUser();
+        RoleManager roleManager = Objects.requireNonNull(
+                mContext.getSystemService(RoleManager.class));
+        try {
+            CountDownLatch latch = new CountDownLatch(1);
+            instrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                    Manifest.permission.MANAGE_ROLE_HOLDERS,
+                    Manifest.permission.BYPASS_ROLE_QUALIFICATION);
+
+            roleManager.setBypassingRoleQualification(true);
+            roleManager.addRoleHolderAsUser(role, packageName, /*  flags = */ 0, user,
+                    mContext.getMainExecutor(), success -> {
+                        if (success) {
+                            latch.countDown();
+                        } else {
+                            Assert.fail("Couldn't set role for test (failure) " + role);
+                        }
+                    });
+            assertWithMessage("Couldn't set role for test (timeout) : " + role)
+                    .that(latch.await(1, TimeUnit.SECONDS)).isTrue();
+            block.run();
+
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        } finally {
+            roleManager.removeRoleHolderAsUser(role, packageName, 0, user,
+                    mContext.getMainExecutor(), (aBool) -> {
+                    });
+            roleManager.setBypassingRoleQualification(false);
+            instrumentation.getUiAutomation()
+                    .dropShellPermissionIdentity();
+        }
+    }
+
     private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub {
         CountDownLatch mLatch = new CountDownLatch(1);
         @Override
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index b997f5d..a49f5a8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -26,8 +26,6 @@
 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
-import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
 import static android.provider.Settings.Global.ZEN_MODE_OFF;
@@ -57,7 +55,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.util.NotificationMessagingUtil;
 import com.android.server.UiServiceTestCase;
 
@@ -188,49 +185,6 @@
     }
 
     @Test
-    public void testSuppressDNDInfo_yes_VisEffectsAllowed() {
-        NotificationRecord r = getNotificationRecord();
-        when(r.getSbn().getPackageName()).thenReturn("android");
-        when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
-        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects()
-                - SUPPRESSED_EFFECT_STATUS_BAR, 0);
-
-        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
-    }
-
-    @Test
-    public void testSuppressDNDInfo_yes_WrongId() {
-        NotificationRecord r = getNotificationRecord();
-        when(r.getSbn().getPackageName()).thenReturn("android");
-        when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION);
-        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
-
-        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
-    }
-
-    @Test
-    public void testSuppressDNDInfo_yes_WrongPackage() {
-        NotificationRecord r = getNotificationRecord();
-        when(r.getSbn().getPackageName()).thenReturn("android2");
-        when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
-        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
-
-        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
-    }
-
-    @Test
-    public void testSuppressDNDInfo_no() {
-        NotificationRecord r = getNotificationRecord();
-        when(r.getSbn().getPackageName()).thenReturn("android");
-        when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
-        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
-
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, policy, r));
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
-    }
-
-    @Test
     public void testSuppressAnything_yes_ZenModeOff() {
         NotificationRecord r = getNotificationRecord();
         when(r.getSbn().getPackageName()).thenReturn("bananas");
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index d4cba8d..294027b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -169,7 +169,6 @@
 
 import com.android.internal.R;
 import com.android.internal.config.sysui.TestableFlagResolver;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.os.AtomsProto;
@@ -747,54 +746,6 @@
     }
 
     @Test
-    public void testZenUpgradeNotification() {
-        /**
-         * Commit a485ec65b5ba947d69158ad90905abf3310655cf disabled DND status change
-         * notification on watches. So, assume that the device is not watch.
-         */
-        when(mContext.getPackageManager()).thenReturn(mPackageManager);
-        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false);
-
-        // shows zen upgrade notification if stored settings says to shows,
-        // zen has not been updated, boot is completed
-        // and we're setting zen mode on
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
-        mZenModeHelper.mIsSystemServicesReady = true;
-        mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
-        mZenModeHelper.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-
-        verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG),
-                eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
-        assertEquals(0, Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, -1));
-    }
-
-    @Test
-    public void testNoZenUpgradeNotification() {
-        // doesn't show upgrade notification if stored settings says don't show
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
-        mZenModeHelper.mIsSystemServicesReady = true;
-        mZenModeHelper.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-
-        verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
-                eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
-    }
-
-    @Test
-    public void testNoZenUpgradeNotificationZenUpdated() {
-        // doesn't show upgrade notification since zen was already updated
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 1);
-        mZenModeHelper.mIsSystemServicesReady = true;
-        mZenModeHelper.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-
-        verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
-                eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
-    }
-
-    @Test
     public void testZenSetInternalRinger_AllPriorityNotificationSoundsMuted() {
         AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
         mZenModeHelper.mAudioManager = mAudioManager;
@@ -3032,6 +2983,33 @@
     }
 
     @Test
+    @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI})
+    public void updateAutomaticZenRule_withTypeBedtime_replacesDisabledSleeping() {
+        ZenRule sleepingRule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID);
+        sleepingRule.enabled = false;
+        sleepingRule.userModifiedFields = 0;
+        sleepingRule.name = "ZZZZZZZ...";
+        mZenModeHelper.mConfig.automaticRules.clear();
+        mZenModeHelper.mConfig.automaticRules.put(sleepingRule.id, sleepingRule);
+
+        AutomaticZenRule futureBedtime = new AutomaticZenRule.Builder("Bedtime (?)", CONDITION_ID)
+                .build();
+        String bedtimeRuleId = mZenModeHelper.addAutomaticZenRule(mPkg, futureBedtime,
+                ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+        assertThat(mZenModeHelper.mConfig.automaticRules.keySet())
+                .containsExactly(sleepingRule.id, bedtimeRuleId);
+
+        AutomaticZenRule bedtime = new AutomaticZenRule.Builder("Bedtime (!)", CONDITION_ID)
+                .setType(TYPE_BEDTIME)
+                .build();
+        mZenModeHelper.updateAutomaticZenRule(bedtimeRuleId, bedtime, ORIGIN_APP, "reason",
+                CUSTOM_PKG_UID);
+
+        assertThat(mZenModeHelper.mConfig.automaticRules.keySet()).containsExactly(bedtimeRuleId);
+    }
+
+    @Test
     @EnableFlags(FLAG_MODES_API)
     public void testSetManualZenMode() {
         setupZenConfig();
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index a85f866..3dc893a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -700,7 +700,7 @@
     void assertPowerWakeUp() {
         mTestLooper.dispatchAll();
         verify(mWindowWakeUpPolicy)
-                .wakeUpFromKey(anyLong(), eq(KeyEvent.KEYCODE_POWER), anyBoolean());
+                .wakeUpFromKey(anyInt(), anyLong(), eq(KeyEvent.KEYCODE_POWER), anyBoolean());
     }
 
     void assertNoPowerSleep() {
diff --git a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
index 7322e5a..4119ad3 100644
--- a/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/WindowWakeUpPolicyTests.java
@@ -35,6 +35,7 @@
 import static com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch;
 import static com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture;
 import static com.android.server.policy.Flags.FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE;
+import static com.android.server.power.feature.flags.Flags.FLAG_PER_DISPLAY_WAKE_BY_TOUCH;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -43,6 +44,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -52,6 +54,8 @@
 import android.content.ContextWrapper;
 import android.content.res.Resources;
 import android.os.PowerManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.view.Display;
@@ -125,6 +129,7 @@
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testMotionWakeUpDelegation_wakePowerManagerIfDelegateDoesNotHandleWake() {
         setTheaterModeEnabled(false);
         mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
@@ -136,7 +141,8 @@
 
         // Verify the policy wake up call succeeds because of the call on the delegate, and not
         // because of a PowerManager wake up.
-        assertThat(mPolicy.wakeUpFromMotion(200, SOURCE_TOUCHSCREEN, true)).isTrue();
+        assertThat(mPolicy.wakeUpFromMotion(
+                mDefaultDisplay.getDisplayId(), 200, SOURCE_TOUCHSCREEN, true)).isTrue();
         verify(mInputWakeUpDelegate).wakeUpFromMotion(200, SOURCE_TOUCHSCREEN, true);
         verifyNoPowerManagerWakeUp();
 
@@ -144,12 +150,14 @@
 
         // Verify the policy wake up call succeeds because of the PowerManager wake up, since the
         // delegate would not handle the wake up request.
-        assertThat(mPolicy.wakeUpFromMotion(300, SOURCE_ROTARY_ENCODER, false)).isTrue();
+        assertThat(mPolicy.wakeUpFromMotion(
+                mDefaultDisplay.getDisplayId(), 300, SOURCE_ROTARY_ENCODER, false)).isTrue();
         verify(mInputWakeUpDelegate).wakeUpFromMotion(300, SOURCE_ROTARY_ENCODER, false);
         verify(mPowerManager).wakeUp(300, WAKE_REASON_WAKE_MOTION, "android.policy:MOTION");
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testKeyWakeUpDelegation_wakePowerManagerIfDelegateDoesNotHandleWake() {
         setTheaterModeEnabled(false);
         mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
@@ -161,7 +169,8 @@
 
         // Verify the policy wake up call succeeds because of the call on the delegate, and not
         // because of a PowerManager wake up.
-        assertThat(mPolicy.wakeUpFromKey(200, KEYCODE_POWER, true)).isTrue();
+        assertThat(mPolicy.wakeUpFromKey(
+                mDefaultDisplay.getDisplayId(), 200, KEYCODE_POWER, true)).isTrue();
         verify(mInputWakeUpDelegate).wakeUpFromKey(200, KEYCODE_POWER, true);
         verifyNoPowerManagerWakeUp();
 
@@ -169,7 +178,8 @@
 
         // Verify the policy wake up call succeeds because of the PowerManager wake up, since the
         // delegate would not handle the wake up request.
-        assertThat(mPolicy.wakeUpFromKey(300, KEYCODE_STEM_PRIMARY, false)).isTrue();
+        assertThat(mPolicy.wakeUpFromKey(
+                mDefaultDisplay.getDisplayId(), 300, KEYCODE_STEM_PRIMARY, false)).isTrue();
         verify(mInputWakeUpDelegate).wakeUpFromKey(300, KEYCODE_STEM_PRIMARY, false);
         verify(mPowerManager).wakeUp(300, WAKE_REASON_WAKE_KEY, "android.policy:KEY");
     }
@@ -186,7 +196,8 @@
                 .setInputWakeUpDelegate(mInputWakeUpDelegate);
 
         // Check that the wake up does not happen because the theater mode policy check fails.
-        assertThat(mPolicy.wakeUpFromKey(200, KEYCODE_POWER, true)).isFalse();
+        assertThat(mPolicy.wakeUpFromKey(
+                mDefaultDisplay.getDisplayId(), 200, KEYCODE_POWER, true)).isFalse();
         verify(mInputWakeUpDelegate, never()).wakeUpFromKey(anyLong(), anyInt(), anyBoolean());
     }
 
@@ -201,11 +212,13 @@
                 .setInputWakeUpDelegate(mInputWakeUpDelegate);
 
         // Check that the wake up does not happen because the theater mode policy check fails.
-        assertThat(mPolicy.wakeUpFromMotion(200, SOURCE_TOUCHSCREEN, true)).isFalse();
+        assertThat(mPolicy.wakeUpFromMotion(
+                mDefaultDisplay.getDisplayId(), 200, SOURCE_TOUCHSCREEN, true)).isFalse();
         verify(mInputWakeUpDelegate, never()).wakeUpFromMotion(anyLong(), anyInt(), anyBoolean());
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testTheaterModeChecksNotAppliedWhenScreenIsOn() {
         mSetFlagsRule.enableFlags(FLAG_SUPPORT_INPUT_WAKEUP_DELEGATE);
         setDefaultDisplayState(Display.STATE_ON);
@@ -213,30 +226,69 @@
         setBooleanRes(config_allowTheaterModeWakeFromMotion, false);
         mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
 
-        mPolicy.wakeUpFromMotion(200L, SOURCE_TOUCHSCREEN, true);
+        mPolicy.wakeUpFromMotion(mDefaultDisplay.getDisplayId(), 200L, SOURCE_TOUCHSCREEN, true);
 
         verify(mPowerManager).wakeUp(200L, WAKE_REASON_WAKE_MOTION, "android.policy:MOTION");
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testWakeUpFromMotion() {
         runPowerManagerUpChecks(
-                () -> mPolicy.wakeUpFromMotion(mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, true),
+                () -> mPolicy.wakeUpFromMotion(mDefaultDisplay.getDisplayId(),
+                        mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, true),
                 config_allowTheaterModeWakeFromMotion,
                 WAKE_REASON_WAKE_MOTION,
                 "android.policy:MOTION");
     }
 
     @Test
+    @EnableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
+    public void testWakeUpFromMotion_perDisplayWakeByTouchEnabled() {
+        setTheaterModeEnabled(false);
+        final int displayId = 555;
+        mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
+
+        boolean displayWokeUp = mPolicy.wakeUpFromMotion(
+                displayId, mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, /* isDown= */ true);
+
+        // Verify that display is woken up
+        assertThat(displayWokeUp).isTrue();
+        verify(mPowerManager).wakeUp(anyLong(), eq(WAKE_REASON_WAKE_MOTION),
+                eq("android.policy:MOTION"), eq(displayId));
+    }
+
+    @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
+    public void testWakeUpFromMotion_perDisplayWakeByTouchDisabled() {
+        setTheaterModeEnabled(false);
+        final int displayId = 555;
+        mPolicy = new WindowWakeUpPolicy(mContextSpy, mClock);
+
+        boolean displayWokeUp = mPolicy.wakeUpFromMotion(
+                displayId, mClock.uptimeMillis(), SOURCE_TOUCHSCREEN, /* isDown= */ true);
+
+        // Verify that power is woken up and display isn't woken up individually
+        assertThat(displayWokeUp).isTrue();
+        verify(mPowerManager).wakeUp(
+                anyLong(), eq(WAKE_REASON_WAKE_MOTION), eq("android.policy:MOTION"));
+        verify(mPowerManager, never()).wakeUp(anyLong(), eq(WAKE_REASON_WAKE_MOTION),
+                eq("android.policy:MOTION"), eq(displayId));
+    }
+
+    @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testWakeUpFromKey_nonPowerKey() {
         runPowerManagerUpChecks(
-                () -> mPolicy.wakeUpFromKey(mClock.uptimeMillis(), KEYCODE_HOME, true),
+                () -> mPolicy.wakeUpFromKey(
+                        mDefaultDisplay.getDisplayId(), mClock.uptimeMillis(), KEYCODE_HOME, true),
                 config_allowTheaterModeWakeFromKey,
                 WAKE_REASON_WAKE_KEY,
                 "android.policy:KEY");
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testWakeUpFromKey_powerKey() {
         // Disable the resource affecting all wake keys because it affects power key as well.
         // That way, power key wake during theater mode will solely be controlled by
@@ -245,7 +297,8 @@
 
         // Test with power key
         runPowerManagerUpChecks(
-                () -> mPolicy.wakeUpFromKey(mClock.uptimeMillis(), KEYCODE_POWER, true),
+                () -> mPolicy.wakeUpFromKey(
+                        mDefaultDisplay.getDisplayId(), mClock.uptimeMillis(), KEYCODE_POWER, true),
                 config_allowTheaterModeWakeFromPowerKey,
                 WAKE_REASON_POWER_BUTTON,
                 "android.policy:POWER");
@@ -254,13 +307,15 @@
         // even if the power-key specific theater mode config is disabled.
         setBooleanRes(config_allowTheaterModeWakeFromPowerKey, false);
         runPowerManagerUpChecks(
-                () -> mPolicy.wakeUpFromKey(mClock.uptimeMillis(), KEYCODE_POWER, false),
+                () -> mPolicy.wakeUpFromKey(mDefaultDisplay.getDisplayId(), mClock.uptimeMillis(),
+                        KEYCODE_POWER, false),
                 config_allowTheaterModeWakeFromKey,
                 WAKE_REASON_POWER_BUTTON,
                 "android.policy:POWER");
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testWakeUpFromLid() {
         runPowerManagerUpChecks(
                 () -> mPolicy.wakeUpFromLid(),
@@ -270,6 +325,7 @@
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testWakeUpFromWakeGesture() {
         runPowerManagerUpChecks(
                 () -> mPolicy.wakeUpFromWakeGesture(),
@@ -279,6 +335,7 @@
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testwakeUpFromCameraCover() {
         runPowerManagerUpChecks(
                 () -> mPolicy.wakeUpFromCameraCover(mClock.uptimeMillis()),
@@ -288,6 +345,7 @@
     }
 
     @Test
+    @DisableFlags({FLAG_PER_DISPLAY_WAKE_BY_TOUCH})
     public void testWakeUpFromPowerKeyCameraGesture() {
         // Disable the resource affecting all wake keys because it affects power key as well.
         // That way, power key wake during theater mode will solely be controlled by
@@ -295,7 +353,7 @@
         setBooleanRes(config_allowTheaterModeWakeFromKey, false);
 
         runPowerManagerUpChecks(
-                () -> mPolicy.wakeUpFromPowerKeyCameraGesture(),
+                () -> mPolicy.wakeUpFromPowerKeyCameraGesture(mDefaultDisplay.getDisplayId()),
                 config_allowTheaterModeWakeFromPowerKey,
                 WAKE_REASON_CAMERA_LAUNCH,
                 "android.policy:CAMERA_GESTURE_PREVENT_LOCK");
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index bd5c759..49ca6f3 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -249,6 +249,13 @@
     public static final String KEY_PROVISION_SATELLITE_TOKENS = "provision_satellite";
 
     /**
+     * Bundle key to get the response from
+     * {@link #deprovisionSatellite(List, Executor, OutcomeReceiver)}.
+     * @hide
+     */
+    public static final String KEY_DEPROVISION_SATELLITE_TOKENS = "deprovision_satellite";
+
+    /**
      * The request was successfully processed.
      */
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
@@ -2791,6 +2798,61 @@
         }
     }
 
+    /**
+     * Deliver the list of deprovisioned satellite subscriber infos.
+     *
+     * @param list The list of deprovisioned satellite subscriber infos.
+     * @param executor The executor on which the callback will be called.
+     * @param callback The callback object to which the result will be delivered.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+    public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                ResultReceiver receiver = new ResultReceiver(null) {
+                    @Override
+                    protected void onReceiveResult(int resultCode, Bundle resultData) {
+                        if (resultCode == SATELLITE_RESULT_SUCCESS) {
+                            if (resultData.containsKey(KEY_DEPROVISION_SATELLITE_TOKENS)) {
+                                boolean isUpdated =
+                                        resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS);
+                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                        callback.onResult(isUpdated)));
+                            } else {
+                                loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist.");
+                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                        callback.onError(new SatelliteException(
+                                                SATELLITE_RESULT_REQUEST_FAILED))));
+                            }
+                        } else {
+                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                    callback.onError(new SatelliteException(resultCode))));
+                        }
+                    }
+                };
+                telephony.deprovisionSatellite(list, receiver);
+            } else {
+                loge("deprovisionSatellite() invalid telephony");
+                executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
+                        new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
+            }
+        } catch (RemoteException ex) {
+            loge("deprovisionSatellite() RemoteException: " + ex);
+            executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
+                    new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
+        }
+    }
+
     @Nullable
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 3161d17..61f0146 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3444,4 +3444,15 @@
      */
     boolean overrideCarrierRoamingNtnEligibilityChanged(
             in boolean status, in boolean resetRequired);
+
+    /**
+     * Deliver the list of deprovisioned satellite subscriber infos.
+     *
+     * @param list The list of deprovisioned satellite subscriber infos.
+     * @param result The result receiver that returns whether deliver success or fail.
+     * @hide
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    void deprovisionSatellite(in List<SatelliteSubscriberInfo> list, in ResultReceiver result);
 }