Merge "dynamic link to "aconfig_settingslib_flags_java_lib"" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 6e37b7e..6393fdb 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -112,6 +112,7 @@
         "framework_graphics_flags_java_lib",
         "hwui_flags_java_lib",
         "interaction_jank_monitor_flags_lib",
+        "keystore2_flags_java-framework",
         "libcore_exported_aconfig_flags_lib",
         "libcore_readonly_aconfig_flags_lib",
         "libgui_flags_java_lib",
diff --git a/core/api/current.txt b/core/api/current.txt
index dc7ccd4..4526de4d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8075,6 +8075,7 @@
     method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
     method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
     method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeEnabled(@Nullable android.content.ComponentName);
+    method @FlaggedApi("android.app.admin.flags.set_auto_time_enabled_coexistence") @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public int getAutoTimePolicy();
     method @Deprecated public boolean getAutoTimeRequired();
     method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME_ZONE, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeZoneEnabled(@Nullable android.content.ComponentName);
     method @FlaggedApi("android.app.admin.flags.set_auto_time_zone_enabled_coexistence") @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME_ZONE, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public int getAutoTimeZonePolicy();
@@ -8233,6 +8234,7 @@
     method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
     method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public void setAutoTimeEnabled(@Nullable android.content.ComponentName, boolean);
+    method @FlaggedApi("android.app.admin.flags.set_auto_time_enabled_coexistence") @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public void setAutoTimePolicy(int);
     method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
     method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public void setAutoTimeZoneEnabled(@Nullable android.content.ComponentName, boolean);
     method @FlaggedApi("android.app.admin.flags.set_auto_time_zone_enabled_coexistence") @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public void setAutoTimeZonePolicy(int);
@@ -8354,6 +8356,9 @@
     field public static final String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
     field public static final String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
     field public static final String ACTION_SYSTEM_UPDATE_POLICY_CHANGED = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";
+    field @FlaggedApi("android.app.admin.flags.set_auto_time_enabled_coexistence") public static final int AUTO_TIME_DISABLED = 1; // 0x1
+    field @FlaggedApi("android.app.admin.flags.set_auto_time_enabled_coexistence") public static final int AUTO_TIME_ENABLED = 2; // 0x2
+    field @FlaggedApi("android.app.admin.flags.set_auto_time_enabled_coexistence") public static final int AUTO_TIME_NOT_CONTROLLED_BY_POLICY = 0; // 0x0
     field @FlaggedApi("android.app.admin.flags.set_auto_time_zone_enabled_coexistence") public static final int AUTO_TIME_ZONE_DISABLED = 1; // 0x1
     field @FlaggedApi("android.app.admin.flags.set_auto_time_zone_enabled_coexistence") public static final int AUTO_TIME_ZONE_ENABLED = 2; // 0x2
     field @FlaggedApi("android.app.admin.flags.set_auto_time_zone_enabled_coexistence") public static final int AUTO_TIME_ZONE_NOT_CONTROLLED_BY_POLICY = 0; // 0x0
@@ -56907,6 +56912,7 @@
     ctor public EditorInfo();
     method public int describeContents();
     method public void dump(android.util.Printer, String);
+    method @FlaggedApi("android.view.inputmethod.public_autofill_id_in_editorinfo") @Nullable public android.view.autofill.AutofillId getAutofillId();
     method @Nullable public CharSequence getInitialSelectedText(int);
     method @Nullable public android.view.inputmethod.SurroundingText getInitialSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
     method @Nullable public CharSequence getInitialTextAfterCursor(@IntRange(from=0) int, int);
@@ -56916,6 +56922,7 @@
     method @NonNull public java.util.List<java.lang.Class<? extends android.view.inputmethod.HandwritingGesture>> getSupportedHandwritingGestures();
     method @FlaggedApi("android.view.inputmethod.editorinfo_handwriting_enabled") public boolean isStylusHandwritingEnabled();
     method public final void makeCompatible(int);
+    method @FlaggedApi("android.view.inputmethod.public_autofill_id_in_editorinfo") public void setAutofillId(@Nullable android.view.autofill.AutofillId);
     method public void setInitialSurroundingSubText(@NonNull CharSequence, int);
     method public void setInitialSurroundingText(@NonNull CharSequence);
     method public void setInitialToolType(int);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c8ecfa9..1192713 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2065,6 +2065,29 @@
     method public boolean isAidlHal();
   }
 
+  public final class MediaCodec {
+    method @FlaggedApi("android.media.codec.codec_availability") @NonNull public static java.util.List<android.media.MediaCodec.GlobalResourceInfo> getGloballyAvailableResources();
+    method @FlaggedApi("android.media.codec.codec_availability") @NonNull public java.util.List<android.media.MediaCodec.InstanceResourceInfo> getRequiredResources();
+  }
+
+  public abstract static class MediaCodec.Callback {
+    method @FlaggedApi("android.media.codec.codec_availability") public void onRequiredResourcesChanged(@NonNull android.media.MediaCodec);
+  }
+
+  @FlaggedApi("android.media.codec.codec_availability") public static final class MediaCodec.GlobalResourceInfo {
+    ctor public MediaCodec.GlobalResourceInfo();
+    method public long getAvailable();
+    method public long getCapacity();
+    method @NonNull public String getName();
+  }
+
+  @FlaggedApi("android.media.codec.codec_availability") public static final class MediaCodec.InstanceResourceInfo {
+    ctor public MediaCodec.InstanceResourceInfo();
+    method @NonNull public String getName();
+    method public long getPerFrameCount();
+    method public long getStaticCount();
+  }
+
   public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 0654ac2..9bb16ae 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -124,7 +124,7 @@
     boolean onlyHasDefaultChannel(String pkg, int uid);
     boolean areChannelsBypassingDnd();
     ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int uid);
-    List<String> getPackagesBypassingDnd(int userId, boolean includeConversationChannels);
+    ParceledListSlice getPackagesBypassingDnd(int userId);
     boolean isPackagePaused(String pkg);
     void deleteNotificationHistoryItem(String pkg, int uid, long postedTime);
     boolean isPermissionFixed(String pkg, int userId);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0381ee0..3d9c55c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5003,7 +5003,7 @@
 
         /**
          * Sets a very short string summarizing the most critical information contained in the
-         * notification. Suggested max length is 5 characters, and there is no guarantee how much or
+         * notification. Suggested max length is 7 characters, and there is no guarantee how much or
          * how little of this text will be shown.
          */
         @FlaggedApi(Flags.FLAG_API_RICH_ONGOING)
