Merge "Add B&R logging for Modes" into main
diff --git a/core/java/android/app/backup/NotificationLoggingConstants.java b/core/java/android/app/backup/NotificationLoggingConstants.java
new file mode 100644
index 0000000..add4562
--- /dev/null
+++ b/core/java/android/app/backup/NotificationLoggingConstants.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.backup;
+
+/**
+ * @hide
+ */
+public class NotificationLoggingConstants {
+
+    // Key under which the payload blob is stored
+    public static final String KEY_NOTIFICATIONS = "notifications";
+
+    @BackupRestoreEventLogger.BackupRestoreDataType
+    public static final String DATA_TYPE_ZEN_CONFIG = KEY_NOTIFICATIONS + ":zen_config";
+    @BackupRestoreEventLogger.BackupRestoreDataType
+    public static final String DATA_TYPE_ZEN_RULES = KEY_NOTIFICATIONS + ":zen_rules";
+
+    @BackupRestoreEventLogger.BackupRestoreError
+    public static final String ERROR_XML_PARSING = KEY_NOTIFICATIONS + ":invalid_xml_parsing";
+}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index e173255..24328eb 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -24,12 +24,12 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
 import static android.service.notification.ZenAdapters.peopleTypeToPrioritySenders;
 import static android.service.notification.ZenAdapters.prioritySendersToPeopleType;
 import static android.service.notification.ZenAdapters.zenPolicyConversationSendersToNotificationPolicy;
-import static android.service.notification.ZenModeConfig.EventInfo.REPLY_YES_OR_MAYBE;
 import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED;
 import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_ALARMS;
 import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_CALLS;
@@ -56,6 +56,7 @@
 import android.app.Flags;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.app.backup.BackupRestoreEventLogger;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -957,8 +958,9 @@
         }
     }
 
-    public static ZenModeConfig readXml(TypedXmlPullParser parser)
-            throws XmlPullParserException, IOException {
+    public static ZenModeConfig readXml(TypedXmlPullParser parser,
+            @Nullable BackupRestoreEventLogger logger) throws XmlPullParserException, IOException {
+        int readRuleCount = 0;
         int type = parser.getEventType();
         if (type != XmlPullParser.START_TAG) return null;
         String tag = parser.getName();
@@ -1048,6 +1050,8 @@
                     readManualRule = true;
                     if (rt.manualRule.zenPolicy == null) {
                         readManualRuleWithoutPolicy = true;
+                    } else {
+                        readRuleCount++;
                     }
                 } else if (AUTOMATIC_TAG.equals(tag)
                         || (Flags.modesApi() && AUTOMATIC_DELETED_TAG.equals(tag))) {
@@ -1062,6 +1066,7 @@
                             }
                         } else if (AUTOMATIC_TAG.equals(tag)) {
                             rt.automaticRules.put(id, automaticRule);
+                            readRuleCount++;
                         }
                     }
                 } else if (STATE_TAG.equals(tag)) {
@@ -1085,8 +1090,17 @@
                         }
                         rt.manualRule.condition = new Condition(rt.manualRule.conditionId, "",
                                 Condition.STATE_TRUE);
+                        readRuleCount++;
                     }
                 }
+
+                if (!Flags.modesUi()){
+                    readRuleCount++;
+                }
+
+                if (logger != null) {
+                    logger.logItemsRestored(DATA_TYPE_ZEN_RULES, readRuleCount);
+                }
                 return rt;
             }
         }
@@ -1110,8 +1124,9 @@
      * @throws IOException
      */
 
