Merge "Transition away notifications when entering glanceable hub" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 1091706..20b9b0e 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12319,7 +12319,6 @@
     method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public void registerPackageInstallerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.content.pm.PackageInstaller.SessionCallback);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
-    method @FlaggedApi("android.content.pm.archiving") public void setArchiveCompatibilityOptions(boolean, boolean);
     method public boolean shouldHideFromSuggestions(@NonNull String, @NonNull android.os.UserHandle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
@@ -44954,7 +44953,7 @@
     method public void addOnSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
     method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
-    method @FlaggedApi("com.android.internal.telephony.flags.enforce_subscription_user_filter") @NonNull public android.telephony.SubscriptionManager createForAllUserProfiles();
+    method @FlaggedApi("com.android.internal.telephony.flags.enforce_subscription_user_filter") @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) public android.telephony.SubscriptionManager createForAllUserProfiles();
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
     method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context);
     method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 8a9f1c4..fe32bad 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -14716,7 +14716,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
-    method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @Nullable @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, "com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"}) public android.telephony.CellIdentity getLastKnownCellIdentity();
+    method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @Nullable @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_LAST_KNOWN_CELL_ID}) public android.telephony.CellIdentity getLastKnownCellIdentity();
     method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
     method public int getMaxNumberOfSimultaneouslyActiveSims();
     method public static long getMaxNumberVerificationTimeoutMillis();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e8a4a82..b8b98a3 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -377,6 +377,7 @@
   public class NotificationManager {
     method @FlaggedApi("android.app.modes_api") @NonNull public String addAutomaticZenRule(@NonNull android.app.AutomaticZenRule, boolean);
     method public void cleanUpCallersAfter(long);
+    method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy getDefaultZenPolicy();
     method public android.content.ComponentName getEffectsSuppressor();
     method public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String);
     method @FlaggedApi("android.app.modes_api") public boolean removeAutomaticZenRule(@NonNull String, boolean);
@@ -3027,6 +3028,10 @@
     method @Deprecated public boolean isBound();
   }
 
+  public final class ZenPolicy implements android.os.Parcelable {
+    method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy overwrittenWith(@Nullable android.service.notification.ZenPolicy);
+  }
+
   public static final class ZenPolicy.Builder {
     ctor public ZenPolicy.Builder(@Nullable android.service.notification.ZenPolicy);
   }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index ea37e7f..d8d136a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1548,24 +1548,9 @@
     public static final int OP_READ_SYSTEM_GRAMMATICAL_GENDER =
             AppProtoEnums.APP_OP_READ_SYSTEM_GRAMMATICAL_GENDER;
 
-    /**
-     * Whether the app has enabled to receive the icon overlay for fetching archived apps.
-     *
-     * @hide
-     */
-    public static final int OP_ARCHIVE_ICON_OVERLAY = AppProtoEnums.APP_OP_ARCHIVE_ICON_OVERLAY;
-
-    /**
-     * Whether the app has enabled compatibility support for unarchival.
-     *
-     * @hide
-     */
-    public static final int OP_UNARCHIVAL_CONFIRMATION =
-            AppProtoEnums.APP_OP_UNARCHIVAL_CONFIRMATION;
-
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 146;
+    public static final int _NUM_OP = 144;
 
     /**
      * All app ops represented as strings.
@@ -1715,8 +1700,6 @@
             OPSTR_ENABLE_MOBILE_DATA_BY_USER,
             OPSTR_RESERVED_FOR_TESTING,
             OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,
-            OPSTR_ARCHIVE_ICON_OVERLAY,
-            OPSTR_UNARCHIVAL_CONFIRMATION,
     })
     public @interface AppOpString {}
 
@@ -2057,20 +2040,6 @@
     public static final String OPSTR_MEDIA_ROUTING_CONTROL = "android:media_routing_control";
 
     /**
-     * Whether the app has enabled to receive the icon overlay for fetching archived apps.
-     *
-     * @hide
-     */
-    public static final String OPSTR_ARCHIVE_ICON_OVERLAY = "android:archive_icon_overlay";
-
-    /**
-     * Whether the app has enabled compatibility support for unarchival.
-     *
-     * @hide
-     */
-    public static final String OPSTR_UNARCHIVAL_CONFIRMATION = "android:unarchival_support";
-
-    /**
      * AppOp granted to apps that we are started via {@code am instrument -e --no-isolated-storage}
      *
      * <p>MediaProvider is the only component (outside of system server) that should care about this
@@ -2535,8 +2504,6 @@
             OP_RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA,
             OP_MEDIA_ROUTING_CONTROL,
             OP_READ_SYSTEM_GRAMMATICAL_GENDER,
-            OP_ARCHIVE_ICON_OVERLAY,
-            OP_UNARCHIVAL_CONFIRMATION,
     };
 
     static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{
@@ -2993,12 +2960,6 @@
                 OPSTR_READ_SYSTEM_GRAMMATICAL_GENDER, "READ_SYSTEM_GRAMMATICAL_GENDER")
                 .setPermission(Manifest.permission.READ_SYSTEM_GRAMMATICAL_GENDER)
                 .build(),
-        new AppOpInfo.Builder(OP_ARCHIVE_ICON_OVERLAY, OPSTR_ARCHIVE_ICON_OVERLAY,
-                "ARCHIVE_ICON_OVERLAY")
-                .setDefaultMode(MODE_ALLOWED).build(),
-        new AppOpInfo.Builder(OP_UNARCHIVAL_CONFIRMATION, OPSTR_UNARCHIVAL_CONFIRMATION,
-                "UNARCHIVAL_CONFIRMATION")
-                .setDefaultMode(MODE_ALLOWED).build(),
     };
 
     // The number of longs needed to form a full bitmask of app ops
@@ -3133,7 +3094,7 @@
 
     /**
      * Retrieve the permission associated with an operation, or null if there is not one.
-
+     *
      * @param op The operation name.
      *
      * @hide
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 4f1db7d..34c44f9 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -4032,8 +4032,7 @@
     private Drawable getArchivedAppIcon(String packageName) {
         try {
             return new BitmapDrawable(null,
-                    mPM.getArchivedAppIcon(packageName, new UserHandle(getUserId()),
-                            mContext.getPackageName()));
+                    mPM.getArchivedAppIcon(packageName, new UserHandle(getUserId())));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c3adbc3..578105f 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -38,6 +38,7 @@
 import android.service.notification.INotificationListener;
 import android.service.notification.NotificationListenerFilter;
 import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenPolicy;
 import android.app.AutomaticZenRule;
 import android.service.notification.ZenModeConfig;
 
@@ -213,6 +214,7 @@
     boolean isNotificationPolicyAccessGrantedForPackage(String pkg);
     void setNotificationPolicyAccessGranted(String pkg, boolean granted);
     void setNotificationPolicyAccessGrantedForUser(String pkg, int userId, boolean granted);
+    ZenPolicy getDefaultZenPolicy();
     AutomaticZenRule getAutomaticZenRule(String id);
     Map<String, AutomaticZenRule> getAutomaticZenRules();
     // TODO: b/310620812 - Remove getZenRules() when MODES_API is inlined.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 0b6e24c..366b45b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1750,6 +1750,20 @@
             @NonNull ComponentName listener, boolean granted) {
         setNotificationListenerAccessGranted(listener, granted, true);
     }
+    /**
+     * Gets the device-default notification policy as a ZenPolicy.
+     * @hide
+     */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public @NonNull ZenPolicy getDefaultZenPolicy() {
+        INotificationManager service = getService();
+        try {
+            return service.getDefaultZenPolicy();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 
     /**
      * For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above, the
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 62db65f..a97de63 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -128,6 +128,4 @@
 
     /** Unregister a callback, so that it won't be called when LauncherApps dumps. */
     void unRegisterDumpCallback(IDumpCallback cb);
-
-    void setArchiveCompatibilityOptions(boolean enableIconOverlay, boolean enableUnarchivalConfirmation);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 380de96..6dc8d47 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -840,7 +840,7 @@
 
     ArchivedPackageParcel getArchivedPackage(in String packageName, int userId);
 
-    Bitmap getArchivedAppIcon(String packageName, in UserHandle user, String callingPackageName);
+    Bitmap getArchivedAppIcon(String packageName, in UserHandle user);
 
     boolean isAppArchivable(String packageName, in UserHandle user);
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 50be983..1d2b1af 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -1801,31 +1801,6 @@
         }
     }
 