diff --git a/core/java/android/app/ZenBypassingApp.java b/core/java/android/app/ZenBypassingApp.java
new file mode 100644
index 0000000..89bcfa2
--- /dev/null
+++ b/core/java/android/app/ZenBypassingApp.java
@@ -0,0 +1,98 @@
+/*
+ * 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 android.app;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import java.util.Objects;
+
+/**
+ * @hide
+ */
+public final class ZenBypassingApp implements Parcelable {
+
+    @NonNull private String mPkg;
+    private boolean mAllChannelsBypass;
+
+
+    public ZenBypassingApp(@NonNull String pkg, boolean allChannelsBypass) {
+        mPkg = pkg;
+        mAllChannelsBypass = allChannelsBypass;
+    }
+
+    public ZenBypassingApp(Parcel source) {
+        mPkg = source.readString();
+        mAllChannelsBypass = source.readBoolean();
+    }
+
+    @NonNull
+    public String getPkg() {
+        return mPkg;
+    }
+
+    public boolean doAllChannelsBypass() {
+        return mAllChannelsBypass;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mPkg);
+        dest.writeBoolean(mAllChannelsBypass);
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<ZenBypassingApp> CREATOR
+            = new Parcelable.Creator<ZenBypassingApp>() {
+        @Override
+        public ZenBypassingApp createFromParcel(Parcel source) {
+            return new ZenBypassingApp(source);
+        }
+        @Override
+        public ZenBypassingApp[] newArray(int size) {
+            return new ZenBypassingApp[size];
+        }
+    };
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof ZenBypassingApp)) return false;
+        ZenBypassingApp that = (ZenBypassingApp) o;
+        return mAllChannelsBypass == that.mAllChannelsBypass && Objects.equals(mPkg,
+                that.mPkg);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPkg, mAllChannelsBypass);
+    }
+
+    @Override
+    public String toString() {
+        return "ZenBypassingApp{" +
+                "mPkg='" + mPkg + '\'' +
+                ", mAllChannelsBypass=" + mAllChannelsBypass +
+                '}';
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index bff77f9..c789c41 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8920,12 +8920,9 @@
     /**
      * Called by a device owner, a profile owner for the primary user or a profile
      * owner of an organization-owned managed profile to turn auto time on and off.
-     * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
-     * to prevent the user from changing this setting.
      * <p>
-     * If user restriction {@link UserManager#DISALLOW_CONFIG_DATE_TIME} is used,
-     * no user will be able set the date and time. Instead, the network date
-     * and time will be used.
+     * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME} to prevent the
+     * user from changing this setting, that way no user will be able set the date and time zone.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
      *              caller is not a device admin.
@@ -8938,7 +8935,13 @@
         throwIfParentInstance("setAutoTimeEnabled");
         if (mService != null) {
             try {
-                mService.setAutoTimeEnabled(admin, mContext.getPackageName(), enabled);
+                if (Flags.setAutoTimeEnabledCoexistence()) {
+                    mService.setAutoTimePolicy(mContext.getPackageName(),
+                            enabled ? DevicePolicyManager.AUTO_TIME_ENABLED
+                                    : DevicePolicyManager.AUTO_TIME_DISABLED);
+                } else {
+                    mService.setAutoTimeEnabled(admin, mContext.getPackageName(), enabled);
+                }
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8968,6 +8971,97 @@
     }
 
     /**
+     * Specifies that the auto time state is not controlled by device policy.
+     *
+     * @see #setAutoTimePolicy(ComponentName, int)
+     */
+    @FlaggedApi(Flags.FLAG_SET_AUTO_TIME_ENABLED_COEXISTENCE)
+    public static final int AUTO_TIME_NOT_CONTROLLED_BY_POLICY = 0;
+
+    /**
+     * Specifies the "disabled" auto time state.
+     *
+     * @see #setAutoTimePolicy(ComponentName, int)
+     */
+    @FlaggedApi(Flags.FLAG_SET_AUTO_TIME_ENABLED_COEXISTENCE)
+    public static final int AUTO_TIME_DISABLED = 1;
+
+    /**
+     * Specifies the "enabled" auto time state.
+     *
+     * @see #setAutoTimePolicy(ComponentName, int)
+     */
+    @FlaggedApi(Flags.FLAG_SET_AUTO_TIME_ENABLED_COEXISTENCE)
+    public static final int AUTO_TIME_ENABLED = 2;
+
+    /**
+     * Flags supplied to {@link #setAutoTimePolicy}(ComponentName, int)}.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "AUTO_TIME_" }, value = {
+            AUTO_TIME_NOT_CONTROLLED_BY_POLICY,
+            AUTO_TIME_DISABLED,
+            AUTO_TIME_ENABLED
+    })
+    public @interface AutoTimePolicy {}
+
+    /**
+     * Called by a device owner, a profile owner for the primary user or a profile owner of an
+     * organization-owned managed profile to turn auto time on and off i.e. Whether time should be
+     * obtained automatically from the network or not.
+     * <p>
+     * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME} to prevent the
+     * user from changing this setting, that way no user will be able set the date and time zone.
+     *
+     * @param policy The desired state among {@link #AUTO_TIME_ENABLED} to enable,
+     *              {@link #AUTO_TIME_DISABLED} to disable and
+     *              {@link #AUTO_TIME_NOT_CONTROLLED_BY_POLICY} to unset the policy.
+     * @throws SecurityException if caller is not a device owner, a profile owner for the
+     * primary user, or a profile owner of an organization-owned managed profile, or if the caller
+     * does not hold the required permission.
+     */
+    @SupportsCoexistence
+    @RequiresPermission(value = SET_TIME, conditional = true)
+    @FlaggedApi(Flags.FLAG_SET_AUTO_TIME_ENABLED_COEXISTENCE)
+    public void setAutoTimePolicy(@AutoTimePolicy int policy) {
+        throwIfParentInstance("setAutoTimePolicy");
+        if (mService != null) {
+            try {
+                mService.setAutoTimePolicy(mContext.getPackageName(), policy);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Returns current auto time policy's state.
+     *
+     * @return One of {@link #AUTO_TIME_ENABLED} if enabled, {@link #AUTO_TIME_DISABLED} if disabled
+     *              and {@link #AUTO_TIME_NOT_CONTROLLED_BY_POLICY} if it's not controlled by
+     *              policy.
+     * @throws SecurityException if caller is not a device owner, a profile owner for the
+     * primary user, or a profile owner of an organization-owned managed profile, or if the caller
+     * does not hold the required permission.
+     */
+    @SupportsCoexistence
+    @RequiresPermission(anyOf = {SET_TIME, QUERY_ADMIN_POLICY}, conditional = true)
+    @FlaggedApi(Flags.FLAG_SET_AUTO_TIME_ENABLED_COEXISTENCE)
+    public @AutoTimePolicy int getAutoTimePolicy() {
+        throwIfParentInstance("getAutoTimePolicy");
+        if (mService != null) {
+            try {
+                return mService.getAutoTimePolicy(mContext.getPackageName());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return DevicePolicyManager.AUTO_TIME_NOT_CONTROLLED_BY_POLICY;
+    }
+
+    /**
      * Called by a device owner, a profile owner for the primary user or a profile
      * owner of an organization-owned managed profile to turn auto time zone on and off.
      * <p>
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 0b8f538..a406802 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -375,6 +375,9 @@
     void setAutoTimeEnabled(in ComponentName who, String callerPackageName, boolean enabled);
     boolean getAutoTimeEnabled(in ComponentName who, String callerPackageName);
 
+    void setAutoTimePolicy(String callerPackageName, int policy);
+    int getAutoTimePolicy(String callerPackageName);
+
     void setAutoTimeZoneEnabled(in ComponentName who, String callerPackageName, boolean enabled);
     boolean getAutoTimeZoneEnabled(in ComponentName who, String callerPackageName);
 
diff --git a/core/java/android/app/ondeviceintelligence/flags/ondevice_intelligence.aconfig b/core/java/android/app/ondeviceintelligence/flags/ondevice_intelligence.aconfig
index 8b6441a..74a96c8 100644
--- a/core/java/android/app/ondeviceintelligence/flags/ondevice_intelligence.aconfig
+++ b/core/java/android/app/ondeviceintelligence/flags/ondevice_intelligence.aconfig
@@ -8,3 +8,10 @@
     description: "Make methods on OnDeviceIntelligenceManager available for local inference."
     bug: "304755128"
 }
+flag {
+    name: "enable_on_device_intelligence_module"
+    is_exported: true
+    namespace: "ondeviceintelligence"
+    description: "Enable migration to mainline module and related changes."
+    bug: "376427781"
+}
\ No newline at end of file
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b776b59..8853304 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -87,7 +87,6 @@
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.expresslog.Counter;
 
@@ -12304,7 +12303,6 @@
     }
 
     /** @hide */
-    @VisibleForTesting
     public Set<NestedIntentKey> getExtraIntentKeys() {
         return mCreatorTokenInfo == null ? null : mCreatorTokenInfo.mNestedIntentKeys;
     }
diff --git a/core/java/android/hardware/display/DisplayTopology.java b/core/java/android/hardware/display/DisplayTopology.java
index e349b81..f00c3a5 100644
--- a/core/java/android/hardware/display/DisplayTopology.java
+++ b/core/java/android/hardware/display/DisplayTopology.java
@@ -23,6 +23,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.graphics.PointF;
 import android.graphics.RectF;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -150,6 +151,138 @@
         }
     }
 
+    /**
+     * Rearranges the topology toward the positions given for each display. The width and height of
+     * each display, as well as the primary display, are not changed by this call.
+     * <p>
+     * Upon returning, the topology will be valid and normalized with each display as close to the
+     * requested positions as possible.
+     *
+     * @param newPos the desired positions (upper-left corner) of each display. The keys in the map
+     *               are the display IDs.
+     * @throws IllegalArgumentException if the keys in {@code positions} are not the exact display
+     *                                  IDs in this topology, no more, no less
+     */
+    public void rearrange(Map<Integer, PointF> newPos) {
+        var availableParents = new ArrayList<TreeNode>();
+
+        availableParents.addLast(mRoot);
+
+        var needsParent = allNodesIdMap();
+
+        // In the case of missing items, if this check doesn't detect it, a NPE will be thrown
+        // later.
+        if (needsParent.size() != newPos.size()) {
+            throw new IllegalArgumentException("newPos has wrong number of entries: " + newPos);
+        }
+
+        mRoot.mChildren.clear();
+        for (TreeNode n : needsParent.values()) {
+            n.mChildren.clear();
+        }
+
+        needsParent.remove(mRoot.mDisplayId);
+        // Start with a root island and add children to it one-by-one until the island consists of
+        // all the displays. The root island begins with only the root node, which has no
+        // parent. Then we greedily choose an optimal pairing of two nodes, consisting of a node
+        // from the island and a node not yet in the island. This is repeating until all nodes are
+        // in the island.
+        //
+        // The optimal pair is the pair which has the smallest deviation. The deviation consists of
+        // an x-axis component and a y-axis component, called xDeviation and yDeviation.
+        //
+        // The deviations are like distances but a little different. They are calculated in two
+        // steps. The first step calculates both axes in a similar way. The next step compares the
+        // two values and chooses which axis to attach along. Depending on which axis is chosen,
+        // the deviation for one axis is updated. See below for details.
+        while (!needsParent.isEmpty()) {
+            double bestDist = Double.POSITIVE_INFINITY;
+            TreeNode bestChild = null, bestParent = null;
+
+            for (var child : needsParent.values()) {
+                PointF childPos = newPos.get(child.mDisplayId);
+                float childRight = childPos.x + child.getWidth();
+                float childBottom = childPos.y + child.getHeight();
+                for (var parent : availableParents) {
+                    PointF parentPos = newPos.get(parent.mDisplayId);
+                    float parentRight = parentPos.x + parent.getWidth();
+                    float parentBottom = parentPos.y + parent.getHeight();
+
+                    // This is the smaller of the two ranges minus the amount of overlap shared
+                    // between them. The "amount of overlap" is negative if there is no overlap, but
+                    // this does not make a parenting ineligible, because we allow for attaching at
+                    // the corner and for floating point error. The overlap is more negative the
+                    // farther apart the closest corner pair is.
+                    //
+                    // For each axis, this calculates (SmallerRange - Overlap). If one range lies
+                    // completely in the other (or they are equal), the axis' deviation will be
+                    // zero.
+                    //
+                    // The "SmallerRange," which refers to smaller of the widths of the two rects,
+                    // or smaller of the heights of the two rects, is added to the deviation so that
+                    // a maximum overlap results in a deviation of zero.
+                    float xSmallerRange = Math.min(child.getWidth(), parent.getWidth());
+                    float ySmallerRange = Math.min(child.getHeight(), parent.getHeight());
+                    float xOverlap
+                            = Math.min(parentRight, childRight)
+                            - Math.max(parentPos.x, childPos.x);
+                    float yOverlap
+                            = Math.min(parentBottom, childBottom)
+                            - Math.max(parentPos.y, childPos.y);
+                    float xDeviation = xSmallerRange - xOverlap;
+                    float yDeviation = ySmallerRange - yOverlap;
+
+                    float offset;
+                    int pos;
+                    if (xDeviation <= yDeviation) {
+                        if (childPos.y < parentPos.y) {
+                            yDeviation = childBottom - parentPos.y;
+                            pos = POSITION_TOP;
+                        } else {
+                            yDeviation = parentBottom - childPos.y;
+                            pos = POSITION_BOTTOM;
+                        }
+                        offset = childPos.x - parentPos.x;
+                    } else {
+                        if (childPos.x < parentPos.x) {
+                            xDeviation = childRight - parentPos.x;
+                            pos = POSITION_LEFT;
+                        } else {
+                            xDeviation = parentRight - childPos.x;
+                            pos = POSITION_RIGHT;
+                        }
+                        offset = childPos.y - parentPos.y;
+                    }
+
+                    double dist = Math.hypot(xDeviation, yDeviation);
+                    if (dist >= bestDist) {
+                        continue;
+                    }
+
+                    bestDist = dist;
+                    bestChild = child;
+                    bestParent = parent;
+                    // Eagerly update the child's parenting info, even though we may not use it, in
+                    // which case it will be overwritten later.
+                    bestChild.mPosition = pos;
+                    bestChild.mOffset = offset;
+                }
+            }
+
+            assert bestParent != null & bestChild != null;
+
+            bestParent.addChild(bestChild);
+            if (null == needsParent.remove(bestChild.mDisplayId)) {
+                throw new IllegalStateException("child not in pending set! " + bestChild);
+            }
+            availableParents.add(bestChild);
+        }
+
+        // The conversion may have introduced an intersection of two display rects. If they are
+        // bigger than our error tolerance, this function will remove them.
+        normalize();
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -450,6 +583,20 @@
         return a == b || (Float.isNaN(a) && Float.isNaN(b)) || Math.abs(a - b) < EPSILON;
     }
 
+    private Map<Integer, TreeNode> allNodesIdMap() {
+        var pend = new ArrayDeque<TreeNode>();
+        var found = new HashMap<Integer, TreeNode>();
+
+        pend.push(mRoot);
+        do {
+            TreeNode node = pend.pop();
+            found.put(node.mDisplayId, node);
+            pend.addAll(node.mChildren);
+        } while (!pend.isEmpty());
+
+        return found;
+    }
+
     public static final class TreeNode implements Parcelable {
         public static final int POSITION_LEFT = 0;
         public static final int POSITION_TOP = 1;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8c3f0ef..70a1909 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -3436,7 +3436,7 @@
         initialize();
         mInlineSuggestionSessionController.notifyOnStartInput(
                 editorInfo == null ? null : editorInfo.packageName,
-                editorInfo == null ? null : editorInfo.autofillId);
+                editorInfo == null ? null : editorInfo.getAutofillId());
         if (DEBUG) Log.v(TAG, "CALL: onStartInput");
         onStartInput(editorInfo, restarting);
         if (mDecorViewVisible) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 4bc8fe0..9ab9228 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3928,9 +3928,9 @@
 
         final int callingUid = Binder.getCallingUid();
         final int processUid = Process.myUid();
-        if (Build.isDebuggable() && callingUid != processUid) {
-            Log.w(TAG, "Uid " + processUid + " is fetching a copy of UserProperties on"
-                            + " behalf of callingUid " + callingUid + ". Possibly"
+        if (processUid == Process.SYSTEM_UID && callingUid != processUid) {
+            Log.w(TAG, "The System (uid " + processUid + ") is fetching a copy of"
+                            + " UserProperties on behalf of callingUid " + callingUid + ". Possibly"
                             + " it should carefully first clearCallingIdentity or perhaps use"
                             + " UserManagerInternal.getUserProperties() instead?",
                     new Throwable());
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 33040be..6264fbb 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -391,3 +391,12 @@
     description: "Batch noteOperations on the client to reduce binder call volume"
     bug: "366013082"
 }
+
+flag {
+    name: "supervision_role_permission_update_enabled"
+    is_fixed_read_only: true
+    is_exported: true
+    namespace: "supervision"
+    description: "This flag is used to enable all the remaining permissions required to the supervision role"
+    bug: "367333883"
+}
\ No newline at end of file
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index ae12132..a42eece 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -614,7 +614,7 @@
                 if (style[j] instanceof TypefaceSpan) {
                     String s = ((TypefaceSpan) style[j]).getFamily();
 
-                    if (s.equals("monospace")) {
+                    if ("monospace".equals(s)) {
                         out.append("</tt>");
                     }
                 }
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index fb3e083..a560339 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -24,6 +24,7 @@
 import static android.view.inputmethod.EditorInfoProto.PRIVATE_IME_OPTIONS;
 import static android.view.inputmethod.EditorInfoProto.TARGET_INPUT_METHOD_USER_ID;
 import static android.view.inputmethod.Flags.FLAG_EDITORINFO_HANDWRITING_ENABLED;
+import static android.view.inputmethod.Flags.FLAG_PUBLIC_AUTOFILL_ID_IN_EDITORINFO;
 
 import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
@@ -470,12 +471,10 @@
     public String packageName;
 
     /**
-     * Autofill Id for the field that's currently on focus.
-     *
-     * <p> Marked as hide since it's only used by framework.</p>
-     * @hide
+     * Autofill Id for the field that's currently on focus. See link {@link AutofillId} for more
+     * details. It is set by {@link View#getAutofillId()}
      */
-    public AutofillId autofillId;
+    private AutofillId autofillId;
 
     /**
      * Identifier for the editor's field.  This is optional, and may be
@@ -1200,6 +1199,28 @@
     }
 
     /**
+     * Returns the {@link AutofillId} of the view that this {@link EditorInfo} is associated with.
+     * The value is filled in with the result of {@link android.view.View#getAutofillId()
+     * View.getAutofillId()} on the view that is being edited.
+     *
+     * Note: For virtual view(e.g. Compose or Webview), default behavior is the autofillId is the id
+     * of the container view, unless the virtual view provider sets the virtual id when the
+     * InputMethodManager calls {@link android.view.View#onCreateInputConnection()} on the container
+     * view.
+     */
+    @FlaggedApi(FLAG_PUBLIC_AUTOFILL_ID_IN_EDITORINFO)
+    @Nullable
+    public AutofillId getAutofillId() {
+        return autofillId;
+    }
+
+    /** Sets the {@link AutofillId} of the view that this {@link EditorInfo} is associated with. */
+    @FlaggedApi(FLAG_PUBLIC_AUTOFILL_ID_IN_EDITORINFO)
+    public void setAutofillId(@Nullable AutofillId autofillId) {
+        this.autofillId = autofillId;
+    }
+
+    /**
      * Export the state of {@link EditorInfo} into a protocol buffer output stream.
      *
      * @param proto Stream to write the state to
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 6026e60..6303c76 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -5179,7 +5179,7 @@
         // system can verify the consistency between the uid of this process and package name passed
         // from here. See comment of Context#getOpPackageName() for details.
         editorInfo.packageName = servedView.getContext().getOpPackageName();
-        editorInfo.autofillId = servedView.getAutofillId();
+        editorInfo.setAutofillId(servedView.getAutofillId());
         editorInfo.fieldId = servedView.getId();
         final InputConnection ic = servedView.onCreateInputConnection(editorInfo);
         if (DEBUG) Log.v(TAG, "Starting input: editorInfo=" + editorInfo + " ic=" + ic);
@@ -5188,7 +5188,7 @@
         // This ensures that even disconnected EditorInfos have well-defined attributes,
         // making them consistently and straightforwardly comparable.
         if (ic == null) {
-            editorInfo.autofillId = AutofillId.NO_AUTOFILL_ID;
+            editorInfo.setAutofillId(AutofillId.NO_AUTOFILL_ID);
             editorInfo.fieldId = 0;
         }
         return new Pair<>(ic, editorInfo);
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index edd9d6c..e619ab0 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -165,4 +165,13 @@
     description: "Writing tools API"
     bug: "373788889"
     is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+  name: "public_autofill_id_in_editorinfo"
+  is_exported: true
+  namespace: "input_method"
+  description: "Guarding public API autofillId in editor info"
+  bug: "342672560"
+  is_fixed_read_only: true
+}
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
index 6c72544..76ead2a 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.cpp
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -22,7 +22,6 @@
 #include <android-base/hex.h>
 #include <android-base/unique_fd.h>
 #include <bionic/macros.h>
-#include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -204,7 +203,8 @@
     return true;
 }
 
-bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
+bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
+                         std::vector<Elf64_Phdr> &programHeaders) {
     // Open Elf file
     Elf64_Ehdr ehdr;
     std::ifstream inputStream(filePath, std::ifstream::in);
@@ -227,11 +227,6 @@
     uint64_t programHeaderOffset = ehdr.e_phoff;
     uint16_t programHeaderNum = ehdr.e_phnum;
 
-    IF_ALOGD() {
-        ALOGD("Punching holes in file: %s programHeaderOffset: %" PRIu64 " programHeaderNum: %hu",
-              filePath, programHeaderOffset, programHeaderNum);
-    }
-
     // if this is a zip file, also consider elf offset inside a file
     uint64_t phOffset;
     if (__builtin_add_overflow(offset, programHeaderOffset, &phOffset)) {
@@ -240,7 +235,6 @@
     }
     inputStream.seekg(phOffset);
 
-    std::vector<Elf64_Phdr> programHeaders;
     for (int headerIndex = 0; headerIndex < programHeaderNum; headerIndex++) {
         Elf64_Phdr header;
         inputStream.read((char *)&header, sizeof(header));
@@ -254,6 +248,15 @@
         programHeaders.push_back(header);
     }
 
+    return true;
+}
+
+bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
+    std::vector<Elf64_Phdr> programHeaders;
+    if (!getLoadSegmentPhdrs(filePath, offset, programHeaders)) {
+        ALOGE("Failed to read program headers from ELF file.");
+        return false;
+    }
     return punchHoles(filePath, offset, programHeaders);
 }
 
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.h b/core/jni/com_android_internal_content_FileSystemUtils.h
index 52445e2..4a95686c 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.h
+++ b/core/jni/com_android_internal_content_FileSystemUtils.h
@@ -15,8 +15,11 @@
  */
 #pragma once
 
+#include <elf.h>
 #include <sys/types.h>
 
+#include <vector>
+
 namespace android {
 
 /*
@@ -35,4 +38,11 @@
  */
 bool punchHolesInZip(const char* filePath, uint64_t offset, uint16_t extraFieldLen);
 
+/*
+ * This function reads program headers from ELF file. ELF can be specified with file path directly
+ * or it should be at offset inside Apk. Program headers passed to function is populated.
+ */
+bool getLoadSegmentPhdrs(const char* filePath, const uint64_t offset,
+                         std::vector<Elf64_Phdr>& programHeaders);
+
 } // namespace android
\ No newline at end of file
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index dc054a4..969ee2e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1849,6 +1849,10 @@
         <item>-1</item>
     </integer-array>
 
+     <!-- Specifies the delay in milliseconds after the last user input before turning off the
+          keyboard backlight.
+    -->
+    <integer name="config_keyboardBacklightTimeoutMs">30000</integer>
     <!-- An array describing the screen's backlight values corresponding to the brightness
          values in the config_screenBrightnessNits array.
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index badb986..9dd3027 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2098,6 +2098,7 @@
   <java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
   <java-symbol type="integer" name="config_autoBrightnessInitialLightSensorRate"/>
   <java-symbol type="integer" name="config_autoBrightnessLightSensorRate"/>
+  <java-symbol type="integer" name="config_keyboardBacklightTimeoutMs" />
   <java-symbol type="integer" name="config_carDockKeepsScreenOn" />
   <java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
   <java-symbol type="integer" name="config_datause_notification_type" />
diff --git a/core/tests/InputMethodCoreTests/src/android/view/inputmethod/EditorInfoTest.java b/core/tests/InputMethodCoreTests/src/android/view/inputmethod/EditorInfoTest.java
index 1721e1e..9dd196d 100644
--- a/core/tests/InputMethodCoreTests/src/android/view/inputmethod/EditorInfoTest.java
+++ b/core/tests/InputMethodCoreTests/src/android/view/inputmethod/EditorInfoTest.java
@@ -79,7 +79,7 @@
         TEST_EDITOR_INFO.label = "testLabel";
         TEST_EDITOR_INFO.packageName = "android.view.inputmethod";
         TEST_EDITOR_INFO.fieldId = 0;
-        TEST_EDITOR_INFO.autofillId = AutofillId.NO_AUTOFILL_ID;
+        TEST_EDITOR_INFO.setAutofillId(AutofillId.NO_AUTOFILL_ID);
         TEST_EDITOR_INFO.fieldName = "testField";
         TEST_EDITOR_INFO.extras = new Bundle();
         TEST_EDITOR_INFO.extras.putString("testKey", "testValue");
@@ -531,7 +531,7 @@
             info.setStylusHandwritingEnabled(true);
         }
         info.packageName = "android.view.inputmethod";
-        info.autofillId = new AutofillId(123);
+        info.setAutofillId(new AutofillId(123));
         info.fieldId = 456;
         info.fieldName = "testField";
         info.extras = new Bundle();
@@ -597,7 +597,7 @@
     @Test
     public void testKindofEqualsComparesAutofillId() {
         final EditorInfo infoCopy = TEST_EDITOR_INFO.createCopyInternal();
-        infoCopy.autofillId = new AutofillId(42);
+        infoCopy.setAutofillId(new AutofillId(42));
         assertFalse(TEST_EDITOR_INFO.kindofEquals(infoCopy));
     }
 
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt b/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
index a6de611..8969b2b 100644
--- a/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
+++ b/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
@@ -16,7 +16,10 @@
 
 package android.hardware.display
 
+import android.graphics.PointF
+import android.graphics.RectF
 import android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM
+import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
 import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
 import android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT
 import android.view.Display
@@ -469,4 +472,205 @@
         assertThat(actualDisplay4.offset).isEqualTo(-400f)
         assertThat(actualDisplay4.children).isEmpty()
     }
-}
\ No newline at end of file
+
+    @Test
+    fun rearrange_twoDisplays() {
+        val nodes = rearrangeRects(
+            // Arrange in staggered manner, connected vertically.
+            RectF(100f, 100f, 250f, 200f),
+            RectF(150f, 200f, 300f, 300f),
+        )
+
+        assertThat(nodes[0].children).containsExactly(nodes[1])
+        assertThat(nodes[1].children).isEmpty()
+        assertPositioning(nodes, Pair(POSITION_BOTTOM, 50f))
+    }
+
+    @Test
+    fun rearrange_reverseOrderOfSeveralDisplays() {
+        val nodes = rearrangeRects(
+            RectF(0f, 0f, 150f, 100f),
+            RectF(-150f, 0f, 0f, 100f),
+            RectF(-300f, 0f, -150f, 100f),
+            RectF(-450f, 0f, -300f, 100f),
+        )
+
+        assertPositioning(
+            nodes,
+            Pair(POSITION_LEFT, 0f),
+            Pair(POSITION_LEFT, 0f),
+            Pair(POSITION_LEFT, 0f),
+        )
+
+        assertThat(nodes[0].children).containsExactly(nodes[1])
+        assertThat(nodes[1].children).containsExactly(nodes[2])
+        assertThat(nodes[2].children).containsExactly(nodes[3])
+        assertThat(nodes[3].children).isEmpty()
+    }
+
+    @Test
+    fun rearrange_crossWithRootInCenter() {
+        val nodes = rearrangeRects(
+            RectF(0f, 0f, 150f, 100f),
+            RectF(-150f, 0f, 0f, 100f),
+            RectF(0f,-100f, 150f, 0f),
+            RectF(150f, 0f, 300f, 100f),
+            RectF(0f, 100f, 150f, 200f),
+        )
+
+        assertPositioning(
+            nodes,
+            Pair(POSITION_LEFT, 0f),
+            Pair(POSITION_TOP, 0f),
+            Pair(POSITION_RIGHT, 0f),
+            Pair(POSITION_BOTTOM, 0f),
+        )
+
+        assertThat(nodes[0].children)
+            .containsExactly(nodes[1], nodes[2], nodes[3], nodes[4])
+    }
+
+    @Test
+    fun rearrange_elbowArrangementDoesNotUseCornerAdjacency1() {
+        val nodes = rearrangeRects(
+            //     2
+            //     |
+            // 0 - 1
+
+            RectF(0f, 0f, 100f, 100f),
+            RectF(100f, 0f, 200f, 100f),
+            RectF(100f, -100f, 200f, 0f),
+        )
+
+        assertThat(nodes[0].children).containsExactly(nodes[1])
+        assertThat(nodes[1].children).containsExactly(nodes[2])
+        assertThat(nodes[2].children).isEmpty()
+
+        assertPositioning(
+            nodes,
+            Pair(POSITION_RIGHT, 0f),
+            Pair(POSITION_TOP, 0f),
+        )
+    }
+
+    @Test
+    fun rearrange_elbowArrangementDoesNotUseCornerAdjacency2() {
+        val nodes = rearrangeRects(
+            //     0
+            //     |
+            //     1
+            //     |
+            // 3 - 2
+
+            RectF(0f, 0f, 100f, 100f),
+            RectF(0f, 100f, 100f, 200f),
+            RectF(0f, 200f, 100f, 300f),
+            RectF(-100f, 200f, 0f, 300f),
+        )
+
+        assertThat(nodes[0].children).containsExactly(nodes[1])
+        assertThat(nodes[1].children).containsExactly(nodes[2])
+        assertThat(nodes[2].children).containsExactly(nodes[3])
+        assertThat(nodes[3].children).isEmpty()
+
+        assertPositioning(
+            nodes,
+            Pair(POSITION_BOTTOM, 0f),
+            Pair(POSITION_BOTTOM, 0f),
+            Pair(POSITION_LEFT, 0f),
+        )
+    }
+
+    @Test
+    fun rearrange_useLargerEdge() {
+        val nodes = rearrangeRects(
+            //444111
+            //444111
+            //444111
+            //  000222
+            //  000222
+            //  000222
+            //    333
+            //    333
+            //    333
+            RectF(20f, 30f, 50f, 60f),
+            RectF(30f, 0f, 60f, 30f),
+            RectF(50f, 30f, 80f, 60f),
+            RectF(40f, 60f, 70f, 90f),
+            RectF(0f, 0f, 30f, 30f),
+        )
+
+        assertPositioning(
+            nodes,
+            Pair(POSITION_TOP, 10f),
+            Pair(POSITION_RIGHT, 0f),
+            Pair(POSITION_BOTTOM, -10f),
+            Pair(POSITION_LEFT, 0f),
+        )
+
+        assertThat(nodes[0].children).containsExactly(nodes[1], nodes[2])
+        assertThat(nodes[1].children).containsExactly(nodes[4])
+        assertThat(nodes[2].children).containsExactly(nodes[3])
+        (3..4).forEach { assertThat(nodes[it].children).isEmpty() }
+    }
+
+    @Test
+    fun rearrange_closeGaps() {
+        val nodes = rearrangeRects(
+            //000
+            //000 111
+            //000 111
+            //    111
+            //
+            //        222
+            //        222
+            //        222
+            RectF(0f, 0f, 30f, 30f),
+            RectF(40f, 10f, 70f, 40f),
+            RectF(80.5f, 50f, 110f, 80f),  // left+=0.5 to cause a preference for TOP/BOTTOM attach
+        )
+
+        assertPositioning(
+            nodes,
+            // In the case of corner adjacency, we prefer a left/right attachment.
+            Pair(POSITION_RIGHT, 10f),
+            Pair(POSITION_BOTTOM, 40.5f),  // TODO: fix implementation to remove this gap
+        )
+
+        assertThat(nodes[0].children).containsExactly(nodes[1])
+        assertThat(nodes[1].children).containsExactly(nodes[2])
+        assertThat(nodes[2].children).isEmpty()
+    }
+
+    /**
+     * Runs the rearrange algorithm and returns the resulting tree as a list of nodes, with the
+     * root at index 0. The number of nodes is inferred from the number of positions passed.
+     */
+    private fun rearrangeRects(vararg pos : RectF) : List<DisplayTopology.TreeNode> {
+        // Generates a linear sequence of nodes in order in the List from root to leaf,
+        // left-to-right. IDs are ascending from 0 to count - 1.
+
+        val nodes = pos.indices.map {
+            DisplayTopology.TreeNode(it, pos[it].width(), pos[it].height(), POSITION_RIGHT, 0f)
+        }
+
+        nodes.forEachIndexed { id, node ->
+            if (id > 0) {
+                nodes[id - 1].addChild(node)
+            }
+        }
+
+        DisplayTopology(nodes[0], 0).rearrange(pos.indices.associateWith {
+            PointF(pos[it].left, pos[it].top)
+        })
+
+        return nodes
+    }
+
+    private fun assertPositioning(
+            nodes : List<DisplayTopology.TreeNode>, vararg positions : Pair<Int, Float>) {
+        assertThat(nodes.drop(1).map { Pair(it.position, it.offset )})
+            .containsExactly(*positions)
+            .inOrder()
+    }
+}
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 7446b88..6928c25 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
@@ -1179,7 +1179,7 @@
         val userContext =
             context.createContextAsUser(userHandle, /* flags= */ 0)
         val intent = Intent(userContext, DesktopWallpaperActivity::class.java)
-        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId)
         val options =
             ActivityOptions.makeBasic().apply {
                 launchWindowingMode = WINDOWING_MODE_FULLSCREEN
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 5ffc64f..79a9ce5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -47,7 +47,6 @@
 import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.common.pip.PipBoundsState;
 import com.android.wm.shell.common.pip.PipMenuController;
-import com.android.wm.shell.common.split.SplitScreenUtils;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.DefaultMixedHandler;
@@ -312,10 +311,10 @@
     }
 
     /** Whether a particular package is same as current pip package. */
-    public boolean isPackageActiveInPip(String packageName) {
-        final TaskInfo inPipTask = mPipOrganizer.getTaskInfo();
-        return packageName != null && inPipTask != null && mPipOrganizer.isInPip()
-                && packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent));
+    public boolean isPackageActiveInPip(@Nullable String packageName) {
+        return packageName != null
+                && mPipBoundsState.getLastPipComponentName() != null
+                && packageName.equals(mPipBoundsState.getLastPipComponentName().getPackageName());
     }
 
     /** Add PiP-related changes to `outWCT` for the given request. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 02f5955..d415c10 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -420,7 +420,8 @@
         }
 
         // Update the src-rect-hint in params in place, to set up initial animator transform.
-        params.getSourceRectHint().set(adjustedSourceRectHint);
+        params.copyOnlySet(new PictureInPictureParams.Builder()
+                .setSourceRectHint(adjustedSourceRectHint).build());
 
         // Config-at-end transitions need to have their activities transformed before starting
         // the animation; this makes the buffer seem like it's been updated to final size.
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowWithDragToTopDragZoneTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowWithDragToTopDragZoneTest.kt
new file mode 100644
index 0000000..7e0b81a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowWithDragToTopDragZoneTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.wm.shell.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.MaximizeAppWindowWithDragToTopDragZone
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [MaximizeAppWindowWithDragToTopDragZone]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class MaximizeAppWindowWithDragToTopDragZoneTest : MaximizeAppWindowWithDragToTopDragZone()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindowWithDragToTopDragZone.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindowWithDragToTopDragZone.kt
new file mode 100644
index 0000000..a2b88f2
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindowWithDragToTopDragZone.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.flicker.rules.ChangeDisplayOrientationRule
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.internal.R
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+/**
+ * Base scenario test for maximizing a desktop app window by dragging it to the top drag zone.
+ */
+@Ignore("Test Base Class")
+abstract class MaximizeAppWindowWithDragToTopDragZone
+constructor(private val rotation: Rotation = Rotation.ROTATION_0) {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+
+    @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        // Skip the test when the drag-to-maximize is disabled on this device.
+        Assume.assumeTrue(Flags.enableDragToMaximize() &&
+            instrumentation.context.resources.getBoolean(R.bool.config_dragToMaximizeInDesktopMode))
+        tapl.setEnableRotation(true)
+        tapl.setExpectedRotation(rotation.value)
+        ChangeDisplayOrientationRule.setRotation(rotation)
+        testApp.enterDesktopWithDrag(wmHelper, device)
+    }
+
+    @Test
+    open fun maximizeAppWithDragToTopDragZone() {
+        testApp.maximizeAppWithDragToTopDragZone(wmHelper, device)
+    }
+
+    @After
+    fun teardown() {
+        testApp.exit(wmHelper)
+    }
+}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 2ae89d3..82e9503 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import static android.media.codec.Flags.FLAG_CODEC_AVAILABILITY;
 import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
 import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
 import static android.media.codec.Flags.FLAG_SUBSESSION_METRICS;
@@ -29,6 +30,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.ImageFormat;
 import android.graphics.Rect;
@@ -1843,6 +1845,12 @@
      */
     private static final int CB_METRICS_FLUSHED = 8;
 
+    /**
+     * Callback ID to notify the change in resource requirement
+     * for the codec component.
+     */
+    private static final int CB_REQUIRED_RESOURCES_CHANGE = 9;
+
     private class EventHandler extends Handler {
         private MediaCodec mCodec;
 
@@ -2017,13 +2025,19 @@
 
                 case CB_METRICS_FLUSHED:
                 {
-
                     if (GetFlag(() -> android.media.codec.Flags.subsessionMetrics())) {
                         mCallback.onMetricsFlushed(mCodec, (PersistableBundle)msg.obj);
                     }
                     break;
                 }
 
+                case CB_REQUIRED_RESOURCES_CHANGE: {
+                    if (android.media.codec.Flags.codecAvailability()) {
+                        mCallback.onRequiredResourcesChanged(mCodec);
+                    }
+                    break;
+                }
+
                 default:
                 {
                     break;
@@ -2302,6 +2316,70 @@
     }
 
     /**
+     * @hide
+     * Abstraction for the Global Codec resources.
+     * This encapsulates all the available codec resources on the device.
+     *
+     * To be able to enforce and test the implementation of codec availability hal APIs,
+     * globally available codec resources are exposed only as TestApi.
+     * This will be tracked and verified through cts.
+     */
+    @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+    @TestApi
+    public static final class GlobalResourceInfo {
+        /**
+         * Identifier for the Resource type.
+         */
+        String mName;
+        /**
+         * Total count/capacity of resources of this type.
+         */
+        long mCapacity;
+        /**
+         * Available count of this resource type.
+         */
+        long mAvailable;
+
+        @NonNull
+        public String getName() {
+            return mName;
+        }
+
+        public long getCapacity() {
+            return mCapacity;
+        }
+
+        public long getAvailable() {
+            return mAvailable;
+        }
+    };
+
+    /**
+     * @hide
+     * Get a list of globally available codec resources.
+     *
+     * To be able to enforce and test the implementation of codec availability hal APIs,
+     * it is exposed only as TestApi.
+     * This will be tracked and verified through cts.
+     *
+     * This returns a {@link java.util.List} list of codec resources.
+     * For every {@link GlobalResourceInfo} in the list, it encapsulates the
+     * information about each resources available globaly on device.
+     *
+     * @return A list of available device codec resources; an empty list if no
+     *         device codec resources are available.
+     * @throws UnsupportedOperationException if not implemented.
+     */
+    @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+    @TestApi
+    public static @NonNull List<GlobalResourceInfo> getGloballyAvailableResources() {
+        return native_getGloballyAvailableResources();
+    }
+
+    @NonNull
+    private static native List<GlobalResourceInfo> native_getGloballyAvailableResources();
+
+    /**
      * Configures a component.
      *
      * @param format The format of the input data (decoder) or the desired
@@ -2443,6 +2521,73 @@
     }
 
     /**
+     * @hide
+     * Abstraction for the resources associated with a codec instance.
+     * This encapsulates the required codec resources for a configured codec instance.
+     *
+     * To be able to enforce and test the implementation of codec availability hal APIs,
+     * required codec resources are exposed only as TestApi.
+     * This will be tracked and verified through cts.
+     */
+    @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+    @TestApi
+    public static final class InstanceResourceInfo {
+        /**
+         * Identifier for the Resource type.
+         */
+        String mName;
+        /**
+         * Required resource count of this type.
+         */
+        long mStaticCount;
+        /**
+         * Per frame resource requirement of this resource type.
+         */
+        long mPerFrameCount;
+
+        @NonNull
+        public String getName() {
+            return mName;
+        }
+
+        public long getStaticCount() {
+            return mStaticCount;
+        }
+
+        public long getPerFrameCount() {
+            return mPerFrameCount;
+        }
+    };
+
+    /**
+     * @hide
+     * Get a list of required codec resources for this configuration.
+     *
+     * To be able to enforce and test the implementation of codec availability hal APIs,
+     * it is exposed only as TestApi.
+     * This will be tracked and verified through cts.
+     *
+     * This returns a {@link java.util.List} list of codec resources.
+     * For every {@link GlobalResourceInfo} in the list, it encapsulates the
+     * information about each resources required for the current configuration.
+     *
+     * NOTE: This may only be called after {@link #configure}.
+     *
+     * @return A list of required device codec resources; an empty list if no
+     *         device codec resources are required.
+     * @throws IllegalStateException if the codec wasn't configured yet.
+     * @throws UnsupportedOperationException if not implemented.
+     */
+    @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+    @TestApi
+    public @NonNull List<InstanceResourceInfo> getRequiredResources() {
+        return native_getRequiredResources();
+    }
+
+    @NonNull
+    private native List<InstanceResourceInfo> native_getRequiredResources();
+
+    /**
      *  Dynamically sets the output surface of a codec.
      *  <p>
      *  This can only be used if the codec was configured with an output surface.  The
@@ -5740,6 +5885,25 @@
                 @NonNull MediaCodec codec, @NonNull PersistableBundle metrics) {
             // default implementation ignores this callback.
         }
+
+        /**
+         * @hide
+         * Called when there is a change in the required resources for the codec.
+         * <p>
+         * Upon receiving this notification, the updated resource requirement
+         * can be queried through {@link #getRequiredResources}.
+         *
+         * @param codec The MediaCodec object.
+         */
+        @FlaggedApi(FLAG_CODEC_AVAILABILITY)
+        @TestApi
+        public void onRequiredResourcesChanged(@NonNull MediaCodec codec) {
+            /*
+             * A default implementation for backward compatibility.
+             * Since this is a TestApi, we are not enforcing the callback to be
+             * overridden.
+             */
+        }
     }
 
     private void postEventFromNative(
diff --git a/media/java/android/media/quality/AmbientBacklightEvent.java b/media/java/android/media/quality/AmbientBacklightEvent.java
index 3bc6b86..5c11def 100644
--- a/media/java/android/media/quality/AmbientBacklightEvent.java
+++ b/media/java/android/media/quality/AmbientBacklightEvent.java
@@ -16,9 +16,11 @@
 
 package android.media.quality;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.media.tv.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,8 +29,10 @@
 import java.util.Objects;
 
 /**
+ * Ambient backlight event
  * @hide
  */
+@FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW)
 public final class AmbientBacklightEvent implements Parcelable {
 
     /** @hide */
@@ -64,6 +68,9 @@
     @Nullable
     private final AmbientBacklightMetadata mMetadata;
 
+    /**
+     * Constructor of AmbientBacklightEvent.
+     */
     public AmbientBacklightEvent(int eventType,
             @Nullable AmbientBacklightMetadata metadata) {
         mEventType = eventType;
@@ -75,10 +82,19 @@
         mMetadata = in.readParcelable(AmbientBacklightMetadata.class.getClassLoader());
     }
 
+    /**
+     * Gets event type.
+     */
     public int getEventType() {
         return mEventType;
     }
 
+    /**
+     * Gets ambient backlight metadata.
+     *
+     * @return the metadata of the event. It's non-null only for
+     * {@link #AMBIENT_BACKLIGHT_EVENT_METADATA}.
+     */
     @Nullable
     public AmbientBacklightMetadata getMetadata() {
         return mMetadata;
@@ -95,7 +111,8 @@
         return 0;
     }
 
-    public static final @NonNull Parcelable.Creator<AmbientBacklightEvent> CREATOR =
+    @NonNull
+    public static final Parcelable.Creator<AmbientBacklightEvent> CREATOR =
             new Parcelable.Creator<AmbientBacklightEvent>() {
                 public AmbientBacklightEvent createFromParcel(Parcel in) {
                     return new AmbientBacklightEvent(in);
diff --git a/media/java/android/media/quality/AmbientBacklightMetadata.java b/media/java/android/media/quality/AmbientBacklightMetadata.java
index fc77934..9c11f9a 100644
--- a/media/java/android/media/quality/AmbientBacklightMetadata.java
+++ b/media/java/android/media/quality/AmbientBacklightMetadata.java
@@ -16,6 +16,10 @@
 
 package android.media.quality;
 
+import android.annotation.FlaggedApi;
+import android.annotation.IntRange;
+import android.graphics.PixelFormat;
+import android.media.tv.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,9 +28,11 @@
 import java.util.Arrays;
 
 /**
+ * Metadata of ambient backlight.
  * @hide
  */
-public class AmbientBacklightMetadata implements Parcelable {
+@FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW)
+public final class AmbientBacklightMetadata implements Parcelable {
     @NonNull
     private final String mPackageName;
     private final int mCompressAlgorithm;
@@ -37,6 +43,9 @@
     @NonNull
     private final int[] mZonesColors;
 
+    /**
+     * Constructor of AmbientBacklightMetadata.
+     */
     public AmbientBacklightMetadata(@NonNull String packageName, int compressAlgorithm,
             int source, int colorFormat, int horizontalZonesNumber, int verticalZonesNumber,
             @NonNull int[] zonesColors) {
@@ -59,31 +68,58 @@
         mZonesColors = in.createIntArray();
     }
 
+    /**
+     * Gets package name.
+     * @hide
+     */
     @NonNull
     public String getPackageName() {
         return mPackageName;
     }
 
+    /**
+     * Gets compress algorithm.
+     */
+    @AmbientBacklightSettings.CompressAlgorithm
     public int getCompressAlgorithm() {
         return mCompressAlgorithm;
     }
 
+    /**
+     * Gets source of ambient backlight detection.
+     */
+    @AmbientBacklightSettings.Source
     public int getSource() {
         return mSource;
     }
 
+    /**
+     * Gets color format.
+     */
+    @PixelFormat.Format
     public int getColorFormat() {
         return mColorFormat;
     }
 
+    /**
+     * Gets the number of lights in each horizontal zone.
+     */
+    @IntRange(from = 0)
     public int getHorizontalZonesNumber() {
         return mHorizontalZonesNumber;
     }
 
+    /**
+     * Gets the number of lights in each vertical zone.
+     */
+    @IntRange(from = 0)
     public int getVerticalZonesNumber() {
         return mVerticalZonesNumber;
     }
 
+    /**
+     * @hide
+     */
     @NonNull
     public int[] getZonesColors() {
         return mZonesColors;
diff --git a/media/java/android/media/quality/AmbientBacklightSettings.java b/media/java/android/media/quality/AmbientBacklightSettings.java
index bb782bf..4ed7bc7 100644
--- a/media/java/android/media/quality/AmbientBacklightSettings.java
+++ b/media/java/android/media/quality/AmbientBacklightSettings.java
@@ -16,7 +16,11 @@
 
 package android.media.quality;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.graphics.PixelFormat;
+import android.media.tv.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -29,7 +33,8 @@
  * Settings for ambient backlight.
  * @hide
  */
-public class AmbientBacklightSettings implements Parcelable {
+@FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW)
+public final class AmbientBacklightSettings implements Parcelable {
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SOURCE_NONE, SOURCE_AUDIO, SOURCE_VIDEO, SOURCE_AUDIO_VIDEO})
@@ -62,6 +67,7 @@
 
     /**
      * The color format is RGB888.
+     * @hide
      */
     public static final int COLOR_FORMAT_RGB888 = 1;
 
@@ -76,7 +82,7 @@
     public static final int ALGORITHM_NONE = 0;
 
     /**
-     * The compress algorithm is RLE.
+     * The compress algorithm is run length encoding (RLE).
      */
     public static final int ALGORITHM_RLE = 1;
 
@@ -115,6 +121,9 @@
      */
     private final int mThreshold;
 
+    /**
+     * Constructs AmbientBacklightSettings.
+     */
     public AmbientBacklightSettings(int source, int maxFps, int colorFormat,
             int horizontalZonesNumber, int verticalZonesNumber, boolean isLetterboxOmitted,
             int threshold) {
@@ -137,32 +146,57 @@
         mThreshold = in.readInt();
     }
 
+    /**
+     * Gets source of ambient backlight detection.
+     */
     @Source
     public int getSource() {
         return mSource;
     }
 
+    /**
+     * Gets max frames per second.
+     */
+    @IntRange(from = 1)
     public int getMaxFps() {
         return mMaxFps;
     }
 
-    @ColorFormat
+    /**
+     * Gets color format.
+     */
+    @PixelFormat.Format
     public int getColorFormat() {
         return mColorFormat;
     }
 
+    /**
+     * Gets the number of lights in each horizontal zone.
+     */
+    @IntRange(from = 0)
     public int getHorizontalZonesNumber() {
         return mHorizontalZonesNumber;
     }
 
+    /**
+     * Gets the number of lights in each vertical zone.
+     */
+    @IntRange(from = 0)
     public int getVerticalZonesNumber() {
         return mVerticalZonesNumber;
     }
 
+    /**
+     * Returns {@code true} if letter box is omitted; {@code false} otherwise.
+     * @hide
+     */
     public boolean isLetterboxOmitted() {
         return mIsLetterboxOmitted;
     }
 
+    /**
+     * @hide
+     */
     public int getThreshold() {
         return mThreshold;
     }
diff --git a/media/java/android/media/quality/MediaQualityManager.java b/media/java/android/media/quality/MediaQualityManager.java
index 26d83ac..4d4526c 100644
--- a/media/java/android/media/quality/MediaQualityManager.java
+++ b/media/java/android/media/quality/MediaQualityManager.java
@@ -567,7 +567,6 @@
 
     /**
      * Registers a {@link AmbientBacklightCallback}.
-     * @hide
      */
     public void registerAmbientBacklightCallback(
             @NonNull @CallbackExecutor Executor executor,
@@ -581,7 +580,6 @@
 
     /**
      * Unregisters the existing {@link AmbientBacklightCallback}.
-     * @hide
      */
     public void unregisterAmbientBacklightCallback(
             @NonNull final AmbientBacklightCallback callback) {
@@ -602,7 +600,6 @@
      * Set the ambient backlight settings.
      *
      * @param settings The settings to use for the backlight detector.
-     * @hide
      */
     public void setAmbientBacklightSettings(
             @NonNull AmbientBacklightSettings settings) {
@@ -618,7 +615,6 @@
      * Enables or disables the ambient backlight detection.
      *
      * @param enabled {@code true} to enable, {@code false} to disable.
-     * @hide
      */
     public void setAmbientBacklightEnabled(boolean enabled) {
         try {
@@ -843,14 +839,12 @@
 
     /**
      * Callback used to monitor status of ambient backlight.
-     * @hide
      */
     public abstract static class AmbientBacklightCallback {
         /**
          * Called when new ambient backlight event is emitted.
-         * @hide
          */
-        public void onAmbientBacklightEvent(AmbientBacklightEvent event) {
+        public void onAmbientBacklightEvent(@NonNull AmbientBacklightEvent event) {
         }
     }
 }
diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig
index 4de6863..6441652 100644
--- a/media/java/android/media/tv/flags/media_tv.aconfig
+++ b/media/java/android/media/tv/flags/media_tv.aconfig
@@ -80,3 +80,11 @@
     description : "Feature flag to add setResourceHolderRetain api to MediaCas and Tuner JAVA."
     bug: "372973197"
 }
+
+flag {
+    name: "apply_picture_profiles"
+    is_exported: true
+    namespace: "media_tv"
+    description : "Feature flag to enable APIs for applying picture profiles"
+    bug: "337330263"
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index c44e26f..f09dc72 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -104,6 +104,7 @@
         "libgrallocusage",
         "libmedia_midiiowrapper",
         "android.companion.virtualdevice.flags-aconfig-cc",
+        "android.media.codec-aconfig-cc",
         "android.media.playback.flags-aconfig-cc",
     ],
 
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 001653b..fc184fe 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -39,6 +39,8 @@
 #include <C2Buffer.h>
 #include <C2PlatformSupport.h>
 
+#include <android_media_codec.h>
+
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 
 #include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -189,6 +191,22 @@
     jmethodID setId;
 } gBufferInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID ctorId;
+    jfieldID resourceId;
+    jfieldID capacityId;
+    jfieldID availableId;
+} gGlobalResourceInfo;
+
+static struct {
+    jclass clazz;
+    jmethodID ctorId;
+    jfieldID resourceId;
+    jfieldID staticCountId;
+    jfieldID perFrameCountId;
+} gInstanceResourceInfo;
+
 struct fields_t {
     jmethodID postEventFromNativeID;
     jmethodID lockAndGetContextID;
@@ -1129,6 +1147,37 @@
     return mCodec->unsubscribeFromVendorParameters(names);
 }
 
+static jobject getJavaResources(
+        JNIEnv *env,
+        const std::vector<MediaCodec::InstanceResourceInfo>& resources) {
+    jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
+    for (const MediaCodec::InstanceResourceInfo& res : resources) {
+        ScopedLocalRef<jobject> object{env, env->NewObject(
+                gInstanceResourceInfo.clazz, gInstanceResourceInfo.ctorId)};
+        ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())};
+        env->SetObjectField(object.get(), gInstanceResourceInfo.resourceId, nameStr.get());
+        env->SetLongField(object.get(),
+                          gInstanceResourceInfo.staticCountId,
+                          (jlong)res.mStaticCount);
+        env->SetLongField(object.get(),
+                          gInstanceResourceInfo.perFrameCountId,
+                          (jlong)res.mPerFrameCount);
+        (void)env->CallBooleanMethod(resourcesObj, gArrayListInfo.addId, object.get());
+    }
+
+    return resourcesObj;
+}
+
+status_t JMediaCodec::getRequiredResources(JNIEnv *env, jobject *resourcesObj) {
+    std::vector<MediaCodec::InstanceResourceInfo> resources;
+    status_t status = mCodec->getRequiredResources(resources);
+    if (status != OK) {
+        return status;
+    }
+    *resourcesObj = getJavaResources(env, resources);
+    return OK;
+}
+
 static jthrowable createCodecException(
         JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
     ScopedLocalRef<jclass> clazz(
@@ -1475,6 +1524,10 @@
             obj = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
             break;
         }
+        case MediaCodec::CB_REQUIRED_RESOURCES_CHANGED:
+        {
+            break;
+        }
 
         default:
             TRESPASS();
@@ -3560,6 +3613,64 @@
     return;
 }
 
+static jobject getJavaResources(
+        JNIEnv *env,
+        const std::vector<MediaCodec::GlobalResourceInfo>& resources) {
+    jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
+    for (const MediaCodec::GlobalResourceInfo& res : resources) {
+        ScopedLocalRef<jobject> object{env, env->NewObject(
+                gGlobalResourceInfo.clazz, gGlobalResourceInfo.ctorId)};
+        ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())};
+        env->SetObjectField(object.get(), gInstanceResourceInfo.resourceId, nameStr.get());
+        env->SetLongField(object.get(), gGlobalResourceInfo.capacityId, (jlong)res.mCapacity);
+        env->SetLongField(object.get(), gGlobalResourceInfo.availableId, (jlong)res.mAvailable);
+        (void)env->CallBooleanMethod(resourcesObj, gArrayListInfo.addId, object.get());
+    }
+
+    return resourcesObj;
+}
+
+static jobject android_media_MediaCodec_getGloballyAvailableResources(
+        JNIEnv *env, jobject thiz) {
+    (void)thiz;
+    std::vector<MediaCodec::GlobalResourceInfo> resources;
+    status_t status = MediaCodec::getGloballyAvailableResources(resources);
+    if (status != OK) {
+        if (status == ERROR_UNSUPPORTED) {
+            jniThrowException(env, "java/lang/UnsupportedOperationException",
+                              "Function Not Implemented");
+        } else {
+            throwExceptionAsNecessary(env, status, nullptr);
+        }
+        return nullptr;
+    }
+
+    return getJavaResources(env, resources);
+}
+
+static jobject android_media_MediaCodec_getRequiredResources(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+    if (codec == nullptr || codec->initCheck() != OK) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
+        return nullptr;
+    }
+
+    jobject ret = nullptr;
+    status_t status = codec->getRequiredResources(env, &ret);
+    if (status != OK) {
+        if (status == ERROR_UNSUPPORTED) {
+            jniThrowException(env, "java/lang/UnsupportedOperationException",
+                              "Function Not Implemented");
+        } else {
+            throwExceptionAsNecessary(env, status, nullptr);
+        }
+        return nullptr;
+    }
+
+    return ret;
+}
+
 static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) {
     ScopedLocalRef<jclass> clazz(
             env, env->FindClass("android/media/MediaCodec"));
@@ -3905,6 +4016,36 @@
     gFields.bufferInfoOffset = env->GetFieldID(clazz.get(), "offset", "I");
     gFields.bufferInfoPresentationTimeUs =
             env->GetFieldID(clazz.get(), "presentationTimeUs", "J");
+
+    // Since these TestApis are defined under the flag, make sure they are
+    // accessed only when the flag is set.
+    if (android::media::codec::codec_availability()) {
+        clazz.reset(env->FindClass("android/media/MediaCodec$GlobalResourceInfo"));
+        CHECK(clazz.get() != NULL);
+        gGlobalResourceInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
+        gGlobalResourceInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
+        CHECK(gGlobalResourceInfo.ctorId != NULL);
+        gGlobalResourceInfo.resourceId =
+                env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;");
+        CHECK(gGlobalResourceInfo.resourceId != NULL);
+        gGlobalResourceInfo.capacityId = env->GetFieldID(clazz.get(), "mCapacity", "J");
+        CHECK(gGlobalResourceInfo.capacityId != NULL);
+        gGlobalResourceInfo.availableId = env->GetFieldID(clazz.get(), "mAvailable", "J");
+        CHECK(gGlobalResourceInfo.availableId != NULL);
+
+        clazz.reset(env->FindClass("android/media/MediaCodec$InstanceResourceInfo"));
+        CHECK(clazz.get() != NULL);
+        gInstanceResourceInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
+        gInstanceResourceInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
+        CHECK(gInstanceResourceInfo.ctorId != NULL);
+        gInstanceResourceInfo.resourceId =
+                env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;");
+        CHECK(gInstanceResourceInfo.resourceId != NULL);
+        gInstanceResourceInfo.staticCountId= env->GetFieldID(clazz.get(), "mStaticCount", "J");
+        CHECK(gInstanceResourceInfo.staticCountId != NULL);
+        gInstanceResourceInfo.perFrameCountId = env->GetFieldID(clazz.get(), "mPerFrameCount", "J");
+        CHECK(gInstanceResourceInfo.perFrameCountId != NULL);
+    }
 }
 
 static void android_media_MediaCodec_native_setup(
@@ -4261,6 +4402,12 @@
 
     { "native_finalize", "()V",
       (void *)android_media_MediaCodec_native_finalize },
+
+    { "native_getGloballyAvailableResources", "()Ljava/util/List;",
+      (void *)android_media_MediaCodec_getGloballyAvailableResources},
+
+    { "native_getRequiredResources", "()Ljava/util/List;",
+      (void *)android_media_MediaCodec_getRequiredResources},
 };
 
 static const JNINativeMethod gLinearBlockMethods[] = {
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index c9b6b7f6..930dbbe 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -185,6 +185,8 @@
 
     status_t unsubscribeFromVendorParameters(JNIEnv *env, jobject names);
 
+    status_t getRequiredResources(JNIEnv *env, jobject *resourcesObj);
+
     bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; }
 
     const sp<ICrypto> &getCrypto() { return mCrypto; }
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index a23845f..c25f77b 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -107,6 +107,7 @@
     method public void onRfDiscoveryStarted(boolean);
     method public void onRfFieldActivated(boolean);
     method public void onRoutingChanged();
+    method public void onRoutingTableFull();
     method public void onStateUpdated(int);
     method public void onTagConnected(boolean);
     method public void onTagDispatch(@NonNull java.util.function.Consumer<java.lang.Boolean>);
diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
index b102e87..fb793b0 100644
--- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
+++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
@@ -52,5 +52,6 @@
    void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent);
    void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category);
    void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category);
