Loading core/api/current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -40757,6 +40757,7 @@ package android.service.notification { public final class ZenPolicy implements android.os.Parcelable { method public int describeContents(); method @FlaggedApi("android.app.modes_api") public int getAllowedChannels(); method public int getPriorityCallSenders(); method public int getPriorityCategoryAlarms(); method public int getPriorityCategoryCalls(); Loading @@ -40777,6 +40778,9 @@ package android.service.notification { method public int getVisualEffectPeek(); method public int getVisualEffectStatusBar(); method public void writeToParcel(android.os.Parcel, int); field @FlaggedApi("android.app.modes_api") public static final int CHANNEL_TYPE_NONE = 2; // 0x2 field @FlaggedApi("android.app.modes_api") public static final int CHANNEL_TYPE_PRIORITY = 1; // 0x1 field @FlaggedApi("android.app.modes_api") public static final int CHANNEL_TYPE_UNSET = 0; // 0x0 field public static final int CONVERSATION_SENDERS_ANYONE = 1; // 0x1 field public static final int CONVERSATION_SENDERS_IMPORTANT = 2; // 0x2 field public static final int CONVERSATION_SENDERS_NONE = 3; // 0x3 Loading @@ -40797,6 +40801,7 @@ package android.service.notification { method @NonNull public android.service.notification.ZenPolicy.Builder allowAlarms(boolean); method @NonNull public android.service.notification.ZenPolicy.Builder allowAllSounds(); method @NonNull public android.service.notification.ZenPolicy.Builder allowCalls(int); method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy.Builder allowChannels(int); method @NonNull public android.service.notification.ZenPolicy.Builder allowConversations(int); method @NonNull public android.service.notification.ZenPolicy.Builder allowEvents(boolean); method @NonNull public android.service.notification.ZenPolicy.Builder allowMedia(boolean); core/api/test-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -373,6 +373,10 @@ package android.app { method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel); } public static class NotificationManager.Policy implements android.os.Parcelable { method @FlaggedApi("android.app.modes_api") public boolean allowPriorityChannels(); } public final class PendingIntent implements android.os.Parcelable { method public boolean addCancelListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.PendingIntent.CancelListener); method @RequiresPermission("android.permission.GET_INTENT_SENDER_INTENT") public boolean intentFilterEquals(@Nullable android.app.PendingIntent); Loading core/java/android/app/NotificationManager.java +65 −14 Original line number Diff line number Diff line Loading @@ -2057,6 +2057,14 @@ public class NotificationManager { */ public static final int STATE_CHANNELS_BYPASSING_DND = 1 << 0; /** * Whether the policy indicates that even priority channels are NOT permitted to bypass DND. * Note that this state explicitly marks the "disallow" state because the default behavior * is to allow priority channels to break through. * @hide */ public static final int STATE_PRIORITY_CHANNELS_BLOCKED = 1 << 1; /** * @hide */ Loading Loading @@ -2272,20 +2280,34 @@ public class NotificationManager { @Override public String toString() { return "NotificationManager.Policy[" + "priorityCategories=" + priorityCategoriesToString(priorityCategories) + ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders) + ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders) + ",priorityConvSenders=" + conversationSendersToString(priorityConversationSenders) + ",suppressedVisualEffects=" + suppressedEffectsToString(suppressedVisualEffects) + ",areChannelsBypassingDnd=" + (state == STATE_UNSET StringBuilder sb = new StringBuilder().append("NotificationManager.Policy[") .append("priorityCategories=") .append(priorityCategoriesToString(priorityCategories)) .append(",priorityCallSenders=") .append(prioritySendersToString(priorityCallSenders)) .append(",priorityMessageSenders=") .append(prioritySendersToString(priorityMessageSenders)) .append(",priorityConvSenders=") .append(conversationSendersToString(priorityConversationSenders)) .append(",suppressedVisualEffects=") .append(suppressedEffectsToString(suppressedVisualEffects)); if (Flags.modesApi()) { sb.append(",hasPriorityChannels="); } else { sb.append(",areChannelsBypassingDnd="); } sb.append((state == STATE_UNSET ? "unset" : ((state & STATE_CHANNELS_BYPASSING_DND) != 0) ? "true" : "false") + "]"; : "false")); if (Flags.modesApi()) { sb.append(",allowPriorityChannels=") .append((state == STATE_UNSET ? "unset" : (allowPriorityChannels() ? "true" : "false"))); } return sb.append("]").toString(); } /** @hide */ Loading Loading @@ -2556,6 +2578,35 @@ public class NotificationManager { return (suppressedVisualEffects & SUPPRESSED_EFFECT_NOTIFICATION_LIST) == 0; } /** @hide **/ @FlaggedApi(Flags.FLAG_MODES_API) @TestApi // so CTS tests can read this state without having to use implementation detail public boolean allowPriorityChannels() { if (state == STATE_UNSET) { return true; // default } return (state & STATE_PRIORITY_CHANNELS_BLOCKED) == 0; } /** @hide */ @FlaggedApi(Flags.FLAG_MODES_API) public boolean hasPriorityChannels() { return (state & STATE_CHANNELS_BYPASSING_DND) != 0; } /** @hide **/ @FlaggedApi(Flags.FLAG_MODES_API) public static int policyState(boolean hasPriorityChannels, boolean allowPriorityChannels) { int state = 0; if (hasPriorityChannels) { state |= STATE_CHANNELS_BYPASSING_DND; } if (!allowPriorityChannels) { state |= STATE_PRIORITY_CHANNELS_BLOCKED; } return state; } /** * returns a deep copy of this policy * @hide Loading core/java/android/service/notification/ZenModeConfig.java +110 −12 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public class ZenModeConfig implements Parcelable { private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = true; private static final boolean DEFAULT_ALLOW_CONV = true; private static final int DEFAULT_ALLOW_CONV_FROM = ZenPolicy.CONVERSATION_SENDERS_IMPORTANT; private static final boolean DEFAULT_ALLOW_PRIORITY_CHANNELS = true; private static final boolean DEFAULT_CHANNELS_BYPASSING_DND = false; // Default setting here is 010011101 = 157 private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS = Loading @@ -141,6 +142,7 @@ public class ZenModeConfig implements Parcelable { private static final String ALLOW_ATT_SCREEN_ON = "visualScreenOn"; private static final String ALLOW_ATT_CONV = "convos"; private static final String ALLOW_ATT_CONV_FROM = "convosFrom"; private static final String ALLOW_ATT_CHANNELS = "channels"; private static final String DISALLOW_TAG = "disallow"; private static final String DISALLOW_ATT_VISUAL_EFFECTS = "visualEffects"; private static final String STATE_TAG = "state"; Loading Loading @@ -213,7 +215,12 @@ public class ZenModeConfig implements Parcelable { public int allowConversationsFrom = DEFAULT_ALLOW_CONV_FROM; public int user = UserHandle.USER_SYSTEM; public int suppressedVisualEffects = DEFAULT_SUPPRESSED_VISUAL_EFFECTS; // Note that when the modes_api flag is true, the areChannelsBypassingDnd boolean only tracks // whether the current user has any priority channels. These channels may bypass DND when // allowPriorityChannels is true. // TODO: b/310620812 - Rename to be more accurate when modes_api flag is inlined. public boolean areChannelsBypassingDnd = DEFAULT_CHANNELS_BYPASSING_DND; public boolean allowPriorityChannels = DEFAULT_ALLOW_PRIORITY_CHANNELS; public int version; public ZenRule manualRule; Loading @@ -221,7 +228,8 @@ public class ZenModeConfig implements Parcelable { public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>(); @UnsupportedAppUsage public ZenModeConfig() { } public ZenModeConfig() { } public ZenModeConfig(Parcel source) { allowCalls = source.readInt() == 1; Loading Loading @@ -250,6 +258,9 @@ public class ZenModeConfig implements Parcelable { areChannelsBypassingDnd = source.readInt() == 1; allowConversations = source.readBoolean(); allowConversationsFrom = source.readInt(); if (Flags.modesApi()) { allowPriorityChannels = source.readBoolean(); } } @Override Loading Loading @@ -284,11 +295,14 @@ public class ZenModeConfig implements Parcelable { dest.writeInt(areChannelsBypassingDnd ? 1 : 0); dest.writeBoolean(allowConversations); dest.writeInt(allowConversationsFrom); if (Flags.modesApi()) { dest.writeBoolean(allowPriorityChannels); } } @Override public String toString() { return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') StringBuilder sb = new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') .append("user=").append(user) .append(",allowAlarms=").append(allowAlarms) .append(",allowMedia=").append(allowMedia) Loading @@ -303,9 +317,14 @@ public class ZenModeConfig implements Parcelable { .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom)) .append(",allowConvFrom=").append(ZenPolicy.conversationTypeToString (allowConversationsFrom)) .append(",suppressedVisualEffects=").append(suppressedVisualEffects) .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd) .append(",\nautomaticRules=").append(rulesToString()) .append(",suppressedVisualEffects=").append(suppressedVisualEffects); if (Flags.modesApi()) { sb.append(",hasPriorityChannels=").append(areChannelsBypassingDnd); sb.append(",allowPriorityChannels=").append(allowPriorityChannels); } else { sb.append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd); } return sb.append(",\nautomaticRules=").append(rulesToString()) .append(",\nmanualRule=").append(manualRule) .append(']').toString(); } Loading Loading @@ -385,7 +404,7 @@ public class ZenModeConfig implements Parcelable { if (!(o instanceof ZenModeConfig)) return false; if (o == this) return true; final ZenModeConfig other = (ZenModeConfig) o; return other.allowAlarms == allowAlarms boolean eq = other.allowAlarms == allowAlarms && other.allowMedia == allowMedia && other.allowSystem == allowSystem && other.allowCalls == allowCalls Loading @@ -402,10 +421,22 @@ public class ZenModeConfig implements Parcelable { && other.areChannelsBypassingDnd == areChannelsBypassingDnd && other.allowConversations == allowConversations && other.allowConversationsFrom == allowConversationsFrom; if (Flags.modesApi()) { return eq && other.allowPriorityChannels == allowPriorityChannels; } return eq; } @Override public int hashCode() { if (Flags.modesApi()) { return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents, user, automaticRules, manualRule, suppressedVisualEffects, areChannelsBypassingDnd, allowConversations, allowConversationsFrom, allowPriorityChannels); } return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents, Loading Loading @@ -511,6 +542,10 @@ public class ZenModeConfig implements Parcelable { rt.allowMedia = safeBoolean(parser, ALLOW_ATT_MEDIA, DEFAULT_ALLOW_MEDIA); rt.allowSystem = safeBoolean(parser, ALLOW_ATT_SYSTEM, DEFAULT_ALLOW_SYSTEM); if (Flags.modesApi()) { rt.allowPriorityChannels = safeBoolean(parser, ALLOW_ATT_CHANNELS, DEFAULT_ALLOW_PRIORITY_CHANNELS); } // migrate old suppressed visual effects fields, if they still exist in the xml Boolean allowWhenScreenOff = unsafeBoolean(parser, ALLOW_ATT_SCREEN_OFF); Loading Loading @@ -584,6 +619,9 @@ public class ZenModeConfig implements Parcelable { out.attributeBoolean(null, ALLOW_ATT_SYSTEM, allowSystem); out.attributeBoolean(null, ALLOW_ATT_CONV, allowConversations); out.attributeInt(null, ALLOW_ATT_CONV_FROM, allowConversationsFrom); if (Flags.modesApi()) { out.attributeBoolean(null, ALLOW_ATT_CHANNELS, allowPriorityChannels); } out.endTag(null, ALLOW_TAG); out.startTag(null, DISALLOW_TAG); Loading Loading @@ -748,6 +786,13 @@ public class ZenModeConfig implements Parcelable { final int system = safeInt(parser, ALLOW_ATT_SYSTEM, ZenPolicy.STATE_UNSET); final int events = safeInt(parser, ALLOW_ATT_EVENTS, ZenPolicy.STATE_UNSET); final int reminders = safeInt(parser, ALLOW_ATT_REMINDERS, ZenPolicy.STATE_UNSET); if (Flags.modesApi()) { final int channels = safeInt(parser, ALLOW_ATT_CHANNELS, ZenPolicy.CHANNEL_TYPE_UNSET); if (channels != ZenPolicy.CHANNEL_TYPE_UNSET) { builder.allowChannels(channels); policySet = true; } } if (calls != ZenPolicy.PEOPLE_TYPE_UNSET) { builder.allowCalls(calls); Loading Loading @@ -856,6 +901,10 @@ public class ZenModeConfig implements Parcelable { writeZenPolicyState(SHOW_ATT_AMBIENT, policy.getVisualEffectAmbient(), out); writeZenPolicyState(SHOW_ATT_NOTIFICATION_LIST, policy.getVisualEffectNotificationList(), out); if (Flags.modesApi()) { writeZenPolicyState(ALLOW_ATT_CHANNELS, policy.getAllowedChannels(), out); } } private static void writeZenPolicyState(String attr, int val, TypedXmlSerializer out) Loading @@ -869,6 +918,10 @@ public class ZenModeConfig implements Parcelable { if (val != ZenPolicy.CONVERSATION_SENDERS_UNSET) { out.attributeInt(null, attr, val); } } else if (Flags.modesApi() && Objects.equals(attr, ALLOW_ATT_CHANNELS)) { if (val != ZenPolicy.CHANNEL_TYPE_UNSET) { out.attributeInt(null, attr, val); } } else { if (val != ZenPolicy.STATE_UNSET) { out.attributeInt(null, attr, val); Loading Loading @@ -1044,6 +1097,11 @@ public class ZenModeConfig implements Parcelable { builder.showInNotificationList( (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST) == 0); } if (Flags.modesApi()) { builder.allowChannels(allowPriorityChannels ? ZenPolicy.CHANNEL_TYPE_PRIORITY : ZenPolicy.CHANNEL_TYPE_NONE); } return builder.build(); } Loading Loading @@ -1169,8 +1227,15 @@ public class ZenModeConfig implements Parcelable { suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; } int state = defaultPolicy.state; if (Flags.modesApi()) { state = Policy.policyState(defaultPolicy.hasPriorityChannels(), getAllowPriorityChannelsWithDefault(zenPolicy.getAllowedChannels(), DEFAULT_ALLOW_PRIORITY_CHANNELS)); } return new NotificationManager.Policy(priorityCategories, callSenders, messageSenders, suppressedVisualEffects, defaultPolicy.state, conversationSenders); messageSenders, suppressedVisualEffects, state, conversationSenders); } private boolean isPriorityCategoryEnabled(int categoryType, Policy policy) { Loading Loading @@ -1207,6 +1272,24 @@ public class ZenModeConfig implements Parcelable { } } /** * Gets whether priority channels are permitted by this channel type, with the specified * default if the value is unset. This effectively converts the channel enum to a boolean, * where "true" indicates priority channels are allowed to break through and "false" means * they are not. */ public static boolean getAllowPriorityChannelsWithDefault( @ZenPolicy.ChannelType int channelType, boolean defaultAllowChannels) { switch (channelType) { case ZenPolicy.CHANNEL_TYPE_PRIORITY: return true; case ZenPolicy.CHANNEL_TYPE_NONE: return false; default: return defaultAllowChannels; } } /** * Maps NotificationManager.Policy senders type to ZenPolicy.PeopleType */ Loading Loading @@ -1259,10 +1342,13 @@ public class ZenModeConfig implements Parcelable { priorityConversationSenders = getConversationSendersWithDefault( allowConversationsFrom, priorityConversationSenders); int state = areChannelsBypassingDnd ? Policy.STATE_CHANNELS_BYPASSING_DND : 0; if (Flags.modesApi()) { state = Policy.policyState(areChannelsBypassingDnd, allowPriorityChannels); } return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders, suppressedVisualEffects, areChannelsBypassingDnd ? Policy.STATE_CHANNELS_BYPASSING_DND : 0, priorityConversationSenders); suppressedVisualEffects, state, priorityConversationSenders); } /** Loading Loading @@ -1342,6 +1428,9 @@ public class ZenModeConfig implements Parcelable { allowConversationsFrom); if (policy.state != Policy.STATE_UNSET) { areChannelsBypassingDnd = (policy.state & Policy.STATE_CHANNELS_BYPASSING_DND) != 0; if (Flags.modesApi()) { allowPriorityChannels = policy.allowPriorityChannels(); } } } Loading Loading @@ -2067,6 +2156,10 @@ public class ZenModeConfig implements Parcelable { boolean allowConversations = (policy.priorityConversationSenders & Policy.PRIORITY_CATEGORY_CONVERSATIONS) != 0; boolean areChannelsBypassingDnd = (policy.state & Policy.STATE_CHANNELS_BYPASSING_DND) != 0; if (Flags.modesApi()) { areChannelsBypassingDnd = policy.hasPriorityChannels() && policy.allowPriorityChannels(); } boolean allowSystem = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_SYSTEM) != 0; return !allowReminders && !allowCalls && !allowMessages && !allowEvents && !allowRepeatCallers && !areChannelsBypassingDnd && !allowSystem Loading Loading @@ -2098,9 +2191,14 @@ public class ZenModeConfig implements Parcelable { * This includes notification, ringer and system sounds */ public static boolean areAllPriorityOnlyRingerSoundsMuted(ZenModeConfig config) { boolean areChannelsBypassingDnd = config.areChannelsBypassingDnd; if (Flags.modesApi()) { areChannelsBypassingDnd = config.areChannelsBypassingDnd && config.allowPriorityChannels; } return !config.allowReminders && !config.allowCalls && !config.allowMessages && !config.allowEvents && !config.allowRepeatCallers && !config.areChannelsBypassingDnd && !config.allowSystem; && !areChannelsBypassingDnd && !config.allowSystem; } /** Loading core/java/android/service/notification/ZenModeDiff.java +8 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.service.notification; import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Flags; import android.util.ArrayMap; import android.util.ArraySet; Loading Loading @@ -221,6 +222,7 @@ public class ZenModeDiff { public static final String FIELD_ALLOW_CONVERSATIONS_FROM = "allowConversationsFrom"; public static final String FIELD_SUPPRESSED_VISUAL_EFFECTS = "suppressedVisualEffects"; public static final String FIELD_ARE_CHANNELS_BYPASSING_DND = "areChannelsBypassingDnd"; public static final String FIELD_ALLOW_PRIORITY_CHANNELS = "allowPriorityChannels"; private static final Set<String> PEOPLE_TYPE_FIELDS = Set.of(FIELD_ALLOW_CALLS_FROM, FIELD_ALLOW_MESSAGES_FROM); Loading Loading @@ -297,6 +299,12 @@ public class ZenModeDiff { addField(FIELD_ARE_CHANNELS_BYPASSING_DND, new FieldDiff<>(from.areChannelsBypassingDnd, to.areChannelsBypassingDnd)); } if (Flags.modesApi()) { if (from.allowPriorityChannels != to.allowPriorityChannels) { addField(FIELD_ALLOW_PRIORITY_CHANNELS, new FieldDiff<>(from.allowPriorityChannels, to.allowPriorityChannels)); } } // Compare automatic and manual rules final ArraySet<String> allRules = new ArraySet<>(); Loading Loading
core/api/current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -40757,6 +40757,7 @@ package android.service.notification { public final class ZenPolicy implements android.os.Parcelable { method public int describeContents(); method @FlaggedApi("android.app.modes_api") public int getAllowedChannels(); method public int getPriorityCallSenders(); method public int getPriorityCategoryAlarms(); method public int getPriorityCategoryCalls(); Loading @@ -40777,6 +40778,9 @@ package android.service.notification { method public int getVisualEffectPeek(); method public int getVisualEffectStatusBar(); method public void writeToParcel(android.os.Parcel, int); field @FlaggedApi("android.app.modes_api") public static final int CHANNEL_TYPE_NONE = 2; // 0x2 field @FlaggedApi("android.app.modes_api") public static final int CHANNEL_TYPE_PRIORITY = 1; // 0x1 field @FlaggedApi("android.app.modes_api") public static final int CHANNEL_TYPE_UNSET = 0; // 0x0 field public static final int CONVERSATION_SENDERS_ANYONE = 1; // 0x1 field public static final int CONVERSATION_SENDERS_IMPORTANT = 2; // 0x2 field public static final int CONVERSATION_SENDERS_NONE = 3; // 0x3 Loading @@ -40797,6 +40801,7 @@ package android.service.notification { method @NonNull public android.service.notification.ZenPolicy.Builder allowAlarms(boolean); method @NonNull public android.service.notification.ZenPolicy.Builder allowAllSounds(); method @NonNull public android.service.notification.ZenPolicy.Builder allowCalls(int); method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy.Builder allowChannels(int); method @NonNull public android.service.notification.ZenPolicy.Builder allowConversations(int); method @NonNull public android.service.notification.ZenPolicy.Builder allowEvents(boolean); method @NonNull public android.service.notification.ZenPolicy.Builder allowMedia(boolean);
core/api/test-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -373,6 +373,10 @@ package android.app { method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel); } public static class NotificationManager.Policy implements android.os.Parcelable { method @FlaggedApi("android.app.modes_api") public boolean allowPriorityChannels(); } public final class PendingIntent implements android.os.Parcelable { method public boolean addCancelListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.PendingIntent.CancelListener); method @RequiresPermission("android.permission.GET_INTENT_SENDER_INTENT") public boolean intentFilterEquals(@Nullable android.app.PendingIntent); Loading
core/java/android/app/NotificationManager.java +65 −14 Original line number Diff line number Diff line Loading @@ -2057,6 +2057,14 @@ public class NotificationManager { */ public static final int STATE_CHANNELS_BYPASSING_DND = 1 << 0; /** * Whether the policy indicates that even priority channels are NOT permitted to bypass DND. * Note that this state explicitly marks the "disallow" state because the default behavior * is to allow priority channels to break through. * @hide */ public static final int STATE_PRIORITY_CHANNELS_BLOCKED = 1 << 1; /** * @hide */ Loading Loading @@ -2272,20 +2280,34 @@ public class NotificationManager { @Override public String toString() { return "NotificationManager.Policy[" + "priorityCategories=" + priorityCategoriesToString(priorityCategories) + ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders) + ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders) + ",priorityConvSenders=" + conversationSendersToString(priorityConversationSenders) + ",suppressedVisualEffects=" + suppressedEffectsToString(suppressedVisualEffects) + ",areChannelsBypassingDnd=" + (state == STATE_UNSET StringBuilder sb = new StringBuilder().append("NotificationManager.Policy[") .append("priorityCategories=") .append(priorityCategoriesToString(priorityCategories)) .append(",priorityCallSenders=") .append(prioritySendersToString(priorityCallSenders)) .append(",priorityMessageSenders=") .append(prioritySendersToString(priorityMessageSenders)) .append(",priorityConvSenders=") .append(conversationSendersToString(priorityConversationSenders)) .append(",suppressedVisualEffects=") .append(suppressedEffectsToString(suppressedVisualEffects)); if (Flags.modesApi()) { sb.append(",hasPriorityChannels="); } else { sb.append(",areChannelsBypassingDnd="); } sb.append((state == STATE_UNSET ? "unset" : ((state & STATE_CHANNELS_BYPASSING_DND) != 0) ? "true" : "false") + "]"; : "false")); if (Flags.modesApi()) { sb.append(",allowPriorityChannels=") .append((state == STATE_UNSET ? "unset" : (allowPriorityChannels() ? "true" : "false"))); } return sb.append("]").toString(); } /** @hide */ Loading Loading @@ -2556,6 +2578,35 @@ public class NotificationManager { return (suppressedVisualEffects & SUPPRESSED_EFFECT_NOTIFICATION_LIST) == 0; } /** @hide **/ @FlaggedApi(Flags.FLAG_MODES_API) @TestApi // so CTS tests can read this state without having to use implementation detail public boolean allowPriorityChannels() { if (state == STATE_UNSET) { return true; // default } return (state & STATE_PRIORITY_CHANNELS_BLOCKED) == 0; } /** @hide */ @FlaggedApi(Flags.FLAG_MODES_API) public boolean hasPriorityChannels() { return (state & STATE_CHANNELS_BYPASSING_DND) != 0; } /** @hide **/ @FlaggedApi(Flags.FLAG_MODES_API) public static int policyState(boolean hasPriorityChannels, boolean allowPriorityChannels) { int state = 0; if (hasPriorityChannels) { state |= STATE_CHANNELS_BYPASSING_DND; } if (!allowPriorityChannels) { state |= STATE_PRIORITY_CHANNELS_BLOCKED; } return state; } /** * returns a deep copy of this policy * @hide Loading
core/java/android/service/notification/ZenModeConfig.java +110 −12 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public class ZenModeConfig implements Parcelable { private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = true; private static final boolean DEFAULT_ALLOW_CONV = true; private static final int DEFAULT_ALLOW_CONV_FROM = ZenPolicy.CONVERSATION_SENDERS_IMPORTANT; private static final boolean DEFAULT_ALLOW_PRIORITY_CHANNELS = true; private static final boolean DEFAULT_CHANNELS_BYPASSING_DND = false; // Default setting here is 010011101 = 157 private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS = Loading @@ -141,6 +142,7 @@ public class ZenModeConfig implements Parcelable { private static final String ALLOW_ATT_SCREEN_ON = "visualScreenOn"; private static final String ALLOW_ATT_CONV = "convos"; private static final String ALLOW_ATT_CONV_FROM = "convosFrom"; private static final String ALLOW_ATT_CHANNELS = "channels"; private static final String DISALLOW_TAG = "disallow"; private static final String DISALLOW_ATT_VISUAL_EFFECTS = "visualEffects"; private static final String STATE_TAG = "state"; Loading Loading @@ -213,7 +215,12 @@ public class ZenModeConfig implements Parcelable { public int allowConversationsFrom = DEFAULT_ALLOW_CONV_FROM; public int user = UserHandle.USER_SYSTEM; public int suppressedVisualEffects = DEFAULT_SUPPRESSED_VISUAL_EFFECTS; // Note that when the modes_api flag is true, the areChannelsBypassingDnd boolean only tracks // whether the current user has any priority channels. These channels may bypass DND when // allowPriorityChannels is true. // TODO: b/310620812 - Rename to be more accurate when modes_api flag is inlined. public boolean areChannelsBypassingDnd = DEFAULT_CHANNELS_BYPASSING_DND; public boolean allowPriorityChannels = DEFAULT_ALLOW_PRIORITY_CHANNELS; public int version; public ZenRule manualRule; Loading @@ -221,7 +228,8 @@ public class ZenModeConfig implements Parcelable { public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>(); @UnsupportedAppUsage public ZenModeConfig() { } public ZenModeConfig() { } public ZenModeConfig(Parcel source) { allowCalls = source.readInt() == 1; Loading Loading @@ -250,6 +258,9 @@ public class ZenModeConfig implements Parcelable { areChannelsBypassingDnd = source.readInt() == 1; allowConversations = source.readBoolean(); allowConversationsFrom = source.readInt(); if (Flags.modesApi()) { allowPriorityChannels = source.readBoolean(); } } @Override Loading Loading @@ -284,11 +295,14 @@ public class ZenModeConfig implements Parcelable { dest.writeInt(areChannelsBypassingDnd ? 1 : 0); dest.writeBoolean(allowConversations); dest.writeInt(allowConversationsFrom); if (Flags.modesApi()) { dest.writeBoolean(allowPriorityChannels); } } @Override public String toString() { return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') StringBuilder sb = new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') .append("user=").append(user) .append(",allowAlarms=").append(allowAlarms) .append(",allowMedia=").append(allowMedia) Loading @@ -303,9 +317,14 @@ public class ZenModeConfig implements Parcelable { .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom)) .append(",allowConvFrom=").append(ZenPolicy.conversationTypeToString (allowConversationsFrom)) .append(",suppressedVisualEffects=").append(suppressedVisualEffects) .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd) .append(",\nautomaticRules=").append(rulesToString()) .append(",suppressedVisualEffects=").append(suppressedVisualEffects); if (Flags.modesApi()) { sb.append(",hasPriorityChannels=").append(areChannelsBypassingDnd); sb.append(",allowPriorityChannels=").append(allowPriorityChannels); } else { sb.append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd); } return sb.append(",\nautomaticRules=").append(rulesToString()) .append(",\nmanualRule=").append(manualRule) .append(']').toString(); } Loading Loading @@ -385,7 +404,7 @@ public class ZenModeConfig implements Parcelable { if (!(o instanceof ZenModeConfig)) return false; if (o == this) return true; final ZenModeConfig other = (ZenModeConfig) o; return other.allowAlarms == allowAlarms boolean eq = other.allowAlarms == allowAlarms && other.allowMedia == allowMedia && other.allowSystem == allowSystem && other.allowCalls == allowCalls Loading @@ -402,10 +421,22 @@ public class ZenModeConfig implements Parcelable { && other.areChannelsBypassingDnd == areChannelsBypassingDnd && other.allowConversations == allowConversations && other.allowConversationsFrom == allowConversationsFrom; if (Flags.modesApi()) { return eq && other.allowPriorityChannels == allowPriorityChannels; } return eq; } @Override public int hashCode() { if (Flags.modesApi()) { return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents, user, automaticRules, manualRule, suppressedVisualEffects, areChannelsBypassingDnd, allowConversations, allowConversationsFrom, allowPriorityChannels); } return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls, allowRepeatCallers, allowMessages, allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents, Loading Loading @@ -511,6 +542,10 @@ public class ZenModeConfig implements Parcelable { rt.allowMedia = safeBoolean(parser, ALLOW_ATT_MEDIA, DEFAULT_ALLOW_MEDIA); rt.allowSystem = safeBoolean(parser, ALLOW_ATT_SYSTEM, DEFAULT_ALLOW_SYSTEM); if (Flags.modesApi()) { rt.allowPriorityChannels = safeBoolean(parser, ALLOW_ATT_CHANNELS, DEFAULT_ALLOW_PRIORITY_CHANNELS); } // migrate old suppressed visual effects fields, if they still exist in the xml Boolean allowWhenScreenOff = unsafeBoolean(parser, ALLOW_ATT_SCREEN_OFF); Loading Loading @@ -584,6 +619,9 @@ public class ZenModeConfig implements Parcelable { out.attributeBoolean(null, ALLOW_ATT_SYSTEM, allowSystem); out.attributeBoolean(null, ALLOW_ATT_CONV, allowConversations); out.attributeInt(null, ALLOW_ATT_CONV_FROM, allowConversationsFrom); if (Flags.modesApi()) { out.attributeBoolean(null, ALLOW_ATT_CHANNELS, allowPriorityChannels); } out.endTag(null, ALLOW_TAG); out.startTag(null, DISALLOW_TAG); Loading Loading @@ -748,6 +786,13 @@ public class ZenModeConfig implements Parcelable { final int system = safeInt(parser, ALLOW_ATT_SYSTEM, ZenPolicy.STATE_UNSET); final int events = safeInt(parser, ALLOW_ATT_EVENTS, ZenPolicy.STATE_UNSET); final int reminders = safeInt(parser, ALLOW_ATT_REMINDERS, ZenPolicy.STATE_UNSET); if (Flags.modesApi()) { final int channels = safeInt(parser, ALLOW_ATT_CHANNELS, ZenPolicy.CHANNEL_TYPE_UNSET); if (channels != ZenPolicy.CHANNEL_TYPE_UNSET) { builder.allowChannels(channels); policySet = true; } } if (calls != ZenPolicy.PEOPLE_TYPE_UNSET) { builder.allowCalls(calls); Loading Loading @@ -856,6 +901,10 @@ public class ZenModeConfig implements Parcelable { writeZenPolicyState(SHOW_ATT_AMBIENT, policy.getVisualEffectAmbient(), out); writeZenPolicyState(SHOW_ATT_NOTIFICATION_LIST, policy.getVisualEffectNotificationList(), out); if (Flags.modesApi()) { writeZenPolicyState(ALLOW_ATT_CHANNELS, policy.getAllowedChannels(), out); } } private static void writeZenPolicyState(String attr, int val, TypedXmlSerializer out) Loading @@ -869,6 +918,10 @@ public class ZenModeConfig implements Parcelable { if (val != ZenPolicy.CONVERSATION_SENDERS_UNSET) { out.attributeInt(null, attr, val); } } else if (Flags.modesApi() && Objects.equals(attr, ALLOW_ATT_CHANNELS)) { if (val != ZenPolicy.CHANNEL_TYPE_UNSET) { out.attributeInt(null, attr, val); } } else { if (val != ZenPolicy.STATE_UNSET) { out.attributeInt(null, attr, val); Loading Loading @@ -1044,6 +1097,11 @@ public class ZenModeConfig implements Parcelable { builder.showInNotificationList( (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST) == 0); } if (Flags.modesApi()) { builder.allowChannels(allowPriorityChannels ? ZenPolicy.CHANNEL_TYPE_PRIORITY : ZenPolicy.CHANNEL_TYPE_NONE); } return builder.build(); } Loading Loading @@ -1169,8 +1227,15 @@ public class ZenModeConfig implements Parcelable { suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; } int state = defaultPolicy.state; if (Flags.modesApi()) { state = Policy.policyState(defaultPolicy.hasPriorityChannels(), getAllowPriorityChannelsWithDefault(zenPolicy.getAllowedChannels(), DEFAULT_ALLOW_PRIORITY_CHANNELS)); } return new NotificationManager.Policy(priorityCategories, callSenders, messageSenders, suppressedVisualEffects, defaultPolicy.state, conversationSenders); messageSenders, suppressedVisualEffects, state, conversationSenders); } private boolean isPriorityCategoryEnabled(int categoryType, Policy policy) { Loading Loading @@ -1207,6 +1272,24 @@ public class ZenModeConfig implements Parcelable { } } /** * Gets whether priority channels are permitted by this channel type, with the specified * default if the value is unset. This effectively converts the channel enum to a boolean, * where "true" indicates priority channels are allowed to break through and "false" means * they are not. */ public static boolean getAllowPriorityChannelsWithDefault( @ZenPolicy.ChannelType int channelType, boolean defaultAllowChannels) { switch (channelType) { case ZenPolicy.CHANNEL_TYPE_PRIORITY: return true; case ZenPolicy.CHANNEL_TYPE_NONE: return false; default: return defaultAllowChannels; } } /** * Maps NotificationManager.Policy senders type to ZenPolicy.PeopleType */ Loading Loading @@ -1259,10 +1342,13 @@ public class ZenModeConfig implements Parcelable { priorityConversationSenders = getConversationSendersWithDefault( allowConversationsFrom, priorityConversationSenders); int state = areChannelsBypassingDnd ? Policy.STATE_CHANNELS_BYPASSING_DND : 0; if (Flags.modesApi()) { state = Policy.policyState(areChannelsBypassingDnd, allowPriorityChannels); } return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders, suppressedVisualEffects, areChannelsBypassingDnd ? Policy.STATE_CHANNELS_BYPASSING_DND : 0, priorityConversationSenders); suppressedVisualEffects, state, priorityConversationSenders); } /** Loading Loading @@ -1342,6 +1428,9 @@ public class ZenModeConfig implements Parcelable { allowConversationsFrom); if (policy.state != Policy.STATE_UNSET) { areChannelsBypassingDnd = (policy.state & Policy.STATE_CHANNELS_BYPASSING_DND) != 0; if (Flags.modesApi()) { allowPriorityChannels = policy.allowPriorityChannels(); } } } Loading Loading @@ -2067,6 +2156,10 @@ public class ZenModeConfig implements Parcelable { boolean allowConversations = (policy.priorityConversationSenders & Policy.PRIORITY_CATEGORY_CONVERSATIONS) != 0; boolean areChannelsBypassingDnd = (policy.state & Policy.STATE_CHANNELS_BYPASSING_DND) != 0; if (Flags.modesApi()) { areChannelsBypassingDnd = policy.hasPriorityChannels() && policy.allowPriorityChannels(); } boolean allowSystem = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_SYSTEM) != 0; return !allowReminders && !allowCalls && !allowMessages && !allowEvents && !allowRepeatCallers && !areChannelsBypassingDnd && !allowSystem Loading Loading @@ -2098,9 +2191,14 @@ public class ZenModeConfig implements Parcelable { * This includes notification, ringer and system sounds */ public static boolean areAllPriorityOnlyRingerSoundsMuted(ZenModeConfig config) { boolean areChannelsBypassingDnd = config.areChannelsBypassingDnd; if (Flags.modesApi()) { areChannelsBypassingDnd = config.areChannelsBypassingDnd && config.allowPriorityChannels; } return !config.allowReminders && !config.allowCalls && !config.allowMessages && !config.allowEvents && !config.allowRepeatCallers && !config.areChannelsBypassingDnd && !config.allowSystem; && !areChannelsBypassingDnd && !config.allowSystem; } /** Loading
core/java/android/service/notification/ZenModeDiff.java +8 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.service.notification; import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Flags; import android.util.ArrayMap; import android.util.ArraySet; Loading Loading @@ -221,6 +222,7 @@ public class ZenModeDiff { public static final String FIELD_ALLOW_CONVERSATIONS_FROM = "allowConversationsFrom"; public static final String FIELD_SUPPRESSED_VISUAL_EFFECTS = "suppressedVisualEffects"; public static final String FIELD_ARE_CHANNELS_BYPASSING_DND = "areChannelsBypassingDnd"; public static final String FIELD_ALLOW_PRIORITY_CHANNELS = "allowPriorityChannels"; private static final Set<String> PEOPLE_TYPE_FIELDS = Set.of(FIELD_ALLOW_CALLS_FROM, FIELD_ALLOW_MESSAGES_FROM); Loading Loading @@ -297,6 +299,12 @@ public class ZenModeDiff { addField(FIELD_ARE_CHANNELS_BYPASSING_DND, new FieldDiff<>(from.areChannelsBypassingDnd, to.areChannelsBypassingDnd)); } if (Flags.modesApi()) { if (from.allowPriorityChannels != to.allowPriorityChannels) { addField(FIELD_ALLOW_PRIORITY_CHANNELS, new FieldDiff<>(from.allowPriorityChannels, to.allowPriorityChannels)); } } // Compare automatic and manual rules final ArraySet<String> allRules = new ArraySet<>(); Loading