diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 42daea24593e7eb2e05425e46e7a9abb02937910..aaeba66e4a40d30cb5e9e0b2dfa18a074215acac 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -369,11 +369,14 @@ package android.app {
   }
 
   public class NotificationManager {
+    method @FlaggedApi("android.app.modes_api") @NonNull public String addAutomaticZenRule(@NonNull android.app.AutomaticZenRule, boolean);
     method public void cleanUpCallersAfter(long);
     method public android.content.ComponentName getEffectsSuppressor();
     method public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String);
+    method @FlaggedApi("android.app.modes_api") public boolean removeAutomaticZenRule(@NonNull String, boolean);
     method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean);
     method @RequiresPermission(android.Manifest.permission.MANAGE_TOAST_RATE_LIMITING) public void setToastRateLimitingEnabled(boolean);
+    method @FlaggedApi("android.app.modes_api") public boolean updateAutomaticZenRule(@NonNull String, @NonNull android.app.AutomaticZenRule, boolean);
     method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel);
   }
 
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 94385717d34964c55b5d7087aa243464e27aafb0..b7db5f5d8b0c822b75858e084a7ead8d16c6dfca 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -167,7 +167,7 @@ interface INotificationManager
     void requestInterruptionFilterFromListener(in INotificationListener token, int interruptionFilter);
     int getInterruptionFilterFromListener(in INotificationListener token);
     void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
-    void setInterruptionFilter(String pkg, int interruptionFilter);
+    void setInterruptionFilter(String pkg, int interruptionFilter, boolean fromUser);
 
     void updateNotificationChannelGroupFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannelGroup group);
     void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannel channel);
@@ -205,11 +205,11 @@ interface INotificationManager
     @UnsupportedAppUsage
     ZenModeConfig getZenModeConfig();
     NotificationManager.Policy getConsolidatedNotificationPolicy();
-    oneway void setZenMode(int mode, in Uri conditionId, String reason);
+    oneway void setZenMode(int mode, in Uri conditionId, String reason, boolean fromUser);
     oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
     boolean isNotificationPolicyAccessGranted(String pkg);
     NotificationManager.Policy getNotificationPolicy(String pkg);
-    void setNotificationPolicy(String pkg, in NotificationManager.Policy policy);
+    void setNotificationPolicy(String pkg, in NotificationManager.Policy policy, boolean fromUser);
     boolean isNotificationPolicyAccessGrantedForPackage(String pkg);
     void setNotificationPolicyAccessGranted(String pkg, boolean granted);
     void setNotificationPolicyAccessGrantedForUser(String pkg, int userId, boolean granted);
@@ -217,12 +217,12 @@ interface INotificationManager
     Map<String, AutomaticZenRule> getAutomaticZenRules();
     // TODO: b/310620812 - Remove getZenRules() when MODES_API is inlined.
     List<ZenModeConfig.ZenRule> getZenRules();
-    String addAutomaticZenRule(in AutomaticZenRule automaticZenRule, String pkg);
-    boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule);
-    boolean removeAutomaticZenRule(String id);
-    boolean removeAutomaticZenRules(String packageName);
+    String addAutomaticZenRule(in AutomaticZenRule automaticZenRule, String pkg, boolean fromUser);
+    boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule, boolean fromUser);
+    boolean removeAutomaticZenRule(String id, boolean fromUser);
+    boolean removeAutomaticZenRules(String packageName, boolean fromUser);
     int getRuleInstanceCount(in ComponentName owner);