+   void onRoutingTableFull();
    void onLogEventNotified(in OemLogItems item);
 }
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index abd99bc..57ee981 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -394,6 +394,13 @@
         void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category);
 
         /**
+         * Callback to indicate that routing table is full and the OEM can optionally launch a
+         * dialog to request the user to remove some Card Emulation apps from the device to free
+         * routing table space.
+         */
+        void onRoutingTableFull();
+
+        /**
          * Callback when OEM specified log event are notified.
          * @param item the log items that contains log information of NFC event.
          */
@@ -853,6 +860,12 @@
                     handleVoidCallback(enabled, cb::onReaderOptionChanged, ex));
         }
 
+        public void onRoutingTableFull() throws RemoteException {
+            mCallbackMap.forEach((cb, ex) ->
+                    handleVoidCallback(null,
+                            (Object input) -> cb.onRoutingTableFull(), ex));
+        }
+
         @Override
         public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer)
                 throws RemoteException {
diff --git a/nfc/java/android/nfc/OemLogItems.java b/nfc/java/android/nfc/OemLogItems.java
index 6671941..4f3e199 100644
--- a/nfc/java/android/nfc/OemLogItems.java
+++ b/nfc/java/android/nfc/OemLogItems.java
@@ -142,8 +142,11 @@
         dest.writeByteArray(mCommandApdus);

         dest.writeInt(mResponseApdus.length);

         dest.writeByteArray(mResponseApdus);

-        dest.writeLong(mRfFieldOnTime.getEpochSecond());

-        dest.writeInt(mRfFieldOnTime.getNano());

+        dest.writeBoolean(mRfFieldOnTime != null);

+        if (mRfFieldOnTime != null) {

+            dest.writeLong(mRfFieldOnTime.getEpochSecond());

+            dest.writeInt(mRfFieldOnTime.getNano());

+        }

         dest.writeParcelable(mTag, 0);

     }

 

