| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.service.notification; |
| |
| import android.annotation.FlaggedApi; |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.app.Flags; |
| import android.app.Notification; |
| import android.app.NotificationChannel; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.util.proto.ProtoOutputStream; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Objects; |
| |
| /** |
| * ZenPolicy determines whether to allow certain notifications and their corresponding sounds to |
| * play when a device is in Do Not Disturb mode. |
| * ZenPolicy also dictates the visual effects of notifications that are intercepted when |
| * a device is in Do Not Disturb mode. |
| */ |
| public final class ZenPolicy implements Parcelable { |
| private ArrayList<Integer> mPriorityCategories; |
| private ArrayList<Integer> mVisualEffects; |
| private @PeopleType int mPriorityMessages = PEOPLE_TYPE_UNSET; |
| private @PeopleType int mPriorityCalls = PEOPLE_TYPE_UNSET; |
| private @ConversationSenders int mConversationSenders = CONVERSATION_SENDERS_UNSET; |
| private @ChannelType int mAllowChannels = CHANNEL_TYPE_UNSET; |
| |
| /** @hide */ |
| @IntDef(prefix = { "PRIORITY_CATEGORY_" }, value = { |
| PRIORITY_CATEGORY_REMINDERS, |
| PRIORITY_CATEGORY_EVENTS, |
| PRIORITY_CATEGORY_MESSAGES, |
| PRIORITY_CATEGORY_CALLS, |
| PRIORITY_CATEGORY_REPEAT_CALLERS, |
| PRIORITY_CATEGORY_ALARMS, |
| PRIORITY_CATEGORY_MEDIA, |
| PRIORITY_CATEGORY_SYSTEM, |
| PRIORITY_CATEGORY_CONVERSATIONS, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface PriorityCategory {} |
| |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_REMINDERS = 0; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_EVENTS = 1; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_MESSAGES = 2; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_CALLS = 3; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 4; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_ALARMS = 5; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_MEDIA = 6; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_SYSTEM = 7; |
| /** @hide */ |
| public static final int PRIORITY_CATEGORY_CONVERSATIONS = 8; |
| |
| /** |
| * Total number of priority categories. Keep updated with any updates to PriorityCategory enum. |
| * @hide |
| */ |
| public static final int NUM_PRIORITY_CATEGORIES = 9; |
| |
| /** @hide */ |
| @IntDef(prefix = { "VISUAL_EFFECT_" }, value = { |
| VISUAL_EFFECT_FULL_SCREEN_INTENT, |
| VISUAL_EFFECT_LIGHTS, |
| VISUAL_EFFECT_PEEK, |
| VISUAL_EFFECT_STATUS_BAR, |
| VISUAL_EFFECT_BADGE, |
| VISUAL_EFFECT_AMBIENT, |
| VISUAL_EFFECT_NOTIFICATION_LIST, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface VisualEffect {} |
| |
| /** @hide */ |
| public static final int VISUAL_EFFECT_FULL_SCREEN_INTENT = 0; |
| /** @hide */ |
| public static final int VISUAL_EFFECT_LIGHTS = 1; |
| /** @hide */ |
| public static final int VISUAL_EFFECT_PEEK = 2; |
| /** @hide */ |
| public static final int VISUAL_EFFECT_STATUS_BAR = 3; |
| /** @hide */ |
| public static final int VISUAL_EFFECT_BADGE = 4; |
| /** @hide */ |
| public static final int VISUAL_EFFECT_AMBIENT = 5; |
| /** @hide */ |
| public static final int VISUAL_EFFECT_NOTIFICATION_LIST = 6; |
| |
| /** |
| * Total number of visual effects. Keep updated with any updates to VisualEffect enum. |
| * @hide |
| */ |
| public static final int NUM_VISUAL_EFFECTS = 7; |
| |
| /** @hide */ |
| @IntDef(prefix = { "PEOPLE_TYPE_" }, value = { |
| PEOPLE_TYPE_UNSET, |
| PEOPLE_TYPE_ANYONE, |
| PEOPLE_TYPE_CONTACTS, |
| PEOPLE_TYPE_STARRED, |
| PEOPLE_TYPE_NONE, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface PeopleType {} |
| |
| /** |
| * Used to indicate no preference for the type of people that can bypass dnd for either |
| * calls or messages. |
| */ |
| public static final int PEOPLE_TYPE_UNSET = 0; |
| |
| /** |
| * Used to indicate all calls or messages can bypass dnd. |
| */ |
| public static final int PEOPLE_TYPE_ANYONE = 1; |
| |
| /** |
| * Used to indicate calls or messages from contacts can bypass dnd. |
| */ |
| public static final int PEOPLE_TYPE_CONTACTS = 2; |
| |
| /** |
| * Used to indicate calls or messages from starred contacts can bypass dnd. |
| */ |
| public static final int PEOPLE_TYPE_STARRED = 3; |
| |
| /** |
| * Used to indicate no calls or messages can bypass dnd. |
| */ |
| public static final int PEOPLE_TYPE_NONE = 4; |
| |
| |
| /** @hide */ |
| @IntDef(prefix = { "CONVERSATION_SENDERS_" }, value = { |
| CONVERSATION_SENDERS_UNSET, |
| CONVERSATION_SENDERS_ANYONE, |
| CONVERSATION_SENDERS_IMPORTANT, |
| CONVERSATION_SENDERS_NONE, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface ConversationSenders {} |
| |
| /** |
| * Used to indicate no preference for the type of conversations that can bypass dnd. |
| */ |
| public static final int CONVERSATION_SENDERS_UNSET = 0; |
| |
| /** |
| * Used to indicate all conversations can bypass dnd. |
| */ |
| public static final int CONVERSATION_SENDERS_ANYONE = 1; |
| |
| /** |
| * Used to indicate important conversations can bypass dnd. |
| */ |
| public static final int CONVERSATION_SENDERS_IMPORTANT = 2; |
| |
| /** |
| * Used to indicate no conversations can bypass dnd. |
| */ |
| public static final int CONVERSATION_SENDERS_NONE = 3; |
| |
| /** @hide */ |
| @IntDef(prefix = { "STATE_" }, value = { |
| STATE_UNSET, |
| STATE_ALLOW, |
| STATE_DISALLOW, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface State {} |
| |
| /** |
| * Indicates no preference for whether a type of sound or visual effect is or isn't allowed |
| * to play/show when DND is active. Will default to the current set policy. |
| */ |
| public static final int STATE_UNSET = 0; |
| |
| /** |
| * Indicates a type of sound or visual effect is allowed to play/show when DND is active. |
| */ |
| public static final int STATE_ALLOW = 1; |
| |
| /** |
| * Indicates a type of sound or visual effect is not allowed to play/show when DND is active. |
| */ |
| public static final int STATE_DISALLOW = 2; |
| |
| /** @hide */ |
| @IntDef(prefix = { "CHANNEL_TYPE_" }, value = { |
| CHANNEL_TYPE_UNSET, |
| CHANNEL_TYPE_PRIORITY, |
| CHANNEL_TYPE_NONE, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface ChannelType {} |
| |
| /** |
| * Indicates no explicit setting for which channels may bypass DND when this policy is active. |
| * Defaults to {@link #CHANNEL_TYPE_PRIORITY}. |
| */ |
| @FlaggedApi(Flags.FLAG_MODES_API) |
| public static final int CHANNEL_TYPE_UNSET = 0; |
| |
| /** |
| * Indicates that channels marked as {@link NotificationChannel#canBypassDnd()} can bypass DND |
| * when this policy is active. |
| */ |
| @FlaggedApi(Flags.FLAG_MODES_API) |
| public static final int CHANNEL_TYPE_PRIORITY = 1; |
| |
| /** |
| * Indicates that no channels can bypass DND when this policy is active, even those marked as |
| * {@link NotificationChannel#canBypassDnd()}. |
| */ |
| @FlaggedApi(Flags.FLAG_MODES_API) |
| public static final int CHANNEL_TYPE_NONE = 2; |
| |
| /** @hide */ |
| public ZenPolicy() { |
| mPriorityCategories = new ArrayList<>(Collections.nCopies(NUM_PRIORITY_CATEGORIES, 0)); |
| mVisualEffects = new ArrayList<>(Collections.nCopies(NUM_VISUAL_EFFECTS, 0)); |
| } |
| |
| /** |
| * Conversation type that can bypass DND. |
| * @return {@link #CONVERSATION_SENDERS_UNSET}, {@link #CONVERSATION_SENDERS_ANYONE}, |
| * {@link #CONVERSATION_SENDERS_IMPORTANT}, {@link #CONVERSATION_SENDERS_NONE}. |
| */ |
| public @PeopleType int getPriorityConversationSenders() { |
| return mConversationSenders; |
| } |
| |
| /** |
| * Message senders that can bypass DND. |
| * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE}, |
| * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE} |
| */ |
| public @PeopleType int getPriorityMessageSenders() { |
| return mPriorityMessages; |
| } |
| |
| /** |
| * Callers that can bypass DND. |
| * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE}, |
| * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE} |
| */ |
| public @PeopleType int getPriorityCallSenders() { |
| return mPriorityCalls; |
| } |
| |
| /** |
| * Whether this policy wants to allow conversation notifications |
| * (see {@link NotificationChannel#getConversationId()}) to play sounds and visually appear |
| * or to intercept them when DND is active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryConversations() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_CONVERSATIONS); |
| } |
| |
| /** |
| * Whether this policy wants to allow notifications with category |
| * {@link Notification#CATEGORY_REMINDER} to play sounds and visually appear |
| * or to intercept them when DND is active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryReminders() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_REMINDERS); |
| } |
| |
| /** |
| * Whether this policy wants to allow notifications with category |
| * {@link Notification#CATEGORY_EVENT} to play sounds and visually appear |
| * or to intercept them when DND is active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryEvents() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_EVENTS); |
| } |
| |
| /** |
| * Whether this policy wants to allow notifications with category |
| * {@link Notification#CATEGORY_MESSAGE} to play sounds and visually appear |
| * or to intercept them when DND is active. Types of message senders that are allowed |
| * are specified by {@link #getPriorityMessageSenders}. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryMessages() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_MESSAGES); |
| } |
| |
| /** |
| * Whether this policy wants to allow notifications with category |
| * {@link Notification#CATEGORY_CALL} to play sounds and visually appear |
| * or to intercept them when DND is active. Types of callers that are allowed |
| * are specified by {@link #getPriorityCallSenders()}. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryCalls() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_CALLS); |
| } |
| |
| /** |
| * Whether this policy wants to allow repeat callers (notifications with category |
| * {@link Notification#CATEGORY_CALL} that have recently called) to play sounds and |
| * visually appear or to intercept them when DND is active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryRepeatCallers() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_REPEAT_CALLERS); |
| } |
| |
| /** |
| * Whether this policy wants to allow notifications with category |
| * {@link Notification#CATEGORY_ALARM} to play sounds and visually appear |
| * or to intercept them when DND is active. |
| * When alarms are {@link #STATE_DISALLOW disallowed}, the alarm stream will be muted when DND |
| * is active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryAlarms() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_ALARMS); |
| } |
| |
| /** |
| * Whether this policy wants to allow media notifications to play sounds and visually appear |
| * or to intercept them when DND is active. |
| * When media is {@link #STATE_DISALLOW disallowed}, the media stream will be muted when DND is |
| * active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategoryMedia() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_MEDIA); |
| } |
| |
| /** |
| * Whether this policy wants to allow system sounds when DND is active. |
| * When system is {@link #STATE_DISALLOW}, the system stream will be muted when DND is active. |
| * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} |
| */ |
| public @State int getPriorityCategorySystem() { |
| return mPriorityCategories.get(PRIORITY_CATEGORY_SYSTEM); |
| } |
| |
| /** |
| * Whether this policy allows {@link Notification#fullScreenIntent full screen intents} from |
| * notifications intercepted by DND. |
| */ |
| public @State int getVisualEffectFullScreenIntent() { |
| return mVisualEffects.get(VISUAL_EFFECT_FULL_SCREEN_INTENT); |
| } |
| |
| /** |
| * Whether this policy allows {@link NotificationChannel#shouldShowLights() notification |
| * lights} from notifications intercepted by DND. |
| */ |
| public @State int getVisualEffectLights() { |
| return mVisualEffects.get(VISUAL_EFFECT_LIGHTS); |
| } |
| |
| /** |
| * Whether this policy allows peeking from notifications intercepted by DND. |
| */ |
| public @State int getVisualEffectPeek() { |
| return mVisualEffects.get(VISUAL_EFFECT_PEEK); |
| } |
| |
| /** |
| * Whether this policy allows notifications intercepted by DND from appearing in the status bar |
| * on devices that support status bars. |
| */ |
| public @State int getVisualEffectStatusBar() { |
| return mVisualEffects.get(VISUAL_EFFECT_STATUS_BAR); |
| } |
| |
| /** |
| * Whether this policy allows {@link NotificationChannel#canShowBadge() badges} from |
| * notifications intercepted by DND on devices that support badging. |
| */ |
| public @State int getVisualEffectBadge() { |
| return mVisualEffects.get(VISUAL_EFFECT_BADGE); |
| } |
| |
| /** |
| * Whether this policy allows notifications intercepted by DND from appearing on ambient |
| * displays on devices that support ambient display. |
| */ |
| public @State int getVisualEffectAmbient() { |
| return mVisualEffects.get(VISUAL_EFFECT_AMBIENT); |
| } |
| |
| /** |
| * Whether this policy allows notifications intercepted by DND from appearing in notification |
| * list views like the notification shade or lockscreen on devices that support those |
| * views. |
| */ |
| public @State int getVisualEffectNotificationList() { |
| return mVisualEffects.get(VISUAL_EFFECT_NOTIFICATION_LIST); |
| } |
| |
| /** |
| * Which types of {@link NotificationChannel channels} this policy allows to bypass DND. When |
| * this value is {@link #CHANNEL_TYPE_PRIORITY priority} channels, any channel with |
| * canBypassDnd() may bypass DND; when it is {@link #CHANNEL_TYPE_NONE none}, even channels |
| * with canBypassDnd() will be intercepted. |
| * @return {@link #CHANNEL_TYPE_UNSET}, {@link #CHANNEL_TYPE_PRIORITY}, or |
| * {@link #CHANNEL_TYPE_NONE} |
| */ |
| @FlaggedApi(Flags.FLAG_MODES_API) |
| public @ChannelType int getAllowedChannels() { |
| return mAllowChannels; |
| } |
| |
| /** |
| * Whether this policy hides all visual effects |
| * @hide |
| */ |
| public boolean shouldHideAllVisualEffects() { |
| for (int i = 0; i < mVisualEffects.size(); i++) { |
| if (mVisualEffects.get(i) != STATE_DISALLOW) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Whether this policy shows all visual effects |
| * @hide |
| */ |
| public boolean shouldShowAllVisualEffects() { |
| for (int i = 0; i < mVisualEffects.size(); i++) { |
| if (mVisualEffects.get(i) != STATE_ALLOW) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Builder class for {@link ZenPolicy} objects. |
| * Provides a convenient way to set the various fields of a {@link ZenPolicy}. If a field |
| * is not set, it is (@link STATE_UNSET} and will not change the current set policy. |
| */ |
| public static final class Builder { |
| private ZenPolicy mZenPolicy; |
| |
| public Builder() { |
| mZenPolicy = new ZenPolicy(); |
| } |
| |
| /** |
| * @hide |
| */ |
| public Builder(ZenPolicy policy) { |
| if (policy != null) { |
| mZenPolicy = policy.copy(); |
| } else { |
| mZenPolicy = new ZenPolicy(); |
| } |
| } |
| |
| /** |
| * Builds the current ZenPolicy. |
| */ |
| public @NonNull ZenPolicy build() { |
| return mZenPolicy.copy(); |
| } |
| |
| /** |
| * Allows all notifications to bypass DND and unmutes all streams. |
| */ |
| public @NonNull Builder allowAllSounds() { |
| for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) { |
| mZenPolicy.mPriorityCategories.set(i, STATE_ALLOW); |
| } |
| mZenPolicy.mPriorityMessages = PEOPLE_TYPE_ANYONE; |
| mZenPolicy.mPriorityCalls = PEOPLE_TYPE_ANYONE; |
| mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_ANYONE; |
| return this; |
| } |
| |
| /** |
| * Intercepts all notifications and prevents them from playing sounds |
| * when DND is active. Also mutes alarm, system and media streams. |
| * Notification channels can still play sounds only if they |
| * {@link NotificationChannel#canBypassDnd can bypass DND}. If no channels can bypass DND, |
| * the ringer stream is also muted. |
| */ |
| public @NonNull Builder disallowAllSounds() { |
| for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) { |
| mZenPolicy.mPriorityCategories.set(i, STATE_DISALLOW); |
| } |
| mZenPolicy.mPriorityMessages = PEOPLE_TYPE_NONE; |
| mZenPolicy.mPriorityCalls = PEOPLE_TYPE_NONE; |
| mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_NONE; |
| return this; |
| } |
| |
| /** |
| * Allows notifications intercepted by DND to show on all surfaces when DND is active. |
| */ |
| public @NonNull Builder showAllVisualEffects() { |
| for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) { |
| mZenPolicy.mVisualEffects.set(i, STATE_ALLOW); |
| } |
| return this; |
| } |
| |
| /** |
| * Disallows notifications intercepted by DND from showing when DND is active. |
| */ |
| public @NonNull Builder hideAllVisualEffects() { |
| for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) { |
| mZenPolicy.mVisualEffects.set(i, STATE_DISALLOW); |
| } |
| return this; |
| } |
| |
| /** |
| * Unsets a priority category, neither allowing or disallowing. When applying this policy, |
| * unset categories will default to the current applied policy. |
| * @hide |
| */ |
| public @NonNull Builder unsetPriorityCategory(@PriorityCategory int category) { |
| mZenPolicy.mPriorityCategories.set(category, STATE_UNSET); |
| |
| if (category == PRIORITY_CATEGORY_MESSAGES) { |
| mZenPolicy.mPriorityMessages = PEOPLE_TYPE_UNSET; |
| } else if (category == PRIORITY_CATEGORY_CALLS) { |
| mZenPolicy.mPriorityCalls = PEOPLE_TYPE_UNSET; |
| } else if (category == PRIORITY_CATEGORY_CONVERSATIONS) { |
| mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_UNSET; |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Unsets a visual effect, neither allowing or disallowing. When applying this policy, |
| * unset effects will default to the current applied policy. |
| * @hide |
| */ |
| public @NonNull Builder unsetVisualEffect(@VisualEffect int effect) { |
| mZenPolicy.mVisualEffects.set(effect, STATE_UNSET); |
| return this; |
| } |
| |
| /** |
| * Whether to allow notifications with category {@link Notification#CATEGORY_REMINDER} |
| * to play sounds and visually appear or to intercept them when DND is active. |
| */ |
| public @NonNull Builder allowReminders(boolean allow) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REMINDERS, |
| allow ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether to allow notifications with category {@link Notification#CATEGORY_EVENT} |
| * to play sounds and visually appear or to intercept them when DND is active. |
| */ |
| public @NonNull Builder allowEvents(boolean allow) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_EVENTS, |
| allow ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether to allow conversation notifications |
| * (see {@link NotificationChannel#setConversationId(String, String)}) |
| * that match audienceType to play sounds and visually appear or to intercept |
| * them when DND is active. |
| * @param audienceType callers that are allowed to bypass DND |
| */ |
| public @NonNull Builder allowConversations(@ConversationSenders int audienceType) { |
| if (audienceType == STATE_UNSET) { |
| return unsetPriorityCategory(PRIORITY_CATEGORY_CONVERSATIONS); |
| } |
| |
| if (audienceType == CONVERSATION_SENDERS_NONE) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CONVERSATIONS, STATE_DISALLOW); |
| } else if (audienceType == CONVERSATION_SENDERS_ANYONE |
| || audienceType == CONVERSATION_SENDERS_IMPORTANT) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CONVERSATIONS, STATE_ALLOW); |
| } else { |
| return this; |
| } |
| |
| mZenPolicy.mConversationSenders = audienceType; |
| return this; |
| } |
| |
| /** |
| * Whether to allow notifications with category {@link Notification#CATEGORY_MESSAGE} |
| * that match audienceType to play sounds and visually appear or to intercept |
| * them when DND is active. |
| * @param audienceType message senders that are allowed to bypass DND |
| */ |
| public @NonNull Builder allowMessages(@PeopleType int audienceType) { |
| if (audienceType == STATE_UNSET) { |
| return unsetPriorityCategory(PRIORITY_CATEGORY_MESSAGES); |
| } |
| |
| if (audienceType == PEOPLE_TYPE_NONE) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_DISALLOW); |
| } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS |
| || audienceType == PEOPLE_TYPE_STARRED) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_ALLOW); |
| } else { |
| return this; |
| } |
| |
| mZenPolicy.mPriorityMessages = audienceType; |
| return this; |
| } |
| |
| /** |
| * Whether to allow notifications with category {@link Notification#CATEGORY_CALL} |
| * that match audienceType to play sounds and visually appear or to intercept |
| * them when DND is active. |
| * @param audienceType callers that are allowed to bypass DND |
| */ |
| public @NonNull Builder allowCalls(@PeopleType int audienceType) { |
| if (audienceType == STATE_UNSET) { |
| return unsetPriorityCategory(PRIORITY_CATEGORY_CALLS); |
| } |
| |
| if (audienceType == PEOPLE_TYPE_NONE) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_DISALLOW); |
| } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS |
| || audienceType == PEOPLE_TYPE_STARRED) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_ALLOW); |
| } else { |
| return this; |
| } |
| |
| mZenPolicy.mPriorityCalls = audienceType; |
| return this; |
| } |
| |
| /** |
| * Whether to allow repeat callers (notifications with category |
| * {@link Notification#CATEGORY_CALL} that have recently called |
| * to play sounds and visually appear. |
| */ |
| public @NonNull Builder allowRepeatCallers(boolean allow) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REPEAT_CALLERS, |
| allow ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether to allow notifications with category {@link Notification#CATEGORY_ALARM} |
| * to play sounds and visually appear or to intercept them when DND is active. |
| * Disallowing alarms will mute the alarm stream when DND is active. |
| */ |
| public @NonNull Builder allowAlarms(boolean allow) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_ALARMS, |
| allow ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether to allow media notifications to play sounds and visually |
| * appear or to intercept them when DND is active. |
| * Disallowing media will mute the media stream when DND is active. |
| */ |
| public @NonNull Builder allowMedia(boolean allow) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MEDIA, |
| allow ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether to allow system sounds to play when DND is active. |
| * Disallowing system sounds will mute the system stream when DND is active. |
| */ |
| public @NonNull Builder allowSystem(boolean allow) { |
| mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_SYSTEM, |
| allow ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether to allow {@link PriorityCategory} sounds to play when DND is active. |
| * @hide |
| */ |
| public @NonNull Builder allowCategory(@PriorityCategory int category, boolean allow) { |
| switch (category) { |
| case PRIORITY_CATEGORY_ALARMS: |
| allowAlarms(allow); |
| break; |
| case PRIORITY_CATEGORY_MEDIA: |
| allowMedia(allow); |
| break; |
| case PRIORITY_CATEGORY_SYSTEM: |
| allowSystem(allow); |
| break; |
| case PRIORITY_CATEGORY_REMINDERS: |
| allowReminders(allow); |
| break; |
| case PRIORITY_CATEGORY_EVENTS: |
| allowEvents(allow); |
| break; |
| case PRIORITY_CATEGORY_REPEAT_CALLERS: |
| allowRepeatCallers(allow); |
| break; |
| } |
| return this; |
| } |
| |
| /** |
| * Whether {@link Notification#fullScreenIntent full screen intents} that are intercepted |
| * by DND are shown. |
| */ |
| public @NonNull Builder showFullScreenIntent(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_FULL_SCREEN_INTENT, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether {@link NotificationChannel#shouldShowLights() notification lights} from |
| * notifications intercepted by DND are blocked. |
| */ |
| public @NonNull Builder showLights(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_LIGHTS, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether notifications intercepted by DND are prevented from peeking. |
| */ |
| public @NonNull Builder showPeeking(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_PEEK, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether notifications intercepted by DND are prevented from appearing in the status bar |
| * on devices that support status bars. |
| */ |
| public @NonNull Builder showStatusBarIcons(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_STATUS_BAR, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether {@link NotificationChannel#canShowBadge() badges} from |
| * notifications intercepted by DND are allowed on devices that support badging. |
| */ |
| public @NonNull Builder showBadges(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_BADGE, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether notification intercepted by DND are prevented from appearing on ambient displays |
| * on devices that support ambient display. |
| */ |
| public @NonNull Builder showInAmbientDisplay(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_AMBIENT, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether notification intercepted by DND are prevented from appearing in notification |
| * list views like the notification shade or lockscreen on devices that support those |
| * views. |
| */ |
| public @NonNull Builder showInNotificationList(boolean show) { |
| mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_NOTIFICATION_LIST, |
| show ? STATE_ALLOW : STATE_DISALLOW); |
| return this; |
| } |
| |
| /** |
| * Whether notifications intercepted by DND are prevented from appearing for |
| * {@link VisualEffect} |
| * @hide |
| */ |
| public @NonNull Builder showVisualEffect(@VisualEffect int effect, boolean show) { |
| switch (effect) { |
| case VISUAL_EFFECT_FULL_SCREEN_INTENT: |
| showFullScreenIntent(show); |
| break; |
| case VISUAL_EFFECT_LIGHTS: |
| showLights(show); |
| break; |
| case VISUAL_EFFECT_PEEK: |
| showPeeking(show); |
| break; |
| case VISUAL_EFFECT_STATUS_BAR: |
| showStatusBarIcons(show); |
| break; |
| case VISUAL_EFFECT_BADGE: |
| showBadges(show); |
| break; |
| case VISUAL_EFFECT_AMBIENT: |
| showInAmbientDisplay(show); |
| break; |
| case VISUAL_EFFECT_NOTIFICATION_LIST: |
| showInNotificationList(show); |
| break; |
| } |
| return this; |
| } |
| |
| /** |
| * Set whether priority channels are permitted to break through DND. |
| */ |
| @FlaggedApi(Flags.FLAG_MODES_API) |
| public @NonNull Builder allowChannels(@ChannelType int channelType) { |
| mZenPolicy.mAllowChannels = channelType; |
| return this; |
| } |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| dest.writeList(mPriorityCategories); |
| dest.writeList(mVisualEffects); |
| dest.writeInt(mPriorityCalls); |
| dest.writeInt(mPriorityMessages); |
| dest.writeInt(mConversationSenders); |
| if (Flags.modesApi()) { |
| dest.writeInt(mAllowChannels); |
| } |
| } |
| |
| public static final @android.annotation.NonNull Parcelable.Creator<ZenPolicy> CREATOR = |
| new Parcelable.Creator<ZenPolicy>() { |
| @Override |
| public ZenPolicy createFromParcel(Parcel source) { |
| ZenPolicy policy = new ZenPolicy(); |
| policy.mPriorityCategories = trimList( |
| source.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class), |
| NUM_PRIORITY_CATEGORIES); |
| policy.mVisualEffects = trimList( |
| source.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class), |
| NUM_VISUAL_EFFECTS); |
| policy.mPriorityCalls = source.readInt(); |
| policy.mPriorityMessages = source.readInt(); |
| policy.mConversationSenders = source.readInt(); |
| if (Flags.modesApi()) { |
| policy.mAllowChannels = source.readInt(); |
| } |
| return policy; |
| } |
| |
| @Override |
| public ZenPolicy[] newArray(int size) { |
| return new ZenPolicy[size]; |
| } |
| }; |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(ZenPolicy.class.getSimpleName()) |
| .append('{') |
| .append("priorityCategories=[").append(priorityCategoriesToString()) |
| .append("], visualEffects=[").append(visualEffectsToString()) |
| .append("], priorityCallsSenders=").append(peopleTypeToString(mPriorityCalls)) |
| .append(", priorityMessagesSenders=").append(peopleTypeToString(mPriorityMessages)) |
| .append(", priorityConversationSenders=").append( |
| conversationTypeToString(mConversationSenders)); |
| if (Flags.modesApi()) { |
| sb.append(", allowChannels=").append(channelTypeToString(mAllowChannels)); |
| } |
| return sb.append('}').toString(); |
| } |
| |
| // Returns a list containing the first maxLength elements of the input list if the list is |
| // longer than that size. For the lists in ZenPolicy, this should not happen unless the input |
| // is corrupt. |
| private static ArrayList<Integer> trimList(ArrayList<Integer> list, int maxLength) { |
| if (list == null || list.size() <= maxLength) { |
| return list; |
| } |
| return new ArrayList<>(list.subList(0, maxLength)); |
| } |
| |
| private String priorityCategoriesToString() { |
| StringBuilder builder = new StringBuilder(); |
| for (int i = 0; i < mPriorityCategories.size(); i++) { |
| if (mPriorityCategories.get(i) != STATE_UNSET) { |
| builder.append(indexToCategory(i)) |
| .append("=") |
| .append(stateToString(mPriorityCategories.get(i))) |
| .append(" "); |
| } |
| |
| } |
| return builder.toString(); |
| } |
| |
| private String visualEffectsToString() { |
| StringBuilder builder = new StringBuilder(); |
| for (int i = 0; i < mVisualEffects.size(); i++) { |
| if (mVisualEffects.get(i) != STATE_UNSET) { |
| builder.append(indexToVisualEffect(i)) |
| .append("=") |
| .append(stateToString(mVisualEffects.get(i))) |
| .append(" "); |
| } |
| |
| } |
| return builder.toString(); |
| } |
| |
| private String indexToVisualEffect(@VisualEffect int visualEffectIndex) { |
| switch (visualEffectIndex) { |
| case VISUAL_EFFECT_FULL_SCREEN_INTENT: |
| return "fullScreenIntent"; |
| case VISUAL_EFFECT_LIGHTS: |
| return "lights"; |
| case VISUAL_EFFECT_PEEK: |
| return "peek"; |
| case VISUAL_EFFECT_STATUS_BAR: |
| return "statusBar"; |
| case VISUAL_EFFECT_BADGE: |
| return "badge"; |
| case VISUAL_EFFECT_AMBIENT: |
| return "ambient"; |
| case VISUAL_EFFECT_NOTIFICATION_LIST: |
| return "notificationList"; |
| } |
| return null; |
| } |
| |
| private String indexToCategory(@PriorityCategory int categoryIndex) { |
| switch (categoryIndex) { |
| case PRIORITY_CATEGORY_REMINDERS: |
| return "reminders"; |
| case PRIORITY_CATEGORY_EVENTS: |
| return "events"; |
| case PRIORITY_CATEGORY_MESSAGES: |
| return "messages"; |
| case PRIORITY_CATEGORY_CALLS: |
| return "calls"; |
| case PRIORITY_CATEGORY_REPEAT_CALLERS: |
| return "repeatCallers"; |
| case PRIORITY_CATEGORY_ALARMS: |
| return "alarms"; |
| case PRIORITY_CATEGORY_MEDIA: |
| return "media"; |
| case PRIORITY_CATEGORY_SYSTEM: |
| return "system"; |
| case PRIORITY_CATEGORY_CONVERSATIONS: |
| return "convs"; |
| } |
| return null; |
| } |
| |
| private String stateToString(@State int state) { |
| switch (state) { |
| case STATE_UNSET: |
| return "unset"; |
| case STATE_DISALLOW: |
| return "disallow"; |
| case STATE_ALLOW: |
| return "allow"; |
| } |
| return "invalidState{" + state + "}"; |
| } |
| |
| private String peopleTypeToString(@PeopleType int peopleType) { |
| switch (peopleType) { |
| case PEOPLE_TYPE_ANYONE: |
| return "anyone"; |
| case PEOPLE_TYPE_CONTACTS: |
| return "contacts"; |
| case PEOPLE_TYPE_NONE: |
| return "none"; |
| case PEOPLE_TYPE_STARRED: |
| return "starred_contacts"; |
| case STATE_UNSET: |
| return "unset"; |
| } |
| return "invalidPeopleType{" + peopleType + "}"; |
| } |
| |
| /** |
| * @hide |
| */ |
| public static String conversationTypeToString(@ConversationSenders int conversationType) { |
| switch (conversationType) { |
| case CONVERSATION_SENDERS_ANYONE: |
| return "anyone"; |
| case CONVERSATION_SENDERS_IMPORTANT: |
| return "important"; |
| case CONVERSATION_SENDERS_NONE: |
| return "none"; |
| case CONVERSATION_SENDERS_UNSET: |
| return "unset"; |
| } |
| return "invalidConversationType{" + conversationType + "}"; |
| } |
| |
| /** |
| * @hide |
| */ |
| @FlaggedApi(Flags.FLAG_MODES_API) |
| public static String channelTypeToString(@ChannelType int channelType) { |
| switch (channelType) { |
| case CHANNEL_TYPE_UNSET: |
| return "unset"; |
| case CHANNEL_TYPE_PRIORITY: |
| return "priority"; |
| case CHANNEL_TYPE_NONE: |
| return "none"; |
| } |
| return "invalidChannelType{" + channelType + "}"; |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object o) { |
| if (!(o instanceof ZenPolicy)) return false; |
| if (o == this) return true; |
| final ZenPolicy other = (ZenPolicy) o; |
| |
| boolean eq = Objects.equals(other.mPriorityCategories, mPriorityCategories) |
| && Objects.equals(other.mVisualEffects, mVisualEffects) |
| && other.mPriorityCalls == mPriorityCalls |
| && other.mPriorityMessages == mPriorityMessages |
| && other.mConversationSenders == mConversationSenders; |
| if (Flags.modesApi()) { |
| return eq && other.mAllowChannels == mAllowChannels; |
| } |
| return eq; |
| } |
| |
| @Override |
| public int hashCode() { |
| if (Flags.modesApi()) { |
| return Objects.hash(mPriorityCategories, mVisualEffects, mPriorityCalls, |
| mPriorityMessages, mConversationSenders, mAllowChannels); |
| } |
| return Objects.hash(mPriorityCategories, mVisualEffects, mPriorityCalls, mPriorityMessages, |
| mConversationSenders); |
| } |
| |
| private @ZenPolicy.State int getZenPolicyPriorityCategoryState(@PriorityCategory int |
| category) { |
| switch (category) { |
| case PRIORITY_CATEGORY_REMINDERS: |
| return getPriorityCategoryReminders(); |
| case PRIORITY_CATEGORY_EVENTS: |
| return getPriorityCategoryEvents(); |
| case PRIORITY_CATEGORY_MESSAGES: |
| return getPriorityCategoryMessages(); |
| case PRIORITY_CATEGORY_CALLS: |
| return getPriorityCategoryCalls(); |
| case PRIORITY_CATEGORY_REPEAT_CALLERS: |
| return getPriorityCategoryRepeatCallers(); |
| case PRIORITY_CATEGORY_ALARMS: |
| return getPriorityCategoryAlarms(); |
| case PRIORITY_CATEGORY_MEDIA: |
| return getPriorityCategoryMedia(); |
| case PRIORITY_CATEGORY_SYSTEM: |
| return getPriorityCategorySystem(); |
| case PRIORITY_CATEGORY_CONVERSATIONS: |
| return getPriorityCategoryConversations(); |
| } |
| return -1; |
| } |
| |
| private @ZenPolicy.State int getZenPolicyVisualEffectState(@VisualEffect int effect) { |
| switch (effect) { |
| case VISUAL_EFFECT_FULL_SCREEN_INTENT: |
| return getVisualEffectFullScreenIntent(); |
| case VISUAL_EFFECT_LIGHTS: |
| return getVisualEffectLights(); |
| case VISUAL_EFFECT_PEEK: |
| return getVisualEffectPeek(); |
| case VISUAL_EFFECT_STATUS_BAR: |
| return getVisualEffectStatusBar(); |
| case VISUAL_EFFECT_BADGE: |
| return getVisualEffectBadge(); |
| case VISUAL_EFFECT_AMBIENT: |
| return getVisualEffectAmbient(); |
| case VISUAL_EFFECT_NOTIFICATION_LIST: |
| return getVisualEffectNotificationList(); |
| } |
| return -1; |
| } |
| |
| /** @hide */ |
| public boolean isCategoryAllowed(@PriorityCategory int category, boolean defaultVal) { |
| switch (getZenPolicyPriorityCategoryState(category)) { |
| case ZenPolicy.STATE_ALLOW: |
| return true; |
| case ZenPolicy.STATE_DISALLOW: |
| return false; |
| default: |
| return defaultVal; |
| } |
| } |
| |
| /** @hide */ |
| public boolean isVisualEffectAllowed(@VisualEffect int effect, boolean defaultVal) { |
| switch (getZenPolicyVisualEffectState(effect)) { |
| case ZenPolicy.STATE_ALLOW: |
| return true; |
| case ZenPolicy.STATE_DISALLOW: |
| return false; |
| default: |
| return defaultVal; |
| } |
| } |
| |
| /** |
| * Applies another policy on top of this policy. For each field, the resulting policy will have |
| * most restrictive setting that is set of the two policies (if only one has a field set, the |
| * result will inherit that policy's setting). |
| * |
| * @hide |
| */ |
| public void apply(ZenPolicy policyToApply) { |
| if (policyToApply == null) { |
| return; |
| } |
| |
| // apply priority categories |
| for (int category = 0; category < mPriorityCategories.size(); category++) { |
| if (mPriorityCategories.get(category) == STATE_DISALLOW) { |
| // if a priority category is already disallowed by the policy, cannot allow |
| continue; |
| } |
| |
| @State int newState = policyToApply.mPriorityCategories.get(category); |
| if (newState != STATE_UNSET) { |
| mPriorityCategories.set(category, newState); |
| |
| if (category == PRIORITY_CATEGORY_MESSAGES |
| && mPriorityMessages < policyToApply.mPriorityMessages) { |
| mPriorityMessages = policyToApply.mPriorityMessages; |
| } else if (category == PRIORITY_CATEGORY_CALLS |
| && mPriorityCalls < policyToApply.mPriorityCalls) { |
| mPriorityCalls = policyToApply.mPriorityCalls; |
| } else if (category == PRIORITY_CATEGORY_CONVERSATIONS |
| && mConversationSenders < policyToApply.mConversationSenders) { |
| mConversationSenders = policyToApply.mConversationSenders; |
| } |
| } |
| } |
| |
| // apply visual effects |
| for (int visualEffect = 0; visualEffect < mVisualEffects.size(); visualEffect++) { |
| if (mVisualEffects.get(visualEffect) == STATE_DISALLOW) { |
| // if a visual effect is already disallowed by the policy, cannot allow |
| continue; |
| } |
| |
| if (policyToApply.mVisualEffects.get(visualEffect) != STATE_UNSET) { |
| mVisualEffects.set(visualEffect, policyToApply.mVisualEffects.get(visualEffect)); |
| } |
| } |
| |
| // apply allowed channels |
| if (Flags.modesApi()) { |
| // if no channels are allowed, can't newly allow them |
| if (mAllowChannels != CHANNEL_TYPE_NONE |
| && policyToApply.mAllowChannels != CHANNEL_TYPE_UNSET) { |
| mAllowChannels = policyToApply.mAllowChannels; |
| } |
| } |
| } |
| |
| /** |
| * @hide |
| */ |
| public void dumpDebug(ProtoOutputStream proto, long fieldId) { |
| final long token = proto.start(fieldId); |
| |
| proto.write(ZenPolicyProto.REMINDERS, getPriorityCategoryReminders()); |
| proto.write(ZenPolicyProto.EVENTS, getPriorityCategoryEvents()); |
| proto.write(ZenPolicyProto.MESSAGES, getPriorityCategoryMessages()); |
| proto.write(ZenPolicyProto.CALLS, getPriorityCategoryCalls()); |
| proto.write(ZenPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers()); |
| proto.write(ZenPolicyProto.ALARMS, getPriorityCategoryAlarms()); |
| proto.write(ZenPolicyProto.MEDIA, getPriorityCategoryMedia()); |
| proto.write(ZenPolicyProto.SYSTEM, getPriorityCategorySystem()); |
| |
| proto.write(ZenPolicyProto.FULL_SCREEN_INTENT, getVisualEffectFullScreenIntent()); |
| proto.write(ZenPolicyProto.LIGHTS, getVisualEffectLights()); |
| proto.write(ZenPolicyProto.PEEK, getVisualEffectPeek()); |
| proto.write(ZenPolicyProto.STATUS_BAR, getVisualEffectStatusBar()); |
| proto.write(ZenPolicyProto.BADGE, getVisualEffectBadge()); |
| proto.write(ZenPolicyProto.AMBIENT, getVisualEffectAmbient()); |
| proto.write(ZenPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList()); |
| |
| proto.write(ZenPolicyProto.PRIORITY_MESSAGES, getPriorityMessageSenders()); |
| proto.write(ZenPolicyProto.PRIORITY_CALLS, getPriorityCallSenders()); |
| proto.end(token); |
| } |
| |
| /** |
| * Converts a policy to a statsd proto. |
| * @hide |
| */ |
| public byte[] toProto() { |
| // TODO: b/308672510 - log user-customized ZenPolicy fields to DNDPolicyProto. |
| ByteArrayOutputStream bytes = new ByteArrayOutputStream(); |
| ProtoOutputStream proto = new ProtoOutputStream(bytes); |
| |
| proto.write(DNDPolicyProto.CALLS, getPriorityCategoryCalls()); |
| proto.write(DNDPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers()); |
| proto.write(DNDPolicyProto.MESSAGES, getPriorityCategoryMessages()); |
| proto.write(DNDPolicyProto.CONVERSATIONS, getPriorityCategoryConversations()); |
| proto.write(DNDPolicyProto.REMINDERS, getPriorityCategoryReminders()); |
| proto.write(DNDPolicyProto.EVENTS, getPriorityCategoryEvents()); |
| proto.write(DNDPolicyProto.ALARMS, getPriorityCategoryAlarms()); |
| proto.write(DNDPolicyProto.MEDIA, getPriorityCategoryMedia()); |
| proto.write(DNDPolicyProto.SYSTEM, getPriorityCategorySystem()); |
| |
| proto.write(DNDPolicyProto.FULLSCREEN, getVisualEffectFullScreenIntent()); |
| proto.write(DNDPolicyProto.LIGHTS, getVisualEffectLights()); |
| proto.write(DNDPolicyProto.PEEK, getVisualEffectPeek()); |
| proto.write(DNDPolicyProto.STATUS_BAR, getVisualEffectStatusBar()); |
| proto.write(DNDPolicyProto.BADGE, getVisualEffectBadge()); |
| proto.write(DNDPolicyProto.AMBIENT, getVisualEffectAmbient()); |
| proto.write(DNDPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList()); |
| |
| proto.write(DNDPolicyProto.ALLOW_CALLS_FROM, getPriorityCallSenders()); |
| proto.write(DNDPolicyProto.ALLOW_MESSAGES_FROM, getPriorityMessageSenders()); |
| proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, getPriorityConversationSenders()); |
| |
| if (Flags.modesApi()) { |
| proto.write(DNDPolicyProto.ALLOW_CHANNELS, getAllowedChannels()); |
| } |
| |
| proto.flush(); |
| return bytes.toByteArray(); |
| } |
| |
| /** |
| * Makes deep copy of this ZenPolicy. |
| * @hide |
| */ |
| public @NonNull ZenPolicy copy() { |
| final Parcel parcel = Parcel.obtain(); |
| try { |
| writeToParcel(parcel, 0); |
| parcel.setDataPosition(0); |
| return CREATOR.createFromParcel(parcel); |
| } finally { |
| parcel.recycle(); |
| } |
| } |
| } |