blob: 96949985cb847bdbfc5a4d5fd1c979c6d025b3d7 [file] [log] [blame]
/*
* 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.IntDef;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationChannel;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.proto.ProtoOutputStream;
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;
/** @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,
})
@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 */
@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;
/** @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 = { "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 */
public ZenPolicy() {
mPriorityCategories = new ArrayList<>(Collections.nCopies(8, 0));
mVisualEffects = new ArrayList<>(Collections.nCopies(7, 0));
}
/**
* 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 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);
}
/**
* 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;
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;
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 = STATE_UNSET;
} else if (category == PRIORITY_CATEGORY_CALLS) {
mZenPolicy.mPriorityCalls = STATE_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 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;
}
}
@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);
}
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 = source.readArrayList(Integer.class.getClassLoader());
policy.mVisualEffects = source.readArrayList(Integer.class.getClassLoader());
policy.mPriorityCalls = source.readInt();
policy.mPriorityMessages = source.readInt();
return policy;
}
@Override
public ZenPolicy[] newArray(int size) {
return new ZenPolicy[size];
}
};
@Override
public String toString() {
return new StringBuilder(ZenPolicy.class.getSimpleName())
.append('{')
.append("priorityCategories=[").append(priorityCategoriesToString())
.append("], visualEffects=[").append(visualEffectsToString())
.append("], priorityCalls=").append(peopleTypeToString(mPriorityCalls))
.append(", priorityMessages=").append(peopleTypeToString(mPriorityMessages))
.append('}')
.toString();
}
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";
}
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 + "}";
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ZenPolicy)) return false;
if (o == this) return true;
final ZenPolicy other = (ZenPolicy) o;
return Objects.equals(other.mPriorityCategories, mPriorityCategories)
&& Objects.equals(other.mVisualEffects, mVisualEffects)
&& other.mPriorityCalls == mPriorityCalls
&& other.mPriorityMessages == mPriorityMessages;
}
@Override
public int hashCode() {
return Objects.hash(mPriorityCategories, mVisualEffects, mPriorityCalls, mPriorityMessages);
}
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();
}
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
* @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;
}
}
}
// 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));
}
}
}
/**
* @hide
*/
public void writeToProto(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);
}
/**
* 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();
}
}
}