@@ -305,7 +308,12 @@
         in.readByteArray(this.mCommandApdus);

         this.mResponseApdus = new byte[in.readInt()];

         in.readByteArray(this.mResponseApdus);

-        this.mRfFieldOnTime = Instant.ofEpochSecond(in.readLong(), in.readInt());

+        boolean isRfFieldOnTimeSet = in.readBoolean();

+        if (isRfFieldOnTimeSet) {

+            this.mRfFieldOnTime = Instant.ofEpochSecond(in.readLong(), in.readInt());

+        } else {

+            this.mRfFieldOnTime = null;

+        }

         this.mTag = in.readParcelable(Tag.class.getClassLoader(), Tag.class);

     }

 

diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index bffda8b..0948931 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -497,6 +497,9 @@
     resource_dirs: [],
     static_libs: [
         "//frameworks/libs/systemui:compilelib",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/util/settings:api",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail:impl",
         "SystemUI-res",
         "WifiTrackerLib",
         "WindowManager-Shell",
@@ -770,6 +773,9 @@
     ],
     static_libs: [
         "//frameworks/libs/systemui:compilelib",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/util/settings:api",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail:impl",
         "SystemUI-tests-base",
         "androidx.test.uiautomator_uiautomator",
         "androidx.core_core-animation-testing",
diff --git a/packages/SystemUI/common/Android.bp b/packages/SystemUI/common/Android.bp
index 91dc3e3..9f15983 100644
--- a/packages/SystemUI/common/Android.bp
+++ b/packages/SystemUI/common/Android.bp
@@ -30,5 +30,9 @@
         "src/**/*.kt",
     ],
 
