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);