-    void setAutomaticZenRuleState(String id, in Condition condition);
+    void setAutomaticZenRuleState(String id, in Condition condition, boolean fromUser);
 
     byte[] getBackupPayload(int user);
     void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index d23b16d636a761fe15748418983e9259049fd6e9..f76a45b376619ecaa3071ac9b647157c7f702417 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1184,14 +1184,20 @@ public class NotificationManager {
      */
     @UnsupportedAppUsage
     public void setZenMode(int mode, Uri conditionId, String reason) {
+        setZenMode(mode, conditionId, reason, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    public void setZenMode(int mode, Uri conditionId, String reason, boolean fromUser) {
         INotificationManager service = getService();
         try {
-            service.setZenMode(mode, conditionId, reason);
+            service.setZenMode(mode, conditionId, reason, fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+
     /**
      * @hide
      */
@@ -1325,9 +1331,19 @@ public class NotificationManager {
      * @return The id of the newly created rule; null if the rule could not be created.
      */
     public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+        return addAutomaticZenRule(automaticZenRule, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    @NonNull
+    public String addAutomaticZenRule(@NonNull AutomaticZenRule automaticZenRule,
+            boolean fromUser) {
         INotificationManager service = getService();
         try {
-            return service.addAutomaticZenRule(automaticZenRule, mContext.getPackageName());
+            return service.addAutomaticZenRule(automaticZenRule,
+                    mContext.getPackageName(), fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1347,9 +1363,17 @@ public class NotificationManager {
      * @return Whether the rule was successfully updated.
      */
     public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
+        return updateAutomaticZenRule(id, automaticZenRule, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public boolean updateAutomaticZenRule(@NonNull String id,
+            @NonNull AutomaticZenRule automaticZenRule, boolean fromUser) {
         INotificationManager service = getService();
         try {
-            return service.updateAutomaticZenRule(id, automaticZenRule);
+            return service.updateAutomaticZenRule(id, automaticZenRule, fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1367,9 +1391,20 @@ public class NotificationManager {
      * @param condition The new state of this rule
      */
     public void setAutomaticZenRuleState(@NonNull String id, @NonNull Condition condition) {
+        if (Flags.modesApi()) {
+            setAutomaticZenRuleState(id, condition,
+                    /* fromUser= */ condition.source == Condition.SOURCE_USER_ACTION);
+        } else {
+            setAutomaticZenRuleState(id, condition, /* fromUser= */ false);
+        }
+    }
+
+    /** @hide */
+    public void setAutomaticZenRuleState(@NonNull String id, @NonNull Condition condition,
+            boolean fromUser) {
         INotificationManager service = getService();
         try {
-            service.setAutomaticZenRuleState(id, condition);
+            service.setAutomaticZenRuleState(id, condition, fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1388,9 +1423,16 @@ public class NotificationManager {
      * @return Whether the rule was successfully deleted.
      */
     public boolean removeAutomaticZenRule(String id) {
+        return removeAutomaticZenRule(id, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public boolean removeAutomaticZenRule(@NonNull String id, boolean fromUser) {
         INotificationManager service = getService();
         try {
-            return service.removeAutomaticZenRule(id);
+            return service.removeAutomaticZenRule(id, fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1402,9 +1444,14 @@ public class NotificationManager {
      * @hide
      */
     public boolean removeAutomaticZenRules(String packageName) {
+        return removeAutomaticZenRules(packageName, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    public boolean removeAutomaticZenRules(String packageName, boolean fromUser) {
         INotificationManager service = getService();
         try {
-            return service.removeAutomaticZenRules(packageName);
+            return service.removeAutomaticZenRules(packageName, fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1685,10 +1732,15 @@ public class NotificationManager {
      */
     // TODO(b/309457271): Update documentation with VANILLA_ICE_CREAM behavior.
     public void setNotificationPolicy(@NonNull Policy policy) {
+        setNotificationPolicy(policy, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    public void setNotificationPolicy(@NonNull Policy policy, boolean fromUser) {
         checkRequired("policy", policy);
         INotificationManager service = getService();
         try {
-            service.setNotificationPolicy(mContext.getOpPackageName(), policy);
+            service.setNotificationPolicy(mContext.getOpPackageName(), policy, fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2685,9 +2737,16 @@ public class NotificationManager {
      */
     // TODO(b/309457271): Update documentation with VANILLA_ICE_CREAM behavior.
     public final void setInterruptionFilter(@InterruptionFilter int interruptionFilter) {
+        setInterruptionFilter(interruptionFilter, /* fromUser= */ false);
+    }
+
+    /** @hide */
+    public final void setInterruptionFilter(@InterruptionFilter int interruptionFilter,
+            boolean fromUser) {
         final INotificationManager service = getService();
         try {
-            service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
+            service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter,
+                    fromUser);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 562d20d05429eebf02c9e29e17ad30526fe8cb17..7fb959ae4d768fe6712d2e012048ce174bf89021 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.AlertDialog;
+import android.app.Flags;
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -143,9 +144,16 @@ public class EnableZenModeDialog {
                                     Slog.d(TAG, "Invalid manual condition: " + tag.condition);
                                 }
                                 // always triggers priority-only dnd with chosen condition
-                                mNotificationManager.setZenMode(
-                                        Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
-                                        getRealConditionId(tag.condition), TAG);
+                                if (Flags.modesApi()) {
+                                    mNotificationManager.setZenMode(
+                                            Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                                            getRealConditionId(tag.condition), TAG,
+                                            /* fromUser= */ true);
+                                } else {
+                                    mNotificationManager.setZenMode(
+                                            Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+                                            getRealConditionId(tag.condition), TAG);
+                                }
                             }
                         });
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index fa0cb5c939ab31647c807ac39683077815bd55ee..66bf527f504755da06ed05abd19a1d9a3103feaa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.policy;
 
 import android.app.AlarmManager;
+import android.app.Flags;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -191,7 +192,11 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
 
     @Override
     public void setZen(int zen, Uri conditionId, String reason) {
-        mNoMan.setZenMode(zen, conditionId, reason);
+        if (Flags.modesApi()) {
+            mNoMan.setZenMode(zen, conditionId, reason, /* fromUser= */ true);
+        } else {
+            mNoMan.setZenMode(zen, conditionId, reason);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 2da1a689f69f29f6dbeb37ceaf851f8deb5f314e..66e61c076030b06a2463aaad9cb2880c034e24b8 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -234,7 +234,7 @@ public class ConditionProviders extends ManagedServices {
             if (pkgList != null && (pkgList.length > 0)) {
                 for (String pkgName : pkgList) {
                     try {
-                        inm.removeAutomaticZenRules(pkgName);
+                        inm.removeAutomaticZenRules(pkgName, /* fromUser= */ false);
                         inm.setNotificationPolicyAccessGranted(pkgName, false);
                     } catch (Exception e) {
                         Slog.e(TAG, "Failed to clean up rules for " + pkgName, e);
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index 885566693b9a55c7c5dd3248220e86ce2c7b6801..71a6b5ed058134073fea651aeed2b8500e8fafec 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -109,7 +109,6 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
         if (origin == ZenModeConfig.UPDATE_ORIGIN_INIT
                 || origin == ZenModeConfig.UPDATE_ORIGIN_INIT_USER
                 || origin == ZenModeConfig.UPDATE_ORIGIN_USER
-                || origin == ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
                 || !mPowerManager.isInteractive()) {
             unregisterScreenOffReceiver();
             updateNightModeImmediately(useNightMode);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 75d3dce55abda02d858e82f6e3f7ec8af4f09d7f..a919db9475935f52b481db2826e2cffec241be93 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5343,13 +5343,14 @@ public class NotificationManagerService extends SystemService {
         }
 
         @Override
-        public void setZenMode(int mode, Uri conditionId, String reason) throws RemoteException {
+        public void setZenMode(int mode, Uri conditionId, String reason, boolean fromUser) {
             enforceSystemOrSystemUI("INotificationManager.setZenMode");
             final int callingUid = Binder.getCallingUid();
             final long identity = Binder.clearCallingIdentity();
+            enforceUserOriginOnlyFromSystem(fromUser, "setZenMode");
+
             try {
-                mZenModeHelper.setManualZenMode(mode, conditionId,
-                        ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, // Checked by enforce()
+                mZenModeHelper.setManualZenMode(mode, conditionId, computeZenOrigin(fromUser),
                         reason, /* caller= */ null, callingUid);
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -5380,7 +5381,8 @@ public class NotificationManagerService extends SystemService {
         }
 
         @Override
-        public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String pkg) {
+        public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String pkg,
+                boolean fromUser) {
             validateAutomaticZenRule(automaticZenRule);
             checkCallerIsSameApp(pkg);
             if (automaticZenRule.getZenPolicy() != null
@@ -5389,6 +5391,7 @@ public class NotificationManagerService extends SystemService {
                         + "INTERRUPTION_FILTER_PRIORITY filters");
             }
             enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
+            enforceUserOriginOnlyFromSystem(fromUser, "addAutomaticZenRule");
 
             // If the calling app is the system (from any user), take the package name from the
             // rule's owner rather than from the caller's package.
@@ -5400,24 +5403,18 @@ public class NotificationManagerService extends SystemService {
             }
 
             return mZenModeHelper.addAutomaticZenRule(rulePkg, automaticZenRule,
-                    // TODO: b/308670715: Distinguish origin properly (e.g. USER if creating a rule
-                    //  manually in Settings).
-                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                            : ZenModeConfig.UPDATE_ORIGIN_APP,
-                    "addAutomaticZenRule", Binder.getCallingUid());
+                    computeZenOrigin(fromUser), "addAutomaticZenRule", Binder.getCallingUid());
         }
 
         @Override
-        public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
+        public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule,
+                boolean fromUser) throws RemoteException {
             validateAutomaticZenRule(automaticZenRule);
             enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
+            enforceUserOriginOnlyFromSystem(fromUser, "updateAutomaticZenRule");
 
-            // TODO: b/308670715: Distinguish origin properly (e.g. USER if updating a rule
-            //  manually in Settings).
             return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
-                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                            : ZenModeConfig.UPDATE_ORIGIN_APP,
-                    "updateAutomaticZenRule", Binder.getCallingUid());
+                    computeZenOrigin(fromUser), "updateAutomaticZenRule", Binder.getCallingUid());
         }
 
         private void validateAutomaticZenRule(AutomaticZenRule rule) {
@@ -5445,27 +5442,24 @@ public class NotificationManagerService extends SystemService {
         }
 
         @Override
-        public boolean removeAutomaticZenRule(String id) throws RemoteException {
+        public boolean removeAutomaticZenRule(String id, boolean fromUser) throws RemoteException {
             Objects.requireNonNull(id, "Id is null");
             // Verify that they can modify zen rules.
             enforcePolicyAccess(Binder.getCallingUid(), "removeAutomaticZenRule");
+            enforceUserOriginOnlyFromSystem(fromUser, "removeAutomaticZenRule");
 
-            // TODO: b/308670715: Distinguish origin properly (e.g. USER if removing a rule
-            //  manually in Settings).
-            return mZenModeHelper.removeAutomaticZenRule(id,
-                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+            return mZenModeHelper.removeAutomaticZenRule(id, computeZenOrigin(fromUser),
                     "removeAutomaticZenRule", Binder.getCallingUid());
         }
 
         @Override
-        public boolean removeAutomaticZenRules(String packageName) throws RemoteException {
+        public boolean removeAutomaticZenRules(String packageName, boolean fromUser)
+                throws RemoteException {
             Objects.requireNonNull(packageName, "Package name is null");
             enforceSystemOrSystemUI("removeAutomaticZenRules");
+            enforceUserOriginOnlyFromSystem(fromUser, "removeAutomaticZenRules");
 
-            return mZenModeHelper.removeAutomaticZenRules(packageName,
-                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+            return mZenModeHelper.removeAutomaticZenRules(packageName, computeZenOrigin(fromUser),
                     packageName + "|removeAutomaticZenRules", Binder.getCallingUid());
         }
 
@@ -5478,28 +5472,54 @@ public class NotificationManagerService extends SystemService {
         }
 
         @Override
-        public void setAutomaticZenRuleState(String id, Condition condition) {
+        public void setAutomaticZenRuleState(String id, Condition condition, boolean fromUser) {
             Objects.requireNonNull(id, "id is null");
             Objects.requireNonNull(condition, "Condition is null");
             condition.validate();
 
             enforcePolicyAccess(Binder.getCallingUid(), "setAutomaticZenRuleState");
 
-            // TODO: b/308670715: Distinguish origin properly (e.g. USER if toggling a rule
-            //  manually in Settings).
-            mZenModeHelper.setAutomaticZenRuleState(id, condition,
-                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+            if (android.app.Flags.modesApi()) {
+                if (fromUser != (condition.source == Condition.SOURCE_USER_ACTION)) {
+                    throw new IllegalArgumentException(String.format(
+                            "Mismatch between fromUser (%s) and condition.source (%s)",
+                            fromUser, Condition.sourceToString(condition.source)));
+                }
+            }
+
+            mZenModeHelper.setAutomaticZenRuleState(id, condition, computeZenOrigin(fromUser),
                     Binder.getCallingUid());
         }
 
+        @ZenModeConfig.ConfigChangeOrigin
+        private int computeZenOrigin(boolean fromUser) {
+            // "fromUser" is introduced with MODES_API, so only consider it in that case.
+            // (Non-MODES_API behavior should also not depend at all on UPDATE_ORIGIN_USER).
+            if (android.app.Flags.modesApi() && fromUser) {
+                return ZenModeConfig.UPDATE_ORIGIN_USER;
+            } else if (isCallerSystemOrSystemUi()) {
+                return ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI;
+            } else {
+                return ZenModeConfig.UPDATE_ORIGIN_APP;
+            }
+        }
+
+        private void enforceUserOriginOnlyFromSystem(boolean fromUser, String method) {
+            if (android.app.Flags.modesApi()
+                    && fromUser
+                    && !isCallerSystemOrSystemUiOrShell()) {
+                throw new SecurityException(String.format(
+                        "Calling %s with fromUser == true is only allowed for system", method));
+            }
+        }
+
         @Override
-        public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
+        public void setInterruptionFilter(String pkg, int filter, boolean fromUser) {
             enforcePolicyAccess(pkg, "setInterruptionFilter");
             final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
             if (zen == -1) throw new IllegalArgumentException("Invalid filter: " + filter);
             final int callingUid = Binder.getCallingUid();
-            final boolean isSystemOrSystemUi = isCallerSystemOrSystemUi();
+            enforceUserOriginOnlyFromSystem(fromUser, "setInterruptionFilter");
 
             if (android.app.Flags.modesApi() && !canManageGlobalZenPolicy(pkg, callingUid)) {
                 mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(pkg, callingUid, zen);
@@ -5508,9 +5528,7 @@ public class NotificationManagerService extends SystemService {
 
             final long identity = Binder.clearCallingIdentity();
             try {
-                mZenModeHelper.setManualZenMode(zen, null,
-                        isSystemOrSystemUi ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                                : ZenModeConfig.UPDATE_ORIGIN_APP,
+                mZenModeHelper.setManualZenMode(zen, null, computeZenOrigin(fromUser),
                         /* reason= */ "setInterruptionFilter", /* caller= */ pkg,
                         callingUid);
             } finally {
@@ -5825,10 +5843,11 @@ public class NotificationManagerService extends SystemService {
          * {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd
          */
         @Override
-        public void setNotificationPolicy(String pkg, Policy policy) {
+        public void setNotificationPolicy(String pkg, Policy policy, boolean fromUser) {
             enforcePolicyAccess(pkg, "setNotificationPolicy");
+            enforceUserOriginOnlyFromSystem(fromUser, "setNotificationPolicy");
             int callingUid = Binder.getCallingUid();
-            boolean isSystemOrSystemUi = isCallerSystemOrSystemUi();
+            @ZenModeConfig.ConfigChangeOrigin int origin = computeZenOrigin(fromUser);
 
             boolean shouldApplyAsImplicitRule = android.app.Flags.modesApi()
                     && !canManageGlobalZenPolicy(pkg, callingUid);
@@ -5873,14 +5892,12 @@ public class NotificationManagerService extends SystemService {
                         newVisualEffects, policy.priorityConversationSenders);
 
                 if (shouldApplyAsImplicitRule) {
-                    mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, callingUid, policy);
+                    mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, callingUid, policy,
+                            origin);
                 } else {
                     ZenLog.traceSetNotificationPolicy(pkg, applicationInfo.targetSdkVersion,
                             policy);
-                    mZenModeHelper.setNotificationPolicy(policy,
-                            isSystemOrSystemUi ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
-                                    : ZenModeConfig.UPDATE_ORIGIN_APP,
-                            callingUid);
+                    mZenModeHelper.setNotificationPolicy(policy, origin, callingUid);
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to set notification policy", e);
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index dc0cf4e092072d0db9a859a6f54e5fc3d138671d..9f3104cbd7b01ddc54768a9322f921ff77a5c752 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -117,7 +117,6 @@ public class NotificationShellCmd extends ShellCommand {
     private final NotificationManagerService mDirectService;
     private final INotificationManager mBinderService;
     private final PackageManager mPm;
-    private NotificationChannel mChannel;
 
     public NotificationShellCmd(NotificationManagerService service) {
         mDirectService = service;
@@ -183,7 +182,13 @@ public class NotificationShellCmd extends ShellCommand {
                             interruptionFilter = INTERRUPTION_FILTER_ALL;
                     }
                     final int filter = interruptionFilter;
-                    mBinderService.setInterruptionFilter(callingPackage, filter);
+                    if (android.app.Flags.modesApi()) {
+                        mBinderService.setInterruptionFilter(callingPackage, filter,
+                                /* fromUser= */ true);
+                    } else {
+                        mBinderService.setInterruptionFilter(callingPackage, filter,
+                                /* fromUser= */ false);
+                    }
                 }
                 break;
                 case "allow_dnd": {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 3f8b5952a1bcc8acc8769bd1796cfbb407b98d3c..d1de9b086c5d2c13d58ff690c5e8da15a206376f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -561,7 +561,7 @@ public class ZenModeHelper {
      * {@link Global#ZEN_MODE_IMPORTANT_INTERRUPTIONS}.
      */
     void applyGlobalPolicyAsImplicitZenRule(String callingPkg, int callingUid,
-            NotificationManager.Policy policy) {
+            NotificationManager.Policy policy, @ConfigChangeOrigin int origin) {
         if (!android.app.Flags.modesApi()) {
             Log.wtf(TAG, "applyGlobalPolicyAsImplicitZenRule called with flag off!");
             return;
@@ -579,7 +579,7 @@ public class ZenModeHelper {
             }
             // TODO: b/308673679 - Keep user customization of this rule!
             rule.zenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
-            setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP,
+            setConfigLocked(newConfig, /* triggeringComponent= */ null, origin,
                     "applyGlobalPolicyAsImplicitZenRule", callingUid);
         }
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 260ee39656eacf08de1eb1f6f0cac7fe2a4cbca4..30843d2227429e09cf5b933bcfbbb7c2c484fc6d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -245,8 +245,8 @@ public class DefaultDeviceEffectsApplierTest {
     }
 
     @Test
-    @TestParameters({"{origin: ORIGIN_USER}", "{origin: ORIGIN_INIT}", "{origin: ORIGIN_INIT_USER}",
-            "{origin: ORIGIN_SYSTEM_OR_SYSTEMUI}"})
+    @TestParameters({"{origin: ORIGIN_USER}", "{origin: ORIGIN_INIT}",
+            "{origin: ORIGIN_INIT_USER}"})
     public void apply_nightModeWithScreenOn_appliedImmediatelyBasedOnOrigin(ChangeOrigin origin) {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
 
@@ -263,7 +263,7 @@ public class DefaultDeviceEffectsApplierTest {
 
     @Test
     @TestParameters({"{origin: ORIGIN_APP}", "{origin: ORIGIN_RESTORE_BACKUP}",
-            "{origin: ORIGIN_UNKNOWN}"})
+            "{origin: ORIGIN_SYSTEM_OR_SYSTEMUI}", "{origin: ORIGIN_UNKNOWN}"})
     public void apply_nightModeWithScreenOn_willBeAppliedLaterBasedOnOrigin(ChangeOrigin origin) {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
 
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 56c75b52cf18e36e3723411cb1f0c95059504661..9a1359591890bd6dbafab369c4fa95e036a1d308 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -80,6 +80,9 @@ import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
 import static android.service.notification.Flags.FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS;
+import static android.service.notification.Condition.SOURCE_CONTEXT;
+import static android.service.notification.Condition.SOURCE_USER_ACTION;
+import static android.service.notification.Condition.STATE_TRUE;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
@@ -224,6 +227,7 @@ import android.provider.DeviceConfig;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
+import android.service.notification.Condition;
 import android.service.notification.ConversationChannelWrapper;
 import android.service.notification.DeviceEffectsApplier;
 import android.service.notification.INotificationListener;
@@ -342,6 +346,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
     private static final String SCHEME_TIMEOUT = "timeout";
     private static final String REDACTED_TEXT = "redacted text";
 
+    private static final AutomaticZenRule SOME_ZEN_RULE =
+            new AutomaticZenRule.Builder("rule", Uri.parse("uri"))
+                    .setOwner(new ComponentName("pkg", "cls"))
+                    .build();
+
     private final int mUid = Binder.getCallingUid();
     private final @UserIdInt int mUserId = UserHandle.getUserId(mUid);
 
@@ -9048,7 +9057,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
 
         try {
-            mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
+            mBinderService.addAutomaticZenRule(rule, mContext.getPackageName(), false);
             fail("Zen policy only applies to priority only mode");
         } catch (IllegalArgumentException e) {
             // yay
@@ -9056,11 +9065,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
 
         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
-        mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
+        mBinderService.addAutomaticZenRule(rule, mContext.getPackageName(), false);
 
         rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
-        mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
+        mBinderService.addAutomaticZenRule(rule, mContext.getPackageName(), false);
     }
 
     @Test
@@ -9075,7 +9084,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         boolean isEnabled = true;
         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
-        mBinderService.addAutomaticZenRule(rule, "com.android.settings");
+        mBinderService.addAutomaticZenRule(rule, "com.android.settings", false);
 
         // verify that zen mode helper gets passed in a package name of "android"
         verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule),
@@ -9097,7 +9106,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         boolean isEnabled = true;
         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
-        mBinderService.addAutomaticZenRule(rule, "com.android.settings");
+        mBinderService.addAutomaticZenRule(rule, "com.android.settings", false);
 
         // verify that zen mode helper gets passed in a package name of "android"
         verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule),
@@ -9117,7 +9126,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         boolean isEnabled = true;
         AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
                 zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
-        mBinderService.addAutomaticZenRule(rule, "another.package");
+        mBinderService.addAutomaticZenRule(rule, "another.package", false);
 
         // verify that zen mode helper gets passed in the package name from the arg, not the owner
         verify(mockZenModeHelper).addAutomaticZenRule(
@@ -9128,10 +9137,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
     @Test
     @EnableFlags(android.app.Flags.FLAG_MODES_API)
     public void testAddAutomaticZenRule_typeManagedCanBeUsedByDeviceOwners() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
         mService.setCallerIsNormalPackage();
-        mService.setZenHelper(mock(ZenModeHelper.class));
-        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
-                .thenReturn(true);
 
         AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri"))
                 .setType(AutomaticZenRule.TYPE_MANAGED)
@@ -9139,8 +9146,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                 .build();
         when(mDevicePolicyManager.isActiveDeviceOwner(anyInt())).thenReturn(true);
 
-        mBinderService.addAutomaticZenRule(rule, "pkg");
-        // No exception!
+        mBinderService.addAutomaticZenRule(rule, "pkg", /* fromUser= */ false);
+
+        verify(zenModeHelper).addAutomaticZenRule(eq("pkg"), eq(rule), anyInt(), any(), anyInt());
     }
 
     @Test
@@ -9158,7 +9166,144 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         when(mDevicePolicyManager.isActiveDeviceOwner(anyInt())).thenReturn(false);
 
         assertThrows(IllegalArgumentException.class,
-                () -> mBinderService.addAutomaticZenRule(rule, "pkg"));
+                () -> mBinderService.addAutomaticZenRule(rule, "pkg", /* fromUser= */ false));
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void addAutomaticZenRule_fromUser_mappedToOriginUser() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.isSystemUid = true;
+
+        mBinderService.addAutomaticZenRule(SOME_ZEN_RULE, "pkg", /* fromUser= */ true);
+
+        verify(zenModeHelper).addAutomaticZenRule(eq("pkg"), eq(SOME_ZEN_RULE),
+                eq(ZenModeConfig.UPDATE_ORIGIN_USER), anyString(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void addAutomaticZenRule_fromSystemNotUser_mappedToOriginSystem() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.isSystemUid = true;
+
+        mBinderService.addAutomaticZenRule(SOME_ZEN_RULE, "pkg", /* fromUser= */ false);
+
+        verify(zenModeHelper).addAutomaticZenRule(eq("pkg"), eq(SOME_ZEN_RULE),
+                eq(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI), anyString(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void addAutomaticZenRule_fromApp_mappedToOriginApp() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.setCallerIsNormalPackage();
+
+        mBinderService.addAutomaticZenRule(SOME_ZEN_RULE, "pkg", /* fromUser= */ false);
+
+        verify(zenModeHelper).addAutomaticZenRule(eq("pkg"), eq(SOME_ZEN_RULE),
+                eq(ZenModeConfig.UPDATE_ORIGIN_APP), anyString(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void addAutomaticZenRule_fromAppFromUser_blocked() throws Exception {
+        setUpMockZenTest();
+        mService.setCallerIsNormalPackage();
+
+        assertThrows(SecurityException.class, () ->
+                mBinderService.addAutomaticZenRule(SOME_ZEN_RULE, "pkg", /* fromUser= */ true));
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void updateAutomaticZenRule_fromUserFromSystem_allowed() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.isSystemUid = true;
+
+        mBinderService.updateAutomaticZenRule("id", SOME_ZEN_RULE, /* fromUser= */ true);
+
+        verify(zenModeHelper).updateAutomaticZenRule(eq("id"), eq(SOME_ZEN_RULE),
+                eq(ZenModeConfig.UPDATE_ORIGIN_USER), anyString(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void updateAutomaticZenRule_fromUserFromApp_blocked() throws Exception {
+        setUpMockZenTest();
+        mService.setCallerIsNormalPackage();
+
+        assertThrows(SecurityException.class, () ->
+                mBinderService.addAutomaticZenRule(SOME_ZEN_RULE, "pkg", /* fromUser= */ true));
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void removeAutomaticZenRule_fromUserFromSystem_allowed() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.isSystemUid = true;
+
+        mBinderService.removeAutomaticZenRule("id", /* fromUser= */ true);
+
+        verify(zenModeHelper).removeAutomaticZenRule(eq("id"),
+                eq(ZenModeConfig.UPDATE_ORIGIN_USER), anyString(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void removeAutomaticZenRule_fromUserFromApp_blocked() throws Exception {
+        setUpMockZenTest();
+        mService.setCallerIsNormalPackage();
+
+        assertThrows(SecurityException.class, () ->
+                mBinderService.removeAutomaticZenRule("id", /* fromUser= */ true));
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void setAutomaticZenRuleState_fromUserMatchesConditionSource_okay() throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.setCallerIsNormalPackage();
+
+        Condition withSourceContext = new Condition(Uri.parse("uri"), "summary", STATE_TRUE,
+                SOURCE_CONTEXT);
+        mBinderService.setAutomaticZenRuleState("id", withSourceContext, /* fromUser= */ false);
+        verify(zenModeHelper).setAutomaticZenRuleState(eq("id"), eq(withSourceContext),
+                eq(ZenModeConfig.UPDATE_ORIGIN_APP), anyInt());
+
+        Condition withSourceUser = new Condition(Uri.parse("uri"), "summary", STATE_TRUE,
+                SOURCE_USER_ACTION);
+        mBinderService.setAutomaticZenRuleState("id", withSourceUser, /* fromUser= */ true);
+        verify(zenModeHelper).setAutomaticZenRuleState(eq("id"), eq(withSourceUser),
+                eq(ZenModeConfig.UPDATE_ORIGIN_USER), anyInt());
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void setAutomaticZenRuleState_fromUserDoesNotMatchConditionSource_blocked()
+            throws Exception {
+        ZenModeHelper zenModeHelper = setUpMockZenTest();
+        mService.setCallerIsNormalPackage();
+
+        Condition withSourceContext = new Condition(Uri.parse("uri"), "summary", STATE_TRUE,
+                SOURCE_CONTEXT);
+        assertThrows(IllegalArgumentException.class,
+                () -> mBinderService.setAutomaticZenRuleState("id", withSourceContext,
+                        /* fromUser= */ true));
+
+        Condition withSourceUser = new Condition(Uri.parse("uri"), "summary", STATE_TRUE,
+                SOURCE_USER_ACTION);
+        assertThrows(IllegalArgumentException.class,
+                () -> mBinderService.setAutomaticZenRuleState("id", withSourceUser,
+                        /* fromUser= */ false));
+    }
+
+    private ZenModeHelper setUpMockZenTest() {
+        ZenModeHelper zenModeHelper = mock(ZenModeHelper.class);
+        mService.setZenHelper(zenModeHelper);
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+        return zenModeHelper;
     }
 
     @Test
@@ -9184,7 +9329,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         });
 
         mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
-                "testing!");
+                "testing!", false);
         waitForIdle();
 
         InOrder inOrder = inOrder(mContext);
@@ -13441,9 +13586,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                 .thenReturn(true);
 
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
-        mBinderService.setNotificationPolicy("package", policy);
+        mBinderService.setNotificationPolicy("package", policy, false);
 
-        verify(zenHelper).applyGlobalPolicyAsImplicitZenRule(eq("package"), anyInt(), eq(policy));
+        verify(zenHelper).applyGlobalPolicyAsImplicitZenRule(eq("package"), anyInt(), eq(policy),
+                eq(ZenModeConfig.UPDATE_ORIGIN_APP));
     }
 
     @Test
@@ -13457,7 +13603,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         mService.isSystemUid = true;
 
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
-        mBinderService.setNotificationPolicy("package", policy);
+        mBinderService.setNotificationPolicy("package", policy, false);
 
         verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
     }
@@ -13479,7 +13625,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                                 .build()));
 
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
-        mBinderService.setNotificationPolicy("package", policy);
+        mBinderService.setNotificationPolicy("package", policy, false);
 
         verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
     }
@@ -13495,7 +13641,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                 .thenReturn(true);
 
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
-        mBinderService.setNotificationPolicy("package", policy);
+        mBinderService.setNotificationPolicy("package", policy, false);
 
         verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
     }
@@ -13525,7 +13671,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
                 .thenReturn(true);
 
-        mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY);
+        mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY, false);
 
         verify(zenHelper).applyGlobalZenModeAsImplicitZenRule(eq("package"), anyInt(),
                 eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS));
@@ -13542,7 +13688,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                 .thenReturn(true);
         mService.isSystemUid = true;
 
-        mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY);
+        mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY, false);
 
         verify(zenModeHelper).setManualZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), eq(null),
                 eq(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI), anyString(), eq("package"),
@@ -13565,7 +13711,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                                 .setDeviceProfile(AssociationRequest.DEVICE_PROFILE_WATCH)
                                 .build()));
 
-        mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY);
+        mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY, false);
 
         verify(zenModeHelper).setManualZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), eq(null),
                 eq(ZenModeConfig.UPDATE_ORIGIN_APP), anyString(), eq("package"), anyInt());
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 1aea56cd8f9f4920591e8e30a3dfeb71e61a1307..bc63c29e99554e83440caed8d92e5c2ce888ea2a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -112,6 +112,7 @@ import android.net.Uri;
 import android.os.Parcel;
 import android.os.Process;
 import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -211,7 +212,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
     private static final ZenDeviceEffects NO_EFFECTS = new ZenDeviceEffects.Builder().build();
 
     @Rule
-    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
+            SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
 
     ConditionProviders mConditionProviders;
     @Mock NotificationManager mNotificationManager;
@@ -3371,6 +3373,29 @@ public class ZenModeHelperTest extends UiServiceTestCase {
         assertEquals(false, mZenModeHelper.mConfig.automaticRules.get(createdId).snoozing);
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void removeAutomaticZenRule_propagatesOriginToEffectsApplier() {
+        mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
+        reset(mDeviceEffectsApplier);
+
+        String ruleId = addRuleWithEffects(new ZenDeviceEffects.Builder()
+                .setShouldSuppressAmbientDisplay(true)
+                .setShouldDimWallpaper(true)
+                .build());
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        mTestableLooper.processAllMessages();
+        verify(mDeviceEffectsApplier).apply(any(), eq(UPDATE_ORIGIN_APP));
+
+        // Now delete the (currently active!) rule. For example, assume this is done from settings.
+        mZenModeHelper.removeAutomaticZenRule(ruleId, UPDATE_ORIGIN_USER, "remove",
+                Process.SYSTEM_UID);
+        mTestableLooper.processAllMessages();
+
+        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS), eq(UPDATE_ORIGIN_USER));
+    }
+
     @Test
     public void testDeviceEffects_applied() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
@@ -3511,8 +3536,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
         AutomaticZenRule rule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
                 .setDeviceEffects(effects)
                 .build();
-        return mZenModeHelper.addAutomaticZenRule("pkg", rule, UPDATE_ORIGIN_APP, "",
-                CUSTOM_PKG_UID);
+        return mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), rule,
+                UPDATE_ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
     }
 
     @Test
@@ -3619,7 +3644,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
         Policy policy = new Policy(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS,
                 PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED,
                 Policy.getAllSuppressedVisualEffects(), CONVERSATION_SENDERS_IMPORTANT);
-        mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, policy);
+        mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, policy,
+                UPDATE_ORIGIN_APP);
 
         ZenPolicy expectedZenPolicy = new ZenPolicy.Builder()
                 .disallowAllSounds()
@@ -3643,13 +3669,14 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                 PRIORITY_SENDERS_CONTACTS, PRIORITY_SENDERS_STARRED,
                 Policy.getAllSuppressedVisualEffects(), CONVERSATION_SENDERS_IMPORTANT);
         mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
-                original);
+                original, UPDATE_ORIGIN_APP);
 
         // Change priorityCallSenders: contacts -> starred.
         Policy updated = new Policy(PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_CONVERSATIONS,
                 PRIORITY_SENDERS_STARRED, PRIORITY_SENDERS_STARRED,
                 Policy.getAllSuppressedVisualEffects(), CONVERSATION_SENDERS_IMPORTANT);
-        mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, updated);
+        mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, updated,
+                UPDATE_ORIGIN_APP);
 
         ZenPolicy expectedZenPolicy = new ZenPolicy.Builder()
                 .disallowAllSounds()
@@ -3671,7 +3698,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
 
         withoutWtfCrash(
                 () -> mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME,
-                        CUSTOM_PKG_UID, new Policy(0, 0, 0)));
+                        CUSTOM_PKG_UID, new Policy(0, 0, 0), UPDATE_ORIGIN_APP));
 
         assertThat(mZenModeHelper.mConfig.automaticRules).isEmpty();
     }
@@ -3684,7 +3711,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                 Policy.getAllSuppressedVisualEffects(), STATE_FALSE,
                 CONVERSATION_SENDERS_IMPORTANT);
         mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
-                writtenPolicy);
+                writtenPolicy, UPDATE_ORIGIN_APP);
 
         Policy readPolicy = mZenModeHelper.getNotificationPolicyFromImplicitZenRule(
                 CUSTOM_PKG_NAME);