+    static_libs: ["SystemUI-shared-utils"],
+
+    libs: ["//frameworks/libs/systemui:tracinglib-platform"],
+
     kotlincflags: ["-Xjvm-default=all"],
 }
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt b/packages/SystemUI/common/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
rename to packages/SystemUI/common/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
diff --git a/packages/SystemUI/src/com/android/systemui/coroutines/Tracing.kt b/packages/SystemUI/common/src/com/android/systemui/coroutines/Tracing.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/coroutines/Tracing.kt
rename to packages/SystemUI/common/src/com/android/systemui/coroutines/Tracing.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
index 93dede5..f1f6c61 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -38,7 +38,7 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.res.R;
 import com.android.systemui.retail.data.repository.FakeRetailModeRepository;
-import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl;
+import com.android.systemui.retail.domain.interactor.impl.RetailModeInteractorImpl;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/data/repository/RetailModeSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/data/repository/RetailModeSettingsRepositoryTest.kt
index ba7a65d..47bfda4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/data/repository/RetailModeSettingsRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/data/repository/RetailModeSettingsRepositoryTest.kt
@@ -21,6 +21,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.retail.data.repository.impl.RetailModeSettingsRepository
 import com.android.systemui.util.settings.FakeGlobalSettings
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/domain/interactor/RetailModeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/domain/interactor/RetailModeInteractorImplTest.kt
index b536520..b47dcb5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/domain/interactor/RetailModeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/retail/domain/interactor/RetailModeInteractorImplTest.kt
@@ -20,6 +20,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.retail.data.repository.FakeRetailModeRepository
+import com.android.systemui.retail.domain.interactor.impl.RetailModeInteractorImpl
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/packages/SystemUI/pods/Android.bp b/packages/SystemUI/pods/Android.bp
new file mode 100644
index 0000000..e45f317
--- /dev/null
+++ b/packages/SystemUI/pods/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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 {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+    // The package default_visibility specified here is inherited to subpackages that do not
+    // specify default_visibility:
+    default_visibility: ["//visibility:private"],
+}
diff --git a/packages/SystemUI/pods/com/android/systemui/dagger/Android.bp b/packages/SystemUI/pods/com/android/systemui/dagger/Android.bp
new file mode 100644
index 0000000..df90be8
--- /dev/null
+++ b/packages/SystemUI/pods/com/android/systemui/dagger/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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.
+//
+
+soong_namespace {
+}
+
+package {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+java_library {
+    name: "api",
+    srcs: [
+        "**/*.java",
+        "**/*.kt",
+    ],
+    libs: [
+        "jsr330",
+    ],
+    visibility: ["//frameworks/base/packages/SystemUI:__subpackages__"],
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUISingleton.java b/packages/SystemUI/pods/com/android/systemui/dagger/SysUISingleton.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/dagger/SysUISingleton.java
rename to packages/SystemUI/pods/com/android/systemui/dagger/SysUISingleton.java
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/Application.java b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Application.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/Application.java
rename to packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Application.java
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/Background.java b/packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Background.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/Background.java
rename to packages/SystemUI/pods/com/android/systemui/dagger/qualifiers/Background.java
diff --git a/packages/SystemUI/pods/com/android/systemui/retail/Android.bp b/packages/SystemUI/pods/com/android/systemui/retail/Android.bp
new file mode 100644
index 0000000..f047848
--- /dev/null
+++ b/packages/SystemUI/pods/com/android/systemui/retail/Android.bp
@@ -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.
+//
+
+soong_namespace {
+}
+
+package {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+java_library {
+    name: "impl",
+    srcs: ["*.kt"],
+    libs: [
+        "jsr330",
+        "dagger2",
+        "SystemUICommon",
+        "kotlinx_coroutines",
+    ],
+    static_libs: [
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/data:impl",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/domain:impl",
+    ],
+    visibility: ["//frameworks/base/packages/SystemUI"],
+}
diff --git a/packages/SystemUI/src/com/android/systemui/retail/dagger/RetailModeModule.kt b/packages/SystemUI/pods/com/android/systemui/retail/RetailModeModule.kt
similarity index 83%
rename from packages/SystemUI/src/com/android/systemui/retail/dagger/RetailModeModule.kt
rename to packages/SystemUI/pods/com/android/systemui/retail/RetailModeModule.kt
index e863949..c20e368 100644
--- a/packages/SystemUI/src/com/android/systemui/retail/dagger/RetailModeModule.kt
+++ b/packages/SystemUI/pods/com/android/systemui/retail/RetailModeModule.kt
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.systemui.retail.dagger
+package com.android.systemui.retail
 
 import com.android.systemui.retail.data.repository.RetailModeRepository
-import com.android.systemui.retail.data.repository.RetailModeSettingsRepository
+import com.android.systemui.retail.data.repository.impl.RetailModeSettingsRepository
 import com.android.systemui.retail.domain.interactor.RetailModeInteractor
-import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl
+import com.android.systemui.retail.domain.interactor.impl.RetailModeInteractorImpl
 import dagger.Binds
 import dagger.Module
 
diff --git a/packages/SystemUI/pods/com/android/systemui/retail/data/Android.bp b/packages/SystemUI/pods/com/android/systemui/retail/data/Android.bp
new file mode 100644
index 0000000..f148a7c
--- /dev/null
+++ b/packages/SystemUI/pods/com/android/systemui/retail/data/Android.bp
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+soong_namespace {
+}
+
+package {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+java_library {
+    name: "api",
+    srcs: ["repository/*.kt"],
+    libs: [
+        "kotlinx_coroutines",
+    ],
+    visibility: [
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/dagger",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/domain",
+    ],
+}
+
+java_library {
+    name: "impl",
+    srcs: ["repository/impl/*.kt"],
+    libs: [
+        "jsr330",
+        "kotlinx_coroutines",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/util/settings:api",
+        "SystemUICommon",
+    ],
+    static_libs: [
+        "api",
+    ],
+    visibility: [
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/dagger",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/domain",
+    ],
+}
diff --git a/packages/SystemUI/pods/com/android/systemui/retail/data/repository/RetailModeRepository.kt b/packages/SystemUI/pods/com/android/systemui/retail/data/repository/RetailModeRepository.kt
new file mode 100644
index 0000000..c9eac25
--- /dev/null
+++ b/packages/SystemUI/pods/com/android/systemui/retail/data/repository/RetailModeRepository.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.retail.data.repository
+
+import kotlinx.coroutines.flow.StateFlow
+
+/** Repository to track if the device is in Retail mode */
+interface RetailModeRepository {
+    /** Flow of whether the device is currently in retail mode. */
+    val retailMode: StateFlow<Boolean>
+
+    /** Last value of whether the device is in retail mode. */
+    val inRetailMode: Boolean
+        get() = retailMode.value
+}
diff --git a/packages/SystemUI/src/com/android/systemui/retail/data/repository/RetailModeRepository.kt b/packages/SystemUI/pods/com/android/systemui/retail/data/repository/impl/RetailModeSettingsRepository.kt
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/retail/data/repository/RetailModeRepository.kt
rename to packages/SystemUI/pods/com/android/systemui/retail/data/repository/impl/RetailModeSettingsRepository.kt
index 09fd7df..8955263 100644
--- a/packages/SystemUI/src/com/android/systemui/retail/data/repository/RetailModeRepository.kt
+++ b/packages/SystemUI/pods/com/android/systemui/retail/data/repository/impl/RetailModeSettingsRepository.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.retail.data.repository
+package com.android.systemui.retail.data.repository.impl
 
 import android.database.ContentObserver
 import android.provider.Settings
@@ -22,6 +22,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.retail.data.repository.RetailModeRepository
 import com.android.systemui.util.settings.GlobalSettings
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -34,16 +35,6 @@
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
 
-/** Repository to track if the device is in Retail mode */
-interface RetailModeRepository {
-    /** Flow of whether the device is currently in retail mode. */
-    val retailMode: StateFlow<Boolean>
-
-    /** Last value of whether the device is in retail mode. */
-    val inRetailMode: Boolean
-        get() = retailMode.value
-}
-
 /**
  * Tracks [Settings.Global.DEVICE_DEMO_MODE].
  *
diff --git a/packages/SystemUI/pods/com/android/systemui/retail/domain/Android.bp b/packages/SystemUI/pods/com/android/systemui/retail/domain/Android.bp
new file mode 100644
index 0000000..787861c
--- /dev/null
+++ b/packages/SystemUI/pods/com/android/systemui/retail/domain/Android.bp
@@ -0,0 +1,46 @@
+//
+// 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.
+//
+
+soong_namespace {
+}
+
+package {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+java_library {
+    name: "api",
+    srcs: ["interactor/*.kt"],
+    visibility: [
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail",
+    ],
+}
+
+java_library {
+    name: "impl",
+    srcs: ["interactor/impl/*.kt"],
+    libs: [
+        "jsr330",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail/data:api",
+    ],
+    static_libs: [
+        "api",
+    ],
+    visibility: [
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail",
+    ],
+}
diff --git a/packages/SystemUI/src/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt b/packages/SystemUI/pods/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
similarity index 65%
copy from packages/SystemUI/src/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
copy to packages/SystemUI/pods/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
index eea452c..748e34d 100644
--- a/packages/SystemUI/src/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
+++ b/packages/SystemUI/pods/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * 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.
@@ -16,22 +16,8 @@
 
 package com.android.systemui.retail.domain.interactor
 
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.retail.data.repository.RetailModeRepository
-import javax.inject.Inject
-
 /** Interactor to determine if the device is currently in retail mode */
 interface RetailModeInteractor {
     /** Whether the device is currently in retail mode */
     val isInRetailMode: Boolean
 }
-
-@SysUISingleton
-class RetailModeInteractorImpl
-@Inject
-constructor(
-    private val repository: RetailModeRepository,
-) : RetailModeInteractor {
-    override val isInRetailMode: Boolean
-        get() = repository.inRetailMode
-}
diff --git a/packages/SystemUI/src/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt b/packages/SystemUI/pods/com/android/systemui/retail/domain/interactor/impl/RetailModeInteractorImpl.kt
similarity index 79%
rename from packages/SystemUI/src/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
rename to packages/SystemUI/pods/com/android/systemui/retail/domain/interactor/impl/RetailModeInteractorImpl.kt
index eea452c..8dbe562 100644
--- a/packages/SystemUI/src/com/android/systemui/retail/domain/interactor/RetailModeInteractor.kt
+++ b/packages/SystemUI/pods/com/android/systemui/retail/domain/interactor/impl/RetailModeInteractorImpl.kt
@@ -14,18 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.retail.domain.interactor
+package com.android.systemui.retail.domain.interactor.impl
 
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.retail.data.repository.RetailModeRepository
+import com.android.systemui.retail.domain.interactor.RetailModeInteractor
 import javax.inject.Inject
 
-/** Interactor to determine if the device is currently in retail mode */
-interface RetailModeInteractor {
-    /** Whether the device is currently in retail mode */
-    val isInRetailMode: Boolean
-}
-
 @SysUISingleton
 class RetailModeInteractorImpl
 @Inject
diff --git a/packages/SystemUI/pods/com/android/systemui/util/settings/Android.bp b/packages/SystemUI/pods/com/android/systemui/util/settings/Android.bp
new file mode 100644
index 0000000..1aa7729
--- /dev/null
+++ b/packages/SystemUI/pods/com/android/systemui/util/settings/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+soong_namespace {
+}
+
+package {
+    default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+java_library {
+    name: "api",
+    srcs: [
+        "*.java",
+        "*.kt",
+    ],
+    libs: [
+        "//frameworks/libs/systemui:tracinglib-platform",
+        "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+        "SystemUICommon",
+        "androidx.annotation_annotation",
+        "kotlinx_coroutines_android",
+        "jsr330",
+    ],
+    kotlincflags: ["-Xjvm-default=all"],
+    visibility: ["//frameworks/base/packages/SystemUI:__subpackages__"],
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettings.java b/packages/SystemUI/pods/com/android/systemui/util/settings/GlobalSettings.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettings.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/GlobalSettings.java
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java b/packages/SystemUI/pods/com/android/systemui/util/settings/GlobalSettingsImpl.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/GlobalSettingsImpl.java
index 7fcabe4..d68501f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java
+++ b/packages/SystemUI/pods/com/android/systemui/util/settings/GlobalSettingsImpl.java
@@ -23,7 +23,7 @@
 import android.net.Uri;
 import android.provider.Settings;
 
-import com.android.systemui.util.kotlin.SettingsSingleThreadBackground;
+import com.android.systemui.util.settings.SettingsSingleThreadBackground;
 
 import kotlinx.coroutines.CoroutineDispatcher;
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettings.java b/packages/SystemUI/pods/com/android/systemui/util/settings/SecureSettings.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/util/settings/SecureSettings.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SecureSettings.java
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java b/packages/SystemUI/pods/com/android/systemui/util/settings/SecureSettingsImpl.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SecureSettingsImpl.java
index c296481..211a6f4 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
+++ b/packages/SystemUI/pods/com/android/systemui/util/settings/SecureSettingsImpl.java
@@ -21,7 +21,7 @@
 import android.net.Uri;
 import android.provider.Settings;
 
-import com.android.systemui.util.kotlin.SettingsSingleThreadBackground;
+import com.android.systemui.util.settings.SettingsSingleThreadBackground;
 
 import kotlinx.coroutines.CoroutineDispatcher;
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt b/packages/SystemUI/pods/com/android/systemui/util/settings/SettingsProxy.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.kt
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SettingsProxy.kt
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxyExt.kt b/packages/SystemUI/pods/com/android/systemui/util/settings/SettingsProxyExt.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxyExt.kt
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SettingsProxyExt.kt
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/SettingsSingleThreadBackground.java b/packages/SystemUI/pods/com/android/systemui/util/settings/SettingsSingleThreadBackground.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/util/kotlin/SettingsSingleThreadBackground.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SettingsSingleThreadBackground.java
index e13981d..5632a36 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/SettingsSingleThreadBackground.java
+++ b/packages/SystemUI/pods/com/android/systemui/util/settings/SettingsSingleThreadBackground.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.util.kotlin;
+package com.android.systemui.util.settings;
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettings.java b/packages/SystemUI/pods/com/android/systemui/util/settings/SystemSettings.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/util/settings/SystemSettings.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SystemSettings.java
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java b/packages/SystemUI/pods/com/android/systemui/util/settings/SystemSettingsImpl.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
rename to packages/SystemUI/pods/com/android/systemui/util/settings/SystemSettingsImpl.java
index e670b2c..1b3f74e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
+++ b/packages/SystemUI/pods/com/android/systemui/util/settings/SystemSettingsImpl.java
@@ -21,7 +21,7 @@
 import android.net.Uri;
 import android.provider.Settings;
 
-import com.android.systemui.util.kotlin.SettingsSingleThreadBackground;
+import com.android.systemui.util.settings.SettingsSingleThreadBackground;
 
 import kotlinx.coroutines.CoroutineDispatcher;
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt b/packages/SystemUI/pods/com/android/systemui/util/settings/UserSettingsProxy.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
rename to packages/SystemUI/pods/com/android/systemui/util/settings/UserSettingsProxy.kt
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 4447dff..b7d3c92 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -100,7 +100,7 @@
 import com.android.systemui.qs.footer.dagger.FooterActionsModule;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recordissue.RecordIssueModule;
-import com.android.systemui.retail.dagger.RetailModeModule;
+import com.android.systemui.retail.RetailModeModule;
 import com.android.systemui.scene.shared.model.SceneContainerConfig;
 import com.android.systemui.scene.shared.model.SceneDataSource;
 import com.android.systemui.scene.shared.model.SceneDataSourceDelegator;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 24dba59..4d77e3e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -17,8 +17,6 @@
 package com.android.systemui.shade;
 
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
 
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -27,16 +25,13 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.os.Binder;
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.util.Log;
 import android.view.Display;
-import android.view.Gravity;
 import android.view.IWindow;
 import android.view.IWindowSession;
 import android.view.View;
@@ -271,33 +266,7 @@
         // Now that the notification shade encompasses the sliding panel and its
         // translucent backdrop, the entire thing is made TRANSLUCENT and is
         // hardware-accelerated.
-        mLp = new LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                LayoutParams.TYPE_NOTIFICATION_SHADE,
-                LayoutParams.FLAG_NOT_FOCUSABLE
-                        | LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                        | LayoutParams.FLAG_SPLIT_TOUCH
-                        | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                        | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
-                PixelFormat.TRANSLUCENT);
-        mLp.token = new Binder();
-        mLp.gravity = Gravity.TOP;
-        mLp.setFitInsetsTypes(0 /* types */);
-        mLp.setTitle("NotificationShade");
-        mLp.packageName = mContext.getPackageName();
-        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        mLp.privateFlags |= PRIVATE_FLAG_OPTIMIZE_MEASURE;
-
-        if (SceneContainerFlag.isEnabled()) {
-            // This prevents the appearance and disappearance of the software keyboard (also known
-            // as the "IME") from scrolling/panning the window to make room for the keyboard.
-            //
-            // The scene container logic does its own adjustment and animation when the IME appears
-            // or disappears.
-            mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-        }
-
+        mLp = ShadeWindowLayoutParams.INSTANCE.create(mContext);
         mWindowManager.addView(mWindowRootView, mLp);
 
         // We use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE here, however, there is special logic in
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLayoutParams.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLayoutParams.kt
new file mode 100644
index 0000000..6bb50f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLayoutParams.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.shade
+
+import android.content.Context
+import android.graphics.PixelFormat
+import android.os.Binder
+import android.view.Gravity
+import android.view.ViewGroup
+import android.view.WindowManager.LayoutParams
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+
+object ShadeWindowLayoutParams {
+    /**
+     * Creates [LayoutParams] for the shade window.
+     *
+     * This is extracted to a single place as those layout params will be used by several places:
+     * - When sysui starts, and the shade is added the first time
+     * - When the shade moves to a different window (e.g. while an external display is connected)
+     */
+    fun create(context: Context): LayoutParams {
+        return LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                LayoutParams.TYPE_NOTIFICATION_SHADE,
+                LayoutParams.FLAG_NOT_FOCUSABLE or
+                    LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING or
+                    LayoutParams.FLAG_SPLIT_TOUCH or
+                    LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
+                    LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                // Now that the notification shade encompasses the sliding panel and its
+                // translucent backdrop, the entire thing is made TRANSLUCENT and is
+                // hardware-accelerated.
+                PixelFormat.TRANSLUCENT,
+            )
+            .apply {
+                token = Binder()
+                gravity = Gravity.TOP
+                fitInsetsTypes = 0
+                title = "NotificationShade"
+                packageName = context.packageName
+                layoutInDisplayCutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+                privateFlags = privateFlags or LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE
+                if (SceneContainerFlag.isEnabled) {
+                    // This prevents the appearance and disappearance of the software keyboard (also
+                    // known as the "IME") from scrolling/panning the window to make room for the
+                    // keyboard.
+                    //
+                    // The scene container logic does its own adjustment and animation when the IME
+                    // appears or disappears.
+                    softInputMode = LayoutParams.SOFT_INPUT_ADJUST_NOTHING
+                }
+            }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt
index 3c06828..2a9b1b9 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/SysUICoroutinesModule.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Tracing
 import com.android.systemui.dagger.qualifiers.UiBackground
+import com.android.systemui.util.settings.SettingsSingleThreadBackground
 import dagger.Module
 import dagger.Provides
 import kotlinx.coroutines.CoroutineDispatcher
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b221d74..827e3ef 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -607,7 +607,8 @@
                     // ... and see if these are hosts we've been awaiting.
                     // NOTE: We are backing up and restoring only the owner.
                     // TODO: http://b/22388012
-                    if (newPackageAdded && userId == UserHandle.USER_SYSTEM) {
+                    UserHandle mainUser = mUserManager.getMainUser();
+                    if (newPackageAdded && mainUser != null && userId == mainUser.getIdentifier()) {
                         final int uid = getUidForPackage(pkgName, userId);
                         if (uid >= 0 ) {
                             resolveHostUidLocked(pkgName, uid);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cb89f28..dfddc08 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -668,6 +668,8 @@
      */
     private static final boolean ENABLE_PROC_LOCK = true;
 
+    private static final int DEFAULT_INTENT_CREATOR_UID = -1;
+
     /**
      * The lock for process management.
      *
@@ -19308,22 +19310,36 @@
         if (!preventIntentRedirect()) return;
 
         if (intent == null) return;
+
+        String targetPackage = intent.getComponent() != null
+                ? intent.getComponent().getPackageName()
+                : intent.getPackage();
+        final boolean isCreatorSameAsTarget = creatorPackage != null && creatorPackage.equals(
+                targetPackage);
+        final boolean noExtraIntentKeys =
+                intent.getExtraIntentKeys() == null || intent.getExtraIntentKeys().isEmpty();
+        final int creatorUid = noExtraIntentKeys ? DEFAULT_INTENT_CREATOR_UID : Binder.getCallingUid();
+
         intent.forEachNestedCreatorToken(extraIntent -> {
-            IntentCreatorToken creatorToken = createIntentCreatorToken(extraIntent, creatorPackage);
+            if (isCreatorSameAsTarget) {
+                FrameworkStatsLog.write(INTENT_CREATOR_TOKEN_ADDED, creatorUid, true);
+                return;
+            }
+            IntentCreatorToken creatorToken = createIntentCreatorToken(extraIntent, creatorUid,
+                    creatorPackage);
             if (creatorToken != null) {
                 extraIntent.setCreatorToken(creatorToken);
                 // TODO remove Slog.wtf once proven FrameworkStatsLog works. b/375396329
                 Slog.wtf(TAG, "A creator token is added to an intent. creatorPackage: "
                         + creatorPackage + "; intent: " + extraIntent);
-                FrameworkStatsLog.write(INTENT_CREATOR_TOKEN_ADDED,
-                        creatorToken.getCreatorUid());
+                FrameworkStatsLog.write(INTENT_CREATOR_TOKEN_ADDED, creatorUid, false);
             }
         });
     }
 
-    private IntentCreatorToken createIntentCreatorToken(Intent intent, String creatorPackage) {
+    private IntentCreatorToken createIntentCreatorToken(Intent intent, int creatorUid,
+            String creatorPackage) {
         if (IntentCreatorToken.isValid(intent)) return null;
-        int creatorUid = getCallingUid();
         IntentCreatorToken.Key key = new IntentCreatorToken.Key(creatorUid, creatorPackage, intent);
         IntentCreatorToken token;
         synchronized (sIntentCreatorTokenCache) {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 3dd5ec9..ef5296e 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -221,6 +221,7 @@
         "preload_safety",
         "printing",
         "privacy_infra_policy",
+        "psap_ai",
         "ravenwood",
         "resource_manager",
         "responsible_apis",
diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java
index c3205af..0defd27 100644
--- a/services/core/java/com/android/server/input/KeyboardBacklightController.java
+++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java
@@ -20,6 +20,7 @@
 import android.annotation.BinderThread;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.hardware.input.IKeyboardBacklightListener;
 import android.hardware.input.IKeyboardBacklightState;
@@ -81,9 +82,6 @@
     private static final String UEVENT_KEYBOARD_BACKLIGHT_TAG = "kbd_backlight";
 
     @VisibleForTesting
-    static final long USER_INACTIVITY_THRESHOLD_MILLIS = Duration.ofSeconds(30).toMillis();
-
-    @VisibleForTesting
     static final int[] DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL =
             new int[DEFAULT_NUM_BRIGHTNESS_CHANGE_STEPS + 1];
 
@@ -112,6 +110,7 @@
     private AmbientKeyboardBacklightController.AmbientKeyboardBacklightListener mAmbientListener;
 
     private int mAmbientBacklightValue = 0;
+    private final int mUserInactivityThresholdMs;
 
     static {
         // Fixed brightness levels to avoid issues when converting back and forth from the
@@ -139,6 +138,9 @@
         mAnimatorFactory = animatorFactory;
         mAmbientController = new AmbientKeyboardBacklightController(context, looper);
         mUEventManager = uEventManager;
+        Resources res = mContext.getResources();
+        mUserInactivityThresholdMs = res.getInteger(
+                com.android.internal.R.integer.config_keyboardBacklightTimeoutMs);
     }
 
     @Override
@@ -300,7 +302,7 @@
         }
         mHandler.removeMessages(MSG_NOTIFY_USER_INACTIVITY);
         mHandler.sendEmptyMessageAtTime(MSG_NOTIFY_USER_INACTIVITY,
-                SystemClock.uptimeMillis() + USER_INACTIVITY_THRESHOLD_MILLIS);
+                SystemClock.uptimeMillis() + mUserInactivityThresholdMs);
     }
 
     private void handleUserInactivity() {
diff --git a/services/core/java/com/android/server/location/contexthub/OWNERS b/services/core/java/com/android/server/location/contexthub/OWNERS
index c62e323..6536ca0 100644
--- a/services/core/java/com/android/server/location/contexthub/OWNERS
+++ b/services/core/java/com/android/server/location/contexthub/OWNERS
@@ -1,3 +1,4 @@
 bduddie@google.com
+arthuri@google.com
 matthewsedam@google.com
 stange@google.com
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java
index 84413d5..c5c8a5e 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -96,7 +96,35 @@
 
         @Override
         public PictureProfile getPictureProfile(int type, String name) {
-            return null;
+            SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
+
+            String selection = PictureQuality.PARAMETER_TYPE + " = ? AND "
+                    + PictureQuality.PARAMETER_NAME + " = ?";
+            String[] selectionArguments = {Integer.toString(type), name};
+
+            try (
+                    Cursor cursor = db.query(
+                            mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+                            getAllPictureProfileColumns(),
+                            selection,
+                            selectionArguments,
+                            /*groupBy=*/ null,
+                            /*having=*/ null,
+                            /*orderBy=*/ null)
+            ) {
+                int count = cursor.getCount();
+                if (count == 0) {
+                    return null;
+                }
+                if (count > 1) {
+                    Log.wtf(TAG, String.format(Locale.US, "%d entries found for type=%d and name=%s"
+                                    + " in %s. Should only ever be 0 or 1.", count, type, name,
+                                    mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+                    return null;
+                }
+                cursor.moveToFirst();
+                return getPictureProfileFromCursor(cursor);
+            }
         }
 
         private String bundleToJson(Bundle bundle) {
@@ -145,17 +173,79 @@
             return bundle;
         }
 
+        private String[] getAllPictureProfileColumns() {
+            return new String[]{
+                    PictureQuality.PARAMETER_ID,
+                    PictureQuality.PARAMETER_TYPE,
+                    PictureQuality.PARAMETER_NAME,
+                    PictureQuality.PARAMETER_INPUT_ID,
+                    PictureQuality.PARAMETER_PACKAGE,
+                    mMediaQualityDbHelper.SETTINGS
+            };
+        }
+
+        private PictureProfile getPictureProfileFromCursor(Cursor cursor) {
+            String returnId = cursor.getString(
+                    cursor.getColumnIndexOrThrow(PictureQuality.PARAMETER_ID));
+            int type = cursor.getInt(
+                    cursor.getColumnIndexOrThrow(PictureQuality.PARAMETER_TYPE));
+            String name = cursor.getString(
+                    cursor.getColumnIndexOrThrow(PictureQuality.PARAMETER_NAME));
+            String inputId = cursor.getString(
+                    cursor.getColumnIndexOrThrow(PictureQuality.PARAMETER_INPUT_ID));
+            String packageName = cursor.getString(
+                    cursor.getColumnIndexOrThrow(PictureQuality.PARAMETER_PACKAGE));
+            String settings = cursor.getString(
+                    cursor.getColumnIndexOrThrow(mMediaQualityDbHelper.SETTINGS));
+            return new PictureProfile(returnId, type, name, inputId,
+                    packageName, jsonToBundle(settings));
+        }
+
         @Override
         public List<PictureProfile> getPictureProfilesByPackage(String packageName) {
-            return new ArrayList<>();
+            String selection = PictureQuality.PARAMETER_PACKAGE + " = ?";
+            String[] selectionArguments = {packageName};
+            return getPictureProfilesBasedOnConditions(getAllPictureProfileColumns(), selection,
+                    selectionArguments);
         }
+
         @Override
         public List<PictureProfile> getAvailablePictureProfiles() {
             return new ArrayList<>();
         }
+
         @Override
         public List<String> getPictureProfilePackageNames() {
-            return new ArrayList<>();
+            String [] column = {PictureQuality.PARAMETER_NAME};
+            List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
+                    null, null);
+            List<String> packageNames = new ArrayList<>();
+            for (PictureProfile pictureProfile: pictureProfiles) {
+                packageNames.add(pictureProfile.getName());
+            }
+            return packageNames;
+        }
+
+        private List<PictureProfile> getPictureProfilesBasedOnConditions(String[] columns,
+                String selection, String[] selectionArguments) {
+            SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
+
+            try (
+                    Cursor cursor = db.query(
+                            mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+                            columns,
+                            selection,
+                            selectionArguments,
+                            /*groupBy=*/ null,
+                            /*having=*/ null,
+                            /*orderBy=*/ null)
+            ) {
+                List<PictureProfile> pictureProfiles = new ArrayList<>();
+                while (cursor.moveToNext()) {
+                    pictureProfiles.add(getPictureProfileFromCursor(cursor));
+                }
+                return pictureProfiles;
+            }
         }
 
         @Override
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index d5d4070..52ddb80 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -22,8 +22,11 @@
 import android.app.backup.BackupRestoreEventLogger;
 import android.service.notification.DeviceEffectsApplier;
 
+import com.android.internal.annotations.Keep;
+
 import java.util.Set;
 
+@Keep
 public interface NotificationManagerInternal {
     NotificationChannel getNotificationChannel(String pkg, int uid, String channelId);
     NotificationChannelGroup getNotificationChannelGroup(String pkg, int uid, String channelId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4d0c7ec..207764b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -211,6 +211,7 @@
 import android.app.RemoteServiceException.BadUserInitiatedJobNotificationException;
 import android.app.StatsManager;
 import android.app.UriGrantsManager;
+import android.app.ZenBypassingApp;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.backup.BackupManager;
 import android.app.backup.BackupRestoreEventLogger;
@@ -238,7 +239,6 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.LauncherApps;
 import android.content.pm.ModuleInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
@@ -3089,7 +3089,7 @@
             migrateDefaultNAS();
             maybeShowInitialReviewPermissionsNotification();
 
-            if (android.app.Flags.modesApi()) {
+            if (android.app.Flags.modesApi() && !mZenModeHelper.hasDeviceEffectsApplier()) {
                 // Cannot be done earlier, as some services aren't ready until this point.
                 mZenModeHelper.setDeviceEffectsApplier(
                         new DefaultDeviceEffectsApplier(getContext()));
@@ -4043,7 +4043,7 @@
                         "canNotifyAsPackage for uid " + uid);
             }
 
-            return areNotificationsEnabledForPackageInt(pkg, uid);
+            return areNotificationsEnabledForPackageInt(uid);
         }
 
         /**
@@ -4864,30 +4864,20 @@
         }
 
         @Override
-        public List<String> getPackagesBypassingDnd(int userId,
-                boolean includeConversationChannels) {
+        public ParceledListSlice<ZenBypassingApp> getPackagesBypassingDnd(int userId)
+                throws RemoteException {
             checkCallerIsSystem();
 
-            final ArraySet<String> packageNames = new ArraySet<>();
-
-            List<PackageInfo> pkgs = mPackageManagerClient.getInstalledPackagesAsUser(0, userId);
-            for (PackageInfo pi : pkgs) {
-                String pkg = pi.packageName;
-                // If any NotificationChannel for this package is bypassing, the
-                // package is considered bypassing.
-                for (NotificationChannel channel : getNotificationChannelsBypassingDnd(pkg,
-                        pi.applicationInfo.uid).getList()) {
-                    // Skips non-demoted conversation channels.
-                    if (!includeConversationChannels
-                            && !TextUtils.isEmpty(channel.getConversationId())
-                            && !channel.isDemoted()) {
-                        continue;
-                    }
-                    packageNames.add(pkg);
+            UserHandle user = UserHandle.of(userId);
+            ArrayList<ZenBypassingApp> bypassing =
+                    mPreferencesHelper.getPackagesBypassingDnd(userId);
+            for (int i = bypassing.size() - 1; i >= 0; i--) {
+                String pkg = bypassing.get(i).getPkg();
+                if (!areNotificationsEnabledForPackage(pkg, getUidForPackageAndUser(pkg, user))) {
+                    bypassing.remove(i);
                 }
             }
-
-            return new ArrayList<String>(packageNames);
+            return new ParceledListSlice<>(bypassing);
         }
 
         @Override
@@ -7763,7 +7753,7 @@
 
         @Override
         public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
-            return areNotificationsEnabledForPackageInt(pkg, uid);
+            return areNotificationsEnabledForPackageInt(uid);
         }
 
         @Override
@@ -8742,7 +8732,7 @@
         }
 
         // blocked apps
-        boolean isBlocked = !areNotificationsEnabledForPackageInt(pkg, uid);
+        boolean isBlocked = !areNotificationsEnabledForPackageInt(uid);
         synchronized (mNotificationLock) {
             isBlocked |= isRecordBlockedLocked(r);
         }
@@ -8792,7 +8782,7 @@
         }
     }
 
-    private boolean areNotificationsEnabledForPackageInt(String pkg, int uid) {
+    private boolean areNotificationsEnabledForPackageInt(int uid) {
         return mPermissionHelper.hasPermission(uid);
     }
 
@@ -9328,7 +9318,7 @@
          * notifying all listeners to a background thread; false otherwise.
          */
         private boolean postNotification() {
-            boolean appBanned = !areNotificationsEnabledForPackageInt(pkg, uid);
+            boolean appBanned = !areNotificationsEnabledForPackageInt(uid);
             boolean isCallNotification = isCallNotification(pkg, uid);
             boolean posted = false;
             synchronized (NotificationManagerService.this.mNotificationLock) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 9f0b4b0..e6f784c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -57,6 +57,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
+import android.app.ZenBypassingApp;
 import android.content.AttributionSource;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -1950,6 +1951,35 @@
     }
 
     /**
+     * Gets all apps that can bypass DND, and a boolean indicating whether all (true) or some
+     * (false) of its notification channels can currently bypass.
+     */
+    public @NonNull ArrayList<ZenBypassingApp> getPackagesBypassingDnd(@UserIdInt int userId) {
+        ArrayList<ZenBypassingApp> bypassing = new ArrayList<>();
+        synchronized (mLock) {
+            for (PackagePreferences p : mPackagePreferences.values()) {
+                if (p.userId != userId) {
+                    continue;
+                }
+                int totalChannelCount = p.channels.size();
+                int bypassingCount = 0;
+                if  (totalChannelCount == 0) {
+                    continue;
+                }
+                for (NotificationChannel channel : p.channels.values()) {
+                    if (channelIsLiveLocked(p, channel) && channel.canBypassDnd()) {
+                        bypassingCount++;
+                    }
+                }
+                if (bypassingCount > 0) {
+                    bypassing.add(new ZenBypassingApp(p.pkg, totalChannelCount == bypassingCount));
+                }
+            }
+        }
+        return bypassing;
+    }
+
+    /**
      * True for pre-O apps that only have the default channel, or pre O apps that have no
      * channels yet. This method will create the default channel for pre-O apps that don't have it.
      * Should never be true for O+ targeting apps, but that's enforced on boot/when an app
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index cfeacdf..ca4f83f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -24,6 +24,8 @@
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN;
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
 import static android.service.notification.Condition.SOURCE_UNKNOWN;
 import static android.service.notification.Condition.SOURCE_USER_ACTION;
 import static android.service.notification.Condition.STATE_FALSE;
@@ -44,8 +46,6 @@
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
 import static com.android.internal.util.Preconditions.checkArgument;
-import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
-import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
 
 import static java.util.Objects.requireNonNull;
 
@@ -303,6 +303,15 @@
     }
 
     /**
+     * @return whether a {@link DeviceEffectsApplier} has already been set or not
+     */
+    boolean hasDeviceEffectsApplier() {
+        synchronized (mConfigLock) {
+            return mDeviceEffectsApplier != null;
+        }
+    }
+
+    /**
      * Set the {@link DeviceEffectsApplier} used to apply the consolidated effects.
      *
      * <p>Previously calculated effects (as loaded from the user's {@link ZenModeConfig}) will be
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index 76ea0b9..4690e02 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -880,7 +880,8 @@
                 PackageInstaller.STATUS_PENDING_USER_ACTION);
         broadcastIntent.putExtra(Intent.EXTRA_INTENT, dialogIntent);
         broadcastIntent.putExtra(Intent.EXTRA_USER, user);
-        sendIntent(statusReceiver, packageName, /* message= */ "", broadcastIntent);
+        mPm.mHandler.post(
+            () -> sendIntent(statusReceiver, packageName, /* message= */ "", broadcastIntent));
     }
 
     private void verifyUninstallPermissions() {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 5518bfa..1052c94 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1022,7 +1022,7 @@
                 // Close.
                 file.finishWrite(outs);
             } catch (IOException e) {
-                Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
+                Slog.w(TAG, "Failed to write to file " + file.getBaseFile(), e);
                 file.failWrite(outs);
             }
         }
@@ -1055,7 +1055,7 @@
                     final String tag = parser.getName();
                     if (depth == 1) {
                         if (!TAG_ROOT.equals(tag)) {
-                            Slog.e(TAG, "Invalid root tag: " + tag);
+                            Slog.v(TAG, "Invalid root tag: " + tag);
                             return;
                         }
                         continue;
@@ -1066,7 +1066,7 @@
                             mRawLastResetTime.set(parseLongAttribute(parser, ATTR_VALUE));
                             break;
                         default:
-                            Slog.e(TAG, "Invalid tag: " + tag);
+                            Slog.v(TAG, "Invalid tag: " + tag);
                             break;
                     }
                 }
@@ -1113,7 +1113,7 @@
                 // Remove all dangling bitmap files.
                 cleanupDanglingBitmapDirectoriesLocked(userId);
             } catch (XmlPullParserException | IOException e) {
-                Slog.e(TAG, "Failed to write to file " + file, e);
+                Slog.w(TAG, "Failed to write to file " + file, e);
                 file.failWrite(os);
             }
         }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d221e8c..8ad8786 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9004,26 +9004,13 @@
         if (!mHasFeature) {
             return;
         }
-
-        CallerIdentity caller;
-        if (Flags.setAutoTimeEnabledCoexistence()) {
-            caller = getCallerIdentity(who, callerPackageName);
-        } else {
-            caller = getCallerIdentity(who);
-        }
-
-        if (Flags.setAutoTimeEnabledCoexistence()) {
-            // The effect of this policy is device-wide.
-            enforcePermission(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
-        } else {
-            Objects.requireNonNull(who, "ComponentName is null");
-            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
-                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
-                    caller));
-        }
+        CallerIdentity caller = getCallerIdentity(who);
+        Objects.requireNonNull(who, "ComponentName is null");
+        Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
+                || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
+                caller));
         mInjector.binderWithCleanCallingIdentity(() ->
                 mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, enabled ? 1 : 0));