-    /**
-     * Enable or disable different archive compatibility options of the launcher.
-     *
-     * @param enableIconOverlay Provides a cloud overlay for archived apps to ensure users are aware
-     * that a certain app is archived. True by default.
-     * Launchers might want to disable this operation if they want to provide custom user experience
-     * to differentiate archived apps.
-     * @param enableUnarchivalConfirmation If true, the user is shown a confirmation dialog when
-     * they click an archived app, which explains that the app will be downloaded and restored in
-     * the background. True by default.
-     * Launchers might want to disable this operation if they provide sufficient, alternative user
-     * guidance to highlight that an unarchival is starting and ongoing once an archived app is
-     * tapped. E.g., this could be achieved by showing the unarchival progress around the icon.
-     */
-    @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
-    public void setArchiveCompatibilityOptions(boolean enableIconOverlay,
-            boolean enableUnarchivalConfirmation) {
-        try {
-            mService.setArchiveCompatibilityOptions(enableIconOverlay,
-                    enableUnarchivalConfirmation);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
     /** @return position in mCallbacks for callback or -1 if not present. */
     private int findCallbackLocked(Callback callback) {
         if (callback == null) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ab98c94..d946430 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3243,9 +3243,17 @@
 
         private static final String NAME_EQ_PLACEHOLDER = "name=?";
 
+        // Cached values of queried settings.
+        // Key is the setting's name, value is the setting's value.
         // Must synchronize on 'this' to access mValues and mValuesVersion.
         private final ArrayMap<String, String> mValues = new ArrayMap<>();
 
+        // Cached values for queried prefixes.
+        // Key is the prefix, value is all of the settings under the prefix, mapped from a setting's
+        // name to a setting's value. The name string doesn't include the prefix.
+        // Must synchronize on 'this' to access.
+        private final ArrayMap<String, ArrayMap<String, String>> mPrefixToValues = new ArrayMap<>();
+
         private final Uri mUri;
         @UnsupportedAppUsage
         private final ContentProviderHolder mProviderHolder;
@@ -3592,15 +3600,13 @@
                     || applicationInfo.isSignedWithPlatformKey();
         }
 
-        private ArrayMap<String, String> getStringsForPrefixStripPrefix(
-                ContentResolver cr, String prefix, String[] names) {
+        private Map<String, String> getStringsForPrefixStripPrefix(
+                ContentResolver cr, String prefix, List<String> names) {
             String namespace = prefix.substring(0, prefix.length() - 1);
             ArrayMap<String, String> keyValues = new ArrayMap<>();
             int substringLength = prefix.length();
-
             int currentGeneration = -1;
             boolean needsGenerationTracker = false;
-
             synchronized (NameValueCache.this) {
                 final GenerationTracker generationTracker = mGenerationTrackers.get(prefix);
                 if (generationTracker != null) {
@@ -3614,40 +3620,24 @@
                         // generation tracker and request a new one
                         generationTracker.destroy();
                         mGenerationTrackers.remove(prefix);
-                        for (int i = mValues.size() - 1; i >= 0; i--) {
-                            String key = mValues.keyAt(i);
-                            if (key.startsWith(prefix)) {
-                                mValues.remove(key);
-                            }
-                        }
+                        mPrefixToValues.remove(prefix);
                         needsGenerationTracker = true;
                     } else {
-                        boolean prefixCached = mValues.containsKey(prefix);
-                        if (prefixCached) {
-                            if (DEBUG) {
-                                Log.i(TAG, "Cache hit for prefix:" + prefix);
-                            }
-                            if (names.length > 0) {
+                        final ArrayMap<String, String> cachedSettings = mPrefixToValues.get(prefix);
+                        if (cachedSettings != null) {
+                            if (!names.isEmpty()) {
                                 for (String name : names) {
-                                    // mValues can contain "null" values, need to use containsKey.
-                                    if (mValues.containsKey(name)) {
+                                    // The cache can contain "null" values, need to use containsKey.
+                                    if (cachedSettings.containsKey(name)) {
                                         keyValues.put(
-                                                name.substring(substringLength),
-                                                mValues.get(name));
+                                                name,
+                                                cachedSettings.get(name));
                                     }
                                 }
                             } else {
-                                for (int i = 0; i < mValues.size(); ++i) {
-                                    String key = mValues.keyAt(i);
-                                    // Explicitly exclude the prefix as it is only there to
-                                    // signal that the prefix has been cached.
-                                    if (key.startsWith(prefix) && !key.equals(prefix)) {
-                                        String value = mValues.valueAt(i);
-                                        keyValues.put(
-                                                key.substring(substringLength),
-                                                value);
-                                    }
-                                }
+                                keyValues.putAll(cachedSettings);
+                                // Remove the hack added for the legacy behavior.
+                                keyValues.remove("");
                             }
                             return keyValues;
                         }
@@ -3657,7 +3647,6 @@
                     needsGenerationTracker = true;
                 }
             }
-
             if (mCallListCommand == null) {
                 // No list command specified, return empty map
                 return keyValues;
@@ -3702,20 +3691,23 @@
                 }
 
                 // All flags for the namespace
-                Map<String, String> flagsToValues =
+                HashMap<String, String> flagsToValues =
                         (HashMap) b.getSerializable(Settings.NameValueTable.VALUE, java.util.HashMap.class);
+                if (flagsToValues == null) {
+                    return keyValues;
+                }
                 // Only the flags requested by the caller
-                if (names.length > 0) {
+                if (!names.isEmpty()) {
                     for (String name : names) {
                         // flagsToValues can contain "null" values, need to use containsKey.
-                        if (flagsToValues.containsKey(name)) {
+                        final String key = Config.createCompositeName(namespace, name);
+                        if (flagsToValues.containsKey(key)) {
                             keyValues.put(
-                                    name.substring(substringLength),
-                                    flagsToValues.get(name));
+                                    name,
+                                    flagsToValues.get(key));
                         }
                     }
                 } else {
-                    keyValues.ensureCapacity(keyValues.size() + flagsToValues.size());
                     for (Map.Entry<String, String> flag : flagsToValues.entrySet()) {
                         keyValues.put(
                                 flag.getKey().substring(substringLength),
@@ -3751,10 +3743,18 @@
                         if (DEBUG) {
                             Log.i(TAG, "Updating cache for prefix:" + prefix);
                         }
-                        // cache the complete list of flags for the namespace
-                        mValues.putAll(flagsToValues);
-                        // Adding the prefix as a signal that the prefix is cached.
-                        mValues.put(prefix, null);
+                        // Cache the complete list of flags for the namespace for bulk queries.
+                        // In this cached list, the setting's name doesn't include the prefix.
+                        ArrayMap<String, String> namesToValues =
+                                new ArrayMap<>(flagsToValues.size() + 1);
+                        for (Map.Entry<String, String> flag : flagsToValues.entrySet()) {
+                            namesToValues.put(
+                                    flag.getKey().substring(substringLength),
+                                    flag.getValue());
+                        }
+                        // Legacy behavior, we return <"", null> when queried with name = ""
+                        namesToValues.put("", null);
+                        mPrefixToValues.put(prefix, namesToValues);
                     }
                 }
                 return keyValues;
@@ -19945,16 +19945,9 @@
         @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
         public static Map<String, String> getStrings(@NonNull ContentResolver resolver,
                 @NonNull String namespace, @NonNull List<String> names) {
-            String[] compositeNames = new String[names.size()];
-            for (int i = 0, size = names.size(); i < size; ++i) {
-                compositeNames[i] = createCompositeName(namespace, names.get(i));
-            }
-
             String prefix = createPrefix(namespace);
 
-            ArrayMap<String, String> keyValues = sNameValueCache.getStringsForPrefixStripPrefix(
-                    resolver, prefix, compositeNames);
-            return keyValues;
+            return sNameValueCache.getStringsForPrefixStripPrefix(resolver, prefix, names);
         }
 
         /**
@@ -20276,7 +20269,7 @@
             }
         }
 
-        private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
+        static String createCompositeName(@NonNull String namespace, @NonNull String name) {
             Preconditions.checkNotNull(namespace);
             Preconditions.checkNotNull(name);
             var sb = new StringBuilder(namespace.length() + 1 + name.length());
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index c479877..9895551 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -185,7 +185,13 @@
             SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
                     | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT;
 
-    public static final int XML_VERSION = 8;
+    // ZenModeConfig XML versions distinguishing key changes.
+    public static final int XML_VERSION_ZEN_UPGRADE = 8;
+    public static final int XML_VERSION_MODES_API = 11;
+
+    // TODO: b/310620812 - Update XML_VERSION and update default_zen_config.xml accordingly when
+    //       modes_api is inlined.
+    private static final int XML_VERSION = 10;
     public static final String ZEN_TAG = "zen";
     private static final String ZEN_ATT_VERSION = "version";
     private static final String ZEN_ATT_USER = "user";
@@ -586,6 +592,10 @@
         }
     }
 
+    public static int getCurrentXmlVersion() {
+        return Flags.modesApi() ? XML_VERSION_MODES_API : XML_VERSION;
+    }
+
     public static ZenModeConfig readXml(TypedXmlPullParser parser)
             throws XmlPullParserException, IOException {
         int type = parser.getEventType();
@@ -593,7 +603,7 @@
         String tag = parser.getName();
         if (!ZEN_TAG.equals(tag)) return null;
         final ZenModeConfig rt = new ZenModeConfig();
-        rt.version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION);
+        rt.version = safeInt(parser, ZEN_ATT_VERSION, getCurrentXmlVersion());
         rt.user = safeInt(parser, ZEN_ATT_USER, rt.user);
         boolean readSuppressedEffects = false;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
@@ -707,14 +717,16 @@
     /**
      * Writes XML of current ZenModeConfig
      * @param out serializer
-     * @param version uses XML_VERSION if version is null
+     * @param version uses the current XML version if version is null
      * @throws IOException
      */
+
     public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup)
             throws IOException {
+        int xmlVersion = getCurrentXmlVersion();
         out.startTag(null, ZEN_TAG);
         out.attribute(null, ZEN_ATT_VERSION, version == null
-                ? Integer.toString(XML_VERSION) : Integer.toString(version));
+                ? Integer.toString(xmlVersion) : Integer.toString(version));
         out.attributeInt(null, ZEN_ATT_USER, user);
         out.startTag(null, ALLOW_TAG);
         out.attributeBoolean(null, ALLOW_ATT_CALLS, allowCalls);
diff --git a/core/java/android/service/notification/ZenPolicy.aidl b/core/java/android/service/notification/ZenPolicy.aidl
new file mode 100644
index 0000000..b56f5c6
--- /dev/null
+++ b/core/java/android/service/notification/ZenPolicy.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 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.service.notification;
+
+parcelable ZenPolicy;
\ No newline at end of file
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index fb491d0..d8318a6 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -1422,6 +1422,54 @@
     }
 
     /**
+     * Overwrites any policy values in this ZenPolicy with set values from newPolicy and
+     * returns a copy of the resulting ZenPolicy.
+     * Unlike apply(), values set in newPolicy will always be kept over pre-existing
+     * fields. Any values in newPolicy that are not set keep their currently set values.
+     *
+     * @hide
+     */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public @NonNull ZenPolicy overwrittenWith(@Nullable ZenPolicy newPolicy) {
+        ZenPolicy result = this.copy();
+
+        if (newPolicy == null) {
+            return result;
+        }
+
+        // set priority categories
+        for (int category = 0; category < mPriorityCategories.size(); category++) {
+            @State int newState = newPolicy.mPriorityCategories.get(category);
+            if (newState != STATE_UNSET) {
+                result.mPriorityCategories.set(category, newState);
+
+                if (category == PRIORITY_CATEGORY_MESSAGES) {
+                    result.mPriorityMessages = newPolicy.mPriorityMessages;
+                } else if (category == PRIORITY_CATEGORY_CALLS) {
+                    result.mPriorityCalls = newPolicy.mPriorityCalls;
+                } else if (category == PRIORITY_CATEGORY_CONVERSATIONS) {
+                    result.mConversationSenders = newPolicy.mConversationSenders;
+                }
+            }
+        }
+
+        // set visual effects
+        for (int visualEffect = 0; visualEffect < mVisualEffects.size(); visualEffect++) {
+            if (newPolicy.mVisualEffects.get(visualEffect) != STATE_UNSET) {
+                result.mVisualEffects.set(visualEffect, newPolicy.mVisualEffects.get(visualEffect));
+            }
+        }
+
+        // set allowed channels
+        if (newPolicy.mAllowChannels != CHANNEL_POLICY_UNSET) {
+            result.mAllowChannels = newPolicy.mAllowChannels;
+        }
+
+        return result;
+    }
+
+    /**
      * @hide
      */
     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 8935ab3..0a813a3 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -38,6 +38,7 @@
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsCallSession;
@@ -116,14 +117,15 @@
     }
 
     /**
-     * Register for changes to the list of active {@link SubscriptionInfo} records or to the
-     * individual records themselves. When a change occurs the onSubscriptionsChanged method of
-     * the listener will be invoked immediately if there has been a notification. The
-     * onSubscriptionChanged method will also be triggered once initially when calling this
-     * function.
+     * Register for changes to the list of {@link SubscriptionInfo} records or to the
+     * individual records (active or inactive) themselves. When a change occurs, the
+     * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method of
+     * the listener will be invoked immediately. The
+     * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method will also be invoked
+     * once initially when calling this method.
      *
-     * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener}
-     *                 with onSubscriptionsChanged overridden.
+     * @param listener an instance of {@link OnSubscriptionsChangedListener} with
+     * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} overridden.
      * @param executor the executor that will execute callbacks.
      * @hide
      */
diff --git a/media/java/android/media/tv/BroadcastInfoRequest.java b/media/java/android/media/tv/BroadcastInfoRequest.java
index cbd8c1f..694756c 100644
--- a/media/java/android/media/tv/BroadcastInfoRequest.java
+++ b/media/java/android/media/tv/BroadcastInfoRequest.java
@@ -32,7 +32,8 @@
 public abstract class BroadcastInfoRequest implements Parcelable {
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({REQUEST_OPTION_REPEAT, REQUEST_OPTION_AUTO_UPDATE})
+    @IntDef({REQUEST_OPTION_REPEAT, REQUEST_OPTION_AUTO_UPDATE,
+            REQUEST_OPTION_ONEWAY, REQUEST_OPTION_ONESHOT})
     public @interface RequestOption {}
 
     /**
@@ -47,6 +48,18 @@
      * first time, new values are detected.
      */
     public static final int REQUEST_OPTION_AUTO_UPDATE = 1;
+    /**
+     * Request option: one-way
+     * <p> With this option, no response is expected after sending the request.
+     * @hide
+     */
+    public static final int REQUEST_OPTION_ONEWAY = 2;
+    /**
+     * Request option: one-shot
+     * <p> With this option, only one response will be given per request.
+     * @hide
+     */
+    public static final int REQUEST_OPTION_ONESHOT = 3;
 
     public static final @NonNull Parcelable.Creator<BroadcastInfoRequest> CREATOR =
             new Parcelable.Creator<BroadcastInfoRequest>() {
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index 0f8a00a..8978277 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -44,6 +44,7 @@
     void onTrackSelected(int type, in String trackId, int seq);
     void onVideoAvailable(int seq);
     void onVideoUnavailable(int reason, int seq);
+    void onVideoFreezeUpdated(boolean isFrozen, int seq);
     void onContentAllowed(int seq);
     void onContentBlocked(in String rating, int seq);
     void onLayoutSurface(int left, int top, int right, int bottom, int seq);
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index a52e9a5..8e2702a 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -41,6 +41,7 @@
     void onTrackSelected(int type, in String trackId);
     void onVideoAvailable();
     void onVideoUnavailable(int reason);
+    void onVideoFreezeUpdated(boolean isFrozen);
     void onContentAllowed();
     void onContentBlocked(in String rating);
     void onLayoutSurface(int left, int top, int right, int bottom);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 51b2542..caddd8a 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -740,6 +740,15 @@
         }
 
         /**
+         * This is called when the video freeze state has been updated.
+         * If {@code true}, the video is frozen on the last frame while audio playback continues.
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param isFrozen Whether the video is frozen
+         */
+        public void onVideoFreezeUpdated(Session session, boolean isFrozen) {
+        }
+
+        /**
          * This is called when the current program content turns out to be allowed to watch since
          * its content rating is not blocked by parental controls.
          *
@@ -1030,6 +1039,19 @@
             });
         }
 
+        void postVideoFreezeUpdated(boolean isFrozen) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onVideoFreezeUpdated(mSession, isFrozen);
+                    if (mSession.mIAppNotificationEnabled
+                            && mSession.getInteractiveAppSession() != null) {
+                        mSession.getInteractiveAppSession().notifyVideoFreezeUpdated(isFrozen);
+                    }
+                }
+            });
+        }
+
         void postContentAllowed() {
             mHandler.post(new Runnable() {
                 @Override
@@ -1546,6 +1568,18 @@
             }
 
             @Override
+            public void onVideoFreezeUpdated(boolean isFrozen, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postVideoFreezeUpdated(isFrozen);
+                }
+            }
+
+            @Override
             public void onContentAllowed(int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 76d8e50..6301a27 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -763,6 +763,34 @@
         }
 
         /**
+         * Informs the application that the video freeze state has been updated.
+         *
+         * When {@code true}, the video is frozen on the last frame but audio playback remains
+         * active.
+         *
+         * @param isFrozen Whether or not the video is frozen
+         * @hide
+         */
+        public void notifyVideoFreezeUpdated(boolean isFrozen) {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) {
+                            Log.d(TAG, "notifyVideoFreezeUpdated");
+                        }
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onVideoFreezeUpdated(isFrozen);
+                        }
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in notifyVideoFreezeUpdated", e);
+                    }
+                }
+            });
+        }
+
+        /**
          * Sends an updated list of all audio presentations available from a Next Generation Audio
          * service. This is used by the framework to maintain the audio presentation information for
          * a given track of {@link TvTrackInfo#TYPE_AUDIO}, which in turn is used by
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
index 4316d05..0f58b29 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
@@ -88,6 +88,7 @@
     void notifyTracksChanged(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
     void notifyVideoAvailable(in IBinder sessionToken, int userId);
     void notifyVideoUnavailable(in IBinder sessionToken, int reason, int userId);
+    void notifyVideoFreezeUpdated(in IBinder sessionToken, boolean isFrozen, int userId);
     void notifyContentAllowed(in IBinder sessionToken, int userId);
     void notifyContentBlocked(in IBinder sessionToken, in String rating, int userId);
     void notifySignalStrength(in IBinder sessionToken, int stength, int userId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
index ba7cf13..06808c9 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
@@ -67,6 +67,7 @@
     void notifyTracksChanged(in List<TvTrackInfo> tracks);
     void notifyVideoAvailable();
     void notifyVideoUnavailable(int reason);
+    void notifyVideoFreezeUpdated(boolean isFrozen);
     void notifyContentAllowed();
     void notifyContentBlocked(in String rating);
     void notifySignalStrength(int strength);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
index 518b08a..77730aa 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -103,6 +103,7 @@
     private static final int DO_SEND_TIME_SHIFT_MODE = 46;
     private static final int DO_SEND_AVAILABLE_SPEEDS = 47;
     private static final int DO_SEND_SELECTED_TRACK_INFO = 48;
+    private static final int DO_NOTIFY_VIDEO_FREEZE_UPDATED = 49;
 
     private final HandlerCaller mCaller;
     private Session mSessionImpl;
@@ -364,6 +365,10 @@
                 args.recycle();
                 break;
             }
+            case DO_NOTIFY_VIDEO_FREEZE_UPDATED: {
+                mSessionImpl.notifyVideoFreezeUpdated((Boolean) msg.obj);
+                break;
+            }
             default: {
                 Log.w(TAG, "Unhandled message code: " + msg.what);
                 break;
@@ -552,6 +557,12 @@
     }
 
     @Override
+    public void notifyVideoFreezeUpdated(boolean isFrozen) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_VIDEO_FREEZE_UPDATED,
+                isFrozen));
+    }
+
+    @Override
     public void notifyContentAllowed() {
         mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_CONTENT_ALLOWED));
     }
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index bf4379f..8a340f6 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -1731,6 +1731,22 @@
         }
 
         /**
+         * Notifies Interactive app session when the video freeze state is updated
+         * @param isFrozen Whether or not the video is frozen
+         */
+        public void notifyVideoFreezeUpdated(boolean isFrozen) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.notifyVideoFreezeUpdated(mToken, isFrozen, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Notifies Interactive APP session when content is allowed.
          */
         public void notifyContentAllowed() {
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 7936403..5247a0e 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -882,6 +882,15 @@
         }
 
         /**
+         * Called when video becomes frozen or unfrozen. Audio playback will continue while
+         * video will be frozen to the last frame if {@code true}.
+         * @param isFrozen Whether or not the video is frozen.
+         * @hide
+         */
+        public void onVideoFreezeUpdated(boolean isFrozen) {
+        }
+
+        /**
          * Called when content is allowed.
          */
         public void onContentAllowed() {
@@ -1770,6 +1779,13 @@
             onVideoUnavailable(reason);
         }
 
+        void notifyVideoFreezeUpdated(boolean isFrozen) {
+            if (DEBUG) {
+                Log.d(TAG, "notifyVideoFreezeUpdated (isFrozen=" + isFrozen + ")");
+            }
+            onVideoFreezeUpdated(isFrozen);
+        }
+
         void notifyContentAllowed() {
             if (DEBUG) {
                 Log.d(TAG, "notifyContentAllowed");
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index 40a12e4..5bb61c2 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -719,6 +719,22 @@
     }
 
     /**
+     * Alerts the TV Interactive app that the video freeze state has been updated.
+     * If {@code true}, the video is frozen on the last frame while audio playback continues.
+     *
+     * @param isFrozen Whether the video is frozen.
+     * @hide
+     */
+    public void notifyVideoFreezeUpdated(boolean isFrozen) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyVideoFreezeUpdated");
+        }
+        if (mSession != null) {
+            mSession.notifyVideoFreezeUpdated(isFrozen);
+        }
+    }
+
+    /**
      * Sends signing result to related TV interactive app.
      *
      * <p>This is used when the corresponding server of the broadcast-independent interactive
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 7088829..d191a3c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -20,7 +20,6 @@
 import android.graphics.Region;
 import android.os.Bundle;
 import android.view.MotionEvent;
-import android.view.SurfaceControl;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 
 // Next ID: 29
@@ -99,11 +98,6 @@
     void enterStageSplitFromRunningApp(boolean leftOrTop) = 25;
 
     /**
-     * Sent when the surface for navigation bar is created or changed
-     */
-    void onNavigationBarSurface(in SurfaceControl surface) = 26;
-
-    /**
      * Sent when the task bar stash state is toggled.
      */
     void onTaskbarToggled() = 27;
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 84a573f..44b0383 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -272,6 +272,12 @@
 
     companion object {
         /**
+         * The user activity timeout which should be used when the communal hub is opened. A value
+         * of -1 means that the user's chosen screen timeout will be used instead.
+         */
+        const val AWAKE_INTERVAL_MS = -1
+
+        /**
          * Calculates the content size dynamically based on the total number of contents of that
          * type.
          *
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 0a72a2f..068e5fd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -504,24 +504,6 @@
                 }
             };
 
-    private final ViewRootImpl.SurfaceChangedCallback mSurfaceChangedCallback =
-            new SurfaceChangedCallback() {
-            @Override
-            public void surfaceCreated(Transaction t) {
-                notifyNavigationBarSurface();
-            }
-
-            @Override
-            public void surfaceDestroyed() {
-                notifyNavigationBarSurface();
-            }
-
-            @Override
-            public void surfaceReplaced(Transaction t) {
-                notifyNavigationBarSurface();
-            }
-    };
-
     private boolean mScreenPinningActive = false;
     private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
         @Override
@@ -787,8 +769,6 @@
 
         mView.getViewTreeObserver().addOnComputeInternalInsetsListener(
                 mOnComputeInternalInsetsListener);
-        mView.getViewRootImpl().addSurfaceChangedCallback(mSurfaceChangedCallback);
-        notifyNavigationBarSurface();
 
         mPipOptional.ifPresent(mView::addPipExclusionBoundsChangeListener);
         mBackAnimation.ifPresent(mView::registerBackAnimation);
@@ -860,13 +840,8 @@
         mHandler.removeCallbacks(mEnableLayoutTransitions);
         mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
         mPipOptional.ifPresent(mView::removePipExclusionBoundsChangeListener);
-        ViewRootImpl viewRoot = mView.getViewRootImpl();
-        if (viewRoot != null) {
-            viewRoot.removeSurfaceChangedCallback(mSurfaceChangedCallback);
-        }
         mFrame = null;
         mOrientationHandle = null;
-        notifyNavigationBarSurface();
     }
 
     // TODO: Remove this when we update nav bar recreation
@@ -1026,17 +1001,6 @@
         }
     }
 
-    private void notifyNavigationBarSurface() {
-        ViewRootImpl viewRoot = mView.getViewRootImpl();
-        SurfaceControl surface = mView.getParent() != null 
-                && viewRoot != null
-                && viewRoot.getSurfaceControl() != null
-                && viewRoot.getSurfaceControl().isValid()
-                        ? viewRoot.getSurfaceControl()
-                        : null;
-        mOverviewProxyService.onNavigationBarSurfaceChanged(surface);
-    }
-
     private int deltaRotation(int oldRotation, int newRotation) {
         int delta = newRotation - oldRotation;
         if (delta < 0) delta += 4;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index fd53423..cc53aab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -169,7 +169,6 @@
     private final DisplayTracker mDisplayTracker;
 
     private Region mActiveNavBarRegion;
-    private SurfaceControl mNavigationBarSurface;
 
     private IOverviewProxy mOverviewProxy;
     private int mConnectionBackoffAttempts;
@@ -488,7 +487,6 @@
                 Log.e(TAG_OPS, "Failed to call onInitialize()", e);
             }
             dispatchNavButtonBounds();
-            dispatchNavigationBarSurface();
 
             // Force-update the systemui state flags
             updateSystemUiStateFlags();
@@ -679,28 +677,6 @@
                 .commitUpdate(mContext.getDisplayId());
     }
 
-    /**
-     * Called when the navigation bar surface is created or changed
-     */
-    public void onNavigationBarSurfaceChanged(SurfaceControl navbarSurface) {
-        mNavigationBarSurface = navbarSurface;
-        dispatchNavigationBarSurface();
-    }
-
-    private void dispatchNavigationBarSurface() {
-        try {
-            if (mOverviewProxy != null) {
-                // Catch all for cases where the surface is no longer valid
-                if (mNavigationBarSurface != null && !mNavigationBarSurface.isValid()) {
-                    mNavigationBarSurface = null;
-                }
-                mOverviewProxy.onNavigationBarSurface(mNavigationBarSurface);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG_OPS, "Failed to notify back action", e);
-        }
-    }
-
     private void updateEnabledAndBinding() {
         updateEnabledState();
         startConnectionToCurrentUser();
@@ -1075,7 +1051,6 @@
         pw.print("  mInputFocusTransferStartY="); pw.println(mInputFocusTransferStartY);
         pw.print("  mInputFocusTransferStartMillis="); pw.println(mInputFocusTransferStartMillis);
         pw.print("  mActiveNavBarRegion="); pw.println(mActiveNavBarRegion);
-        pw.print("  mNavigationBarSurface="); pw.println(mNavigationBarSurface);
         pw.print("  mNavBarMode="); pw.println(mNavBarMode);
         mSysUiState.dump(pw, args);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 60feb82..0053474 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -50,6 +50,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.communal.domain.interactor.CommunalInteractor;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -118,6 +119,7 @@
     private final Lazy<SelectedUserInteractor> mUserInteractor;
     private final Lazy<ShadeInteractor> mShadeInteractorLazy;
     private final SceneContainerFlags mSceneContainerFlags;
+    private final Lazy<CommunalInteractor> mCommunalInteractor;
     private ViewGroup mWindowRootView;
     private LayoutParams mLp;
     private boolean mHasTopUi;
@@ -165,7 +167,8 @@
             ShadeWindowLogger logger,
             Lazy<SelectedUserInteractor> userInteractor,
             UserTracker userTracker,
-            SceneContainerFlags sceneContainerFlags) {
+            SceneContainerFlags sceneContainerFlags,
+            Lazy<CommunalInteractor> communalInteractor) {
         mContext = context;
         mWindowRootViewComponentFactory = windowRootViewComponentFactory;
         mWindowManager = windowManager;
@@ -184,6 +187,7 @@
         mAuthController = authController;
         mUserInteractor = userInteractor;
         mSceneContainerFlags = sceneContainerFlags;
+        mCommunalInteractor = communalInteractor;
         mLastKeyguardRotationAllowed = mKeyguardStateController.isKeyguardScreenRotationAllowed();
         mLockScreenDisplayTimeout = context.getResources()
                 .getInteger(R.integer.config_lockScreenDisplayTimeout);
@@ -325,6 +329,11 @@
                 mShadeInteractorLazy.get().isQsExpanded(),
                 this::onQsExpansionChanged
         );
+        collectFlow(
+                mWindowRootView,
+                mCommunalInteractor.get().isCommunalShowing(),
+                this::onCommunalShowingChanged
+        );
     }
 
     @Override