-    public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup)
-            throws IOException {
+    public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup,
+            @Nullable BackupRestoreEventLogger logger) throws IOException {
+        int writtenRuleCount = 0;
         int xmlVersion = getCurrentXmlVersion();
         out.startTag(null, ZEN_TAG);
         out.attribute(null, ZEN_ATT_VERSION, version == null
@@ -1147,6 +1162,7 @@
             writeRuleXml(manualRule, out, forBackup);
             out.endTag(null, MANUAL_TAG);
         }
+        writtenRuleCount++;
         final int N = automaticRules.size();
         for (int i = 0; i < N; i++) {
             final String id = automaticRules.keyAt(i);
@@ -1155,6 +1171,7 @@
             out.attribute(null, RULE_ATT_ID, id);
             writeRuleXml(automaticRule, out, forBackup);
             out.endTag(null, AUTOMATIC_TAG);
+            writtenRuleCount++;
         }
         if (Flags.modesApi() && !forBackup) {
             for (int i = 0; i < deletedRules.size(); i++) {
@@ -1171,6 +1188,9 @@
         out.endTag(null, STATE_TAG);
 
         out.endTag(null, ZEN_TAG);
+        if (logger != null) {
+            logger.logItemsBackedUp(DATA_TYPE_ZEN_RULES, writtenRuleCount);
+        }
     }
 
     @NonNull
diff --git a/services/core/java/com/android/server/notification/NotificationBackupHelper.java b/services/core/java/com/android/server/notification/NotificationBackupHelper.java
index ee9ec15..9df44a4 100644
--- a/services/core/java/com/android/server/notification/NotificationBackupHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationBackupHelper.java
@@ -16,6 +16,8 @@
 
 package com.android.server.notification;
 
+import static android.app.backup.NotificationLoggingConstants.KEY_NOTIFICATIONS;
+
 import android.app.INotificationManager;
 import android.app.backup.BlobBackupHelper;
 import android.os.ServiceManager;
@@ -31,9 +33,6 @@
     // Current version of the blob schema
     static final int BLOB_VERSION = 1;
 
-    // Key under which the payload blob is stored
-    static final String KEY_NOTIFICATIONS = "notifications";
-
     private final int mUserId;
 
     private final NotificationManagerInternal mNm;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bb0aaaf..62df825 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -161,6 +161,8 @@
 import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
 import static com.android.server.notification.Flags.expireBitmaps;
 import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_ANIM_BUFFER;
 import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
@@ -1098,7 +1100,7 @@
     }
 
     void readPolicyXml(InputStream stream, boolean forRestore, int userId,
-            BackupRestoreEventLogger logger)
+            @Nullable BackupRestoreEventLogger logger)
             throws XmlPullParserException, NumberFormatException, IOException {
         final TypedXmlPullParser parser;
         if (forRestore) {
@@ -1114,7 +1116,27 @@
         int outerDepth = parser.getDepth();
         while (XmlUtils.nextElementWithin(parser, outerDepth)) {
             if (ZenModeConfig.ZEN_TAG.equals(parser.getName())) {
-                mZenModeHelper.readXml(parser, forRestore, userId);
+                int successfulReads = 0;
+                int unsuccessfulReads = 0;
+                try {
+                    boolean loadedCorrectly =
+                            mZenModeHelper.readXml(parser, forRestore, userId, logger);
+                    if (loadedCorrectly)
+                        successfulReads++;
+                    else
+                        unsuccessfulReads++;
+                } catch (Exception e) {
+                    Slog.wtf(TAG, "failed to read config", e);
+                    unsuccessfulReads++;
+                }
+                if (logger != null) {
+                    logger.logItemsRestored(DATA_TYPE_ZEN_CONFIG, successfulReads);
+                    if (unsuccessfulReads > 0) {
+                        logger.logItemsRestoreFailed(
+                                DATA_TYPE_ZEN_CONFIG, unsuccessfulReads, ERROR_XML_PARSING);
+                    }
+                }
+
             } else if (PreferencesHelper.TAG_RANKING.equals(parser.getName())){
                 mPreferencesHelper.readXml(parser, forRestore, userId);
             }
@@ -1246,7 +1268,7 @@
         }
     }
 
-    private void writePolicyXml(OutputStream stream, boolean forBackup, int userId,
+    void writePolicyXml(OutputStream stream, boolean forBackup, int userId,
             BackupRestoreEventLogger logger)  throws IOException {
         final TypedXmlSerializer out;
         if (forBackup) {
@@ -1258,7 +1280,7 @@
         out.startDocument(null, true);
         out.startTag(null, TAG_NOTIFICATION_POLICY);
         out.attributeInt(null, ATTR_VERSION, DB_VERSION);
-        mZenModeHelper.writeXml(out, forBackup, null, userId);
+        mZenModeHelper.writeXml(out, forBackup, null, userId, logger);
         mPreferencesHelper.writeXml(out, forBackup, userId);
         mListeners.writeXml(out, forBackup, userId);
         mAssistants.writeXml(out, forBackup, userId);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 3900870..ce249c6 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -43,6 +43,8 @@
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
 import static com.android.internal.util.Preconditions.checkArgument;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
 
 import static java.util.Objects.requireNonNull;
 
@@ -56,6 +58,7 @@
 import android.app.Flags;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.app.backup.BackupRestoreEventLogger;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
@@ -1759,11 +1762,10 @@
         pw.println(config);
     }
 
-    public void readXml(TypedXmlPullParser parser, boolean forRestore, int userId)
-            throws XmlPullParserException, IOException {
-        ZenModeConfig config = ZenModeConfig.readXml(parser);
+    public boolean readXml(TypedXmlPullParser parser, boolean forRestore, int userId,
+            @Nullable BackupRestoreEventLogger logger) throws XmlPullParserException, IOException {
+        ZenModeConfig config = ZenModeConfig.readXml(parser, logger);
         String reason = "readXml";
-
         if (config != null) {
             if (forRestore) {
                 config.user = userId;
@@ -1855,22 +1857,38 @@
 
             if (DEBUG) Log.d(TAG, reason);
             synchronized (mConfigLock) {
-                setConfigLocked(config, null,
+                return setConfigLocked(config, null,
                         forRestore ? ORIGIN_RESTORE_BACKUP : ORIGIN_INIT, reason,
                         Process.SYSTEM_UID);
             }
         }
+        return false;
     }
 
-    public void writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId)
-            throws IOException {
+    public void writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId,
+            @Nullable BackupRestoreEventLogger logger) throws IOException {
         synchronized (mConfigLock) {
+            int successfulWrites = 0;
+            int unsuccessfulWrites = 0;
             final int n = mConfigs.size();
             for (int i = 0; i < n; i++) {
                 if (forBackup && mConfigs.keyAt(i) != userId) {
                     continue;
                 }
-                mConfigs.valueAt(i).writeXml(out, version, forBackup);
+                try {
+                    mConfigs.valueAt(i).writeXml(out, version, forBackup, logger);
+                    successfulWrites++;
+                } catch (Exception e) {
+                    Slog.e(TAG, "failed to write config", e);
+                    unsuccessfulWrites++;
+                }
+            }
+            if (logger != null) {
+                logger.logItemsBackedUp(DATA_TYPE_ZEN_CONFIG, successfulWrites);
+                if (unsuccessfulWrites > 0) {
+                    logger.logItemsBackupFailed(DATA_TYPE_ZEN_CONFIG,
+                            unsuccessfulWrites, ERROR_XML_PARSING);
+                }
             }
         }
     }
@@ -2501,7 +2519,8 @@
         try {
             parser = resources.getXml(R.xml.default_zen_mode_config);
             while (parser.next() != XmlPullParser.END_DOCUMENT) {
-                final ZenModeConfig config = ZenModeConfig.readXml(XmlUtils.makeTyped(parser));
+                final ZenModeConfig config =
+                        ZenModeConfig.readXml(XmlUtils.makeTyped(parser), null);
                 if (config != null) return config;
             }
         } catch (Exception e) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index f60ec99..b99ab05 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -77,6 +77,8 @@
 import static android.app.PendingIntent.FLAG_ONE_SHOT;
 import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
 import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.PackageManager.FEATURE_TELECOM;
 import static android.content.pm.PackageManager.FEATURE_WATCH;
@@ -92,6 +94,7 @@
 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.UserHandle.USER_SYSTEM;
 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
+import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
 import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
 import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
@@ -361,6 +364,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.OutputStream;
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -6499,6 +6503,35 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_BACKUP_RESTORE_LOGGING)
+    public void testReadPolicyXml_backupRestoreLogging() throws Exception {
+        BackupRestoreEventLogger logger = mock(BackupRestoreEventLogger.class);
+
+        UserInfo ui = new UserInfo(ActivityManager.getCurrentUser(), "Clone", UserInfo.FLAG_FULL);
+        ui.userType = USER_TYPE_FULL_SYSTEM;
+        when(mUmInternal.getUserInfo(ActivityManager.getCurrentUser())).thenReturn(ui);
+        when(mPermissionHelper.getNotificationPermissionValues(0)).thenReturn(new ArrayMap<>());
+        TypedXmlSerializer serializer = Xml.newFastSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        mService.writePolicyXml(baos, true, ActivityManager.getCurrentUser(), logger);
+        serializer.flush();
+
+        mService.readPolicyXml(
+                new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+                true, ActivityManager.getCurrentUser(), logger);
+
+        verify(logger).logItemsBackedUp(DATA_TYPE_ZEN_CONFIG, 1);
+        verify(logger, never())
+                .logItemsBackupFailed(eq(DATA_TYPE_ZEN_CONFIG), anyInt(), anyString());
+
+        verify(logger).logItemsRestored(DATA_TYPE_ZEN_CONFIG, 1);
+        verify(logger, never())
+                .logItemsRestoreFailed(eq(DATA_TYPE_ZEN_CONFIG), anyInt(), anyString());
+    }
+
+    @Test
     public void testLocaleChangedCallsUpdateDefaultZenModeRules() throws Exception {
         ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
         mService.mZenModeHelper = mZenModeHelper;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 5709d88..bdf146f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -17,6 +17,8 @@
 package com.android.server.notification;
 
 import static android.app.AutomaticZenRule.TYPE_BEDTIME;
+import static android.app.Flags.FLAG_BACKUP_RESTORE_LOGGING;
+import static android.app.Flags.FLAG_MODES_API;
 import static android.app.Flags.FLAG_MODES_UI;
 import static android.app.Flags.modesUi;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
@@ -24,6 +26,8 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 import static android.app.NotificationManager.Policy.suppressedEffectsToString;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 import static android.provider.Settings.Global.ZEN_MODE_OFF;
 import static android.service.notification.Condition.SOURCE_UNKNOWN;
@@ -52,17 +56,22 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.AutomaticZenRule;
 import android.app.Flags;
 import android.app.NotificationManager.Policy;
+import android.app.backup.BackupRestoreEventLogger;
 import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Parcel;
+import android.os.UserHandle;
 import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.FlagsParameterization;
@@ -135,7 +144,7 @@
     @Parameters(name = "{0}")
     public static List<FlagsParameterization> getParams() {
         return FlagsParameterization.allCombinationsOf(
-                FLAG_MODES_UI);
+                FLAG_MODES_UI, FLAG_BACKUP_RESTORE_LOGGING);
     }
 
     public ZenModeConfigTest(FlagsParameterization flags) {
@@ -144,7 +153,6 @@
 
     @Before
     public final void setUp() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API);
         MockitoAnnotations.initMocks(this);
         mContext.setMockPackageManager(mPm);
     }
@@ -515,6 +523,98 @@
     }
 
     @Test
+    @EnableFlags({FLAG_MODES_UI, FLAG_BACKUP_RESTORE_LOGGING})
+    public void testBackupRestore_fromPreModesUi() throws IOException, XmlPullParserException {
+        String xml = "<zen version=\"12\">\n"
+                + "<allow calls=\"true\" repeatCallers=\"true\" messages=\"true\""
+                + " reminders=\"false\" events=\"false\" callsFrom=\"2\" messagesFrom=\"2\""
+                + " alarms=\"true\" media=\"true\" system=\"false\" convos=\"true\" convosFrom=\"2\""
+                + " priorityChannelsAllowed=\"true\" />\n"
+                + "<disallow visualEffects=\"157\" />\n"
+                + "<manual enabled=\"true\" zen=\"1\" creationTime=\"0\" modified=\"false\" />\n"
+                + "<state areChannelsBypassingDnd=\"true\" />\n"
+                + "</zen>";
+
+        BackupRestoreEventLogger logger = mock(BackupRestoreEventLogger.class);
+        readConfigXml(new ByteArrayInputStream(xml.getBytes()), logger);
+
+        verify(logger).logItemsRestored(DATA_TYPE_ZEN_RULES, 1);
+    }
+
+    @Test
+    public void testBackupRestore() throws IOException, XmlPullParserException {
+        ZenModeConfig config = new ZenModeConfig();
+        ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+        rule.configurationActivity = CONFIG_ACTIVITY;
+        rule.component = OWNER;
+        rule.conditionId = CONDITION_ID;
+        rule.condition = CONDITION;
+        rule.enabled = ENABLED;
+        rule.creationTime = 123;
+        rule.id = "id";
+        rule.zenMode = INTERRUPTION_FILTER;
+        rule.modified = true;
+        rule.name = NAME;
+        rule.setConditionOverride(OVERRIDE_DEACTIVATE);
+        rule.pkg = OWNER.getPackageName();
+        rule.zenPolicy = POLICY;
+
+        rule.allowManualInvocation = ALLOW_MANUAL;
+        rule.type = TYPE;
+        rule.userModifiedFields = 16;
+        rule.zenPolicyUserModifiedFields = 5;
+        rule.zenDeviceEffectsUserModifiedFields = 2;
+        rule.iconResName = ICON_RES_NAME;
+        rule.triggerDescription = TRIGGER_DESC;
+        rule.deletionInstant = Instant.ofEpochMilli(1701790147000L);
+        if (Flags.modesUi()) {
+            rule.disabledOrigin = ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI;
+        }
+        config.automaticRules.put(rule.id, rule);
+
+        BackupRestoreEventLogger logger = null;
+        if (Flags.backupRestoreLogging()) {
+            logger = mock(BackupRestoreEventLogger.class);
+        }
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        writeConfigXml(config, XML_VERSION_MODES_API, true, baos, logger);
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        ZenModeConfig fromXml = readConfigXml(bais, logger);
+
+        ZenModeConfig.ZenRule ruleActual = fromXml.automaticRules.get(rule.id);
+        assertEquals(rule.pkg, ruleActual.pkg);
+        assertEquals(OVERRIDE_NONE, ruleActual.getConditionOverride());
+        assertEquals(rule.enabler, ruleActual.enabler);
+        assertEquals(rule.component, ruleActual.component);
+        assertEquals(rule.configurationActivity, ruleActual.configurationActivity);
+        assertEquals(rule.condition, ruleActual.condition);
+        assertEquals(rule.enabled, ruleActual.enabled);
+        assertEquals(rule.creationTime, ruleActual.creationTime);
+        assertEquals(rule.modified, ruleActual.modified);
+        assertEquals(rule.conditionId, ruleActual.conditionId);
+        assertEquals(rule.name, ruleActual.name);
+        assertEquals(rule.zenMode, ruleActual.zenMode);
+
+        assertEquals(rule.allowManualInvocation, ruleActual.allowManualInvocation);
+        assertEquals(rule.iconResName, ruleActual.iconResName);
+        assertEquals(rule.type, ruleActual.type);
+        assertEquals(rule.userModifiedFields, ruleActual.userModifiedFields);
+        assertEquals(rule.zenPolicyUserModifiedFields, ruleActual.zenPolicyUserModifiedFields);
+        assertEquals(rule.zenDeviceEffectsUserModifiedFields,
+                ruleActual.zenDeviceEffectsUserModifiedFields);
+        assertEquals(rule.triggerDescription, ruleActual.triggerDescription);
+        assertEquals(rule.zenPolicy, ruleActual.zenPolicy);
+        assertEquals(rule.deletionInstant, ruleActual.deletionInstant);
+        if (Flags.modesUi()) {
+            assertEquals(rule.disabledOrigin, ruleActual.disabledOrigin);
+        }
+        if (Flags.backupRestoreLogging()) {
+            verify(logger).logItemsBackedUp(DATA_TYPE_ZEN_RULES, 2);
+            verify(logger).logItemsRestored(DATA_TYPE_ZEN_RULES, 2);
+        }
+    }
+
+    @Test
     public void testWriteToParcel() {
         ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
         rule.configurationActivity = CONFIG_ACTIVITY;
@@ -1023,9 +1123,9 @@
 
         // write out entire config xml
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos);
+        writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos, null);
         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        ZenModeConfig fromXml = readConfigXml(bais);
+        ZenModeConfig fromXml = readConfigXml(bais, null);
 
 
         // The result should be valid and contain a manual rule; the rule should have a non-null
@@ -1055,9 +1155,9 @@
 
         // write out entire config xml
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos);
+        writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos, null);
         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        ZenModeConfig fromXml = readConfigXml(bais);