-
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_AUTO_TIME)
                 .setAdmin(caller.getPackageName())
@@ -9039,26 +9026,77 @@
         if (!mHasFeature) {
             return false;
         }
-        CallerIdentity caller;
-        if (Flags.setAutoTimeEnabledCoexistence()) {
-            caller = getCallerIdentity(who, callerPackageName);
-        } else {
-            caller = getCallerIdentity(who);
-        }
+        CallerIdentity caller = getCallerIdentity(who);
 
-        if (Flags.setAutoTimeEnabledCoexistence()) {
-            enforceCanQuery(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
-        } else {
-            Objects.requireNonNull(who, "ComponentName is null");
-            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
-                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
-                    caller));
-        }
+        Objects.requireNonNull(who, "ComponentName is null");
+        Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
+                || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
 
         return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
     }
 
     /**
+     * Set whether auto time is enabled on the device.
+     */
+    @Override
+    public void setAutoTimePolicy(String callerPackageName, int policy) {
+        if (!mHasFeature) {
+            return;
+        }
+
+        final Set<Integer> allowedValues =
+                Set.of(
+                        DevicePolicyManager.AUTO_TIME_ENABLED,
+                        DevicePolicyManager.AUTO_TIME_DISABLED,
+                        DevicePolicyManager.AUTO_TIME_NOT_CONTROLLED_BY_POLICY);
+        Preconditions.checkArgument(
+                allowedValues.contains(policy), "Provided mode is not one of the allowed values.");
+
+        CallerIdentity caller = getCallerIdentity(callerPackageName);
+        // The effect of this policy is device-wide.
+        EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                /* who */ null,
+                SET_TIME,
+                caller.getPackageName(),
+                UserHandle.USER_ALL
+        );
+        if (policy == DevicePolicyManager.AUTO_TIME_NOT_CONTROLLED_BY_POLICY) {
+            mDevicePolicyEngine.removeGlobalPolicy(PolicyDefinition.AUTO_TIME, enforcingAdmin);
+        } else {
+            mDevicePolicyEngine.setGlobalPolicy(
+                    PolicyDefinition.AUTO_TIME,
+                    enforcingAdmin,
+                    new IntegerPolicyValue(policy));
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.SET_AUTO_TIME)
+                    .setAdmin(caller.getPackageName())
+                    .setBoolean(policy == DevicePolicyManager.AUTO_TIME_ENABLED)
+                    .write();
+        }
+    }
+
+    /**
+     * Returns whether auto time is used on the device or not.
+     */
+    @Override
+    public int getAutoTimePolicy(String callerPackageName) {
+        if (!mHasFeature) {
+            return DevicePolicyManager.AUTO_TIME_NOT_CONTROLLED_BY_POLICY;
+        }
+        CallerIdentity caller = getCallerIdentity(callerPackageName);
+        // The effect of this policy is device-wide.
+        EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                /* who */ null,
+                SET_TIME,
+                caller.getPackageName(),
+                UserHandle.USER_ALL
+        );
+        Integer state = mDevicePolicyEngine.getGlobalPolicySetByAdmin(
+                PolicyDefinition.AUTO_TIME, enforcingAdmin);
+        return state != null ? state : DevicePolicyManager.AUTO_TIME_NOT_CONTROLLED_BY_POLICY;
+    }
+
+    /**
      * Set whether auto time zone is enabled on the device.
      */
     @Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index a5aeaac..24b16b7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -349,6 +349,16 @@
                     PolicyEnforcerCallbacks::setMtePolicy,
                     new IntegerPolicySerializer());
 
