1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.service.notification; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.Notification; 23 import android.app.NotificationChannel; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.util.proto.ProtoOutputStream; 27 28 import java.io.ByteArrayOutputStream; 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.util.ArrayList; 32 import java.util.Collections; 33 import java.util.Objects; 34 35 /** 36 * ZenPolicy determines whether to allow certain notifications and their corresponding sounds to 37 * play when a device is in Do Not Disturb mode. 38 * ZenPolicy also dictates the visual effects of notifications that are intercepted when 39 * a device is in Do Not Disturb mode. 40 */ 41 public final class ZenPolicy implements Parcelable { 42 private ArrayList<Integer> mPriorityCategories; 43 private ArrayList<Integer> mVisualEffects; 44 private @PeopleType int mPriorityMessages = PEOPLE_TYPE_UNSET; 45 private @PeopleType int mPriorityCalls = PEOPLE_TYPE_UNSET; 46 private @ConversationSenders int mConversationSenders = CONVERSATION_SENDERS_UNSET; 47 48 /** @hide */ 49 @IntDef(prefix = { "PRIORITY_CATEGORY_" }, value = { 50 PRIORITY_CATEGORY_REMINDERS, 51 PRIORITY_CATEGORY_EVENTS, 52 PRIORITY_CATEGORY_MESSAGES, 53 PRIORITY_CATEGORY_CALLS, 54 PRIORITY_CATEGORY_REPEAT_CALLERS, 55 PRIORITY_CATEGORY_ALARMS, 56 PRIORITY_CATEGORY_MEDIA, 57 PRIORITY_CATEGORY_SYSTEM, 58 PRIORITY_CATEGORY_CONVERSATIONS, 59 }) 60 @Retention(RetentionPolicy.SOURCE) 61 public @interface PriorityCategory {} 62 63 /** @hide */ 64 public static final int PRIORITY_CATEGORY_REMINDERS = 0; 65 /** @hide */ 66 public static final int PRIORITY_CATEGORY_EVENTS = 1; 67 /** @hide */ 68 public static final int PRIORITY_CATEGORY_MESSAGES = 2; 69 /** @hide */ 70 public static final int PRIORITY_CATEGORY_CALLS = 3; 71 /** @hide */ 72 public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 4; 73 /** @hide */ 74 public static final int PRIORITY_CATEGORY_ALARMS = 5; 75 /** @hide */ 76 public static final int PRIORITY_CATEGORY_MEDIA = 6; 77 /** @hide */ 78 public static final int PRIORITY_CATEGORY_SYSTEM = 7; 79 /** @hide */ 80 public static final int PRIORITY_CATEGORY_CONVERSATIONS = 8; 81 82 /** 83 * Total number of priority categories. Keep updated with any updates to PriorityCategory enum. 84 * @hide 85 */ 86 public static final int NUM_PRIORITY_CATEGORIES = 9; 87 88 /** @hide */ 89 @IntDef(prefix = { "VISUAL_EFFECT_" }, value = { 90 VISUAL_EFFECT_FULL_SCREEN_INTENT, 91 VISUAL_EFFECT_LIGHTS, 92 VISUAL_EFFECT_PEEK, 93 VISUAL_EFFECT_STATUS_BAR, 94 VISUAL_EFFECT_BADGE, 95 VISUAL_EFFECT_AMBIENT, 96 VISUAL_EFFECT_NOTIFICATION_LIST, 97 }) 98 @Retention(RetentionPolicy.SOURCE) 99 public @interface VisualEffect {} 100 101 /** @hide */ 102 public static final int VISUAL_EFFECT_FULL_SCREEN_INTENT = 0; 103 /** @hide */ 104 public static final int VISUAL_EFFECT_LIGHTS = 1; 105 /** @hide */ 106 public static final int VISUAL_EFFECT_PEEK = 2; 107 /** @hide */ 108 public static final int VISUAL_EFFECT_STATUS_BAR = 3; 109 /** @hide */ 110 public static final int VISUAL_EFFECT_BADGE = 4; 111 /** @hide */ 112 public static final int VISUAL_EFFECT_AMBIENT = 5; 113 /** @hide */ 114 public static final int VISUAL_EFFECT_NOTIFICATION_LIST = 6; 115 116 /** 117 * Total number of visual effects. Keep updated with any updates to VisualEffect enum. 118 * @hide 119 */ 120 public static final int NUM_VISUAL_EFFECTS = 7; 121 122 /** @hide */ 123 @IntDef(prefix = { "PEOPLE_TYPE_" }, value = { 124 PEOPLE_TYPE_UNSET, 125 PEOPLE_TYPE_ANYONE, 126 PEOPLE_TYPE_CONTACTS, 127 PEOPLE_TYPE_STARRED, 128 PEOPLE_TYPE_NONE, 129 }) 130 @Retention(RetentionPolicy.SOURCE) 131 public @interface PeopleType {} 132 133 /** 134 * Used to indicate no preference for the type of people that can bypass dnd for either 135 * calls or messages. 136 */ 137 public static final int PEOPLE_TYPE_UNSET = 0; 138 139 /** 140 * Used to indicate all calls or messages can bypass dnd. 141 */ 142 public static final int PEOPLE_TYPE_ANYONE = 1; 143 144 /** 145 * Used to indicate calls or messages from contacts can bypass dnd. 146 */ 147 public static final int PEOPLE_TYPE_CONTACTS = 2; 148 149 /** 150 * Used to indicate calls or messages from starred contacts can bypass dnd. 151 */ 152 public static final int PEOPLE_TYPE_STARRED = 3; 153 154 /** 155 * Used to indicate no calls or messages can bypass dnd. 156 */ 157 public static final int PEOPLE_TYPE_NONE = 4; 158 159 160 /** @hide */ 161 @IntDef(prefix = { "CONVERSATION_SENDERS_" }, value = { 162 CONVERSATION_SENDERS_UNSET, 163 CONVERSATION_SENDERS_ANYONE, 164 CONVERSATION_SENDERS_IMPORTANT, 165 CONVERSATION_SENDERS_NONE, 166 }) 167 @Retention(RetentionPolicy.SOURCE) 168 public @interface ConversationSenders {} 169 170 /** 171 * Used to indicate no preference for the type of conversations that can bypass dnd. 172 */ 173 public static final int CONVERSATION_SENDERS_UNSET = 0; 174 175 /** 176 * Used to indicate all conversations can bypass dnd. 177 */ 178 public static final int CONVERSATION_SENDERS_ANYONE = 1; 179 180 /** 181 * Used to indicate important conversations can bypass dnd. 182 */ 183 public static final int CONVERSATION_SENDERS_IMPORTANT = 2; 184 185 /** 186 * Used to indicate no conversations can bypass dnd. 187 */ 188 public static final int CONVERSATION_SENDERS_NONE = 3; 189 190 /** @hide */ 191 @IntDef(prefix = { "STATE_" }, value = { 192 STATE_UNSET, 193 STATE_ALLOW, 194 STATE_DISALLOW, 195 }) 196 @Retention(RetentionPolicy.SOURCE) 197 public @interface State {} 198 199 /** 200 * Indicates no preference for whether a type of sound or visual effect is or isn't allowed 201 * to play/show when DND is active. Will default to the current set policy. 202 */ 203 public static final int STATE_UNSET = 0; 204 205 /** 206 * Indicates a type of sound or visual effect is allowed to play/show when DND is active. 207 */ 208 public static final int STATE_ALLOW = 1; 209 210 /** 211 * Indicates a type of sound or visual effect is not allowed to play/show when DND is active. 212 */ 213 public static final int STATE_DISALLOW = 2; 214 215 /** @hide */ ZenPolicy()216 public ZenPolicy() { 217 mPriorityCategories = new ArrayList<>(Collections.nCopies(NUM_PRIORITY_CATEGORIES, 0)); 218 mVisualEffects = new ArrayList<>(Collections.nCopies(NUM_VISUAL_EFFECTS, 0)); 219 } 220 221 /** 222 * Conversation type that can bypass DND. 223 * @return {@link #CONVERSATION_SENDERS_UNSET}, {@link #CONVERSATION_SENDERS_ANYONE}, 224 * {@link #CONVERSATION_SENDERS_IMPORTANT}, {@link #CONVERSATION_SENDERS_NONE}. 225 */ getPriorityConversationSenders()226 public @PeopleType int getPriorityConversationSenders() { 227 return mConversationSenders; 228 } 229 230 /** 231 * Message senders that can bypass DND. 232 * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE}, 233 * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE} 234 */ getPriorityMessageSenders()235 public @PeopleType int getPriorityMessageSenders() { 236 return mPriorityMessages; 237 } 238 239 /** 240 * Callers that can bypass DND. 241 * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE}, 242 * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE} 243 */ getPriorityCallSenders()244 public @PeopleType int getPriorityCallSenders() { 245 return mPriorityCalls; 246 } 247 248 /** 249 * Whether this policy wants to allow conversation notifications 250 * (see {@link NotificationChannel#getConversationId()}) to play sounds and visually appear 251 * or to intercept them when DND is active. 252 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 253 */ getPriorityCategoryConversations()254 public @State int getPriorityCategoryConversations() { 255 return mPriorityCategories.get(PRIORITY_CATEGORY_CONVERSATIONS); 256 } 257 258 /** 259 * Whether this policy wants to allow notifications with category 260 * {@link Notification#CATEGORY_REMINDER} to play sounds and visually appear 261 * or to intercept them when DND is active. 262 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 263 */ getPriorityCategoryReminders()264 public @State int getPriorityCategoryReminders() { 265 return mPriorityCategories.get(PRIORITY_CATEGORY_REMINDERS); 266 } 267 268 /** 269 * Whether this policy wants to allow notifications with category 270 * {@link Notification#CATEGORY_EVENT} to play sounds and visually appear 271 * or to intercept them when DND is active. 272 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 273 */ getPriorityCategoryEvents()274 public @State int getPriorityCategoryEvents() { 275 return mPriorityCategories.get(PRIORITY_CATEGORY_EVENTS); 276 } 277 278 /** 279 * Whether this policy wants to allow notifications with category 280 * {@link Notification#CATEGORY_MESSAGE} to play sounds and visually appear 281 * or to intercept them when DND is active. Types of message senders that are allowed 282 * are specified by {@link #getPriorityMessageSenders}. 283 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 284 */ getPriorityCategoryMessages()285 public @State int getPriorityCategoryMessages() { 286 return mPriorityCategories.get(PRIORITY_CATEGORY_MESSAGES); 287 } 288 289 /** 290 * Whether this policy wants to allow notifications with category 291 * {@link Notification#CATEGORY_CALL} to play sounds and visually appear 292 * or to intercept them when DND is active. Types of callers that are allowed 293 * are specified by {@link #getPriorityCallSenders()}. 294 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 295 */ getPriorityCategoryCalls()296 public @State int getPriorityCategoryCalls() { 297 return mPriorityCategories.get(PRIORITY_CATEGORY_CALLS); 298 } 299 300 /** 301 * Whether this policy wants to allow repeat callers (notifications with category 302 * {@link Notification#CATEGORY_CALL} that have recently called) to play sounds and 303 * visually appear or to intercept them when DND is active. 304 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 305 */ getPriorityCategoryRepeatCallers()306 public @State int getPriorityCategoryRepeatCallers() { 307 return mPriorityCategories.get(PRIORITY_CATEGORY_REPEAT_CALLERS); 308 } 309 310 /** 311 * Whether this policy wants to allow notifications with category 312 * {@link Notification#CATEGORY_ALARM} to play sounds and visually appear 313 * or to intercept them when DND is active. 314 * When alarms are {@link #STATE_DISALLOW disallowed}, the alarm stream will be muted when DND 315 * is active. 316 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 317 */ getPriorityCategoryAlarms()318 public @State int getPriorityCategoryAlarms() { 319 return mPriorityCategories.get(PRIORITY_CATEGORY_ALARMS); 320 } 321 322 /** 323 * Whether this policy wants to allow media notifications to play sounds and visually appear 324 * or to intercept them when DND is active. 325 * When media is {@link #STATE_DISALLOW disallowed}, the media stream will be muted when DND is 326 * active. 327 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 328 */ getPriorityCategoryMedia()329 public @State int getPriorityCategoryMedia() { 330 return mPriorityCategories.get(PRIORITY_CATEGORY_MEDIA); 331 } 332 333 /** 334 * Whether this policy wants to allow system sounds when DND is active. 335 * When system is {@link #STATE_DISALLOW}, the system stream will be muted when DND is active. 336 * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW} 337 */ getPriorityCategorySystem()338 public @State int getPriorityCategorySystem() { 339 return mPriorityCategories.get(PRIORITY_CATEGORY_SYSTEM); 340 } 341 342 /** 343 * Whether this policy allows {@link Notification#fullScreenIntent full screen intents} from 344 * notifications intercepted by DND. 345 */ getVisualEffectFullScreenIntent()346 public @State int getVisualEffectFullScreenIntent() { 347 return mVisualEffects.get(VISUAL_EFFECT_FULL_SCREEN_INTENT); 348 } 349 350 /** 351 * Whether this policy allows {@link NotificationChannel#shouldShowLights() notification 352 * lights} from notifications intercepted by DND. 353 */ getVisualEffectLights()354 public @State int getVisualEffectLights() { 355 return mVisualEffects.get(VISUAL_EFFECT_LIGHTS); 356 } 357 358 /** 359 * Whether this policy allows peeking from notifications intercepted by DND. 360 */ getVisualEffectPeek()361 public @State int getVisualEffectPeek() { 362 return mVisualEffects.get(VISUAL_EFFECT_PEEK); 363 } 364 365 /** 366 * Whether this policy allows notifications intercepted by DND from appearing in the status bar 367 * on devices that support status bars. 368 */ getVisualEffectStatusBar()369 public @State int getVisualEffectStatusBar() { 370 return mVisualEffects.get(VISUAL_EFFECT_STATUS_BAR); 371 } 372 373 /** 374 * Whether this policy allows {@link NotificationChannel#canShowBadge() badges} from 375 * notifications intercepted by DND on devices that support badging. 376 */ getVisualEffectBadge()377 public @State int getVisualEffectBadge() { 378 return mVisualEffects.get(VISUAL_EFFECT_BADGE); 379 } 380 381 /** 382 * Whether this policy allows notifications intercepted by DND from appearing on ambient 383 * displays on devices that support ambient display. 384 */ getVisualEffectAmbient()385 public @State int getVisualEffectAmbient() { 386 return mVisualEffects.get(VISUAL_EFFECT_AMBIENT); 387 } 388 389 /** 390 * Whether this policy allows notifications intercepted by DND from appearing in notification 391 * list views like the notification shade or lockscreen on devices that support those 392 * views. 393 */ getVisualEffectNotificationList()394 public @State int getVisualEffectNotificationList() { 395 return mVisualEffects.get(VISUAL_EFFECT_NOTIFICATION_LIST); 396 } 397 398 /** 399 * Whether this policy hides all visual effects 400 * @hide 401 */ shouldHideAllVisualEffects()402 public boolean shouldHideAllVisualEffects() { 403 for (int i = 0; i < mVisualEffects.size(); i++) { 404 if (mVisualEffects.get(i) != STATE_DISALLOW) { 405 return false; 406 } 407 } 408 return true; 409 } 410 411 /** 412 * Whether this policy shows all visual effects 413 * @hide 414 */ shouldShowAllVisualEffects()415 public boolean shouldShowAllVisualEffects() { 416 for (int i = 0; i < mVisualEffects.size(); i++) { 417 if (mVisualEffects.get(i) != STATE_ALLOW) { 418 return false; 419 } 420 } 421 return true; 422 } 423 424 /** 425 * Builder class for {@link ZenPolicy} objects. 426 * Provides a convenient way to set the various fields of a {@link ZenPolicy}. If a field 427 * is not set, it is (@link STATE_UNSET} and will not change the current set policy. 428 */ 429 public static final class Builder { 430 private ZenPolicy mZenPolicy; 431 Builder()432 public Builder() { 433 mZenPolicy = new ZenPolicy(); 434 } 435 436 /** 437 * @hide 438 */ Builder(ZenPolicy policy)439 public Builder(ZenPolicy policy) { 440 if (policy != null) { 441 mZenPolicy = policy.copy(); 442 } else { 443 mZenPolicy = new ZenPolicy(); 444 } 445 } 446 447 /** 448 * Builds the current ZenPolicy. 449 */ build()450 public @NonNull ZenPolicy build() { 451 return mZenPolicy.copy(); 452 } 453 454 /** 455 * Allows all notifications to bypass DND and unmutes all streams. 456 */ allowAllSounds()457 public @NonNull Builder allowAllSounds() { 458 for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) { 459 mZenPolicy.mPriorityCategories.set(i, STATE_ALLOW); 460 } 461 mZenPolicy.mPriorityMessages = PEOPLE_TYPE_ANYONE; 462 mZenPolicy.mPriorityCalls = PEOPLE_TYPE_ANYONE; 463 mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_ANYONE; 464 return this; 465 } 466 467 /** 468 * Intercepts all notifications and prevents them from playing sounds 469 * when DND is active. Also mutes alarm, system and media streams. 470 * Notification channels can still play sounds only if they 471 * {@link NotificationChannel#canBypassDnd can bypass DND}. If no channels can bypass DND, 472 * the ringer stream is also muted. 473 */ disallowAllSounds()474 public @NonNull Builder disallowAllSounds() { 475 for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) { 476 mZenPolicy.mPriorityCategories.set(i, STATE_DISALLOW); 477 } 478 mZenPolicy.mPriorityMessages = PEOPLE_TYPE_NONE; 479 mZenPolicy.mPriorityCalls = PEOPLE_TYPE_NONE; 480 mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_NONE; 481 return this; 482 } 483 484 /** 485 * Allows notifications intercepted by DND to show on all surfaces when DND is active. 486 */ showAllVisualEffects()487 public @NonNull Builder showAllVisualEffects() { 488 for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) { 489 mZenPolicy.mVisualEffects.set(i, STATE_ALLOW); 490 } 491 return this; 492 } 493 494 /** 495 * Disallows notifications intercepted by DND from showing when DND is active. 496 */ hideAllVisualEffects()497 public @NonNull Builder hideAllVisualEffects() { 498 for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) { 499 mZenPolicy.mVisualEffects.set(i, STATE_DISALLOW); 500 } 501 return this; 502 } 503 504 /** 505 * Unsets a priority category, neither allowing or disallowing. When applying this policy, 506 * unset categories will default to the current applied policy. 507 * @hide 508 */ unsetPriorityCategory(@riorityCategory int category)509 public @NonNull Builder unsetPriorityCategory(@PriorityCategory int category) { 510 mZenPolicy.mPriorityCategories.set(category, STATE_UNSET); 511 512 if (category == PRIORITY_CATEGORY_MESSAGES) { 513 mZenPolicy.mPriorityMessages = PEOPLE_TYPE_UNSET; 514 } else if (category == PRIORITY_CATEGORY_CALLS) { 515 mZenPolicy.mPriorityCalls = PEOPLE_TYPE_UNSET; 516 } else if (category == PRIORITY_CATEGORY_CONVERSATIONS) { 517 mZenPolicy.mConversationSenders = CONVERSATION_SENDERS_UNSET; 518 } 519 520 return this; 521 } 522 523 /** 524 * Unsets a visual effect, neither allowing or disallowing. When applying this policy, 525 * unset effects will default to the current applied policy. 526 * @hide 527 */ unsetVisualEffect(@isualEffect int effect)528 public @NonNull Builder unsetVisualEffect(@VisualEffect int effect) { 529 mZenPolicy.mVisualEffects.set(effect, STATE_UNSET); 530 return this; 531 } 532 533 /** 534 * Whether to allow notifications with category {@link Notification#CATEGORY_REMINDER} 535 * to play sounds and visually appear or to intercept them when DND is active. 536 */ allowReminders(boolean allow)537 public @NonNull Builder allowReminders(boolean allow) { 538 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REMINDERS, 539 allow ? STATE_ALLOW : STATE_DISALLOW); 540 return this; 541 } 542 543 /** 544 * Whether to allow notifications with category {@link Notification#CATEGORY_EVENT} 545 * to play sounds and visually appear or to intercept them when DND is active. 546 */ allowEvents(boolean allow)547 public @NonNull Builder allowEvents(boolean allow) { 548 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_EVENTS, 549 allow ? STATE_ALLOW : STATE_DISALLOW); 550 return this; 551 } 552 553 /** 554 * Whether to allow conversation notifications 555 * (see {@link NotificationChannel#setConversationId(String, String)}) 556 * that match audienceType to play sounds and visually appear or to intercept 557 * them when DND is active. 558 * @param audienceType callers that are allowed to bypass DND 559 */ allowConversations(@onversationSenders int audienceType)560 public @NonNull Builder allowConversations(@ConversationSenders int audienceType) { 561 if (audienceType == STATE_UNSET) { 562 return unsetPriorityCategory(PRIORITY_CATEGORY_CONVERSATIONS); 563 } 564 565 if (audienceType == CONVERSATION_SENDERS_NONE) { 566 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CONVERSATIONS, STATE_DISALLOW); 567 } else if (audienceType == CONVERSATION_SENDERS_ANYONE 568 || audienceType == CONVERSATION_SENDERS_IMPORTANT) { 569 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CONVERSATIONS, STATE_ALLOW); 570 } else { 571 return this; 572 } 573 574 mZenPolicy.mConversationSenders = audienceType; 575 return this; 576 } 577 578 /** 579 * Whether to allow notifications with category {@link Notification#CATEGORY_MESSAGE} 580 * that match audienceType to play sounds and visually appear or to intercept 581 * them when DND is active. 582 * @param audienceType message senders that are allowed to bypass DND 583 */ allowMessages(@eopleType int audienceType)584 public @NonNull Builder allowMessages(@PeopleType int audienceType) { 585 if (audienceType == STATE_UNSET) { 586 return unsetPriorityCategory(PRIORITY_CATEGORY_MESSAGES); 587 } 588 589 if (audienceType == PEOPLE_TYPE_NONE) { 590 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_DISALLOW); 591 } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS 592 || audienceType == PEOPLE_TYPE_STARRED) { 593 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_ALLOW); 594 } else { 595 return this; 596 } 597 598 mZenPolicy.mPriorityMessages = audienceType; 599 return this; 600 } 601 602 /** 603 * Whether to allow notifications with category {@link Notification#CATEGORY_CALL} 604 * that match audienceType to play sounds and visually appear or to intercept 605 * them when DND is active. 606 * @param audienceType callers that are allowed to bypass DND 607 */ allowCalls(@eopleType int audienceType)608 public @NonNull Builder allowCalls(@PeopleType int audienceType) { 609 if (audienceType == STATE_UNSET) { 610 return unsetPriorityCategory(PRIORITY_CATEGORY_CALLS); 611 } 612 613 if (audienceType == PEOPLE_TYPE_NONE) { 614 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_DISALLOW); 615 } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS 616 || audienceType == PEOPLE_TYPE_STARRED) { 617 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_ALLOW); 618 } else { 619 return this; 620 } 621 622 mZenPolicy.mPriorityCalls = audienceType; 623 return this; 624 } 625 626 /** 627 * Whether to allow repeat callers (notifications with category 628 * {@link Notification#CATEGORY_CALL} that have recently called 629 * to play sounds and visually appear. 630 */ allowRepeatCallers(boolean allow)631 public @NonNull Builder allowRepeatCallers(boolean allow) { 632 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REPEAT_CALLERS, 633 allow ? STATE_ALLOW : STATE_DISALLOW); 634 return this; 635 } 636 637 /** 638 * Whether to allow notifications with category {@link Notification#CATEGORY_ALARM} 639 * to play sounds and visually appear or to intercept them when DND is active. 640 * Disallowing alarms will mute the alarm stream when DND is active. 641 */ allowAlarms(boolean allow)642 public @NonNull Builder allowAlarms(boolean allow) { 643 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_ALARMS, 644 allow ? STATE_ALLOW : STATE_DISALLOW); 645 return this; 646 } 647 648 /** 649 * Whether to allow media notifications to play sounds and visually 650 * appear or to intercept them when DND is active. 651 * Disallowing media will mute the media stream when DND is active. 652 */ allowMedia(boolean allow)653 public @NonNull Builder allowMedia(boolean allow) { 654 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MEDIA, 655 allow ? STATE_ALLOW : STATE_DISALLOW); 656 return this; 657 } 658 659 /** 660 * Whether to allow system sounds to play when DND is active. 661 * Disallowing system sounds will mute the system stream when DND is active. 662 */ allowSystem(boolean allow)663 public @NonNull Builder allowSystem(boolean allow) { 664 mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_SYSTEM, 665 allow ? STATE_ALLOW : STATE_DISALLOW); 666 return this; 667 } 668 669 /** 670 * Whether to allow {@link PriorityCategory} sounds to play when DND is active. 671 * @hide 672 */ allowCategory(@riorityCategory int category, boolean allow)673 public @NonNull Builder allowCategory(@PriorityCategory int category, boolean allow) { 674 switch (category) { 675 case PRIORITY_CATEGORY_ALARMS: 676 allowAlarms(allow); 677 break; 678 case PRIORITY_CATEGORY_MEDIA: 679 allowMedia(allow); 680 break; 681 case PRIORITY_CATEGORY_SYSTEM: 682 allowSystem(allow); 683 break; 684 case PRIORITY_CATEGORY_REMINDERS: 685 allowReminders(allow); 686 break; 687 case PRIORITY_CATEGORY_EVENTS: 688 allowEvents(allow); 689 break; 690 case PRIORITY_CATEGORY_REPEAT_CALLERS: 691 allowRepeatCallers(allow); 692 break; 693 } 694 return this; 695 } 696 697 /** 698 * Whether {@link Notification#fullScreenIntent full screen intents} that are intercepted 699 * by DND are shown. 700 */ showFullScreenIntent(boolean show)701 public @NonNull Builder showFullScreenIntent(boolean show) { 702 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_FULL_SCREEN_INTENT, 703 show ? STATE_ALLOW : STATE_DISALLOW); 704 return this; 705 } 706 707 /** 708 * Whether {@link NotificationChannel#shouldShowLights() notification lights} from 709 * notifications intercepted by DND are blocked. 710 */ showLights(boolean show)711 public @NonNull Builder showLights(boolean show) { 712 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_LIGHTS, 713 show ? STATE_ALLOW : STATE_DISALLOW); 714 return this; 715 } 716 717 /** 718 * Whether notifications intercepted by DND are prevented from peeking. 719 */ showPeeking(boolean show)720 public @NonNull Builder showPeeking(boolean show) { 721 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_PEEK, 722 show ? STATE_ALLOW : STATE_DISALLOW); 723 return this; 724 } 725 726 /** 727 * Whether notifications intercepted by DND are prevented from appearing in the status bar 728 * on devices that support status bars. 729 */ showStatusBarIcons(boolean show)730 public @NonNull Builder showStatusBarIcons(boolean show) { 731 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_STATUS_BAR, 732 show ? STATE_ALLOW : STATE_DISALLOW); 733 return this; 734 } 735 736 /** 737 * Whether {@link NotificationChannel#canShowBadge() badges} from 738 * notifications intercepted by DND are allowed on devices that support badging. 739 */ showBadges(boolean show)740 public @NonNull Builder showBadges(boolean show) { 741 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_BADGE, 742 show ? STATE_ALLOW : STATE_DISALLOW); 743 return this; 744 } 745 746 /** 747 * Whether notification intercepted by DND are prevented from appearing on ambient displays 748 * on devices that support ambient display. 749 */ showInAmbientDisplay(boolean show)750 public @NonNull Builder showInAmbientDisplay(boolean show) { 751 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_AMBIENT, 752 show ? STATE_ALLOW : STATE_DISALLOW); 753 return this; 754 } 755 756 /** 757 * Whether notification intercepted by DND are prevented from appearing in notification 758 * list views like the notification shade or lockscreen on devices that support those 759 * views. 760 */ showInNotificationList(boolean show)761 public @NonNull Builder showInNotificationList(boolean show) { 762 mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_NOTIFICATION_LIST, 763 show ? STATE_ALLOW : STATE_DISALLOW); 764 return this; 765 } 766 767 /** 768 * Whether notifications intercepted by DND are prevented from appearing for 769 * {@link VisualEffect} 770 * @hide 771 */ showVisualEffect(@isualEffect int effect, boolean show)772 public @NonNull Builder showVisualEffect(@VisualEffect int effect, boolean show) { 773 switch (effect) { 774 case VISUAL_EFFECT_FULL_SCREEN_INTENT: 775 showFullScreenIntent(show); 776 break; 777 case VISUAL_EFFECT_LIGHTS: 778 showLights(show); 779 break; 780 case VISUAL_EFFECT_PEEK: 781 showPeeking(show); 782 break; 783 case VISUAL_EFFECT_STATUS_BAR: 784 showStatusBarIcons(show); 785 break; 786 case VISUAL_EFFECT_BADGE: 787 showBadges(show); 788 break; 789 case VISUAL_EFFECT_AMBIENT: 790 showInAmbientDisplay(show); 791 break; 792 case VISUAL_EFFECT_NOTIFICATION_LIST: 793 showInNotificationList(show); 794 break; 795 } 796 return this; 797 } 798 } 799 800 @Override describeContents()801 public int describeContents() { 802 return 0; 803 } 804 805 @Override writeToParcel(Parcel dest, int flags)806 public void writeToParcel(Parcel dest, int flags) { 807 dest.writeList(mPriorityCategories); 808 dest.writeList(mVisualEffects); 809 dest.writeInt(mPriorityCalls); 810 dest.writeInt(mPriorityMessages); 811 dest.writeInt(mConversationSenders); 812 } 813 814 public static final @android.annotation.NonNull Parcelable.Creator<ZenPolicy> CREATOR = 815 new Parcelable.Creator<ZenPolicy>() { 816 @Override 817 public ZenPolicy createFromParcel(Parcel source) { 818 ZenPolicy policy = new ZenPolicy(); 819 policy.mPriorityCategories = trimList( 820 source.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class), 821 NUM_PRIORITY_CATEGORIES); 822 policy.mVisualEffects = trimList( 823 source.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class), 824 NUM_VISUAL_EFFECTS); 825 policy.mPriorityCalls = source.readInt(); 826 policy.mPriorityMessages = source.readInt(); 827 policy.mConversationSenders = source.readInt(); 828 return policy; 829 } 830 831 @Override 832 public ZenPolicy[] newArray(int size) { 833 return new ZenPolicy[size]; 834 } 835 }; 836 837 @Override toString()838 public String toString() { 839 return new StringBuilder(ZenPolicy.class.getSimpleName()) 840 .append('{') 841 .append("priorityCategories=[").append(priorityCategoriesToString()) 842 .append("], visualEffects=[").append(visualEffectsToString()) 843 .append("], priorityCallsSenders=").append(peopleTypeToString(mPriorityCalls)) 844 .append(", priorityMessagesSenders=").append(peopleTypeToString(mPriorityMessages)) 845 .append(", priorityConversationSenders=").append( 846 conversationTypeToString(mConversationSenders)) 847 .append('}') 848 .toString(); 849 } 850 851 // Returns a list containing the first maxLength elements of the input list if the list is 852 // longer than that size. For the lists in ZenPolicy, this should not happen unless the input 853 // is corrupt. trimList(ArrayList<Integer> list, int maxLength)854 private static ArrayList<Integer> trimList(ArrayList<Integer> list, int maxLength) { 855 if (list == null || list.size() <= maxLength) { 856 return list; 857 } 858 return new ArrayList<>(list.subList(0, maxLength)); 859 } 860 priorityCategoriesToString()861 private String priorityCategoriesToString() { 862 StringBuilder builder = new StringBuilder(); 863 for (int i = 0; i < mPriorityCategories.size(); i++) { 864 if (mPriorityCategories.get(i) != STATE_UNSET) { 865 builder.append(indexToCategory(i)) 866 .append("=") 867 .append(stateToString(mPriorityCategories.get(i))) 868 .append(" "); 869 } 870 871 } 872 return builder.toString(); 873 } 874 visualEffectsToString()875 private String visualEffectsToString() { 876 StringBuilder builder = new StringBuilder(); 877 for (int i = 0; i < mVisualEffects.size(); i++) { 878 if (mVisualEffects.get(i) != STATE_UNSET) { 879 builder.append(indexToVisualEffect(i)) 880 .append("=") 881 .append(stateToString(mVisualEffects.get(i))) 882 .append(" "); 883 } 884 885 } 886 return builder.toString(); 887 } 888 indexToVisualEffect(@isualEffect int visualEffectIndex)889 private String indexToVisualEffect(@VisualEffect int visualEffectIndex) { 890 switch (visualEffectIndex) { 891 case VISUAL_EFFECT_FULL_SCREEN_INTENT: 892 return "fullScreenIntent"; 893 case VISUAL_EFFECT_LIGHTS: 894 return "lights"; 895 case VISUAL_EFFECT_PEEK: 896 return "peek"; 897 case VISUAL_EFFECT_STATUS_BAR: 898 return "statusBar"; 899 case VISUAL_EFFECT_BADGE: 900 return "badge"; 901 case VISUAL_EFFECT_AMBIENT: 902 return "ambient"; 903 case VISUAL_EFFECT_NOTIFICATION_LIST: 904 return "notificationList"; 905 } 906 return null; 907 } 908 indexToCategory(@riorityCategory int categoryIndex)909 private String indexToCategory(@PriorityCategory int categoryIndex) { 910 switch (categoryIndex) { 911 case PRIORITY_CATEGORY_REMINDERS: 912 return "reminders"; 913 case PRIORITY_CATEGORY_EVENTS: 914 return "events"; 915 case PRIORITY_CATEGORY_MESSAGES: 916 return "messages"; 917 case PRIORITY_CATEGORY_CALLS: 918 return "calls"; 919 case PRIORITY_CATEGORY_REPEAT_CALLERS: 920 return "repeatCallers"; 921 case PRIORITY_CATEGORY_ALARMS: 922 return "alarms"; 923 case PRIORITY_CATEGORY_MEDIA: 924 return "media"; 925 case PRIORITY_CATEGORY_SYSTEM: 926 return "system"; 927 case PRIORITY_CATEGORY_CONVERSATIONS: 928 return "convs"; 929 } 930 return null; 931 } 932 stateToString(@tate int state)933 private String stateToString(@State int state) { 934 switch (state) { 935 case STATE_UNSET: 936 return "unset"; 937 case STATE_DISALLOW: 938 return "disallow"; 939 case STATE_ALLOW: 940 return "allow"; 941 } 942 return "invalidState{" + state + "}"; 943 } 944 peopleTypeToString(@eopleType int peopleType)945 private String peopleTypeToString(@PeopleType int peopleType) { 946 switch (peopleType) { 947 case PEOPLE_TYPE_ANYONE: 948 return "anyone"; 949 case PEOPLE_TYPE_CONTACTS: 950 return "contacts"; 951 case PEOPLE_TYPE_NONE: 952 return "none"; 953 case PEOPLE_TYPE_STARRED: 954 return "starred_contacts"; 955 case STATE_UNSET: 956 return "unset"; 957 } 958 return "invalidPeopleType{" + peopleType + "}"; 959 } 960 961 /** 962 * @hide 963 */ conversationTypeToString(@onversationSenders int conversationType)964 public static String conversationTypeToString(@ConversationSenders int conversationType) { 965 switch (conversationType) { 966 case CONVERSATION_SENDERS_ANYONE: 967 return "anyone"; 968 case CONVERSATION_SENDERS_IMPORTANT: 969 return "important"; 970 case CONVERSATION_SENDERS_NONE: 971 return "none"; 972 case CONVERSATION_SENDERS_UNSET: 973 return "unset"; 974 } 975 return "invalidConversationType{" + conversationType + "}"; 976 } 977 978 @Override equals(@ullable Object o)979 public boolean equals(@Nullable Object o) { 980 if (!(o instanceof ZenPolicy)) return false; 981 if (o == this) return true; 982 final ZenPolicy other = (ZenPolicy) o; 983 984 return Objects.equals(other.mPriorityCategories, mPriorityCategories) 985 && Objects.equals(other.mVisualEffects, mVisualEffects) 986 && other.mPriorityCalls == mPriorityCalls 987 && other.mPriorityMessages == mPriorityMessages 988 && other.mConversationSenders == mConversationSenders; 989 } 990 991 @Override hashCode()992 public int hashCode() { 993 return Objects.hash(mPriorityCategories, mVisualEffects, mPriorityCalls, mPriorityMessages, 994 mConversationSenders); 995 } 996 getZenPolicyPriorityCategoryState(@riorityCategory int category)997 private @ZenPolicy.State int getZenPolicyPriorityCategoryState(@PriorityCategory int 998 category) { 999 switch (category) { 1000 case PRIORITY_CATEGORY_REMINDERS: 1001 return getPriorityCategoryReminders(); 1002 case PRIORITY_CATEGORY_EVENTS: 1003 return getPriorityCategoryEvents(); 1004 case PRIORITY_CATEGORY_MESSAGES: 1005 return getPriorityCategoryMessages(); 1006 case PRIORITY_CATEGORY_CALLS: 1007 return getPriorityCategoryCalls(); 1008 case PRIORITY_CATEGORY_REPEAT_CALLERS: 1009 return getPriorityCategoryRepeatCallers(); 1010 case PRIORITY_CATEGORY_ALARMS: 1011 return getPriorityCategoryAlarms(); 1012 case PRIORITY_CATEGORY_MEDIA: 1013 return getPriorityCategoryMedia(); 1014 case PRIORITY_CATEGORY_SYSTEM: 1015 return getPriorityCategorySystem(); 1016 case PRIORITY_CATEGORY_CONVERSATIONS: 1017 return getPriorityCategoryConversations(); 1018 } 1019 return -1; 1020 } 1021 getZenPolicyVisualEffectState(@isualEffect int effect)1022 private @ZenPolicy.State int getZenPolicyVisualEffectState(@VisualEffect int effect) { 1023 switch (effect) { 1024 case VISUAL_EFFECT_FULL_SCREEN_INTENT: 1025 return getVisualEffectFullScreenIntent(); 1026 case VISUAL_EFFECT_LIGHTS: 1027 return getVisualEffectLights(); 1028 case VISUAL_EFFECT_PEEK: 1029 return getVisualEffectPeek(); 1030 case VISUAL_EFFECT_STATUS_BAR: 1031 return getVisualEffectStatusBar(); 1032 case VISUAL_EFFECT_BADGE: 1033 return getVisualEffectBadge(); 1034 case VISUAL_EFFECT_AMBIENT: 1035 return getVisualEffectAmbient(); 1036 case VISUAL_EFFECT_NOTIFICATION_LIST: 1037 return getVisualEffectNotificationList(); 1038 } 1039 return -1; 1040 } 1041 1042 /** @hide */ isCategoryAllowed(@riorityCategory int category, boolean defaultVal)1043 public boolean isCategoryAllowed(@PriorityCategory int category, boolean defaultVal) { 1044 switch (getZenPolicyPriorityCategoryState(category)) { 1045 case ZenPolicy.STATE_ALLOW: 1046 return true; 1047 case ZenPolicy.STATE_DISALLOW: 1048 return false; 1049 default: 1050 return defaultVal; 1051 } 1052 } 1053 1054 /** @hide */ isVisualEffectAllowed(@isualEffect int effect, boolean defaultVal)1055 public boolean isVisualEffectAllowed(@VisualEffect int effect, boolean defaultVal) { 1056 switch (getZenPolicyVisualEffectState(effect)) { 1057 case ZenPolicy.STATE_ALLOW: 1058 return true; 1059 case ZenPolicy.STATE_DISALLOW: 1060 return false; 1061 default: 1062 return defaultVal; 1063 } 1064 } 1065 1066 /** 1067 * Applies another policy on top of this policy 1068 * @hide 1069 */ apply(ZenPolicy policyToApply)1070 public void apply(ZenPolicy policyToApply) { 1071 if (policyToApply == null) { 1072 return; 1073 } 1074 1075 // apply priority categories 1076 for (int category = 0; category < mPriorityCategories.size(); category++) { 1077 if (mPriorityCategories.get(category) == STATE_DISALLOW) { 1078 // if a priority category is already disallowed by the policy, cannot allow 1079 continue; 1080 } 1081 1082 @State int newState = policyToApply.mPriorityCategories.get(category); 1083 if (newState != STATE_UNSET) { 1084 mPriorityCategories.set(category, newState); 1085 1086 if (category == PRIORITY_CATEGORY_MESSAGES 1087 && mPriorityMessages < policyToApply.mPriorityMessages) { 1088 mPriorityMessages = policyToApply.mPriorityMessages; 1089 } else if (category == PRIORITY_CATEGORY_CALLS 1090 && mPriorityCalls < policyToApply.mPriorityCalls) { 1091 mPriorityCalls = policyToApply.mPriorityCalls; 1092 } else if (category == PRIORITY_CATEGORY_CONVERSATIONS 1093 && mConversationSenders < policyToApply.mConversationSenders) { 1094 mConversationSenders = policyToApply.mConversationSenders; 1095 } 1096 } 1097 } 1098 1099 // apply visual effects 1100 for (int visualEffect = 0; visualEffect < mVisualEffects.size(); visualEffect++) { 1101 if (mVisualEffects.get(visualEffect) == STATE_DISALLOW) { 1102 // if a visual effect is already disallowed by the policy, cannot allow 1103 continue; 1104 } 1105 1106 if (policyToApply.mVisualEffects.get(visualEffect) != STATE_UNSET) { 1107 mVisualEffects.set(visualEffect, policyToApply.mVisualEffects.get(visualEffect)); 1108 } 1109 } 1110 } 1111 1112 /** 1113 * @hide 1114 */ dumpDebug(ProtoOutputStream proto, long fieldId)1115 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 1116 final long token = proto.start(fieldId); 1117 1118 proto.write(ZenPolicyProto.REMINDERS, getPriorityCategoryReminders()); 1119 proto.write(ZenPolicyProto.EVENTS, getPriorityCategoryEvents()); 1120 proto.write(ZenPolicyProto.MESSAGES, getPriorityCategoryMessages()); 1121 proto.write(ZenPolicyProto.CALLS, getPriorityCategoryCalls()); 1122 proto.write(ZenPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers()); 1123 proto.write(ZenPolicyProto.ALARMS, getPriorityCategoryAlarms()); 1124 proto.write(ZenPolicyProto.MEDIA, getPriorityCategoryMedia()); 1125 proto.write(ZenPolicyProto.SYSTEM, getPriorityCategorySystem()); 1126 1127 proto.write(ZenPolicyProto.FULL_SCREEN_INTENT, getVisualEffectFullScreenIntent()); 1128 proto.write(ZenPolicyProto.LIGHTS, getVisualEffectLights()); 1129 proto.write(ZenPolicyProto.PEEK, getVisualEffectPeek()); 1130 proto.write(ZenPolicyProto.STATUS_BAR, getVisualEffectStatusBar()); 1131 proto.write(ZenPolicyProto.BADGE, getVisualEffectBadge()); 1132 proto.write(ZenPolicyProto.AMBIENT, getVisualEffectAmbient()); 1133 proto.write(ZenPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList()); 1134 1135 proto.write(ZenPolicyProto.PRIORITY_MESSAGES, getPriorityMessageSenders()); 1136 proto.write(ZenPolicyProto.PRIORITY_CALLS, getPriorityCallSenders()); 1137 proto.end(token); 1138 } 1139 1140 /** 1141 * Converts a policy to a statsd proto. 1142 * @hides 1143 */ toProto()1144 public byte[] toProto() { 1145 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 1146 ProtoOutputStream proto = new ProtoOutputStream(bytes); 1147 1148 proto.write(DNDPolicyProto.CALLS, getPriorityCategoryCalls()); 1149 proto.write(DNDPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers()); 1150 proto.write(DNDPolicyProto.MESSAGES, getPriorityCategoryMessages()); 1151 proto.write(DNDPolicyProto.CONVERSATIONS, getPriorityCategoryConversations()); 1152 proto.write(DNDPolicyProto.REMINDERS, getPriorityCategoryReminders()); 1153 proto.write(DNDPolicyProto.EVENTS, getPriorityCategoryEvents()); 1154 proto.write(DNDPolicyProto.ALARMS, getPriorityCategoryAlarms()); 1155 proto.write(DNDPolicyProto.MEDIA, getPriorityCategoryMedia()); 1156 proto.write(DNDPolicyProto.SYSTEM, getPriorityCategorySystem()); 1157 1158 proto.write(DNDPolicyProto.FULLSCREEN, getVisualEffectFullScreenIntent()); 1159 proto.write(DNDPolicyProto.LIGHTS, getVisualEffectLights()); 1160 proto.write(DNDPolicyProto.PEEK, getVisualEffectPeek()); 1161 proto.write(DNDPolicyProto.STATUS_BAR, getVisualEffectStatusBar()); 1162 proto.write(DNDPolicyProto.BADGE, getVisualEffectBadge()); 1163 proto.write(DNDPolicyProto.AMBIENT, getVisualEffectAmbient()); 1164 proto.write(DNDPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList()); 1165 1166 proto.write(DNDPolicyProto.ALLOW_CALLS_FROM, getPriorityCallSenders()); 1167 proto.write(DNDPolicyProto.ALLOW_MESSAGES_FROM, getPriorityMessageSenders()); 1168 proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, getPriorityConversationSenders()); 1169 1170 proto.flush(); 1171 return bytes.toByteArray(); 1172 } 1173 1174 /** 1175 * Makes deep copy of this ZenPolicy. 1176 * @hide 1177 */ copy()1178 public @NonNull ZenPolicy copy() { 1179 final Parcel parcel = Parcel.obtain(); 1180 try { 1181 writeToParcel(parcel, 0); 1182 parcel.setDataPosition(0); 1183 return CREATOR.createFromParcel(parcel); 1184 } finally { 1185 parcel.recycle(); 1186 } 1187 } 1188 } 1189