@@ -501,14 +510,21 @@
     }
 
     private void applyUserActivityTimeout(NotificationShadeWindowState state) {
-        if (state.isKeyguardShowingAndNotOccluded()
+        final Boolean communalShowing = state.isCommunalShowingAndNotOccluded();
+        final Boolean keyguardShowing = state.isKeyguardShowingAndNotOccluded();
+        long timeout = -1;
+        if ((communalShowing || keyguardShowing)
                 && state.statusBarState == StatusBarState.KEYGUARD
                 && !state.qsExpanded) {
-            mLpChanged.userActivityTimeout = state.bouncerShowing
-                    ? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout;
-        } else {
-            mLpChanged.userActivityTimeout = -1;
+            if (state.bouncerShowing) {
+                timeout = KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS;
+            } else if (communalShowing) {
+                timeout = CommunalInteractor.AWAKE_INTERVAL_MS;
+            } else if (keyguardShowing) {
+                timeout = mLockScreenDisplayTimeout;
+            }
         }
+        mLpChanged.userActivityTimeout = timeout;
     }
 
     private void applyInputFeatures(NotificationShadeWindowState state) {
@@ -607,7 +623,8 @@
                 state.forcePluginOpen,
                 state.dozing,
                 state.scrimsVisibility,
-                state.backgroundBlurRadius
+                state.backgroundBlurRadius,
+                state.communalShowing
         );
     }
 
@@ -731,6 +748,12 @@
         apply(mCurrentState);
     }
 
+    @VisibleForTesting
+    void onCommunalShowingChanged(Boolean showing) {
+        mCurrentState.communalShowing = showing;
+        apply(mCurrentState);
+    }
+
     @Override
     public void setForceUserActivity(boolean forceUserActivity) {
         mCurrentState.forceUserActivity = forceUserActivity;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
index 0b20170..f9c9d83 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
@@ -58,12 +58,17 @@
     @JvmField var dreaming: Boolean = false,
     @JvmField var scrimsVisibility: Int = 0,
     @JvmField var backgroundBlurRadius: Int = 0,
+    @JvmField var communalShowing: Boolean = false,
 ) {
 
     fun isKeyguardShowingAndNotOccluded(): Boolean {
         return keyguardShowing && !keyguardOccluded
     }
 
+    fun isCommunalShowingAndNotOccluded(): Boolean {
+        return communalShowing && !keyguardOccluded
+    }
+
     /** List of [String] to be used as a [Row] with [DumpsysTableLogger]. */
     val asStringList: List<String> by lazy {
         listOf(
@@ -93,7 +98,8 @@
             forcePluginOpen.toString(),
             dozing.toString(),
             scrimsVisibility.toString(),
-            backgroundBlurRadius.toString()
+            backgroundBlurRadius.toString(),
+            communalShowing.toString(),
         )
     }
 
@@ -134,6 +140,7 @@
             dozing: Boolean,
             scrimsVisibility: Int,
             backgroundBlurRadius: Int,
+            communalShowing: Boolean,
         ) {
             buffer.advance().apply {
                 this.keyguardShowing = keyguardShowing
@@ -165,6 +172,7 @@
                 this.dozing = dozing
                 this.scrimsVisibility = scrimsVisibility
                 this.backgroundBlurRadius = backgroundBlurRadius
+                this.communalShowing = communalShowing
             }
         }
 
@@ -209,7 +217,8 @@
                 "forcePluginOpen",
                 "dozing",
                 "scrimsVisibility",
-                "backgroundBlurRadius"
+                "backgroundBlurRadius",
+                "communalShowing"
             )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index b57cf53..754a7fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -97,6 +97,7 @@
 import com.android.systemui.flags.SystemPropertiesHelper;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.scene.FakeWindowRootViewComponent;
@@ -150,6 +151,7 @@
 @TestableLooper.RunWithLooper
 @SmallTest
 public class KeyguardViewMediatorTest extends SysuiTestCase {
+    private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
     private KeyguardViewMediator mViewMediator;
 
     private final TestScope mTestScope = TestScopeProvider.getTestScope();
@@ -265,7 +267,8 @@
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
                 mUserTracker,
-                mSceneContainerFlags);
+                mSceneContainerFlags,
+                mKosmos::getCommunalInteractor);
         mFeatureFlags = new FakeFeatureFlags();
         mFeatureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false);
         mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 0bffa1c..200e758 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -301,7 +301,8 @@
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
                 mUserTracker,
-                mSceneContainerFlags) {
+                mSceneContainerFlags,
+                () -> communalInteractor) {
                     @Override
                     protected boolean isDebuggable() {
                         return false;
@@ -449,6 +450,24 @@
     }
 
     @Test
+    public void setCommunalShowing_userTimeout() {
+        setKeyguardShowing();
+        clearInvocations(mWindowManager);
+
+        mNotificationShadeWindowController.onCommunalShowingChanged(true);
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().userActivityTimeout)
+                .isEqualTo(CommunalInteractor.AWAKE_INTERVAL_MS);
+        clearInvocations(mWindowManager);
+
+        // Bouncer showing over communal overrides communal value
+        mNotificationShadeWindowController.setBouncerShowing(true);
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat(mLayoutParameters.getValue().userActivityTimeout)
+                .isEqualTo(KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS);
+    }
+
+    @Test
     public void setKeyguardShowing_notFocusable_byDefault() {
         mNotificationShadeWindowController.setKeyguardShowing(false);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 744f424..93d8dcc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -534,7 +534,8 @@
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
                 mUserTracker,
-                mSceneContainerFlags
+                mSceneContainerFlags,
+                mKosmos::getCommunalInteractor
         );
         mNotificationShadeWindowController.fetchWindowRootView();
         mNotificationShadeWindowController.attach();
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 50e1862..84e1d90 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -247,6 +247,11 @@
         final Context context = getContext();
 
         mPersistentStore = new PersistentDataStore();
+        mAssociationRequestsProcessor = new AssociationRequestsProcessor(
+                /* cdmService */ this, mAssociationStore);
+        mBackupRestoreProcessor = new BackupRestoreProcessor(
+                /* cdmService */ this, mAssociationStore, mPersistentStore,
+                mSystemDataTransferRequestStore, mAssociationRequestsProcessor);
 
         loadAssociationsFromDisk();
         mAssociationStore.registerListener(mAssociationStoreChangeListener);
@@ -254,17 +259,12 @@
         mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(mUserManager,
                 mAssociationStore, mDevicePresenceCallback);
 
-        mAssociationRequestsProcessor = new AssociationRequestsProcessor(
-                /* cdmService */this, mAssociationStore);
         mCompanionAppController = new CompanionApplicationController(
                 context, mAssociationStore, mDevicePresenceMonitor);
         mTransportManager = new CompanionTransportManager(context, mAssociationStore);
         mSystemDataTransferProcessor = new SystemDataTransferProcessor(this,
                 mPackageManagerInternal, mAssociationStore,
                 mSystemDataTransferRequestStore, mTransportManager);
-        mBackupRestoreProcessor = new BackupRestoreProcessor(
-                /* cdmService */ this, mAssociationStore, mPersistentStore,
-                mSystemDataTransferRequestStore, mAssociationRequestsProcessor);
         // TODO(b/279663946): move context sync to a dedicated system service
         mCrossDeviceSyncController = new CrossDeviceSyncController(getContext(), mTransportManager);
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 2cac7a0..db0f03f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1244,9 +1244,11 @@
     }
 
     private void deliveryTimeout(@NonNull BroadcastProcessQueue queue) {
+        final int cookie = traceBegin("deliveryTimeout");
         synchronized (mService) {
             deliveryTimeoutLocked(queue);
         }
+        traceEnd(cookie);
     }
 
     private void deliveryTimeoutLocked(@NonNull BroadcastProcessQueue queue) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index c1d5ebf..67c23fc 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3475,6 +3475,10 @@
     private void applyAdditionalDisplayInputPropertiesLocked(
             AdditionalDisplayInputProperties properties) {
         // Handle changes to each of the individual properties.
+        // TODO(b/293587049): This approach for updating pointer display properties is only for when
+        //  PointerChoreographer is disabled. Remove this logic when PointerChoreographer is
+        //  permanently enabled.
+
         if (properties.pointerIconVisible != mCurrentDisplayProperties.pointerIconVisible) {
             mCurrentDisplayProperties.pointerIconVisible = properties.pointerIconVisible;
             if (properties.pointerIconVisible) {
@@ -3493,7 +3497,6 @@
                 != mCurrentDisplayProperties.mousePointerAccelerationEnabled) {
             mCurrentDisplayProperties.mousePointerAccelerationEnabled =
                     properties.mousePointerAccelerationEnabled;
-            mNative.setMousePointerAccelerationEnabled(properties.mousePointerAccelerationEnabled);
         }
     }
 
@@ -3507,10 +3510,15 @@
                 mAdditionalDisplayInputProperties.put(displayId, properties);
             }
             final boolean oldPointerIconVisible = properties.pointerIconVisible;
+            final boolean oldMouseAccelerationEnabled = properties.mousePointerAccelerationEnabled;
             updater.accept(properties);
             if (oldPointerIconVisible != properties.pointerIconVisible) {
                 mNative.setPointerIconVisibility(displayId, properties.pointerIconVisible);
             }
+            if (oldMouseAccelerationEnabled != properties.mousePointerAccelerationEnabled) {
+                mNative.setMousePointerAccelerationEnabled(displayId,
+                        properties.mousePointerAccelerationEnabled);
+            }
             if (properties.allDefaults()) {
                 mAdditionalDisplayInputProperties.remove(displayId);
             }
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 706db3d..6f52020 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -119,7 +119,7 @@
 
     void setPointerSpeed(int speed);
 
-    void setMousePointerAccelerationEnabled(boolean enabled);
+    void setMousePointerAccelerationEnabled(int displayId, boolean enabled);
 
     void setTouchpadPointerSpeed(int speed);
 
@@ -354,7 +354,7 @@
         public native void setPointerSpeed(int speed);
 
         @Override
-        public native void setMousePointerAccelerationEnabled(boolean enabled);
+        public native void setMousePointerAccelerationEnabled(int displayId, boolean enabled);
 
         @Override
         public native void setTouchpadPointerSpeed(int speed);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 308d441..425659e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -282,6 +282,7 @@
 import android.service.notification.StatusBarNotification;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeProto;
+import android.service.notification.ZenPolicy;
 import android.telecom.TelecomManager;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
@@ -5968,6 +5969,20 @@
             }
         }
 
+        /**
+         * Gets the device-default zen policy as a ZenPolicy.
+         */
+        @Override
+        public ZenPolicy getDefaultZenPolicy() {
+            enforceSystemOrSystemUI("INotificationManager.getDefaultZenPolicy");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                return mZenModeHelper.getDefaultZenPolicy();
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
         @Override
         public List<String> getEnabledNotificationListenerPackages() {
             checkCallerIsSystem();
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 153af13..c067fa0 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -604,6 +604,14 @@
                 ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg));
                 if (rule == null) {
                     rule = newImplicitZenRule(callingPkg);
+
+                    // For new implicit rules, create a policy matching the current global
+                    // (manual rule) settings, for consistency with the policy that
+                    // would apply if changing the global interruption filter. We only do this
+                    // for newly created rules, as existing rules have a pre-existing policy
+                    // (whether initialized here or set via app or user).
+                    rule.zenPolicy = mConfig.toZenPolicy();
+
                     newConfig.automaticRules.put(rule.id, rule);
                 }
                 // If the user has changed the rule's *zenMode*, then don't let app overwrite it.
@@ -615,6 +623,7 @@
                 rule.condition = new Condition(rule.conditionId,
                         mContext.getString(R.string.zen_mode_implicit_activated),
                         Condition.STATE_TRUE);
+
                 setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP,
                         "applyGlobalZenModeAsImplicitZenRule", callingUid);
             }
@@ -643,8 +652,10 @@
                 return;
             }
             ZenModeConfig newConfig = mConfig.copy();
+            boolean isNew = false;
             ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg));
             if (rule == null) {
+                isNew = true;
                 rule = newImplicitZenRule(callingPkg);
                 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
                 newConfig.automaticRules.put(rule.id, rule);
@@ -652,10 +663,20 @@
             // If the user has changed the rule's *ZenPolicy*, then don't let app overwrite it.
             // We allow the update if the user has only changed other aspects of the rule.
             if (rule.zenPolicyUserModifiedFields == 0) {
+                ZenPolicy newZenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
+                if (isNew) {
+                    // For new rules only, fill anything underspecified in the new policy with
+                    // values from the global configuration, for consistency with the policy that
+                    // would take effect if changing the global policy.
+                    // Note that NotificationManager.Policy cannot have any unset priority
+                    // categories, but *can* have unset visual effects, which is why we do this.
+                    newZenPolicy = mConfig.toZenPolicy().overwrittenWith(newZenPolicy);
+                }
                 updatePolicy(
                         rule,
-                        ZenAdapters.notificationPolicyToZenPolicy(policy),
-                        /* updateBitmask= */ false);
+                        newZenPolicy,
+                        /* updateBitmask= */ false,
+                        isNew);
 
                 setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP,
                         "applyGlobalPolicyAsImplicitZenRule", callingUid);