+    static PolicyDefinition<Integer> AUTO_TIME = new PolicyDefinition<>(
+            new NoArgsPolicyKey(DevicePolicyIdentifiers.AUTO_TIME_POLICY),
+            new TopPriority<>(List.of(
+                    EnforcingAdmin.getRoleAuthorityOf(SYSTEM_SUPERVISION_ROLE),
+                    EnforcingAdmin.getRoleAuthorityOf(DEVICE_LOCK_CONTROLLER_ROLE),
+                    EnforcingAdmin.DPC_AUTHORITY)),
+            POLICY_FLAG_GLOBAL_ONLY_POLICY,
+            PolicyEnforcerCallbacks::setAutoTimePolicy,
+            new IntegerPolicySerializer());
+
     private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>();
     private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>();
 
@@ -397,6 +407,7 @@
                 PACKAGES_SUSPENDED);
         POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.MEMORY_TAGGING_POLICY,
                 MEMORY_TAGGING);
+        POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.AUTO_TIME_POLICY, AUTO_TIME);
 
         // User Restriction Policies
         USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
index 40d8dae..8f80004 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
@@ -212,6 +212,25 @@
         return AndroidFuture.completedFuture(true);
     }
 
+    public static CompletableFuture<Boolean> setAutoTimePolicy(
+            Integer policy, Context context, Integer userId, PolicyKey policyKey) {
+        if (!Flags.setAutoTimeEnabledCoexistence()) {
+            Slogf.w(LOG_TAG, "Trying to enforce setAutoTimePolicy while flag is off.");
+            return AndroidFuture.completedFuture(true);
+        }
+        return Binder.withCleanCallingIdentity(() -> {
+            Objects.requireNonNull(context);
+            if (policy != null
+                    && policy == DevicePolicyManager.AUTO_TIME_NOT_CONTROLLED_BY_POLICY) {
+                return AndroidFuture.completedFuture(false);
+            }
+            int enabled = policy != null && policy == DevicePolicyManager.AUTO_TIME_ENABLED ? 1 : 0;
+            return AndroidFuture.completedFuture(
+                    Settings.Global.putInt(
+                            context.getContentResolver(), Settings.Global.AUTO_TIME,  enabled));
+        });
+    }
+
     private static class BlockingCallback {
         private final CountDownLatch mLatch = new CountDownLatch(1);
         private final AtomicReference<Boolean> mValue = new AtomicReference<>();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 19b0343..d0bf02d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2761,8 +2761,9 @@
             mSystemServiceManager.startService(WEAR_MODE_SERVICE_CLASS);
             t.traceEnd();
 
-            boolean enableWristOrientationService = SystemProperties.getBoolean(
-                    "config.enable_wristorientation", false);
+            boolean enableWristOrientationService =
+                    !android.server.Flags.migrateWristOrientation()
+                    && SystemProperties.getBoolean("config.enable_wristorientation", false);
             if (enableWristOrientationService) {
                 t.traceBegin("StartWristOrientationService");
                 mSystemServiceManager.startService(WRIST_ORIENTATION_SERVICE_CLASS);
diff --git a/services/java/com/android/server/flags.aconfig b/services/java/com/android/server/flags.aconfig
index e2ac22d..4412968 100644
--- a/services/java/com/android/server/flags.aconfig
+++ b/services/java/com/android/server/flags.aconfig
@@ -39,6 +39,14 @@
 }
 
 flag {
+     name: "migrate_wrist_orientation"
+     namespace: "wear_frameworks"
+     description: "Migrate wrist orientation service functionality to wear settings service"
+     bug: "352725980"
+     is_fixed_read_only: true
+}
+
+flag {
     name: "allow_network_time_update_service"
     namespace: "wear_systems"
     description: "Allow NetworkTimeUpdateService on Wear"
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index eae587b..704c1b8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -210,6 +210,7 @@
 import android.app.RemoteInput;
 import android.app.RemoteInputHistoryItem;
 import android.app.StatsManager;
+import android.app.ZenBypassingApp;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.backup.BackupRestoreEventLogger;
 import android.app.job.JobScheduler;
@@ -360,6 +361,9 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
@@ -374,9 +378,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.function.Consumer;
 
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
-
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4.class)
 @RunWithLooper
@@ -489,7 +490,8 @@
     private final NotificationChannel mParentChannel =
             new NotificationChannel(PARENT_CHANNEL_ID, "parentName", IMPORTANCE_DEFAULT);
     private final NotificationChannel mConversationChannel =
-            new NotificationChannel(CONVERSATION_CHANNEL_ID, "conversationName", IMPORTANCE_DEFAULT);
+            new NotificationChannel(
+                    CONVERSATION_CHANNEL_ID, "conversationName", IMPORTANCE_DEFAULT);
 
     private static final String PARENT_CHANNEL_ID = "parentChannelId";
     private static final String CONVERSATION_CHANNEL_ID = "conversationChannelId";
@@ -4296,8 +4298,13 @@
                     new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
 
         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
-        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "testTvExtenderChannelOverride_onTv", 0,
-                generateNotificationRecord(null, tv).getNotification(), mUserId);
+        mBinderService.enqueueNotificationWithTag(
+                mPkg,
+                mPkg,
+                "testTvExtenderChannelOverride_onTv",
+                0,
+                generateNotificationRecord(null, tv).getNotification(),
+                mUserId);
         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
                 anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
     }
@@ -4311,8 +4318,13 @@
                 mTestNotificationChannel);
 
         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
-        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "testTvExtenderChannelOverride_notOnTv",
-                0, generateNotificationRecord(null, tv).getNotification(), mUserId);
+        mBinderService.enqueueNotificationWithTag(
+                mPkg,
+                mPkg,
+                "testTvExtenderChannelOverride_notOnTv",
+                0,
+                generateNotificationRecord(null, tv).getNotification(),
+                mUserId);
         verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
                 anyBoolean(), anyBoolean());
@@ -7745,9 +7757,21 @@
                 .setContentTitle("foo")
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
                 .setStyle(new Notification.MessagingStyle("").addMessage(message2));
-        NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(mPkg,
-                mPkg, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
-                c);
+        NotificationRecord recordB =
+                new NotificationRecord(
+                        mContext,
+                        new StatusBarNotification(
+                                mPkg,
+                                mPkg,
+                                0,
+                                "tag",
+                                mUid,
+                                0,
+                                nbB.build(),
+                                UserHandle.getUserHandleForUid(mUid),
+                                null,
+                                0),
+                        c);
 
         // Update means we drop access to first
         reset(mUgmInternal);