+        ZenModeConfig fromXml = readConfigXml(bais, null);
 
         // The result should have a manual rule; it should have a non-null ZenPolicy and a condition
         // whose state is true. The conditionId and enabler data should also be preserved.
@@ -1084,9 +1184,9 @@
 
         // write out entire config xml
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos);
+        writeConfigXml(config, XML_VERSION_MODES_API, /* forBackup= */ false, baos, null);
         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        ZenModeConfig fromXml = readConfigXml(bais);
+        ZenModeConfig fromXml = readConfigXml(bais, null);
 
         // The result should have a manual rule; it should not be changed from the previous rule.
         assertThat(fromXml.manualRule).isEqualTo(config.manualRule);
@@ -1213,9 +1313,9 @@
         config.manualRule.enabled = false;
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        writeConfigXml(config, XML_VERSION_MODES_UI, /* forBackup= */ false, baos);
+        writeConfigXml(config, XML_VERSION_MODES_UI, /* forBackup= */ false, baos, null);
         ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-        ZenModeConfig fromXml = readConfigXml(bais);
+        ZenModeConfig fromXml = readConfigXml(bais, null);
 
         assertThat(fromXml.manualRule.enabled).isTrue();
     }
@@ -1359,23 +1459,23 @@
     }
 
     private void writeConfigXml(ZenModeConfig config, Integer version, boolean forBackup,
-            ByteArrayOutputStream os) throws IOException {
+            ByteArrayOutputStream os, BackupRestoreEventLogger logger) throws IOException {
         String tag = ZEN_TAG;
 
         TypedXmlSerializer out = Xml.newFastSerializer();
         out.setOutput(new BufferedOutputStream(os), "utf-8");
         out.startDocument(null, true);
         out.startTag(null, tag);
-        config.writeXml(out, version, forBackup);
+        config.writeXml(out, version, forBackup, logger);
         out.endTag(null, tag);
         out.endDocument();
     }
 