@@ -685,6 +706,11 @@
             }
             ZenRule implicitRule = mConfig.automaticRules.get(implicitRuleId(callingPkg));
             if (implicitRule != null && implicitRule.zenPolicy != null) {
+                // toNotificationPolicy takes defaults from mConfig, and technically, those are not
+                // the defaults that would apply if any fields were unset. However, all rules should
+                // have all fields set in their ZenPolicy objects upon rule creation, so in
+                // practice, this is only filling in the areChannelsBypassingDnd field, which is a
+                // state rather than a part of the policy.
                 return mConfig.toNotificationPolicy(implicitRule.zenPolicy);
             } else {
                 return getNotificationPolicy();
@@ -1072,7 +1098,8 @@
             rule.zenMode = newZenMode;
 
             // Updates the bitmask and values for all policy fields, based on the origin.
-            updatePolicy(rule, automaticZenRule.getZenPolicy(), updateBitmask);
+            updatePolicy(rule, automaticZenRule.getZenPolicy(), updateBitmask, isNew);
+
             // Updates the bitmask and values for all device effect fields, based on the origin.
             updateZenDeviceEffects(rule, automaticZenRule.getDeviceEffects(),
                     origin == UPDATE_ORIGIN_APP, updateBitmask);
@@ -1111,14 +1138,19 @@
     /**
      * Modifies the {@link ZenPolicy} associated to a new or updated ZenRule.
      *
-     * <p>The new policy is {@code newPolicy}, while the user-modified bitmask is updated to reflect
-     * the changes being applied (if applicable, i.e. if the update is from the user).
+     * <p>The update takes any set fields in {@code newPolicy} as new policy settings for the
+     * provided {@code ZenRule}, keeping any pre-existing settings from {@code zenRule.zenPolicy}
+     * for any unset policy fields in {@code newPolicy}. The user-modified bitmask is updated to
+     * reflect the changes being applied (if applicable, i.e. if the update is from the user).
      */
     private void updatePolicy(ZenRule zenRule, @Nullable ZenPolicy newPolicy,
-            boolean updateBitmask) {
+            boolean updateBitmask, boolean isNew) {
         if (newPolicy == null) {
-            // TODO: b/319242206 - Treat as newPolicy == default policy and continue below.
-            zenRule.zenPolicy = null;
+            if (isNew) {
+                // Newly created rule with no provided policy; fill in with the default.
+                zenRule.zenPolicy = mDefaultConfig.toZenPolicy();
+            }
+            // Otherwise, a null policy means no policy changes, so we can stop here.
             return;
         }
 
@@ -1127,6 +1159,16 @@
         ZenPolicy oldPolicy =
                 zenRule.zenPolicy != null ? zenRule.zenPolicy : mDefaultConfig.toZenPolicy();
 
+        // If this is updating a rule rather than creating a new one, keep any fields from the
+        // old policy if they are unspecified in the new policy. For newly created rules, oldPolicy
+        // has been set to the default settings above, so any unspecified fields in a newly created
+        // policy are filled with default values. Then use the fully-specified version of the new
+        // policy for comparison below.
+        //
+        // Although we do not expect a policy update from the user to contain any unset fields,
+        // filling in fields here also guards against any unset fields counting as a "diff" when
+        // comparing fields for bitmask editing below.
+        newPolicy = oldPolicy.overwrittenWith(newPolicy);
         zenRule.zenPolicy = newPolicy;
 
         if (updateBitmask) {
@@ -1452,11 +1494,27 @@
                     }
 
                     allRulesDisabled &= !automaticRule.enabled;
+
+                    // Upon upgrading to a version with modes_api enabled, keep all behaviors of
+                    // rules with null ZenPolicies explicitly as a copy of the global policy.
+                    if (Flags.modesApi() && config.version < ZenModeConfig.XML_VERSION_MODES_API) {
+                        // Keep the manual ("global") policy that from config.
+                        ZenPolicy manualRulePolicy = config.toZenPolicy();
+                        if (automaticRule.zenPolicy == null) {
+                            automaticRule.zenPolicy = manualRulePolicy;
+                        } else {
+                            // newPolicy is a policy with all unset fields in the rule's zenPolicy
+                            // set to their values from the values in config. Then convert that back
+                            // to ZenPolicy to store with the automatic zen rule.
+                            automaticRule.zenPolicy =
+                                    manualRulePolicy.overwrittenWith(automaticRule.zenPolicy);
+                        }
+                    }
                 }
             }
 
             if (!hasDefaultRules && allRulesDisabled
-                    && (forRestore || config.version < ZenModeConfig.XML_VERSION)) {
+                    && (forRestore || config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE)) {
                 // reset zen automatic rules to default on restore or upgrade if:
                 // - doesn't already have default rules and
                 // - all previous automatic rules were disabled
@@ -1473,7 +1531,7 @@
 
             // Resolve user id for settings.
             userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
-            if (config.version < ZenModeConfig.XML_VERSION) {
+            if (config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE) {
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
                         Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId);
             } else {
@@ -1600,6 +1658,14 @@
         return mConsolidatedPolicy.copy();
     }
 
+    /**
+     * Returns a copy of the device default policy as a ZenPolicy object.
+     */
+    @VisibleForTesting
+    protected ZenPolicy getDefaultZenPolicy() {
+        return mDefaultConfig.toZenPolicy();
+    }
+
     @GuardedBy("mConfigLock")
     private boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
             @ConfigChangeOrigin int origin, String reason, int callingUid) {
@@ -1783,7 +1849,7 @@
     }
 
     @GuardedBy("mConfigLock")
-    private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) {
+    private void applyCustomPolicy(ZenPolicy policy, ZenRule rule, boolean useManualConfig) {
         if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
             policy.apply(new ZenPolicy.Builder()
                     .disallowAllSounds()
@@ -1797,8 +1863,22 @@
         } else if (rule.zenPolicy != null) {
             policy.apply(rule.zenPolicy);
         } else {
-            // active rule with no specified policy inherits the default settings
-            policy.apply(mConfig.toZenPolicy());
+            if (Flags.modesApi()) {
+                if (useManualConfig) {
+                    // manual rule is configured using the settings stored directly in mConfig
+                    policy.apply(mConfig.toZenPolicy());
+                } else {
+                    // under modes_api flag, an active automatic rule with no specified policy
+                    // inherits the device default settings as stored in mDefaultConfig. While the
+                    // rule's policy fields should be set upon creation, this is a fallback to
+                    // catch any that may have fallen through the cracks.
+                    Log.wtf(TAG, "active automatic rule found with no specified policy: " + rule);
+                    policy.apply(mDefaultConfig.toZenPolicy());
+                }
+            } else {
+                // active rule with no specified policy inherits the global config settings
+                policy.apply(mConfig.toZenPolicy());
+            }
         }
     }
 
@@ -1810,7 +1890,7 @@
             ZenPolicy policy = new ZenPolicy();
             ZenDeviceEffects.Builder deviceEffectsBuilder = new ZenDeviceEffects.Builder();
             if (mConfig.manualRule != null) {
-                applyCustomPolicy(policy, mConfig.manualRule);
+                applyCustomPolicy(policy, mConfig.manualRule, true);
                 if (Flags.modesApi()) {
                     deviceEffectsBuilder.add(mConfig.manualRule.zenDeviceEffects);
                 }
@@ -1822,7 +1902,7 @@
                     // policy. This is relevant in case some other active rule has a more
                     // restrictive INTERRUPTION_FILTER but a more lenient ZenPolicy!
                     if (!Flags.modesApi() || automaticRule.zenMode != Global.ZEN_MODE_OFF) {
-                        applyCustomPolicy(policy, automaticRule);
+                        applyCustomPolicy(policy, automaticRule, false);
                     }
                     if (Flags.modesApi()) {
                         deviceEffectsBuilder.add(automaticRule.zenDeviceEffects);
@@ -1830,6 +1910,14 @@
                 }
             }
 
+            // While mConfig.toNotificationPolicy fills in any unset fields from the provided
+            // config (which, in this case is the manual "global" config), under modes API changes,
+            // we should have no remaining unset fields: the manual policy gets every field from
+            // the global policy, and each automatic rule has all policy fields filled in on
+            // creation or update.
+            // However, the piece of information that comes from mConfig that we must keep is the
+            // areChannelsBypassingDnd bit, which is a state, rather than a policy, and even when
+            // all policy fields are set, this state comes to the new policy from this call.
             Policy newPolicy = mConfig.toNotificationPolicy(policy);
             if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
                 mConsolidatedPolicy = newPolicy;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 68c95b1..ac826af 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -18,10 +18,6 @@
 
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.app.ActivityOptions.KEY_SPLASH_SCREEN_THEME;
-import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.app.AppOpsManager.OP_ARCHIVE_ICON_OVERLAY;
-import static android.app.AppOpsManager.OP_UNARCHIVAL_CONFIRMATION;
 import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
 import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -47,7 +43,6 @@
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
-import android.app.AppOpsManager;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyCache;
@@ -218,7 +213,6 @@
         private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
         private final ShortcutServiceInternal mShortcutServiceInternal;
         private final PackageManagerInternal mPackageManagerInternal;
-        private final AppOpsManager mAppOpsManager;
         private final PackageCallbackList<IOnAppsChangedListener> mListeners
                 = new PackageCallbackList<IOnAppsChangedListener>();
         private final DevicePolicyManager mDpm;
@@ -259,7 +253,6 @@
                     LocalServices.getService(ShortcutServiceInternal.class));
             mPackageManagerInternal = Objects.requireNonNull(
                     LocalServices.getService(PackageManagerInternal.class));
-            mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
             mShortcutServiceInternal.addListener(mPackageMonitor);
             mShortcutChangeHandler = new ShortcutChangeHandler(mUserManagerInternal);
             mShortcutServiceInternal.addShortcutChangeCallback(mShortcutChangeHandler);
@@ -2005,23 +1998,6 @@
             }
         }
 
-        @Override
-        public void setArchiveCompatibilityOptions(boolean enableIconOverlay,
-                boolean enableUnarchivalConfirmation) {
-            int callingUid = Binder.getCallingUid();
-            Binder.withCleanCallingIdentity(
-                    () -> {
-                        mAppOpsManager.setUidMode(
-                                OP_ARCHIVE_ICON_OVERLAY,
-                                callingUid,
-                                enableIconOverlay ? MODE_ALLOWED : MODE_IGNORED);
-                        mAppOpsManager.setUidMode(
-                                OP_UNARCHIVAL_CONFIRMATION,
-                                callingUid,
-                                enableUnarchivalConfirmation ? MODE_ALLOWED : MODE_IGNORED);
-                    });
-        }
-
         /** Checks if user is a profile of or same as listeningUser.
          * and the user is enabled. */
         private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user,
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index c1b3673..1a20c8d 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -20,7 +20,6 @@
 import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
 import static android.app.ActivityManager.START_PERMISSION_DENIED;
 import static android.app.ActivityManager.START_SUCCESS;
-import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
 import static android.content.pm.ArchivedActivityInfo.bytesFromBitmap;
@@ -274,12 +273,11 @@
         Slog.i(TAG, TextUtils.formatSimple("Unarchival is starting for: %s", packageName));
 
         try {
+            // TODO(b/311709794) Make showUnarchivalConfirmation dependent on the compat options.
             requestUnarchive(packageName, callerPackageName,
                     getOrCreateLauncherListener(userId, packageName),
                     UserHandle.of(userId),
-                    getAppOpsManager().checkOp(
-                            AppOpsManager.OP_UNARCHIVAL_CONFIRMATION, callingUid, callerPackageName)
-                            == MODE_ALLOWED);
+                    false /* showUnarchivalConfirmation= */);
         } catch (Throwable t) {
             Slog.e(TAG, TextUtils.formatSimple(
                     "Unexpected error occurred while unarchiving package %s: %s.", packageName,
@@ -796,8 +794,7 @@
      * <p> The icon is returned without any treatment/overlay. In the rare case the app had multiple
      * launcher activities, only one of the icons is returned arbitrarily.
      */
-    public Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user,
-            String callingPackageName) {
+    public Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user) {
         Objects.requireNonNull(packageName);
         Objects.requireNonNull(user);
 
@@ -820,13 +817,7 @@
         // TODO(b/298452477) Handle monochrome icons.
         // In the rare case the archived app defined more than two launcher activities, we choose
         // the first one arbitrarily.
-        Bitmap icon = decodeIcon(archiveState.getActivityInfos().get(0));
-        if (getAppOpsManager().checkOp(
-                AppOpsManager.OP_ARCHIVE_ICON_OVERLAY, callingUid, callingPackageName)
-                == MODE_ALLOWED) {
-            icon = includeCloudOverlay(icon);
-        }
-        return icon;
+        return includeCloudOverlay(decodeIcon(archiveState.getActivityInfos().get(0)));
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f09fa21..609b3aa 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6388,10 +6388,8 @@
         }
 
         @Override
-        public Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user,
-                @NonNull String callingPackageName) {
-            return mInstallerService.mPackageArchiver.getArchivedAppIcon(packageName, user,
-                    callingPackageName);
+        public Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user) {
+            return mInstallerService.mPackageArchiver.getArchivedAppIcon(packageName, user);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 88dc60c..bdde272 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3716,7 +3716,19 @@
                         // remember to set it themselves.
                         params.installerPackageName = "com.android.shell";
                     }
-                    sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
+                    int rollbackStrategy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
+                    try {
+                        rollbackStrategy = Integer.parseInt(peekNextArg());
+                        if (rollbackStrategy < PackageManager.ROLLBACK_DATA_POLICY_RESTORE
+                                || rollbackStrategy > PackageManager.ROLLBACK_DATA_POLICY_RETAIN) {
+                            throw new IllegalArgumentException(
+                                    rollbackStrategy + " is not a valid rollback data policy.");
+                        }
+                        getNextArg(); // pop the argument
+                    } catch (NumberFormatException e) {
+                        // not followed by a number assume ROLLBACK_DATA_POLICY_RESTORE.
+                    }
+                    sessionParams.setEnableRollback(true, rollbackStrategy);
                     break;
                 case "--staged-ready-timeout":
                     params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired());
@@ -3751,6 +3763,11 @@
         } else if (staged) {
             sessionParams.setStaged();
         }
+        if ((sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0
+                && (sessionParams.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
+                && sessionParams.rollbackDataPolicy == PackageManager.ROLLBACK_DATA_POLICY_WIPE) {
+            throw new IllegalArgumentException("Data policy 'wipe' is not supported for apex.");
+        }
         return params;
     }
 
@@ -4829,7 +4846,7 @@
         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
         pw.println("       [--preload] [--instant] [--full] [--dont-kill]");
-        pw.println("       [--enable-rollback]");
+        pw.println("       [--enable-rollback [0/1/2]]");
         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
         pw.println("       [--apex] [--non-staged] [--force-non-staged]");
         pw.println("       [--staged-ready-timeout TIMEOUT] [--ignore-dexopt-profile]");
@@ -4853,6 +4870,8 @@
         pw.println("      --abi: override the default ABI of the platform");
         pw.println("      --instant: cause the app to be installed as an ephemeral install app");
         pw.println("      --full: cause the app to be installed as a non-ephemeral full app");
+        pw.println("      --enable-rollback: enable rollbacks for the upgrade.");
+        pw.println("          0=restore (default), 1=wipe, 2=retain");
         pw.println("      --install-location: force the install location:");
         pw.println("          0=auto, 1=internal only, 2=prefer external");
         pw.println("      --install-reason: indicates why the app is being installed:");
diff --git a/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java b/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java
index 5e8b4de..7808c4e 100644
--- a/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java
+++ b/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java
@@ -30,6 +30,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
 import android.os.Environment;
+import android.permission.flags.Flags;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -368,6 +369,7 @@
             dataOutputStream.writeUTF(profileOwner);
             dataOutputStream.writeInt(Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.DEVICE_DEMO_MODE, 0));