@@ -13174,6 +13198,37 @@
     }
 
     @Test
+    public void getPackagesBypassingDnd_blocked()
+            throws RemoteException, PackageManager.NameNotFoundException {
+
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel2 = new NotificationChannel("id3", "name3",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel3 = new NotificationChannel("id4", "name3",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel2.setBypassDnd(true);
+        channel3.setBypassDnd(false);
+        // has DND access, so can set bypassDnd attribute
+        mService.mPreferencesHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true,
+                /*has DND access*/ true, UID_N_MR1, false);
+        mService.mPreferencesHelper.createNotificationChannel(PKG_P, UID_P, channel2, true, true,
+                UID_P, false);
+        mService.mPreferencesHelper.createNotificationChannel(PKG_P, UID_P, channel3, true, true,
+                UID_P, false);
+
+        when(mPackageManager.getPackageUid(eq(PKG_P), anyLong(), anyInt())).thenReturn(UID_P);
+        when(mPackageManager.getPackageUid(eq(PKG_N_MR1), anyLong(), anyInt()))
+                .thenReturn(UID_N_MR1);
+        when(mPermissionHelper.hasPermission(UID_N_MR1)).thenReturn(false);
+        when(mPermissionHelper.hasPermission(UID_P)).thenReturn(true);
+
+        assertThat(mBinderService.getPackagesBypassingDnd(UserHandle.getUserId(UID_P)).getList())
+                .containsExactly(new ZenBypassingApp(PKG_P, false));
+    }
+
+    @Test
     public void testGetNotificationChannelsBypassingDnd_blocked() throws RemoteException {
         mService.setPreferencesHelper(mPreferencesHelper);
 
@@ -13187,125 +13242,11 @@
     @Test
     public void testGetPackagesBypassingDnd_empty() throws RemoteException {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> result = mBinderService.getPackagesBypassingDnd(mUserId, true);
+        List<String> result = mBinderService.getPackagesBypassingDnd(mUserId).getList();
         assertThat(result).isEmpty();
     }
 
     @Test
-    public void testGetPackagesBypassingDnd_excludeConversationChannels() throws RemoteException {
-        mService.setPreferencesHelper(mPreferencesHelper);
-
-        // Set packages
-        PackageInfo pkg0 = new PackageInfo();
-        pkg0.packageName = "pkg0";
-        pkg0.applicationInfo = new ApplicationInfo();
-        pkg0.applicationInfo.uid = mUid;
-        PackageInfo pkg1 = new PackageInfo();
-        pkg1.packageName = "pkg1";
-        pkg1.applicationInfo = new ApplicationInfo();
-        pkg1.applicationInfo.uid = mUid;
-        PackageInfo pkg2 = new PackageInfo();
-        pkg2.packageName = "pkg2";
-        pkg2.applicationInfo = new ApplicationInfo();
-        pkg2.applicationInfo.uid = mUid;
-
-        when(mPackageManagerClient.getInstalledPackagesAsUser(0, mUserId))
-                .thenReturn(List.of(pkg0, pkg1, pkg2));
-
-        // Conversation channels
-        NotificationChannel nc0 = new NotificationChannel("id0", "id0",
-                NotificationManager.IMPORTANCE_HIGH);
-        nc0.setConversationId("parentChannel", "conversationId");
-
-        // Demoted conversation channel
-        NotificationChannel nc1 = new NotificationChannel("id1", "id1",
-                NotificationManager.IMPORTANCE_HIGH);
-        nc1.setConversationId("parentChannel", "conversationId");
-        nc1.setDemoted(true);
-
-        // Non-conversation channels
-        NotificationChannel nc2 = new NotificationChannel("id2", "id2",
-                NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel nc3 = new NotificationChannel("id3", "id3",
-                NotificationManager.IMPORTANCE_HIGH);
-
-        ParceledListSlice<NotificationChannel> pls0 =
-                new ParceledListSlice(ImmutableList.of(nc0));
-        ParceledListSlice<NotificationChannel> pls1 =
-                new ParceledListSlice(ImmutableList.of(nc1));
-        ParceledListSlice<NotificationChannel> pls2 =
-                new ParceledListSlice(ImmutableList.of(nc2, nc3));
-
-        when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg0", mUid))
-                .thenReturn(pls0);
-        when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg1", mUid))
-                .thenReturn(pls1);
-        when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg2", mUid))
-                .thenReturn(pls2);
-
-        List<String> result = mBinderService.getPackagesBypassingDnd(mUserId, false);
-
-        assertThat(result).containsExactly("pkg1", "pkg2");
-    }
-
-    @Test
-    public void testGetPackagesBypassingDnd_includeConversationChannels() throws RemoteException {
-        mService.setPreferencesHelper(mPreferencesHelper);
-
-        // Set packages
-        PackageInfo pkg0 = new PackageInfo();
-        pkg0.packageName = "pkg0";
-        pkg0.applicationInfo = new ApplicationInfo();
-        pkg0.applicationInfo.uid = mUid;
-        PackageInfo pkg1 = new PackageInfo();
-        pkg1.packageName = "pkg1";
-        pkg1.applicationInfo = new ApplicationInfo();
-        pkg1.applicationInfo.uid = mUid;
-        PackageInfo pkg2 = new PackageInfo();
-        pkg2.packageName = "pkg2";
-        pkg2.applicationInfo = new ApplicationInfo();
-        pkg2.applicationInfo.uid = mUid;
-
-        when(mPackageManagerClient.getInstalledPackagesAsUser(0, mUserId))
-                .thenReturn(List.of(pkg0, pkg1, pkg2));
-
-        // Conversation channels
-        NotificationChannel nc0 = new NotificationChannel("id0", "id0",
-                NotificationManager.IMPORTANCE_HIGH);
-        nc0.setConversationId("parentChannel", "conversationId");
-
-        // Demoted conversation channel
-        NotificationChannel nc1 = new NotificationChannel("id1", "id1",
-                NotificationManager.IMPORTANCE_HIGH);
-        nc1.setConversationId("parentChannel", "conversationId");
-        nc1.setDemoted(true);
-
-        // Non-conversation channels
-        NotificationChannel nc2 = new NotificationChannel("id2", "id2",
-                NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel nc3 = new NotificationChannel("id3", "id3",
-                NotificationManager.IMPORTANCE_HIGH);
-
-        ParceledListSlice<NotificationChannel> pls0 =
-                new ParceledListSlice(ImmutableList.of(nc0));
-        ParceledListSlice<NotificationChannel> pls1 =
-                new ParceledListSlice(ImmutableList.of(nc1));
-        ParceledListSlice<NotificationChannel> pls2 =
-                new ParceledListSlice(ImmutableList.of(nc2, nc3));
-
-        when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg0", mUid))
-                .thenReturn(pls0);
-        when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg1", mUid))
-                .thenReturn(pls1);
-        when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg2", mUid))
-                .thenReturn(pls2);
-
-        List<String> result = mBinderService.getPackagesBypassingDnd(mUserId, true);
-
-        assertThat(result).containsExactly("pkg0", "pkg1", "pkg2");
-    }
-
-    @Test
     public void testMatchesCallFilter_noPermissionShouldThrow() throws Exception {
         // set the testable NMS to not system uid/appid
         mService.isSystemUid = false;
@@ -15482,8 +15423,13 @@
         for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
             StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
                     i, null, false).getSbn();
-            mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "testCannotPostNonUijWhenOverLimit",
-                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
+            mBinderService.enqueueNotificationWithTag(
+                    mPkg,
+                    mPkg,
+                    "testCannotPostNonUijWhenOverLimit",
+                    sbn.getId(),
+                    sbn.getNotification(),
+                    sbn.getUserId());
             waitForIdle();
         }
 
@@ -16213,6 +16159,8 @@
         initNMS(SystemService.PHASE_SYSTEM_SERVICES_READY);
 
         mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class));
+
+        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
         // No exception!
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index e1b478c..dda060d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -108,6 +108,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
+import android.app.ZenBypassingApp;
 import android.content.AttributionSource;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -2620,6 +2621,72 @@
     }
 
     @Test
+    public void getPackagesBypassingDnd_noChannelsBypassing() throws Exception {
+        assertThat(mHelper.getPackagesBypassingDnd(UserHandle.getUserId(UID_N_MR1))).isEmpty();
+    }
+
+    @Test
+    public void getPackagesBypassingDnd_oneChannelBypassing_deleted() {
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel1.setDeleted(true);
+        // has DND access, so can set bypassDnd attribute
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true,
+                /*has DND access*/ true, UID_N_MR1, false);
+
+        assertThat(mHelper.getPackagesBypassingDnd(UserHandle.getUserId(UID_N_MR1))).isEmpty();
+    }
+
+    @Test
+    public void getPackagesBypassingDnd_oneChannelBypassing_groupBlocked() {
+        int uid = UID_N_MR1;
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, uid, ncg,  /* fromTargetApp */ true,
+                uid, false);
+        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel1, true, /*has DND access*/ true,
+                uid, false);
+        ncg.setBlocked(true);
+
+        assertThat(mHelper.getPackagesBypassingDnd(UserHandle.getUserId(uid))).isEmpty();
+    }
+
+    @Test
+    public void getPackagesBypassingDnd_multipleApps() {
+        List<ZenBypassingApp> expected = ImmutableList.of(
+                new ZenBypassingApp(PKG_O, true), new ZenBypassingApp(PKG_P, false));
+
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel2 = new NotificationChannel("id2", "name2",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel3 = new NotificationChannel("id3", "name3",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel4 = new NotificationChannel("id4", "name3",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(false);
+        channel2.setBypassDnd(true);
+        channel3.setBypassDnd(true);
+        channel4.setBypassDnd(false);
+        // has DND access, so can set bypassDnd attribute
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true,
+                /*has DND access*/ true, UID_N_MR1, false);
+        mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, true,
+                UID_O, false);
+        mHelper.createNotificationChannel(PKG_P, UID_P, channel3, true, true,
+                UID_P, false);
+        mHelper.createNotificationChannel(PKG_P, UID_P, channel4, true, true,
+                UID_P, false);
+
+        assertThat(mHelper.getPackagesBypassingDnd(UserHandle.getUserId(UID_O)))
+                .containsExactlyElementsIn(expected);
+    }
+
+    @Test
     public void testCreateAndDeleteCanChannelsBypassDnd_localSettings() {
         int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1;
         when(mPermissionHelper.hasPermission(uid)).thenReturn(true);
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 4b94e10..020670d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -49,6 +49,8 @@
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
 import static android.app.NotificationManager.Policy.STATE_PRIORITY_CHANNELS_BLOCKED;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Process.SYSTEM_UID;
 import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
@@ -84,8 +86,6 @@
 import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
 import static com.android.os.dnd.DNDProtoEnums.STATE_ALLOW;
 import static com.android.os.dnd.DNDProtoEnums.STATE_DISALLOW;
-import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
-import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
 import static com.android.server.notification.ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL;
 import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
 
@@ -102,6 +102,7 @@
 
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -200,6 +201,9 @@
 import org.mockito.MockitoAnnotations;
 import org.xmlpull.v1.XmlPullParserException;
 
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
@@ -219,9 +223,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
-
 @SmallTest
 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
 @RunWith(ParameterizedAndroidJunit4.class)
@@ -5348,6 +5349,22 @@
         mTestableLooper.processAllMessages();
 
         verify(mDeviceEffectsApplier).apply(eq(effects), eq(ORIGIN_APP));
+        assertTrue(mZenModeHelper.hasDeviceEffectsApplier());
+    }
+
+    @Test
+    public void testHasDeviceEffectsApplier_returnsFalseIfNotSet() {
+        assertFalse(mZenModeHelper.hasDeviceEffectsApplier());
+    }
+
+    @Test
+    @EnableFlags(FLAG_MODES_API)
+    public void testSettingDeviceEffects_throwsExceptionIfAlreadySet() {
+        mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
+
+        assertThrows(
+                IllegalStateException.class,
+                () -> mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier));
     }
 
     @Test
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
index ea61ad9..9f5e6d1 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -347,6 +347,14 @@
         waitForTransitionToFullscreen(wmHelper)
     }
 
+    /** Maximize an app by dragging the app handle to the top drag zone. */
+    fun maximizeAppWithDragToTopDragZone(
+        wmHelper: WindowManagerStateHelper,
+        device: UiDevice,
+    ) {
+        dragAppWindowToTopDragZone(wmHelper, device)
+    }
+
     private fun dragAppWindowToTopDragZone(wmHelper: WindowManagerStateHelper, device: UiDevice) {
         val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
         val displayRect = getDisplayRect(wmHelper)
diff --git a/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index 58fb4e1..938e2f8 100644
--- a/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -19,6 +19,7 @@
 import android.animation.ValueAnimator
 import android.content.Context
 import android.content.ContextWrapper
+import android.content.res.Resources
 import android.graphics.Color
 import android.hardware.input.IKeyboardBacklightListener
 import android.hardware.input.IKeyboardBacklightState
@@ -28,11 +29,12 @@
 import android.os.test.TestLooper
 import android.platform.test.annotations.Presubmit
 import android.view.InputDevice
+import android.util.TypedValue
 import androidx.test.annotation.UiThreadTest
 import androidx.test.core.app.ApplicationProvider
+import com.android.internal.R
 import com.android.server.input.KeyboardBacklightController.DEFAULT_BRIGHTNESS_VALUE_FOR_LEVEL
 import com.android.server.input.KeyboardBacklightController.MAX_BRIGHTNESS_CHANGE_STEPS
-import com.android.server.input.KeyboardBacklightController.USER_INACTIVITY_THRESHOLD_MILLIS
 import com.android.test.input.MockInputManagerRule
 import java.io.FileNotFoundException
 import java.io.FileOutputStream
@@ -49,6 +51,7 @@
 import org.junit.Test
 import org.mockito.Mock
 import org.mockito.Mockito.any
+import org.mockito.Mockito.anyBoolean
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.spy
@@ -94,6 +97,7 @@
         const val LIGHT_ID = 2
         const val SECOND_LIGHT_ID = 3
         const val MAX_BRIGHTNESS = 255
+        const val USER_INACTIVITY_THRESHOLD_MILLIS = 30000
     }
 
     @get:Rule
@@ -105,6 +109,8 @@
     private lateinit var native: NativeInputManagerService
     @Mock
     private lateinit var uEventManager: UEventManager
+    @Mock
+    private lateinit var resources: Resources
     private lateinit var keyboardBacklightController: KeyboardBacklightController
     private lateinit var context: Context
     private lateinit var dataStore: PersistentDataStore
@@ -117,6 +123,7 @@
     @Before
     fun setup() {
         context = spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+        `when`(context.resources).thenReturn(resources)
         dataStore = PersistentDataStore(object : PersistentDataStore.Injector() {
             override fun openRead(): InputStream? {
                 throw FileNotFoundException()
@@ -129,6 +136,7 @@
             override fun finishWrite(fos: FileOutputStream?, success: Boolean) {}
         })
         testLooper = TestLooper()
+        setupConfig()
         keyboardBacklightController = KeyboardBacklightController(context, native, dataStore,
                 testLooper.looper, FakeAnimatorFactory(), uEventManager)
         val inputManager = InputManager(context)
@@ -147,7 +155,31 @@
             sysfsNodeChanges++
         }
     }
-
+    private fun setupConfig() {
+        val brightnessValues = intArrayOf(100, 200, 0)
+        val decreaseThresholds = intArrayOf(-1, 900, 1900)
+        val increaseThresholds = intArrayOf(1000, 2000, -1)
+        `when`(resources.getIntArray(R.array.config_autoKeyboardBacklightBrightnessValues))
+            .thenReturn(brightnessValues)
+        `when`(resources.getIntArray(R.array.config_autoKeyboardBacklightDecreaseLuxThreshold))
+            .thenReturn(decreaseThresholds)
+        `when`(resources.getIntArray(R.array.config_autoKeyboardBacklightIncreaseLuxThreshold))
+            .thenReturn(increaseThresholds)
+        `when`(resources.getInteger(R.integer.config_keyboardBacklightTimeoutMs))
+            .thenReturn(USER_INACTIVITY_THRESHOLD_MILLIS)
+        `when`(
+            resources.getValue(
+                eq(R.dimen.config_autoKeyboardBrightnessSmoothingConstant),
+                any(TypedValue::class.java),
+                anyBoolean()
+            )
+        ).then {
+            val args = it.arguments
+            val outValue = args[1] as TypedValue
+            outValue.data = java.lang.Float.floatToRawIntBits(1.0f)
+            Unit
+        }
+    }
     @Test
     fun testKeyboardBacklightIncrementDecrement() {
         KeyboardBacklightFlags(
@@ -365,7 +397,7 @@
                 lightColorMap[LIGHT_ID]
             )
 
-            testLooper.moveTimeForward(USER_INACTIVITY_THRESHOLD_MILLIS + 1000)
+            testLooper.moveTimeForward((USER_INACTIVITY_THRESHOLD_MILLIS + 1000).toLong())
             testLooper.dispatchNext()
             assertEquals(
                 "Keyboard backlight level should be turned off after inactivity",