-    private ZenModeConfig readConfigXml(ByteArrayInputStream is)
+    private ZenModeConfig readConfigXml(ByteArrayInputStream is, BackupRestoreEventLogger logger)
             throws XmlPullParserException, IOException {
         TypedXmlPullParser parser = Xml.newFastPullParser();
         parser.setInput(new BufferedInputStream(is), null);
         parser.nextTag();
-        return ZenModeConfig.readXml(parser);
+        return ZenModeConfig.readXml(parser, logger);
     }
 }
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 a196594..6792377 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -20,6 +20,7 @@
 import static android.app.AutomaticZenRule.TYPE_IMMERSIVE;
 import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
 import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
+import static android.app.Flags.FLAG_BACKUP_RESTORE_LOGGING;
 import static android.app.Flags.FLAG_MODES_API;
 import static android.app.Flags.FLAG_MODES_MULTIUSER;
 import static android.app.Flags.FLAG_MODES_UI;
@@ -83,6 +84,8 @@
 import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
 import static com.android.os.dnd.DNDProtoEnums.STATE_ALLOW;
 import static com.android.os.dnd.DNDProtoEnums.STATE_DISALLOW;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
+import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
 import static com.android.server.notification.ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL;
 import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
 
@@ -104,6 +107,7 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.notNull;
@@ -118,15 +122,17 @@
 import android.Manifest;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