+            dataOutputStream.writeBoolean(Flags.walletRoleEnabled());
             dataOutputStream.flush();
         } catch (IOException e) {
             // Never happens for MessageDigestOutputStream and DataOutputStream.
diff --git a/services/core/java/com/android/server/rollback/README.md b/services/core/java/com/android/server/rollback/README.md
index 08800da..f6bcbd0 100644
--- a/services/core/java/com/android/server/rollback/README.md
+++ b/services/core/java/com/android/server/rollback/README.md
@@ -187,13 +187,22 @@
 
 ### Installing an App with Rollback Enabled
 
-The `adb install` command accepts the `--enable-rollback` flag to install an app
+The `adb install` command accepts the `--enable-rollback [0/1/2]` flag to install an app
 with rollback enabled. For example:
 
 ```
 $ adb install --enable-rollback FooV2.apk
 ```
 
+The default rollback data policy is `ROLLBACK_DATA_POLICY_RESTORE` (0). To use
+a different `RollbackDataPolicy`, like `ROLLBACK_DATA_POLICY_RETAIN` (1) or
+`ROLLBACK_DATA_POLICY_WIPE` (2), provide the int value after
+`--enable-rollback`. For example:
+
+```
+$ adb install --enable-rollback 1 FooV2.apk
+```
+
 ### Triggering Rollback Manually
 
 If rollback is available for an application, the pm command can be used to
@@ -217,7 +226,7 @@
   -state: committed
   -timestamp: 2019-04-23T14:57:35.944Z
   -packages:
-    com.android.tests.rollback.testapp.B 2 -> 1
+    com.android.tests.rollback.testapp.B 2 -> 1 [0]
   -causePackages:
   -committedSessionId: 1845805640
 649899517:
@@ -225,7 +234,7 @@
   -timestamp: 2019-04-23T12:55:21.342Z
   -stagedSessionId: 343374391
   -packages:
-    com.android.tests.rollback.testapex 2 -> 1
+    com.android.tests.rollback.testapex 2 -> 1 [0]
   -causePackages:
   -committedSessionId: 2096717281
 ```
@@ -233,7 +242,8 @@
 The example above shows two recently committed rollbacks. The update of
 com.android.tests.rollback.testapp.B from version 1 to version 2 was rolled
 back, and the update of com.android.tests.rollback.testapex from version 1 to
-version 2 was rolled back.
+version 2 was rolled back. For each package the value inside '[' and ']'
+indicates the `RollbackDataPolicy` for the rollback back.
 
 The state is 'available' or 'committed'. The timestamp gives the time when the
 rollback was first made available. If a stagedSessionId is present, then the
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index a580bb7..d1f91c8 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -967,7 +967,8 @@
         for (PackageRollbackInfo pkg : info.getPackages()) {
             ipw.println(pkg.getPackageName()
                     + " " + pkg.getVersionRolledBackFrom().getLongVersionCode()
-                    + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
+                    + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode()
+                    + " [" + pkg.getRollbackDataPolicy() + "]");
         }
         ipw.decreaseIndent();
         if (isCommitted()) {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 73fc8e9..ac1b4df 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -3860,6 +3860,23 @@
         }
 
         @Override
+        public void onVideoFreezeUpdated(boolean isFrozen) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onVideoFreezeUpdated(" + isFrozen + ")");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onVideoFreezeUpdated(isFrozen, mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onVideoFreezeUpdated", e);
+                }
+            }
+        }
+
+        @Override
         public void onContentAllowed() {
             synchronized (mLock) {
                 if (DEBUG) {
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index 7ab075e..9c60fbb 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -1470,6 +1470,28 @@
         }
 
         @Override
+        public void notifyVideoFreezeUpdated(IBinder sessionToken, boolean isFrozen, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+                    "notifyVideoFreezeUpdated");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
+                                resolvedUserId);
+                        getSessionLocked(sessionState).notifyVideoFreezeUpdated(isFrozen);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in notifyVideoFreezeUpdated", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void notifyContentAllowed(IBinder sessionToken, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
@@ -1557,7 +1579,6 @@
             }
         }
 
-
         @Override
         public void notifyRecordingStarted(IBinder sessionToken, String recordingId,
                 String requestId, int userId) {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index ce0efe1..2049331 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -46,6 +46,7 @@
 #include <com_android_input_flags.h>
 #include <input/Input.h>
 #include <input/PointerController.h>
+#include <input/PrintTools.h>
 #include <input/SpriteController.h>
 #include <inputflinger/InputManager.h>
 #include <limits.h>
@@ -230,10 +231,6 @@
     return a > b ? a : b;
 }
 
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
 static SpriteIcon toSpriteIcon(PointerIcon pointerIcon) {
     // As a minor optimization, do not make a copy of the PointerIcon bitmap here. The loaded
     // PointerIcons are only cached by InputManagerService in java, so we can safely assume they
@@ -288,7 +285,7 @@
     void setSystemUiLightsOut(bool lightsOut);
     void setPointerDisplayId(int32_t displayId);
     void setPointerSpeed(int32_t speed);
-    void setMousePointerAccelerationEnabled(bool enabled);
+    void setMousePointerAccelerationEnabled(int32_t displayId, bool enabled);
     void setTouchpadPointerSpeed(int32_t speed);
     void setTouchpadNaturalScrollingEnabled(bool enabled);
     void setTouchpadTapToClickEnabled(bool enabled);
@@ -401,8 +398,8 @@
         // Pointer speed.
         int32_t pointerSpeed{0};
 
-        // True if pointer acceleration is enabled for mice.
-        bool mousePointerAccelerationEnabled{true};
+        // Displays on which its associated mice will have pointer acceleration disabled.
+        std::set<int32_t> displaysWithMousePointerAccelerationDisabled{};
 
         // True if pointer gestures are enabled.
         bool pointerGesturesEnabled{true};
@@ -493,8 +490,8 @@
         dump += StringPrintf(INDENT "System UI Lights Out: %s\n",
                              toString(mLocked.systemUiLightsOut));
         dump += StringPrintf(INDENT "Pointer Speed: %" PRId32 "\n", mLocked.pointerSpeed);
-        dump += StringPrintf(INDENT "Mouse Pointer Acceleration: %s\n",
-                             mLocked.mousePointerAccelerationEnabled ? "Enabled" : "Disabled");
+        dump += StringPrintf(INDENT "Display with Mouse Pointer Acceleration Disabled: %s\n",
+                             dumpSet(mLocked.displaysWithMousePointerAccelerationDisabled).c_str());
         dump += StringPrintf(INDENT "Pointer Gestures Enabled: %s\n",
                 toString(mLocked.pointerGesturesEnabled));
         dump += StringPrintf(INDENT "Show Touches: %s\n", toString(mLocked.showTouches));
@@ -677,11 +674,13 @@
         std::scoped_lock _l(mLock);
 
         outConfig->mousePointerSpeed = mLocked.pointerSpeed;
-        outConfig->mousePointerAccelerationEnabled = mLocked.mousePointerAccelerationEnabled;
-        outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed
-                * POINTER_SPEED_EXPONENT);
+        outConfig->displaysWithMousePointerAccelerationDisabled =
+                mLocked.displaysWithMousePointerAccelerationDisabled;
+        outConfig->pointerVelocityControlParameters.scale =
+                exp2f(mLocked.pointerSpeed * POINTER_SPEED_EXPONENT);
         outConfig->pointerVelocityControlParameters.acceleration =
-                mLocked.mousePointerAccelerationEnabled
+                mLocked.displaysWithMousePointerAccelerationDisabled.count(
+                        mLocked.pointerDisplayId) == 0
                 ? android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION
                 : 1;
         outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
@@ -1225,16 +1224,23 @@
             InputReaderConfiguration::Change::POINTER_SPEED);
 }
 
-void NativeInputManager::setMousePointerAccelerationEnabled(bool enabled) {
+void NativeInputManager::setMousePointerAccelerationEnabled(int32_t displayId, bool enabled) {
     { // acquire lock
         std::scoped_lock _l(mLock);
 
-        if (mLocked.mousePointerAccelerationEnabled == enabled) {
+        const bool oldEnabled =
+                mLocked.displaysWithMousePointerAccelerationDisabled.count(displayId) == 0;
+        if (oldEnabled == enabled) {
             return;
         }
 
-        ALOGI("Setting mouse pointer acceleration to %s", toString(enabled));
-        mLocked.mousePointerAccelerationEnabled = enabled;
+        ALOGI("Setting mouse pointer acceleration to %s on display %d", toString(enabled),
+              displayId);
+        if (enabled) {
+            mLocked.displaysWithMousePointerAccelerationDisabled.erase(displayId);
+        } else {
+            mLocked.displaysWithMousePointerAccelerationDisabled.emplace(displayId);
+        }
     } // release lock
 
     mInputManager->getReader().requestRefreshConfiguration(
@@ -2176,10 +2182,10 @@
 }
 
 static void nativeSetMousePointerAccelerationEnabled(JNIEnv* env, jobject nativeImplObj,
-                                                     jboolean enabled) {
+                                                     jint displayId, jboolean enabled) {
     NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
 
-    im->setMousePointerAccelerationEnabled(enabled);
+    im->setMousePointerAccelerationEnabled(displayId, enabled);
 }
 
 static void nativeSetTouchpadPointerSpeed(JNIEnv* env, jobject nativeImplObj, jint speed) {
@@ -2806,7 +2812,7 @@
          (void*)nativeTransferTouchFocus},
         {"transferTouch", "(Landroid/os/IBinder;I)Z", (void*)nativeTransferTouch},
         {"setPointerSpeed", "(I)V", (void*)nativeSetPointerSpeed},
-        {"setMousePointerAccelerationEnabled", "(Z)V",
+        {"setMousePointerAccelerationEnabled", "(IZ)V",
          (void*)nativeSetMousePointerAccelerationEnabled},
         {"setTouchpadPointerSpeed", "(I)V", (void*)nativeSetTouchpadPointerSpeed},
         {"setTouchpadNaturalScrollingEnabled", "(Z)V",
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 11c40d7..9c033e2 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -675,7 +675,8 @@
     options.enableCorrVecOutputs = enableCorrVecOutputs;
     options.intervalMs = intervalMs;
 
-    return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(),
+    return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(
+                                                     gnssMeasurementIface->getInterfaceVersion()),
                                              options);
 }
 
diff --git a/services/core/jni/gnss/Gnss.cpp b/services/core/jni/gnss/Gnss.cpp
index 8934c3a..da8928b5 100644
--- a/services/core/jni/gnss/Gnss.cpp
+++ b/services/core/jni/gnss/Gnss.cpp
@@ -196,7 +196,8 @@
 
 jboolean GnssHal::setCallback() {
     if (gnssHalAidl != nullptr) {
-        sp<IGnssCallbackAidl> gnssCbIfaceAidl = new GnssCallbackAidl();
+        sp<IGnssCallbackAidl> gnssCbIfaceAidl =
+                new GnssCallbackAidl(gnssHalAidl->getInterfaceVersion());
         auto status = gnssHalAidl->setCallback(gnssCbIfaceAidl);
         if (!checkAidlStatus(status, "IGnssAidl setCallback() failed.")) {
             return JNI_FALSE;
diff --git a/services/core/jni/gnss/GnssCallback.cpp b/services/core/jni/gnss/GnssCallback.cpp
index 60eed8e6..3d598f7 100644
--- a/services/core/jni/gnss/GnssCallback.cpp
+++ b/services/core/jni/gnss/GnssCallback.cpp
@@ -120,7 +120,7 @@
 
 Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
     ALOGD("%s: %du\n", __func__, capabilities);
-    bool isAdrCapabilityKnown = (getInterfaceVersion() >= 3) ? true : false;
+    bool isAdrCapabilityKnown = (interfaceVersion >= 3) ? true : false;
     JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities,
                         isAdrCapabilityKnown);
@@ -178,7 +178,7 @@
 
 Status GnssCallbackAidl::gnssNmeaCb(const int64_t timestamp, const std::string& nmea) {
     // In AIDL v1, if no listener is registered, do not report nmea to the framework.
-    if (getInterfaceVersion() <= 1) {
+    if (interfaceVersion <= 1) {
         if (!isNmeaRegistered) {
             return Status::ok();
         }
diff --git a/services/core/jni/gnss/GnssCallback.h b/services/core/jni/gnss/GnssCallback.h
index 33acec8..0622e53 100644
--- a/services/core/jni/gnss/GnssCallback.h
+++ b/services/core/jni/gnss/GnssCallback.h
@@ -60,6 +60,7 @@
  */
 class GnssCallbackAidl : public hardware::gnss::BnGnssCallback {
 public:
+    GnssCallbackAidl(int version) : interfaceVersion(version){};
     binder::Status gnssSetCapabilitiesCb(const int capabilities) override;
     binder::Status gnssSetSignalTypeCapabilitiesCb(
             const std::vector<android::hardware::gnss::GnssSignalType>& signalTypes) override;
@@ -73,6 +74,9 @@
     binder::Status gnssRequestTimeCb() override;
     binder::Status gnssRequestLocationCb(const bool independentFromGnss,
                                          const bool isUserEmergency) override;
+
+private:
+    const int interfaceVersion;
 };
 
 /*
diff --git a/services/core/jni/gnss/GnssMeasurement.h b/services/core/jni/gnss/GnssMeasurement.h
index 7a95db8..20400fd 100644
--- a/services/core/jni/gnss/GnssMeasurement.h
+++ b/services/core/jni/gnss/GnssMeasurement.h
@@ -41,6 +41,7 @@
             const std::unique_ptr<GnssMeasurementCallback>& callback,
             const android::hardware::gnss::IGnssMeasurementInterface::Options& options) = 0;
     virtual jboolean close() = 0;
+    virtual int getInterfaceVersion() = 0;
 };
 
 class GnssMeasurement : public GnssMeasurementInterface {
@@ -50,6 +51,9 @@
             const std::unique_ptr<GnssMeasurementCallback>& callback,
             const android::hardware::gnss::IGnssMeasurementInterface::Options& options) override;
     jboolean close() override;
+    int getInterfaceVersion() override {
+        return mIGnssMeasurement->getInterfaceVersion();
+    }
 
 private:
     const sp<android::hardware::gnss::IGnssMeasurementInterface> mIGnssMeasurement;
@@ -63,6 +67,9 @@
             const std::unique_ptr<GnssMeasurementCallback>& callback,
             const android::hardware::gnss::IGnssMeasurementInterface::Options& options) override;
     jboolean close() override;
+    int getInterfaceVersion() override {
+        return 0;
+    }
 
 private:
     const sp<android::hardware::gnss::V1_0::IGnssMeasurement> mIGnssMeasurement_V1_0;
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index 2982546..ebab4c3 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -392,7 +392,7 @@
 
     jobjectArray gnssAgcArray = nullptr;
     gnssAgcArray = translateAllGnssAgcs(env, data.gnssAgcs);
-    if (this->getInterfaceVersion() >= 3) {
+    if (interfaceVersion >= 3) {
         setMeasurementData(env, mCallbacksObj, clock, measurementArray, gnssAgcArray,
                            /*hasIsFullTracking=*/true, data.isFullTracking);
     } else {
@@ -467,7 +467,7 @@
                                            satellitePvt.tropoDelayMeters);
         }
 
-        if (this->getInterfaceVersion() >= 2) {
+        if (interfaceVersion >= 2) {
             callObjectMethodIgnoringResult(env, satellitePvtBuilderObject,
                                            method_satellitePvtBuilderSetTimeOfClock,
                                            satellitePvt.timeOfClockSeconds);
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.h b/services/core/jni/gnss/GnssMeasurementCallback.h
index b3de486..3cb47ce 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.h
+++ b/services/core/jni/gnss/GnssMeasurementCallback.h
@@ -53,7 +53,8 @@
 
 class GnssMeasurementCallbackAidl : public hardware::gnss::BnGnssMeasurementCallback {
 public:
-    GnssMeasurementCallbackAidl() : mCallbacksObj(getCallbacksObj()) {}
+    GnssMeasurementCallbackAidl(int version)
+          : mCallbacksObj(getCallbacksObj()), interfaceVersion(version) {}
     android::binder::Status gnssMeasurementCb(const hardware::gnss::GnssData& data) override;
 
 private:
@@ -71,6 +72,7 @@
     void translateGnssClock(JNIEnv* env, const hardware::gnss::GnssData& data, JavaObject& object);
 
     jobject& mCallbacksObj;
+    const int interfaceVersion;
 };
 
 /*
@@ -110,10 +112,10 @@
 
 class GnssMeasurementCallback {
 public:
-    GnssMeasurementCallback() {}
+    GnssMeasurementCallback(int version) : interfaceVersion(version) {}
     sp<GnssMeasurementCallbackAidl> getAidl() {
         if (callbackAidl == nullptr) {
-            callbackAidl = sp<GnssMeasurementCallbackAidl>::make();
+            callbackAidl = sp<GnssMeasurementCallbackAidl>::make(interfaceVersion);
         }
         return callbackAidl;
     }
@@ -128,6 +130,7 @@
 private:
     sp<GnssMeasurementCallbackAidl> callbackAidl;
     sp<GnssMeasurementCallbackHidl> callbackHidl;
+    const int interfaceVersion;
 };
 
 template <class T>
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index f469ab5..097d73a 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -960,8 +960,8 @@
 
         if (permissionName !in androidPackage.requestedPermissions && oldFlags == 0) {
             if (reportError) {
-                throw SecurityException(
-                    "Permission $permissionName isn't requested by package $packageName"
+                Slog.e(
+                    LOG_TAG, "Permission $permissionName isn't requested by package $packageName"
                 )
             }
             return
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index e989d7b..ec7e359 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -552,22 +552,20 @@
         when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
                 null);
 
-        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT,
-                CALLER_PACKAGE)).isNull();
+        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT)).isNull();
     }
 
     @Test
     public void getArchivedAppIcon_notArchived() {
-        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT,
-                CALLER_PACKAGE)).isNull();
+        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT)).isNull();
     }
 
     @Test
     public void getArchivedAppIcon_success() {
         mUserState.setArchiveState(createArchiveState()).setInstalled(false);
 
-        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT,
-                CALLER_PACKAGE)).isEqualTo(mIcon);
+        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT)).isEqualTo(
+                mIcon);
     }
 
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 81df597..0805485 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -157,7 +157,6 @@
                     return mMockDevicePolicyManager;
                 case Context.APP_SEARCH_SERVICE:
                 case Context.ROLE_SERVICE:
-                case Context.APP_OPS_SERVICE:
                     // RoleManager is final and cannot be mocked, so we only override the inject
                     // accessor methods in ShortcutService.
                     return getTestContext().getSystemService(name);
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 2486838..25ad7db 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -59,6 +59,7 @@
 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;
 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER;
 import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS;
+import static android.service.notification.ZenPolicy.PEOPLE_TYPE_NONE;
 import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED;
 
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.LOG_DND_STATE_EVENTS;
@@ -123,6 +124,7 @@
 import android.os.Process;
 import android.os.SimpleClock;
 import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
@@ -238,15 +240,19 @@
     public TestWithLooperRule mLooperRule = new TestWithLooperRule();
 
     ConditionProviders mConditionProviders;
-    @Mock NotificationManager mNotificationManager;
-    @Mock PackageManager mPackageManager;
+    @Mock
+    NotificationManager mNotificationManager;
+    @Mock
+    PackageManager mPackageManager;
     private Resources mResources;
     private TestableLooper mTestableLooper;
     private final TestClock mTestClock = new TestClock();
     private ZenModeHelper mZenModeHelper;
     private ContentResolver mContentResolver;
-    @Mock DeviceEffectsApplier mDeviceEffectsApplier;
-    @Mock AppOpsManager mAppOps;
+    @Mock
+    DeviceEffectsApplier mDeviceEffectsApplier;
+    @Mock
+    AppOpsManager mAppOps;
     TestableFlagResolver mTestFlagResolver = new TestableFlagResolver();
     ZenModeEventLoggerFake mZenModeEventLogger;
 
@@ -290,7 +296,7 @@
         when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt()))
                 .thenReturn(CUSTOM_PKG_UID);
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
-                new String[] {pkg});
+                new String[]{pkg});
 
         ApplicationInfo appInfoSpy = spy(new ApplicationInfo());
         appInfoSpy.icon = ICON_RES_ID;
@@ -305,24 +311,26 @@
     }
 
     private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException {
-        String xml = "<zen version=\"8\" user=\"0\">\n"
-                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
-                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
-                + "visualScreenOff=\"true\" alarms=\"true\" "
-                + "media=\"true\" system=\"false\" conversations=\"true\""
-                + " conversationsFrom=\"2\"/>\n"
-                + "<automatic ruleId=\"" + EVENTS_DEFAULT_RULE_ID
-                + "\" enabled=\"false\" snoozing=\"false\""
-                + " name=\"Event\" zen=\"1\""
-                + " component=\"android/com.android.server.notification.EventConditionProvider\""
-                + " conditionId=\"condition://android/event?userId=-10000&amp;calendar=&amp;"
+        String xml = "<zen version=\"10\">\n"
+                + "<allow alarms=\"true\" media=\"true\" system=\"false\" calls=\"true\" "
+                + "callsFrom=\"2\" messages=\"true\"\n"
+                + "messagesFrom=\"2\" reminders=\"false\" events=\"false\" "
+                + "repeatCallers=\"true\" convos=\"true\"\n"
+                + "convosFrom=\"2\"/>\n"
+                + "<automatic ruleId=" + EVENTS_DEFAULT_RULE_ID
+                + " enabled=\"false\" snoozing=\"false\""
+                + " name=\"Event\" zen=\"1\"\n"
+                + "  component=\"android/com.android.server.notification.EventConditionProvider\"\n"
+                + "  conditionId=\"condition://android/event?userId=-10000&amp;calendar=&amp;"
                 + "reply=1\"/>\n"
-                + "<automatic ruleId=\"" + SCHEDULE_DEFAULT_RULE_ID + "\" enabled=\"false\""
-                + " snoozing=\"false\" name=\"Sleeping\" zen=\"1\""
-                + " component=\"android/com.android.server.notification.ScheduleConditionProvider\""
-                + " conditionId=\"condition://android/schedule?days=1.2.3.4.5.6.7 &amp;start=22.0"
-                + "&amp;end=7.0&amp;exitAtAlarm=true\"/>"
-                + "<disallow visualEffects=\"511\" />"
+                + "<automatic ruleId=" + SCHEDULE_DEFAULT_RULE_ID + " enabled=\"false\""
+                + " snoozing=\"false\" name=\"Sleeping\"\n zen=\"1\""
+                + " component=\"android/com.android.server.notification"
+                + ".ScheduleConditionProvider\"\n"
+                + " conditionId=\"condition://android/schedule?days=1.2.3.4.5.6.7&amp;start=22.0"
+                + "&amp;end=7.0&amp;exitAtAlarm=true\"/>\n"
+                + "<disallow visualEffects=\"157\" />\n"
+                + "<state areChannelsBypassingDnd=\"false\" />\n"
                 + "</zen>";
         TypedXmlPullParser parser = Xml.newFastPullParser();
         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), null);
@@ -408,7 +416,7 @@
     @Test
     public void testZenOff_NoMuteApplied() {
         mZenModeHelper.mZenMode = ZEN_MODE_OFF;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS
                 | PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
@@ -421,7 +429,7 @@
     @Test
     public void testZenOn_NotificationApplied() {
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         // The most permissive policy
         mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS
                 | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
@@ -442,7 +450,7 @@
     @Test
     public void testZenOn_StarredCallers_CallTypesBlocked() {
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         // The most permissive policy
         mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS
                 | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
@@ -462,7 +470,7 @@
     @Test
     public void testZenOn_AllCallers_CallTypesAllowed() {
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         // The most permissive policy
         mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS
                 | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
@@ -481,7 +489,7 @@
     @Test
     public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() {
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS
                 | PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
 
@@ -493,7 +501,7 @@
     @Test
     public void testZenOn_DisallowAlarmsMedia_AlarmMediaMuteApplied() {
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
         verifyApplyRestrictions(true, true, AudioAttributes.USAGE_ALARM);
@@ -506,7 +514,7 @@
     @Test
     public void testTotalSilence() {
         mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS
                 | PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
@@ -525,7 +533,7 @@
     @Test
     public void testAlarmsOnly_alarmMediaMuteNotApplied() {
         mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
 
@@ -545,7 +553,7 @@
     @Test
     public void testAlarmsOnly_callsMuteApplied() {
         mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
 
@@ -559,7 +567,7 @@
     public void testAlarmsOnly_allZenConfigToggledCannotBypass_alarmMuteNotApplied() {
         // Only audio attributes with SUPPRESIBLE_NEVER can bypass
         mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
 
@@ -571,7 +579,7 @@
         // Only audio attributes with SUPPRESIBLE_NEVER can bypass
         // with special case USAGE_ASSISTANCE_SONIFICATION
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
 
@@ -592,7 +600,7 @@
 
     @Test
     public void testApplyRestrictions_whitelist_priorityOnlyMode() {
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
@@ -607,7 +615,7 @@
 
     @Test
     public void testApplyRestrictions_whitelist_alarmsOnlyMode() {
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mZenMode = Global.ZEN_MODE_ALARMS;
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
@@ -622,7 +630,7 @@
 
     @Test
     public void testApplyRestrictions_whitelist_totalSilenceMode() {
-        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O});
         mZenModeHelper.mZenMode = Global.ZEN_MODE_NO_INTERRUPTIONS;
         mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
         mZenModeHelper.applyRestrictions();
@@ -1007,7 +1015,7 @@
         mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
 
         assertEquals("Config mismatch: current vs expected: "
-                + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, expected), expected,
+                        + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, expected), expected,
                 mZenModeHelper.mConfig);
     }
 
@@ -1336,7 +1344,7 @@
         mZenModeHelper.readXml(parser, true, UserHandle.USER_SYSTEM);
 
         assertEquals("Config mismatch: current vs original: "
-                + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, original),
+                        + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, original),
                 original, mZenModeHelper.mConfig);
         assertEquals(original.hashCode(), mZenModeHelper.mConfig.hashCode());
     }
@@ -1778,6 +1786,225 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testReadXml_onModesApi_noUpgrade() throws Exception {
+        // When reading XML for something that is already on the modes API system, make sure no
+        // rules' policies get changed.
+        setupZenConfig();
+
+        // Shared for rules
+        ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRules = new ArrayMap<>();
+        final ScheduleInfo weeknights = new ScheduleInfo();
+
+        // Custom rule with a custom policy
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        customRule.enabled = true;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
+        customRule.component = new ComponentName("android", "ScheduleConditionProvider");
+        ZenPolicy policy = new ZenPolicy.Builder()
+                .allowCalls(PEOPLE_TYPE_CONTACTS)
+                .allowAlarms(true)
+                .allowRepeatCallers(false)
+                .build();
+        // Fill in policy fields, since on modes api we do not expect any rules to have unset fields
+        customRule.zenPolicy = mZenModeHelper.getDefaultZenPolicy().overwrittenWith(policy);
+        enabledAutoRules.put("customRule", customRule);
+        mZenModeHelper.mConfig.automaticRules = enabledAutoRules;
+
+        // set version to post-modes-API = 11
+        ByteArrayOutputStream baos = writeXmlAndPurge(11);
+        TypedXmlPullParser parser = Xml.newFastPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+        // basic check: global config maintained
+        setupZenConfigMaintained();
+
+        // Find our automatic rules.
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
+        assertThat(rules).hasSize(1);
+        assertThat(rules).containsKey("customRule");
+        ZenRule rule = rules.get("customRule");
+        assertThat(rule.zenPolicy).isEqualTo(customRule.zenPolicy);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testReadXml_upgradeToModesApi_makesCustomPolicies() throws Exception {
+        // When reading in an XML file written from a pre-modes-API version, confirm that we create
+        // a custom policy matching the global config for any automatic rule with no specified
+        // policy.
+        setupZenConfig();
+
+        ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo weeknights = new ScheduleInfo();
+        customRule.enabled = true;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
+        customRule.component = new ComponentName("android", "ScheduleConditionProvider");
+        enabledAutoRule.put("customRule", customRule);  // no custom policy set
+        mZenModeHelper.mConfig.automaticRules = enabledAutoRule;
+
+        // set version to pre-modes-API = 10
+        ByteArrayOutputStream baos = writeXmlAndPurge(10);
+        TypedXmlPullParser parser = Xml.newFastPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+        // basic check: global config maintained
+        setupZenConfigMaintained();
+
+        // Find our automatic rule and check that it has a policy set now
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
+        assertThat(rules).hasSize(1);
+        assertThat(rules).containsKey("customRule");
+        ZenRule rule = rules.get("customRule");
+        assertThat(rule.zenPolicy).isNotNull();
+
+        // Check policy values as set up in setupZenConfig() to confirm they match
+        assertThat(rule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_DISALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryMedia()).isEqualTo(STATE_DISALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategorySystem()).isEqualTo(STATE_DISALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryReminders()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryCalls()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_STARRED);
+        assertThat(rule.zenPolicy.getPriorityCategoryMessages()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryConversations()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryEvents()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryRepeatCallers()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getVisualEffectBadge()).isEqualTo(STATE_DISALLOW);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testReadXml_upgradeToModesApi_fillsInCustomPolicies() throws Exception {
+        // When reading in an XML file written from a pre-modes-API version, confirm that for an
+        // underspecified ZenPolicy, we fill in all of the gaps with things from the global config
+        // in order to maintain consistency of behavior.
+        setupZenConfig();
+
+        ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo weeknights = new ScheduleInfo();
+        customRule.enabled = true;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
+        customRule.component = new ComponentName("android", "ScheduleConditionProvider");
+        customRule.zenPolicy = new ZenPolicy.Builder()
+                .allowAlarms(true)
+                .allowMedia(true)
+                .allowRepeatCallers(false)
+                .build();
+        enabledAutoRule.put("customRule", customRule);
+        mZenModeHelper.mConfig.automaticRules = enabledAutoRule;
+
+        // set version to pre-modes-API = 10
+        ByteArrayOutputStream baos = writeXmlAndPurge(10);
+        TypedXmlPullParser parser = Xml.newFastPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+        // basic check: global config maintained
+        setupZenConfigMaintained();
+
+        // Find our automatic rule and check that it has a policy set now
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
+        assertThat(rules).hasSize(1);
+        assertThat(rules).containsKey("customRule");
+        ZenRule rule = rules.get("customRule");
+        assertThat(rule.zenPolicy).isNotNull();
+
+        // Check unset policy values match values in setupZenConfig().
+        // Check that set policy values match the values set in the policy.
+        assertThat(rule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryMedia()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryRepeatCallers()).isEqualTo(STATE_DISALLOW);
+
+        // Check that the rest is filled in from the default
+        assertThat(rule.zenPolicy.getPriorityCategorySystem()).isEqualTo(STATE_DISALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryReminders()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryCalls()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_STARRED);
+        assertThat(rule.zenPolicy.getPriorityCategoryMessages()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryConversations()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getPriorityCategoryEvents()).isEqualTo(STATE_ALLOW);
+        assertThat(rule.zenPolicy.getVisualEffectBadge()).isEqualTo(STATE_DISALLOW);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testReadXml_upgradeToModesApi_existingDefaultRulesGetCustomPolicy()
+            throws Exception {
+        setupZenConfig();
+
+        // Default rules, if they exist and have no policies, should get a snapshot of the global
+        // policy, even if they are disabled upon upgrade.
+        ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
+        ZenModeConfig.ZenRule defaultScheduleRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
+        defaultScheduleRule.enabled = false;
+        defaultScheduleRule.name = "Default Schedule Rule";
+        defaultScheduleRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
+                defaultScheduleRuleInfo);
+        defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+        automaticRules.put(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID, defaultScheduleRule);
+
+        ZenModeConfig.ZenRule defaultEventRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo defaultEventRuleInfo = new ScheduleInfo();
+        defaultEventRule.enabled = false;
+        defaultEventRule.name = "Default Event Rule";
+        defaultEventRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        defaultEventRule.conditionId = ZenModeConfig.toScheduleConditionId(
+                defaultEventRuleInfo);
+        defaultEventRule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
+        automaticRules.put(ZenModeConfig.EVENTS_DEFAULT_RULE_ID, defaultEventRule);
+
+        mZenModeHelper.mConfig.automaticRules = automaticRules;
+
+        // set previous version
+        ByteArrayOutputStream baos = writeXmlAndPurge(10);
+        TypedXmlPullParser parser = Xml.newFastPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+        // check default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
+        assertThat(rules.size()).isGreaterThan(0);
+        for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
+            assertThat(rules).containsKey(defaultId);
+            ZenRule rule = rules.get(defaultId);
+            assertThat(rule.zenPolicy).isNotNull();
+
+            // Check policy values as set up in setupZenConfig() to confirm they match
+            assertThat(rule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_DISALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategoryMedia()).isEqualTo(STATE_DISALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategorySystem()).isEqualTo(STATE_DISALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategoryReminders()).isEqualTo(STATE_ALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategoryCalls()).isEqualTo(STATE_ALLOW);
+            assertThat(rule.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_STARRED);
+            assertThat(rule.zenPolicy.getPriorityCategoryMessages()).isEqualTo(STATE_ALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategoryConversations()).isEqualTo(STATE_ALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategoryEvents()).isEqualTo(STATE_ALLOW);
+            assertThat(rule.zenPolicy.getPriorityCategoryRepeatCallers()).isEqualTo(STATE_ALLOW);
+            assertThat(rule.zenPolicy.getVisualEffectBadge()).isEqualTo(STATE_DISALLOW);
+        }
+    }
+
+    @Test
     public void testCountdownConditionSubscription() throws Exception {
         ZenModeConfig config = new ZenModeConfig();
         mZenModeHelper.mConfig = config;
@@ -2036,6 +2263,69 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testAddAutomaticZenRule_modesApi_fillsInDefaultValues() {
+        // When a new automatic zen rule is added with only some fields filled in, ensure that
+        // all unset fields are filled in with device defaults.
+
+        // Zen rule with null policy: should get entirely the default state
+        AutomaticZenRule zenRule1 = new AutomaticZenRule("name",
+                new ComponentName("android", "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id1 = mZenModeHelper.addAutomaticZenRule("android", zenRule1,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+
+        // Zen rule with partially-filled policy: should get all of the filled fields set, and the
+        // rest filled with default state
+        AutomaticZenRule zenRule2 = new AutomaticZenRule("name",
+                null,
+                new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                new ZenPolicy.Builder()
+                        .allowCalls(PEOPLE_TYPE_NONE)
+                        .allowMessages(PEOPLE_TYPE_CONTACTS)
+                        .showFullScreenIntent(true)
+                        .build(),
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id2 = mZenModeHelper.addAutomaticZenRule("android", zenRule2,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+
+        // rule 1 should exist
+        assertThat(id1).isNotNull();
+        ZenModeConfig.ZenRule rule1InConfig = mZenModeHelper.mConfig.automaticRules.get(id1);
+        assertThat(rule1InConfig).isNotNull();
+        assertThat(rule1InConfig.zenPolicy).isNotNull();  // we passed in null; it should now not be
+
+        // all of rule 1 should be the device default's policy
+        assertThat(rule1InConfig.zenPolicy).isEqualTo(mZenModeHelper.getDefaultZenPolicy());
+
+        // rule 2 should exist
+        assertThat(id2).isNotNull();
+        ZenModeConfig.ZenRule rule2InConfig = mZenModeHelper.mConfig.automaticRules.get(id2);
+        assertThat(rule2InConfig).isNotNull();
+
+        // rule 2: values set from the policy itself
+        assertThat(rule2InConfig.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_NONE);
+        assertThat(rule2InConfig.zenPolicy.getPriorityMessageSenders())
+                .isEqualTo(PEOPLE_TYPE_CONTACTS);
+        assertThat(rule2InConfig.zenPolicy.getVisualEffectFullScreenIntent())
+                .isEqualTo(ZenPolicy.STATE_ALLOW);
+
+        // the rest of rule 2's settings should be the device defaults
+        assertThat(rule2InConfig.zenPolicy.getPriorityConversationSenders())
+                .isEqualTo(CONVERSATION_SENDERS_IMPORTANT);
+        assertThat(rule2InConfig.zenPolicy.getPriorityCategorySystem())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);
+        assertThat(rule2InConfig.zenPolicy.getPriorityCategoryAlarms())
+                .isEqualTo(ZenPolicy.STATE_ALLOW);
+        assertThat(rule2InConfig.zenPolicy.getVisualEffectPeek())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);
+        assertThat(rule2InConfig.zenPolicy.getVisualEffectNotificationList())
+                .isEqualTo(ZenPolicy.STATE_ALLOW);
+    }
+
+    @Test
     public void testSetAutomaticZenRuleState_nullPkg() {
         AutomaticZenRule zenRule = new AutomaticZenRule("name",
                 null,
@@ -2357,6 +2647,68 @@
 
     @Test
     @EnableFlags(Flags.FLAG_MODES_API)
+    public void updateAutomaticZenRule_nullPolicy_doesNothing() {
+        // Test that when updateAutomaticZenRule is called with a null policy, nothing changes
+        // about the existing policy.
+        String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+                new AutomaticZenRule.Builder("Rule", CONDITION_ID)
+                        .setOwner(OWNER)
+                        .setZenPolicy(new ZenPolicy.Builder()
+                                .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // default is stars
+                                .build())
+                        .build(),
+                UPDATE_ORIGIN_APP, "reasons", 0);
+
+        mZenModeHelper.updateAutomaticZenRule(ruleId,
+                new AutomaticZenRule.Builder("Rule", CONDITION_ID)
+                        // no zen policy
+                        .build(),
+                UPDATE_ORIGIN_APP, "reasons", 0);
+
+        AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
+        assertThat(savedRule.getZenPolicy().getPriorityCategoryCalls())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void updateAutomaticZenRule_overwritesExistingPolicy() {
+        // Test that when updating an automatic zen rule with an existing policy, the newly set
+        // fields overwrite those from the previous policy, but unset fields in the new policy
+        // keep values from the previous one.
+        String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
+                new AutomaticZenRule.Builder("Rule", CONDITION_ID)
+                        .setOwner(OWNER)
+                        .setZenPolicy(new ZenPolicy.Builder()
+                                .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // default is stars
+                                .allowAlarms(false)
+                                .allowReminders(true)
+                                .build())
+                        .build(),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0);
+
+        mZenModeHelper.updateAutomaticZenRule(ruleId,
+                new AutomaticZenRule.Builder("Rule", CONDITION_ID)
+                        .setZenPolicy(new ZenPolicy.Builder()
+                                .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+                                .build())
+                        .build(),
+                UPDATE_ORIGIN_APP, "reasons", 0);
+
+        AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
+        assertThat(savedRule.getZenPolicy().getPriorityCategoryCalls())
+                .isEqualTo(ZenPolicy.STATE_ALLOW);  // from update
+        assertThat(savedRule.getZenPolicy().getPriorityCallSenders())
+                .isEqualTo(ZenPolicy.PEOPLE_TYPE_CONTACTS);  // from update
+        assertThat(savedRule.getZenPolicy().getPriorityCategoryAlarms())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);  // from original
+        assertThat(savedRule.getZenPolicy().getPriorityCategoryReminders())
+                .isEqualTo(ZenPolicy.STATE_ALLOW);  // from original
+    }
+
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
     public void addAutomaticZenRule_withTypeBedtime_replacesDisabledSleeping() {
         ZenRule sleepingRule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                 ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID);
@@ -2460,7 +2812,8 @@
         DISABLED(false, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI);
 
         private final boolean mEnabled;
-        @ConfigChangeOrigin private final int mOriginForUserActionInSystemUi;
+        @ConfigChangeOrigin
+        private final int mOriginForUserActionInSystemUi;
 
         ModesApiFlag(boolean enabled, @ConfigChangeOrigin int originForUserActionInSystemUi) {
             this.mEnabled = enabled;
@@ -2506,7 +2859,7 @@
         //   - rules active = 1
         //   - user action = true (system-based turning zen mode on)
         //   - package uid = system (as set above)
-        //   - resulting DNDPolicyProto the same as the values in setupZenConfig()
+        //   - resulting DNDPolicyProto the same as the values in setupZenConfig() (global policy)
         assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId(),
                 mZenModeEventLogger.getEventId(0));
         assertEquals(ZEN_MODE_OFF, mZenModeEventLogger.getPrevZenMode(0));
@@ -2600,7 +2953,7 @@
         //   - 1 rule (newly) active
         //   - automatic (is not a user action)
         //   - package UID is written to be the rule *owner* even though it "comes from system"
-        //   - zen policy is the same as the set-up zen config
+        //   - zen policy is the default as it's unspecified
         assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId(),
                 mZenModeEventLogger.getEventId(0));
         assertEquals(ZEN_MODE_OFF, mZenModeEventLogger.getPrevZenMode(0));
@@ -2609,10 +2962,10 @@
         assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
         assertFalse(mZenModeEventLogger.getIsUserAction(0));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
-        checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0));
+        checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0));
 
         // When the automatic rule is disabled, this should turn off zen mode and also count as a
-        // user action.
+        // user action. We don't care what the consolidated policy is when DND turns off.
         assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_OFF.getId(),
                 mZenModeEventLogger.getEventId(1));
         assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeEventLogger.getPrevZenMode(1));
@@ -2835,28 +3188,28 @@
         // First: turn on rule 1
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Second: turn on rule 2
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Third: turn on rule 3
         mZenModeHelper.setAutomaticZenRuleState(id3,
                 new Condition(zenRule3.getConditionId(), "", STATE_TRUE),
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Fourth: Turn *off* rule 2
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_FALSE),
-                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // This should result in a total of four events
         assertEquals(4, mZenModeEventLogger.numLoggedChanges());
 
         // Event 1: rule 1 turns on. We expect this to turn on DND (zen mode) overall, so that's
-        // what the event should reflect. At this time, the policy is the same as initial setup.
+        // what the event should reflect. At this time, the policy is the default.
         assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId(),
                 mZenModeEventLogger.getEventId(0));
         assertEquals(ZEN_MODE_OFF, mZenModeEventLogger.getPrevZenMode(0));
@@ -2864,7 +3217,7 @@
         assertEquals(1, mZenModeEventLogger.getNumRulesActive(0));
         assertFalse(mZenModeEventLogger.getIsUserAction(0));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0));
-        checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0));
+        checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0));
 
         // Event 2: rule 2 turns on. This should not change anything about the policy, so the only
         // change is that there are more rules active now.
@@ -2873,7 +3226,7 @@
         assertEquals(2, mZenModeEventLogger.getNumRulesActive(1));
         assertFalse(mZenModeEventLogger.getIsUserAction(1));
         assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1));
-        checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1));
+        checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(1));
 
         // Event 3: rule 3 turns on. This should trigger a policy change, and be classified as such,
         // but meanwhile also change the number of active rules.
@@ -2926,12 +3279,16 @@
         mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true);
         setupZenConfig();
 
+        // Explicitly set up all rules with the same policy as the manual rule so there will be
+        // no policy changes in this test case.
+        ZenPolicy manualRulePolicy = mZenModeHelper.mConfig.toZenPolicy();
+
         // Rule 1, owned by a package
         AutomaticZenRule zenRule = new AutomaticZenRule("name",
                 null,
                 new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
-                null,
+                manualRulePolicy,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
                 UPDATE_ORIGIN_APP, "test", Process.SYSTEM_UID);
@@ -2941,7 +3298,7 @@
                 null,
                 new ComponentName("android", "ScheduleConditionProvider"),
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
-                null,
+                manualRulePolicy,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
                 modesApiFlag.mOriginForUserActionInSystemUi, "test", Process.SYSTEM_UID);
@@ -3172,7 +3529,8 @@
     }
 
     @Test
-    public void testUpdateConsolidatedPolicy_defaultRulesOnly() {
+    @DisableFlags(Flags.FLAG_MODES_API)
+    public void testUpdateConsolidatedPolicy_preModesApiDefaultRulesOnly_takesGlobalDefault() {
         setupZenConfig();
 
         // When there's one automatic rule active and it doesn't specify a policy, test that the
@@ -3205,12 +3563,39 @@
     }
 
     @Test
-    public void testUpdateConsolidatedPolicy_customPolicyOnly() {
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testUpdateConsolidatedPolicy_modesApiDefaultRulesOnly_takesDeviceDefault() {
+        setupZenConfig();
+
+        // When there's one automatic rule active and it doesn't specify a policy, test that the
+        // resulting consolidated policy is one that matches the default *device* settings.
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                null,  // null policy
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+
+        // enable the rule
+        mZenModeHelper.setAutomaticZenRuleState(id,
+                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
+
+        // inspect the consolidated policy, which should match the device default settings.
+        assertThat(ZenAdapters.notificationPolicyToZenPolicy(mZenModeHelper.mConsolidatedPolicy))
+                .isEqualTo(mZenModeHelper.getDefaultZenPolicy());
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MODES_API)
+    public void testUpdateConsolidatedPolicy_preModesApiCustomPolicyOnly_fillInWithGlobal() {
         setupZenConfig();
 
         // when there's only one automatic rule active and it has a custom policy, make sure that's
-        // what the consolidated policy reflects whether or not it's stricter than what the default
-        // would specify.
+        // what the consolidated policy reflects whether or not it's stricter than what the global
+        // config would specify.
         ZenPolicy customPolicy = new ZenPolicy.Builder()
                 .allowAlarms(true)  // more lenient than default
                 .allowMedia(true)  // more lenient than default
@@ -3249,7 +3634,51 @@
     }
 
     @Test
-    public void testUpdateConsolidatedPolicy_defaultAndCustomActive() {
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testUpdateConsolidatedPolicy_modesApiCustomPolicyOnly_fillInWithDeviceDefault() {
+        setupZenConfig();
+
+        // when there's only one automatic rule active and it has a custom policy, make sure that's
+        // what the consolidated policy reflects whether or not it's stricter than what the default
+        // would specify.
+        ZenPolicy customPolicy = new ZenPolicy.Builder()
+                .allowSystem(true)  // more lenient than default
+                .allowRepeatCallers(false)  // more restrictive than default
+                .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE)  // more restrictive than default
+                .showFullScreenIntent(true)  // more lenient
+                .showBadges(false)  // more restrictive
+                .build();
+
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                customPolicy,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+
+        // enable the rule; this will update the consolidated policy
+        mZenModeHelper.setAutomaticZenRuleState(id,
+                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
+
+        // since this is the only active rule, the consolidated policy should match the custom
+        // policy for every field specified, and take default values for unspecified things
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isTrue();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isTrue();  // custom
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isFalse();  // custom
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()).isFalse();  // custom
+        assertThat(mZenModeHelper.mConsolidatedPolicy.showBadges()).isFalse();  // custom
+        assertThat(mZenModeHelper.mConsolidatedPolicy.showFullScreenIntents()).isTrue();  // custom
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_MODES_API)
+    public void testUpdateConsolidatedPolicy_preModesApiDefaultAndCustomActive_mergesWithGlobal() {
         setupZenConfig();
 
         // when there are two rules active, one inheriting the default policy and one setting its
@@ -3309,6 +3738,68 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void testUpdateConsolidatedPolicy_modesApiDefaultAndCustomActive_mergesWithDefault() {
+        setupZenConfig();
+
+        // when there are two rules active, one inheriting the default policy and one setting its
+        // own custom policy, they should be merged to form the most restrictive combination.
+
+        // rule 1: no custom policy
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                null,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+
+        // enable rule 1
+        mZenModeHelper.setAutomaticZenRuleState(id,
+                new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
+
+        // custom policy for rule 2
+        ZenPolicy customPolicy = new ZenPolicy.Builder()
+                .allowAlarms(false) // more restrictive than default
+                .allowSystem(true)  // more lenient than default
+                .allowRepeatCallers(false)  // more restrictive than default
+                .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE)  // more restrictive than default
+                .showBadges(false)  // more restrictive
+                .showPeeking(true)  // more lenient
+                .build();
+
+        AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
+                null,
+                new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                customPolicy,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
+
+        // enable rule 2; this will update the consolidated policy
+        mZenModeHelper.setAutomaticZenRuleState(id2,
+                new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
+
+        // now both rules should be on, and the consolidated policy should reflect the most
+        // restrictive option of each of the two
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isFalse();  // custom stricter
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isFalse();  // default stricter
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isFalse();  // custom stricter
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers())
+                .isFalse();  // custom stricter
+        assertThat(mZenModeHelper.mConsolidatedPolicy.showBadges()).isFalse();  // custom stricter
+        assertThat(mZenModeHelper.mConsolidatedPolicy.showPeeking()).isFalse();  // default stricter
+    }
+
+    @Test
     public void testUpdateConsolidatedPolicy_allowChannels() {
         mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
         setupZenConfig();
@@ -3372,7 +3863,10 @@
                 null,
                 new ComponentName(CUSTOM_PKG_NAME, "cls"),
                 Uri.parse("priority"),
-                new ZenPolicy.Builder().allowMedia(true).build(),
+                new ZenPolicy.Builder()
+                        .allowMedia(true)
+                        .allowSystem(true)
+                        .build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String rule1Id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
                 zenRuleWithPriority, UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);
@@ -3394,10 +3888,10 @@
                 UPDATE_ORIGIN_APP, CUSTOM_PKG_UID);
 
         // Consolidated Policy should be default + rule1.
-        assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isFalse();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isTrue();  // default
         assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // priority rule
-        assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isFalse();  // default
-        assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isTrue();  // default
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isTrue();  // priority rule
+        assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse();  // default
         assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isTrue();  // default
         assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default
         assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue();  // default
@@ -3408,7 +3902,7 @@
     public void zenRuleToAutomaticZenRule_allFields() {
         mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
-                new String[] {OWNER.getPackageName()});
+                new String[]{OWNER.getPackageName()});
 
         ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
         rule.configurationActivity = CONFIG_ACTIVITY;
@@ -3452,7 +3946,7 @@
     public void automaticZenRuleToZenRule_allFields() {
         mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
-                new String[] {OWNER.getPackageName()});
+                new String[]{OWNER.getPackageName()});
 
         AutomaticZenRule azr = new AutomaticZenRule.Builder(NAME, CONDITION_ID)
                 .setEnabled(true)
@@ -3478,7 +3972,8 @@
         assertEquals(CONDITION_ID, storedRule.conditionId);
         assertEquals(INTERRUPTION_FILTER_ZR, storedRule.zenMode);
         assertEquals(ENABLED, storedRule.enabled);
-        assertEquals(POLICY, storedRule.zenPolicy);
+        assertEquals(mZenModeHelper.getDefaultZenPolicy().overwrittenWith(POLICY),
+                storedRule.zenPolicy);
         assertEquals(CONFIG_ACTIVITY, storedRule.configurationActivity);
         assertEquals(TYPE, storedRule.type);
         assertEquals(ALLOW_MANUAL, storedRule.allowManualInvocation);
@@ -3561,12 +4056,12 @@
 
         // Modifies the zen policy and device effects
         ZenPolicy policy = new ZenPolicy.Builder(rule.getZenPolicy())
-                .allowPriorityChannels(true)
+                .allowPriorityChannels(false)
                 .build();
         ZenDeviceEffects deviceEffects =
                 new ZenDeviceEffects.Builder(rule.getDeviceEffects())
-                .setShouldDisplayGrayscale(true)
-                .build();
+                        .setShouldDisplayGrayscale(true)
+                        .build();
         AutomaticZenRule azrUpdate = new AutomaticZenRule.Builder(rule)
                 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                 .setZenPolicy(policy)
@@ -3580,7 +4075,8 @@
 
         // UPDATE_ORIGIN_USER should change the bitmask and change the values.
         assertThat(rule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_PRIORITY);
-        assertThat(rule.getZenPolicy().getPriorityChannels()).isEqualTo(ZenPolicy.STATE_ALLOW);
+        assertThat(rule.getZenPolicy().getPriorityChannels()).isEqualTo(ZenPolicy.STATE_DISALLOW);
+
         assertThat(rule.getDeviceEffects().shouldDisplayGrayscale()).isTrue();
 
         ZenRule storedRule = mZenModeHelper.mConfig.automaticRules.get(ruleId);
@@ -3770,9 +4266,9 @@
     @Test
     @EnableFlags(Flags.FLAG_MODES_API)
     public void updateAutomaticZenRule_nullPolicyUpdate() {
-        // Adds a starting rule with empty zen policies and device effects
+        // Adds a starting rule with set zen policy and empty device effects
         AutomaticZenRule azrBase = new AutomaticZenRule.Builder(NAME, CONDITION_ID)
-                .setZenPolicy(new ZenPolicy.Builder().build())
+                .setZenPolicy(POLICY)
                 .build();
         // Adds the rule using the app, to avoid having any user modified bits set.
         String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
@@ -3790,8 +4286,10 @@
                 Process.SYSTEM_UID);
         rule = mZenModeHelper.getAutomaticZenRule(ruleId);
 
-        // When AZR's ZenPolicy is null, we expect the updated rule's policy to be null.
-        assertThat(rule.getZenPolicy()).isNull();
+        // When AZR's ZenPolicy is null, we expect the updated rule's policy to be unchanged
+        // (equivalent to the provided policy, with additional fields filled in with defaults).
+        assertThat(rule.getZenPolicy()).isEqualTo(
+                mZenModeHelper.getDefaultZenPolicy().overwrittenWith(POLICY));
     }
 
     @Test
@@ -3847,13 +4345,13 @@
         assertThat(storedRule.canBeUpdatedByApp()).isFalse();
         assertThat(storedRule.zenPolicyUserModifiedFields).isEqualTo(
                 ZenPolicy.FIELD_ALLOW_CHANNELS
-                | ZenPolicy.FIELD_PRIORITY_CATEGORY_REMINDERS
-                | ZenPolicy.FIELD_PRIORITY_CATEGORY_EVENTS
-                | ZenPolicy.FIELD_PRIORITY_CATEGORY_SYSTEM
-                | ZenPolicy.FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT
-                | ZenPolicy.FIELD_VISUAL_EFFECT_LIGHTS
-                | ZenPolicy.FIELD_VISUAL_EFFECT_PEEK
-                | ZenPolicy.FIELD_VISUAL_EFFECT_AMBIENT
+                        | ZenPolicy.FIELD_PRIORITY_CATEGORY_REMINDERS
+                        | ZenPolicy.FIELD_PRIORITY_CATEGORY_EVENTS
+                        | ZenPolicy.FIELD_PRIORITY_CATEGORY_SYSTEM
+                        | ZenPolicy.FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT
+                        | ZenPolicy.FIELD_VISUAL_EFFECT_LIGHTS
+                        | ZenPolicy.FIELD_VISUAL_EFFECT_PEEK
+                        | ZenPolicy.FIELD_VISUAL_EFFECT_AMBIENT
         );
     }
 
@@ -4016,6 +4514,7 @@
         final int[] actualStatus = new int[2];
         ZenModeHelper.Callback callback = new ZenModeHelper.Callback() {
             int i = 0;
+
             @Override
             void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {
                 if (Objects.equals(createdId, id)) {
@@ -4056,6 +4555,7 @@
         final int[] actualStatus = new int[2];
         ZenModeHelper.Callback callback = new ZenModeHelper.Callback() {
             int i = 0;
+
             @Override
             void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {
                 if (Objects.equals(createdId, id)) {
@@ -4202,6 +4702,7 @@
                         .build()),
                 eq(UPDATE_ORIGIN_APP));
     }
+
     @Test
     public void testDeviceEffects_noChangeToConsolidatedEffects_notApplied() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
@@ -4607,7 +5108,8 @@
                 .comparingElementsUsing(IGNORE_METADATA)
                 .containsExactly(
                         expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
-                                null, true));
+                                mZenModeHelper.mConfig.toZenPolicy(), // copy of global config
+                                true));
     }
 
     @Test
@@ -4626,7 +5128,9 @@
         assertThat(mZenModeHelper.mConfig.automaticRules.values())
                 .comparingElementsUsing(IGNORE_METADATA)
                 .containsExactly(
-                        expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_ALARMS, null, true));
+                        expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_ALARMS,
+                                mZenModeHelper.mConfig.toZenPolicy(), // copy of global config
+                                true));
     }
 
     @Test
@@ -4820,6 +5324,10 @@
         mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, originalPolicy);
         String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet());
 
+        // Store this for checking later.
+        ZenPolicy originalEffectiveZenPolicy = new ZenPolicy.Builder(
+                mZenModeHelper.mConfig.toZenPolicy()).allowMedia(true).build();
+
         // From user, update that rule's policy.
         AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
         ZenPolicy userUpdateZenPolicy = new ZenPolicy.Builder().disallowAllSounds()
@@ -4839,7 +5347,9 @@
                 .comparingElementsUsing(IGNORE_METADATA)
                 .containsExactly(
                         expectedImplicitRule(pkg, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
-                                userUpdateZenPolicy,
+                                // the final policy for the rule should contain the user's update
+                                // overlaid on top of the original existing policy.
+                                originalEffectiveZenPolicy.overwrittenWith(userUpdateZenPolicy),
                                 /* conditionActive= */ null));
     }
 
@@ -4854,6 +5364,10 @@
         mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, originalPolicy);
         String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet());
 
+        // Store this for checking later.
+        ZenPolicy originalEffectiveZenPolicy = new ZenPolicy.Builder(
+                mZenModeHelper.mConfig.toZenPolicy()).allowMedia(true).build();
+
         // From user, update something in that rule, but not the ZenPolicy.
         AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId);
         AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
@@ -4873,7 +5387,7 @@
                 .allowPriorityChannels(true)
                 .build();
         assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenPolicy)
-                .isEqualTo(appsSecondZenPolicy);
+                .isEqualTo(originalEffectiveZenPolicy.overwrittenWith(appsSecondZenPolicy));
     }
 
     @Test
@@ -4905,14 +5419,18 @@
     }
 
     @Test
-    public void getNotificationPolicyFromImplicitZenRule_ruleWithoutPolicy_returnsGlobalPolicy() {
+    public void getNotificationPolicyFromImplicitZenRule_ruleWithoutPolicy_copiesGlobalPolicy() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
-
-        mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
-                ZEN_MODE_ALARMS);
         mZenModeHelper.mConfig.allowCalls = true;
         mZenModeHelper.mConfig.allowConversations = false;
 
+        // Implicit rule will get the global policy at the time of rule creation.
+        mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
+                ZEN_MODE_ALARMS);
+
+        // If the policy then changes afterwards, we should keep the snapshotted version.
+        mZenModeHelper.mConfig.allowCalls = false;
+
         Policy readPolicy = mZenModeHelper.getNotificationPolicyFromImplicitZenRule(
                 CUSTOM_PKG_NAME);
 
@@ -4952,7 +5470,7 @@
                     p.recycle();
                 }
             },
-            "Ignoring timestamp and userModifiedFields");
+              "Ignoring timestamp and userModifiedFields");
 
     private ZenRule expectedImplicitRule(String ownerPkg, int zenMode, ZenPolicy policy,
             @Nullable Boolean conditionActive) {
@@ -4962,7 +5480,7 @@
         if (conditionActive != null) {
             rule.condition = conditionActive
                     ? new Condition(rule.conditionId,
-                            mContext.getString(R.string.zen_mode_implicit_activated), STATE_TRUE)
+                    mContext.getString(R.string.zen_mode_implicit_activated), STATE_TRUE)
                     : new Condition(rule.conditionId,
                             mContext.getString(R.string.zen_mode_implicit_deactivated),
                             STATE_FALSE);
@@ -5030,8 +5548,35 @@
         assertEquals(STATE_ALLOW, dndProto.getNotificationList().getNumber());
     }
 
+    private void checkDndProtoMatchesDefaultZenConfig(DNDPolicyProto dndProto) {
+        if (!Flags.modesApi()) {
+            checkDndProtoMatchesSetupZenConfig(dndProto);
+            return;
+        }
+
+        // When modes_api flag is on, the default zen config is the device defaults.
+        assertThat(dndProto.getAlarms().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getMedia().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getSystem().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getReminders().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getCalls().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getAllowCallsFrom().getNumber()).isEqualTo(PEOPLE_STARRED);
+        assertThat(dndProto.getMessages().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getAllowMessagesFrom().getNumber()).isEqualTo(PEOPLE_STARRED);
+        assertThat(dndProto.getEvents().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getRepeatCallers().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getFullscreen().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getLights().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getPeek().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getStatusBar().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getBadge().getNumber()).isEqualTo(STATE_ALLOW);
+        assertThat(dndProto.getAmbient().getNumber()).isEqualTo(STATE_DISALLOW);
+        assertThat(dndProto.getNotificationList().getNumber()).isEqualTo(STATE_ALLOW);
+    }
+
     private static void withoutWtfCrash(Runnable test) {
-        Log.TerribleFailureHandler oldHandler = Log.setWtfHandler((tag, what, system) -> {});
+        Log.TerribleFailureHandler oldHandler = Log.setWtfHandler((tag, what, system) -> {
+        });
         try {
             test.run();
         } finally {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
index 4ed55df..57e1132 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
@@ -269,6 +269,78 @@
     }
 
     @Test
+    public void testZenPolicyOverwrite_allUnsetPolicies() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
+
+        ZenPolicy.Builder builder = new ZenPolicy.Builder();
+        ZenPolicy unset = builder.build();
+
+        builder.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS);
+        builder.allowMedia(false);
+        builder.allowEvents(true);
+        builder.showFullScreenIntent(false);
+        builder.showInNotificationList(false);
+        ZenPolicy set = builder.build();
+
+        ZenPolicy overwritten = set.overwrittenWith(unset);
+        assertThat(overwritten).isEqualTo(set);
+
+        // should actually work the other way too.
+        ZenPolicy overwrittenWithSet = unset.overwrittenWith(set);
+        assertThat(overwrittenWithSet).isEqualTo(set);
+    }
+
+    @Test
+    public void testZenPolicyOverwrite_someOverlappingFields_takeNewPolicy() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
+
+        ZenPolicy p1 = new ZenPolicy.Builder()
+                .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+                .allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED)
+                .allowMedia(false)
+                .showBadges(true)
+                .build();
+
+        ZenPolicy p2 = new ZenPolicy.Builder()
+                .allowRepeatCallers(false)
+                .allowConversations(ZenPolicy.CONVERSATION_SENDERS_IMPORTANT)
+                .allowMessages(ZenPolicy.PEOPLE_TYPE_NONE)
+                .showBadges(false)
+                .showPeeking(true)
+                .build();
+
+        // when p1 is overwritten with p2, all values from p2 win regardless of strictness, and
+        // remaining fields take values from p1.
+        ZenPolicy p1OverwrittenWithP2 = p1.overwrittenWith(p2);
+        assertThat(p1OverwrittenWithP2.getPriorityCallSenders())
+                .isEqualTo(ZenPolicy.PEOPLE_TYPE_CONTACTS);  // from p1
+        assertThat(p1OverwrittenWithP2.getPriorityMessageSenders())
+                .isEqualTo(ZenPolicy.PEOPLE_TYPE_NONE);  // from p2
+        assertThat(p1OverwrittenWithP2.getPriorityCategoryRepeatCallers())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);  // from p2
+        assertThat(p1OverwrittenWithP2.getPriorityCategoryMedia())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);  // from p1
+        assertThat(p1OverwrittenWithP2.getVisualEffectBadge())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);  // from p2
+        assertThat(p1OverwrittenWithP2.getVisualEffectPeek())
+                .isEqualTo(ZenPolicy.STATE_ALLOW); // from p2
+
+        ZenPolicy p2OverwrittenWithP1 = p2.overwrittenWith(p1);
+        assertThat(p2OverwrittenWithP1.getPriorityCallSenders())
+                .isEqualTo(ZenPolicy.PEOPLE_TYPE_CONTACTS);  // from p1
+        assertThat(p2OverwrittenWithP1.getPriorityMessageSenders())
+                .isEqualTo(ZenPolicy.PEOPLE_TYPE_STARRED);  // from p1
+        assertThat(p2OverwrittenWithP1.getPriorityCategoryRepeatCallers())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);  // from p2
+        assertThat(p2OverwrittenWithP1.getPriorityCategoryMedia())
+                .isEqualTo(ZenPolicy.STATE_DISALLOW);  // from p1
+        assertThat(p2OverwrittenWithP1.getVisualEffectBadge())
+                .isEqualTo(ZenPolicy.STATE_ALLOW);  // from p1
+        assertThat(p2OverwrittenWithP1.getVisualEffectPeek())
+                .isEqualTo(ZenPolicy.STATE_ALLOW); // from p2
+    }
+
+    @Test
     public void testZenPolicyMessagesInvalid() {
         ZenPolicy.Builder builder = new ZenPolicy.Builder();
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a5c6d57..1bf11df 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1618,14 +1618,15 @@
     }
 
     /**
-     * Register for changes to the list of active {@link SubscriptionInfo} records or to the
-     * individual records themselves. When a change occurs the onSubscriptionsChanged method of
-     * the listener will be invoked immediately if there has been a notification. The
-     * onSubscriptionChanged method will also be triggered once initially when calling this
-     * function.
+     * Register for changes to the list of {@link SubscriptionInfo} records or to the
+     * individual records (active or inactive) themselves. When a change occurs, the
+     * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method of
+     * the listener will be invoked immediately. The
+     * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method will also be invoked
+     * once initially when calling this method.
      *
      * @param listener an instance of {@link OnSubscriptionsChangedListener} with
-     *                 onSubscriptionsChanged overridden.
+     * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} overridden.
      * @param executor the executor that will execute callbacks.
      */
     public void addOnSubscriptionsChangedListener(
@@ -1953,7 +1954,6 @@
      *          {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    // @RequiresPermission(TODO(b/308809058))
     public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
         List<SubscriptionInfo> activeList = null;
 
@@ -2010,6 +2010,9 @@
      * Create a new subscription manager instance that can see all subscriptions across
      * user profiles.
      *
+     * The permission check for accessing all subscriptions will be enforced upon calling the
+     * individual APIs linked below.
+     *
      * @return a SubscriptionManager that can see all subscriptions regardless its user profile
      * association.
      *
@@ -2018,9 +2021,7 @@
      * @see UserHandle
      */
     @FlaggedApi(Flags.FLAG_ENFORCE_SUBSCRIPTION_USER_FILTER)
-    // @RequiresPermission(TODO(b/308809058))
-    // The permission check for accessing all subscriptions will be enforced upon calling the
-    // individual APIs linked above.
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES)
     @NonNull public SubscriptionManager createForAllUserProfiles() {
         return new SubscriptionManager(mContext, true/*isForAllUserProfiles*/);
     }
@@ -2215,7 +2216,6 @@
      *          {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    // @RequiresPermission(TODO(b/308809058))
     public int getActiveSubscriptionInfoCount() {
         int result = 0;
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 67bb1f0..b22d8ac 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -18492,7 +18492,6 @@
 
     /**
      * Get last known cell identity.
-     * Require appropriate permissions, otherwise throws SecurityException.
      *
      * If there is current registered network this value will be same as the registered cell
      * identity. If the device goes out of service the previous cell identity is cached and
@@ -18504,7 +18503,7 @@
     @SystemApi
     @FlaggedApi(com.android.server.telecom.flags.Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES)
     @RequiresPermission(allOf = {Manifest.permission.ACCESS_FINE_LOCATION,
-            "com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"})
+            Manifest.permission.ACCESS_LAST_KNOWN_CELL_ID})
     public @Nullable CellIdentity getLastKnownCellIdentity() {
         try {
             ITelephony telephony = getITelephony();
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index 60a9f0b..256a469 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -295,13 +295,13 @@
         verify(native).setPointerIconVisibility(10, false)
         verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
         localService.setMousePointerAccelerationEnabled(false, 10)
-        verify(native).setMousePointerAccelerationEnabled(eq(false))
+        verify(native).setMousePointerAccelerationEnabled(10, false)
 
         service.onDisplayRemoved(10)
         verify(native).setPointerIconVisibility(10, true)
         verify(native).displayRemoved(eq(10))
         verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED))
-        verify(native).setMousePointerAccelerationEnabled(true)
+        verify(native).setMousePointerAccelerationEnabled(10, true)
         verifyNoMoreInteractions(native)
 
         // This call should not block because the virtual mouse pointer override was never removed.
@@ -319,26 +319,24 @@
         verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
         verify(native).setPointerIconVisibility(10, false)
         localService.setMousePointerAccelerationEnabled(false, 10)
-        verify(native).setMousePointerAccelerationEnabled(eq(false))
+        verify(native).setMousePointerAccelerationEnabled(10, false)
 
         localService.setPointerIconVisible(true, 10)
         verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED))
         verify(native).setPointerIconVisibility(10, true)
         localService.setMousePointerAccelerationEnabled(true, 10)
-        verify(native).setMousePointerAccelerationEnabled(eq(true))
+        verify(native).setMousePointerAccelerationEnabled(10, true)
 
-        // Verify that setting properties on a different display is not propagated until the
-        // pointer is moved to that display.
         localService.setPointerIconVisible(false, 20)
         verify(native).setPointerIconVisibility(20, false)
         localService.setMousePointerAccelerationEnabled(false, 20)
+        verify(native).setMousePointerAccelerationEnabled(20, false)
         verifyNoMoreInteractions(native)
 
         clearInvocations(native)
         setVirtualMousePointerDisplayIdAndVerify(20)
 
         verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
-        verify(native).setMousePointerAccelerationEnabled(eq(false))
     }
 
     @Test
@@ -347,12 +345,12 @@
         localService.setMousePointerAccelerationEnabled(false, 10)
 
         verify(native).setPointerIconVisibility(10, false)
+        verify(native).setMousePointerAccelerationEnabled(10, false)
         verifyNoMoreInteractions(native)
 
         setVirtualMousePointerDisplayIdAndVerify(10)
 
         verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
-        verify(native).setMousePointerAccelerationEnabled(eq(false))
     }
 
     @Test