+import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
 import android.app.Flags;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.app.backup.BackupRestoreEventLogger;
 import android.app.compat.CompatChanges;
 import android.content.ComponentName;
-import android.content.ContentResolver;
+import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -273,7 +279,6 @@
     private TestableLooper mTestableLooper;
     private final TestClock mTestClock = new TestClock();
     private ZenModeHelper mZenModeHelper;
-    private ContentResolver mContentResolver;
     @Mock
     DeviceEffectsApplier mDeviceEffectsApplier;
     @Mock
@@ -284,8 +289,7 @@
 
     @Parameters(name = "{0}")
     public static List<FlagsParameterization> getParams() {
-        return FlagsParameterization.progressionOf(FLAG_MODES_API,
-                FLAG_MODES_UI);
+        return FlagsParameterization.allCombinationsOf(FLAG_MODES_UI, FLAG_BACKUP_RESTORE_LOGGING);
     }
 
     public ZenModeHelperTest(FlagsParameterization flags) {
@@ -298,7 +302,6 @@
 
         mTestableLooper = TestableLooper.get(this);
         mContext.ensureTestableResources();
-        mContentResolver = mContext.getContentResolver();
         mResources = mock(Resources.class, withSettings()
                 .spiedInstance(mContext.getResources()));
         mPkg = mContext.getPackageName();
@@ -316,11 +319,16 @@
 
         mContext.addMockSystemService(AppOpsManager.class, mAppOps);
         mContext.addMockSystemService(NotificationManager.class, mNotificationManager);
+        mContext.addMockSystemService(Context.ALARM_SERVICE, mock(AlarmManager.class));
 
         mConditionProviders = new ConditionProviders(mContext, new UserProfiles(),
                 AppGlobals.getPackageManager());
-        mConditionProviders.addSystemProvider(new CountdownConditionProvider());
-        mConditionProviders.addSystemProvider(new ScheduleConditionProvider());
+        CountdownConditionProvider countdown = spy(new CountdownConditionProvider());
+        ScheduleConditionProvider schedule = spy(new ScheduleConditionProvider());
+        doNothing().when(countdown).notifyConditions(any());
+        doNothing().when(schedule).notifyConditions(any());
+        mConditionProviders.addSystemProvider(countdown);
+        mConditionProviders.addSystemProvider(schedule);
         mZenModeEventLogger = new ZenModeEventLoggerFake(mPackageManager);
         mZenModeHelper = new ZenModeHelper(mContext, mTestableLooper.getLooper(), mTestClock,
                 mConditionProviders, mTestFlagResolver, mZenModeEventLogger);
@@ -379,7 +387,7 @@
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
         serializer.startDocument(null, true);
-        mZenModeHelper.writeXml(serializer, false, version, UserHandle.USER_ALL);
+        mZenModeHelper.writeXml(serializer, false, version, UserHandle.USER_ALL, null);
         serializer.endDocument();
         serializer.flush();
         mZenModeHelper.setConfig(new ZenModeConfig(), null, ORIGIN_INIT, "writing xml",
@@ -387,13 +395,14 @@
         return baos;
     }
 
-    private ByteArrayOutputStream writeXmlAndPurgeForUser(Integer version, int userId)
+    private ByteArrayOutputStream writeXmlAndPurgeForUser(Integer version, int userId,
+            boolean forBackup, BackupRestoreEventLogger logger)
             throws Exception {
         TypedXmlSerializer serializer = Xml.newFastSerializer();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
         serializer.startDocument(null, true);
-        mZenModeHelper.writeXml(serializer, true, version, userId);
+        mZenModeHelper.writeXml(serializer, forBackup, version, userId, logger);
         serializer.endDocument();
         serializer.flush();
         ZenModeConfig newConfig = new ZenModeConfig();
@@ -1093,7 +1102,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(null);
         TypedXmlPullParser parser = getParserForByteStream(baos);
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertEquals("Config mismatch: current vs expected: "
                         + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, expected), expected,
@@ -1169,7 +1178,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
         List<StatsEvent> events = new LinkedList<>();
         mZenModeHelper.pullRules(events);
 
@@ -1377,6 +1386,10 @@
 
     @Test
     public void testWriteXml_onlyBackupsTargetUser() throws Exception {
+        BackupRestoreEventLogger logger = null;
+        if (android.app.Flags.backupRestoreLogging()) {
+            logger = mock(BackupRestoreEventLogger.class);
+        }
         // Setup configs for user 10 and 11.
         setupZenConfig();
         ZenModeConfig config10 = mZenModeHelper.mConfig.copy();
@@ -1393,15 +1406,16 @@
                 SYSTEM_UID);
 
         // Backup user 10 and reset values.
-        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(null, 10);
+        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(null, 10, true, logger);
         ZenModeConfig newConfig11 = new ZenModeConfig();
         newConfig11.user = 11;
         mZenModeHelper.mConfigs.put(11, newConfig11);
 
         // Parse backup data.
         TypedXmlPullParser parser = getParserForByteStream(baos);
-        mZenModeHelper.readXml(parser, true, 10);
-        mZenModeHelper.readXml(parser, true, 11);
+        mZenModeHelper.readXml(parser, true, 10, logger);
+        parser = getParserForByteStream(baos);
+        mZenModeHelper.readXml(parser, true, 11, logger);
 
         ZenModeConfig actual = mZenModeHelper.mConfigs.get(10);
         if (Flags.modesUi()) {
@@ -1415,39 +1429,72 @@
                 "Config mismatch: current vs expected: "
                         + new ZenModeDiff.ConfigDiff(actual, config10), config10, actual);
         assertNotEquals("Expected config mismatch", config11, mZenModeHelper.mConfigs.get(11));
+
+        if (android.app.Flags.backupRestoreLogging()) {
+            verify(logger).logItemsBackedUp(DATA_TYPE_ZEN_CONFIG, 1);
+            // If this is modes_ui, this is manual + single default rule
+            // If not modes_ui, it's two default automatic rules + manual policy
+            verify(logger).logItemsBackedUp(DATA_TYPE_ZEN_RULES, Flags.modesUi() ? 2 : 3);
+            verify(logger, never())
+                    .logItemsBackupFailed(anyString(), anyInt(), anyString());
+
+            verify(logger, times(2)).logItemsRestored(DATA_TYPE_ZEN_RULES, Flags.modesUi() ? 2 : 3);
+            verify(logger, never())
+                    .logItemsRestoreFailed(anyString(), anyInt(), anyString());
+        }
     }
 
     @Test
     public void testReadXmlRestore_forSystemUser() throws Exception {
+        BackupRestoreEventLogger logger = null;
+        if (android.app.Flags.backupRestoreLogging()) {
+            logger = mock(BackupRestoreEventLogger.class);
+        }
         setupZenConfig();
         // one enabled automatic rule
         mZenModeHelper.mConfig.automaticRules = getCustomAutomaticRules();
         ZenModeConfig original = mZenModeHelper.mConfig.copy();
 
-        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(null, UserHandle.USER_SYSTEM);
+        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(
+                null, UserHandle.USER_SYSTEM, true, logger);
         TypedXmlPullParser parser = getParserForByteStream(baos);
-        mZenModeHelper.readXml(parser, true, UserHandle.USER_SYSTEM);
+        mZenModeHelper.readXml(parser, true, UserHandle.USER_SYSTEM, logger);
 
         assertEquals("Config mismatch: current vs original: "
                         + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, original),
                 original, mZenModeHelper.mConfig);
         assertEquals(original.hashCode(), mZenModeHelper.mConfig.hashCode());
+
+        if (android.app.Flags.backupRestoreLogging()) {
+            verify(logger).logItemsBackedUp(DATA_TYPE_ZEN_CONFIG, 1);
+            verify(logger).logItemsBackedUp(DATA_TYPE_ZEN_RULES, 2);
+            verify(logger, never())
+                    .logItemsBackupFailed(anyString(), anyInt(), anyString());
+            verify(logger).logItemsRestored(DATA_TYPE_ZEN_RULES, 2);
+            verify(logger, never())
+                    .logItemsRestoreFailed(anyString(), anyInt(), anyString());
+        }
     }
 
     /** Restore should ignore the data's user id and restore for the target user. */
     @Test
     public void testReadXmlRestore_forNonSystemUser() throws Exception {
+        BackupRestoreEventLogger logger = null;
+        if (android.app.Flags.backupRestoreLogging()) {
+            logger = mock(BackupRestoreEventLogger.class);
+        }
         // Setup config.
         setupZenConfig();
         mZenModeHelper.mConfig.automaticRules = getCustomAutomaticRules();
         ZenModeConfig expected = mZenModeHelper.mConfig.copy();
 
         // Backup data for user 0.
-        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(null, UserHandle.USER_SYSTEM);
+        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(
+                null, UserHandle.USER_SYSTEM, true, logger);
 
         // Restore data for user 10.
         TypedXmlPullParser parser = getParserForByteStream(baos);
-        mZenModeHelper.readXml(parser, true, 10);
+        mZenModeHelper.readXml(parser, true, 10, logger);
 
         ZenModeConfig actual = mZenModeHelper.mConfigs.get(10);
         expected.user = 10;
@@ -1461,6 +1508,10 @@
 
     @Test
     public void testReadXmlRestore_doesNotEnableManualRule() throws Exception {
+        BackupRestoreEventLogger logger = null;
+        if (android.app.Flags.backupRestoreLogging()) {
+            logger = mock(BackupRestoreEventLogger.class);
+        }
         setupZenConfig();
 
         // Turn on manual zen mode
@@ -1471,7 +1522,7 @@
 
         ByteArrayOutputStream baos = writeXmlAndPurge(null);
         TypedXmlPullParser parser = getParserForByteStream(baos);
-        mZenModeHelper.readXml(parser, true, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, true, UserHandle.USER_ALL, logger);
 
         ZenModeConfig result = mZenModeHelper.getConfig();
         assertThat(result.isManualActive()).isFalse();
@@ -1525,7 +1576,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         ZenModeConfig.ZenRule original = expected.automaticRules.get(ruleId);
         ZenModeConfig.ZenRule current = mZenModeHelper.mConfig.automaticRules.get(ruleId);
@@ -1536,6 +1587,10 @@
 
     @Test
     public void testReadXmlRestoreWithZenPolicy_forSystemUser() throws Exception {
+        BackupRestoreEventLogger logger = null;
+        if (android.app.Flags.backupRestoreLogging()) {
+            logger = mock(BackupRestoreEventLogger.class);
+        }
         final String ruleId = "customRule";
         setupZenConfig();
 
@@ -1567,9 +1622,10 @@
             SystemZenRules.maybeUpgradeRules(mContext, expected);
         }
 
-        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(null, UserHandle.USER_SYSTEM);
+        ByteArrayOutputStream baos = writeXmlAndPurgeForUser(
+                null, UserHandle.USER_SYSTEM, true, logger);
         TypedXmlPullParser parser = getParserForByteStream(baos);
-        mZenModeHelper.readXml(parser, true, UserHandle.USER_SYSTEM);
+        mZenModeHelper.readXml(parser, true, UserHandle.USER_SYSTEM, logger);
 
         ZenModeConfig.ZenRule original = expected.automaticRules.get(ruleId);
         ZenModeConfig.ZenRule current = mZenModeHelper.mConfig.automaticRules.get(ruleId);
@@ -1601,7 +1657,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertTrue(mZenModeHelper.mConfig.automaticRules.containsKey("customRule"));
         assertEquals(originalPolicy, mZenModeHelper.getNotificationPolicy(UserHandle.CURRENT));
@@ -1621,7 +1677,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml.getBytes())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertTrue(mZenModeHelper.mConfig.getZenPolicy().shouldShowAllVisualEffects());
 
@@ -1637,7 +1693,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml.getBytes())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertTrue(mZenModeHelper.mConfig.getZenPolicy().shouldShowAllVisualEffects());
     }
@@ -1656,7 +1712,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml.getBytes())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertTrue(mZenModeHelper.mConfig.getZenPolicy().shouldShowAllVisualEffects());
     }
@@ -1675,7 +1731,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml.getBytes())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertThat(mZenModeHelper.mConfig.getZenPolicy()
                 .isVisualEffectAllowed(VISUAL_EFFECT_FULL_SCREEN_INTENT, true)).isFalse();
@@ -1700,7 +1756,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml.getBytes())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertThat(mZenModeHelper.mConfig.getZenPolicy()
                 .isVisualEffectAllowed(VISUAL_EFFECT_PEEK, true)).isFalse();
@@ -1719,7 +1775,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml.getBytes())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertThat(mZenModeHelper.mConfig.getZenPolicy()
                 .isVisualEffectAllowed(VISUAL_EFFECT_FULL_SCREEN_INTENT, true)).isFalse();
@@ -1746,7 +1802,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // check default rules
         ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
@@ -1782,7 +1838,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // check default rules
         ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
@@ -1836,7 +1892,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // check default rules
         ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
@@ -1906,7 +1962,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // check default rules
         int expectedNumAutoRules = 1 + ZenModeConfig.getDefaultRuleIds().size(); // custom + default
@@ -1959,7 +2015,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // basic check: global config maintained
         assertEquals(originalPolicy, mZenModeHelper.getNotificationPolicy(UserHandle.CURRENT));
@@ -1998,7 +2054,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // basic check: global config maintained
         assertEquals(originalPolicy, mZenModeHelper.getNotificationPolicy(UserHandle.CURRENT));
@@ -2055,7 +2111,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // basic check: global config maintained
         assertEquals(originalPolicy, mZenModeHelper.getNotificationPolicy(UserHandle.CURRENT));
@@ -2121,7 +2177,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // check default rules
         ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules;
@@ -2173,7 +2229,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // Implicit rule was updated.
         assertThat(mZenModeHelper.mConfig.automaticRules.get(implicitRuleBeforeModesUi.id))
@@ -2211,7 +2267,7 @@
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
         parser.nextTag();
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         // Both rules were untouched
         assertThat(mZenModeHelper.mConfig.automaticRules.get(implicitRuleWithModesUi.id))
@@ -6965,7 +7021,7 @@
 
         // Now simulate a reboot -> reload the configuration after purging.
         TypedXmlPullParser parser = getParserForByteStream(xmlBytes);
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         if (Flags.modesUi()) {
             assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
@@ -7006,7 +7062,7 @@
 
         // Now simulate a reboot -> reload the configuration after purging.
         TypedXmlPullParser parser = getParserForByteStream(xmlBytes);
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
                 .isEqualTo(STATE_TRUE);
@@ -7045,7 +7101,7 @@
         ByteArrayOutputStream xmlBytes = writeXmlAndPurge(ZenModeConfig.XML_VERSION_MODES_UI);
         TypedXmlPullParser parser = getParserForByteStream(xmlBytes);
 
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertThat(mZenModeHelper.mConfig.automaticRules).doesNotContainKey(
                 ZenModeConfig.EVENTS_OBSOLETE_RULE_ID);
@@ -7065,7 +7121,7 @@
         ByteArrayOutputStream xmlBytes = writeXmlAndPurge(ZenModeConfig.XML_VERSION_MODES_UI);
         TypedXmlPullParser parser = getParserForByteStream(xmlBytes);
 
-        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL);
+        mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
 
         assertThat(mZenModeHelper.mConfig.automaticRules).containsKey(
                 ZenModeConfig.EVENTS_OBSOLETE_RULE_ID);