1 /* 2 * Copyright (C) 2017 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.app; 18 19 import static android.app.Notification.CarExtender.UnreadConversation.KEY_ON_READ; 20 import static android.app.Notification.CarExtender.UnreadConversation.KEY_ON_REPLY; 21 import static android.app.Notification.CarExtender.UnreadConversation.KEY_REMOTE_INPUT; 22 import static android.app.Notification.DEFAULT_SOUND; 23 import static android.app.Notification.DEFAULT_VIBRATE; 24 import static android.app.Notification.EXTRA_ANSWER_INTENT; 25 import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO; 26 import static android.app.Notification.EXTRA_CALL_PERSON; 27 import static android.app.Notification.EXTRA_CONVERSATION_ICON; 28 import static android.app.Notification.EXTRA_DECLINE_INTENT; 29 import static android.app.Notification.EXTRA_HANG_UP_INTENT; 30 import static android.app.Notification.EXTRA_LARGE_ICON; 31 import static android.app.Notification.EXTRA_LARGE_ICON_BIG; 32 import static android.app.Notification.EXTRA_MEDIA_REMOTE_INTENT; 33 import static android.app.Notification.EXTRA_MEDIA_SESSION; 34 import static android.app.Notification.EXTRA_MESSAGING_PERSON; 35 import static android.app.Notification.EXTRA_PEOPLE_LIST; 36 import static android.app.Notification.EXTRA_PICTURE; 37 import static android.app.Notification.EXTRA_PICTURE_ICON; 38 import static android.app.Notification.EXTRA_SUMMARY_TEXT; 39 import static android.app.Notification.EXTRA_TITLE; 40 import static android.app.Notification.FLAG_CAN_COLORIZE; 41 import static android.app.Notification.GROUP_ALERT_CHILDREN; 42 import static android.app.Notification.GROUP_ALERT_SUMMARY; 43 import static android.app.Notification.GROUP_KEY_SILENT; 44 import static android.app.Notification.MessagingStyle.Message.KEY_DATA_URI; 45 import static android.app.Notification.MessagingStyle.Message.KEY_SENDER_PERSON; 46 import static android.app.Notification.MessagingStyle.Message.KEY_TEXT; 47 import static android.app.Notification.MessagingStyle.Message.KEY_TIMESTAMP; 48 import static android.app.Notification.TvExtender.EXTRA_CONTENT_INTENT; 49 import static android.app.Notification.TvExtender.EXTRA_DELETE_INTENT; 50 import static android.app.Notification.WearableExtender.KEY_BACKGROUND; 51 import static android.app.Notification.WearableExtender.KEY_DISPLAY_INTENT; 52 53 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 54 import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsAtLeast; 55 import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsWithinRange; 56 57 import static com.google.common.truth.Truth.assertThat; 58 59 import static junit.framework.Assert.assertNotNull; 60 import static junit.framework.Assert.fail; 61 62 import static org.junit.Assert.assertEquals; 63 import static org.junit.Assert.assertFalse; 64 import static org.junit.Assert.assertNotSame; 65 import static org.junit.Assert.assertNull; 66 import static org.junit.Assert.assertSame; 67 import static org.junit.Assert.assertTrue; 68 import static org.mockito.Mockito.mock; 69 import static org.mockito.Mockito.spy; 70 import static org.mockito.Mockito.when; 71 72 import android.annotation.Nullable; 73 import android.compat.testing.PlatformCompatChangeRule; 74 import android.content.Context; 75 import android.content.Intent; 76 import android.content.LocusId; 77 import android.content.res.Configuration; 78 import android.graphics.Bitmap; 79 import android.graphics.BitmapFactory; 80 import android.graphics.Color; 81 import android.graphics.Typeface; 82 import android.graphics.drawable.Icon; 83 import android.net.Uri; 84 import android.os.Build; 85 import android.os.Bundle; 86 import android.os.Parcel; 87 import android.os.Parcelable; 88 import android.platform.test.annotations.DisableFlags; 89 import android.platform.test.annotations.EnableFlags; 90 import android.platform.test.annotations.Presubmit; 91 import android.platform.test.flag.junit.SetFlagsRule; 92 import android.text.Spannable; 93 import android.text.SpannableString; 94 import android.text.SpannableStringBuilder; 95 import android.text.Spanned; 96 import android.text.style.ForegroundColorSpan; 97 import android.text.style.StyleSpan; 98 import android.text.style.TextAppearanceSpan; 99 import android.util.Pair; 100 import android.widget.RemoteViews; 101 102 import androidx.test.InstrumentationRegistry; 103 import androidx.test.ext.junit.runners.AndroidJUnit4; 104 import androidx.test.filters.SmallTest; 105 106 import com.android.internal.R; 107 import com.android.internal.util.ContrastColorUtil; 108 import com.android.internal.widget.NotificationProgressModel; 109 110 import junit.framework.Assert; 111 112 import libcore.junit.util.compat.CoreCompatChangeRule; 113 114 import org.junit.Before; 115 import org.junit.Ignore; 116 import org.junit.Rule; 117 import org.junit.Test; 118 import org.junit.rules.TestRule; 119 import org.junit.runner.RunWith; 120 121 import java.util.Collections; 122 import java.util.List; 123 import java.util.function.Consumer; 124 125 @RunWith(AndroidJUnit4.class) 126 @SmallTest 127 @Presubmit 128 public class NotificationTest { 129 130 private Context mContext; 131 132 private RemoteViews mRemoteViews; 133 134 @Rule 135 public TestRule compatChangeRule = new PlatformCompatChangeRule(); 136 @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 137 138 @Before setUp()139 public void setUp() { 140 mContext = InstrumentationRegistry.getContext(); 141 mRemoteViews = new RemoteViews( 142 mContext.getPackageName(), R.layout.notification_template_header); 143 } 144 145 @Test testColorizedByPermission()146 public void testColorizedByPermission() { 147 Notification n = new Notification.Builder(mContext, "test") 148 .setFlag(FLAG_CAN_COLORIZE, true) 149 .setColorized(true).setColor(Color.WHITE) 150 .build(); 151 assertTrue(n.isColorized()); 152 153 n = new Notification.Builder(mContext, "test") 154 .setFlag(FLAG_CAN_COLORIZE, true) 155 .build(); 156 assertFalse(n.isColorized()); 157 158 n = new Notification.Builder(mContext, "test") 159 .setFlag(FLAG_CAN_COLORIZE, false) 160 .setColorized(true).setColor(Color.WHITE) 161 .build(); 162 assertFalse(n.isColorized()); 163 } 164 165 @Test testColorizedByForeground()166 public void testColorizedByForeground() { 167 Notification n = new Notification.Builder(mContext, "test") 168 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true) 169 .setColorized(true).setColor(Color.WHITE) 170 .build(); 171 assertTrue(n.isColorized()); 172 173 n = new Notification.Builder(mContext, "test") 174 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true) 175 .build(); 176 assertFalse(n.isColorized()); 177 178 n = new Notification.Builder(mContext, "test") 179 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, false) 180 .setColorized(true).setColor(Color.WHITE) 181 .build(); 182 assertFalse(n.isColorized()); 183 } 184 185 @Test testHasCompletedProgress_noProgress()186 public void testHasCompletedProgress_noProgress() { 187 Notification n = new Notification.Builder(mContext).build(); 188 189 assertFalse(n.hasCompletedProgress()); 190 } 191 192 @Test testHasCompletedProgress_complete()193 public void testHasCompletedProgress_complete() { 194 Notification n = new Notification.Builder(mContext) 195 .setProgress(100, 100, true) 196 .build(); 197 Notification n2 = new Notification.Builder(mContext) 198 .setProgress(10, 10, false) 199 .build(); 200 assertTrue(n.hasCompletedProgress()); 201 assertTrue(n2.hasCompletedProgress()); 202 } 203 204 @Test testHasCompletedProgress_notComplete()205 public void testHasCompletedProgress_notComplete() { 206 Notification n = new Notification.Builder(mContext) 207 .setProgress(100, 99, true) 208 .build(); 209 Notification n2 = new Notification.Builder(mContext) 210 .setProgress(10, 4, false) 211 .build(); 212 assertFalse(n.hasCompletedProgress()); 213 assertFalse(n2.hasCompletedProgress()); 214 } 215 216 @Test testHasCompletedProgress_zeroMax()217 public void testHasCompletedProgress_zeroMax() { 218 Notification n = new Notification.Builder(mContext) 219 .setProgress(0, 0, true) 220 .build(); 221 assertFalse(n.hasCompletedProgress()); 222 } 223 224 @Test 225 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasTitle_noStyle()226 public void testHasTitle_noStyle() { 227 Notification n = new Notification.Builder(mContext, "test") 228 .setContentTitle("TITLE") 229 .build(); 230 assertThat(n.hasTitle()).isTrue(); 231 } 232 233 @Test 234 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasTitle_bigText()235 public void testHasTitle_bigText() { 236 Notification n = new Notification.Builder(mContext, "test") 237 .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) 238 .build(); 239 assertThat(n.hasTitle()).isTrue(); 240 } 241 242 @Test 243 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasTitle_noTitle()244 public void testHasTitle_noTitle() { 245 Notification n = new Notification.Builder(mContext, "test") 246 .setContentText("text not title") 247 .build(); 248 assertThat(n.hasTitle()).isFalse(); 249 } 250 251 @Test 252 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_none()253 public void testContainsCustomViews_none() { 254 Notification np = new Notification.Builder(mContext, "test") 255 .setSmallIcon(android.R.drawable.sym_def_app_icon) 256 .setContentText("test") 257 .build(); 258 Notification n = new Notification.Builder(mContext, "test") 259 .setSmallIcon(android.R.drawable.sym_def_app_icon) 260 .setContentText("test") 261 .setPublicVersion(np) 262 .build(); 263 assertThat(n.containsCustomViews()).isFalse(); 264 } 265 266 @Test 267 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_content()268 public void testContainsCustomViews_content() { 269 Notification np = new Notification.Builder(mContext, "test") 270 .setSmallIcon(android.R.drawable.sym_def_app_icon) 271 .setContentText("test") 272 .build(); 273 Notification n = new Notification.Builder(mContext, "test") 274 .setSmallIcon(android.R.drawable.sym_def_app_icon) 275 .setContentText("test") 276 .setCustomContentView(mRemoteViews) 277 .setPublicVersion(np) 278 .build(); 279 assertThat(n.containsCustomViews()).isTrue(); 280 } 281 282 @Test 283 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_big()284 public void testContainsCustomViews_big() { 285 Notification np = new Notification.Builder(mContext, "test") 286 .setSmallIcon(android.R.drawable.sym_def_app_icon) 287 .setContentText("test") 288 .build(); 289 Notification n = new Notification.Builder(mContext, "test") 290 .setSmallIcon(android.R.drawable.sym_def_app_icon) 291 .setContentText("test") 292 .setCustomBigContentView(mRemoteViews) 293 .setPublicVersion(np) 294 .build(); 295 assertThat(n.containsCustomViews()).isTrue(); 296 } 297 298 @Test 299 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_headsUp()300 public void testContainsCustomViews_headsUp() { 301 Notification np = new Notification.Builder(mContext, "test") 302 .setSmallIcon(android.R.drawable.sym_def_app_icon) 303 .setContentText("test") 304 .build(); 305 Notification n = new Notification.Builder(mContext, "test") 306 .setSmallIcon(android.R.drawable.sym_def_app_icon) 307 .setContentText("test") 308 .setCustomHeadsUpContentView(mRemoteViews) 309 .setPublicVersion(np) 310 .build(); 311 assertThat(n.containsCustomViews()).isTrue(); 312 } 313 314 @Test 315 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_content_public()316 public void testContainsCustomViews_content_public() { 317 Notification np = new Notification.Builder(mContext, "test") 318 .setSmallIcon(android.R.drawable.sym_def_app_icon) 319 .setContentText("public") 320 .setCustomContentView(mRemoteViews) 321 .build(); 322 Notification n = new Notification.Builder(mContext, "test") 323 .setSmallIcon(android.R.drawable.sym_def_app_icon) 324 .setContentText("test") 325 .setPublicVersion(np) 326 .build(); 327 assertThat(n.containsCustomViews()).isTrue(); 328 } 329 330 @Test 331 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_big_public()332 public void testContainsCustomViews_big_public() { 333 Notification np = new Notification.Builder(mContext, "test") 334 .setSmallIcon(android.R.drawable.sym_def_app_icon) 335 .setContentText("test") 336 .setCustomBigContentView(mRemoteViews) 337 .build(); 338 Notification n = new Notification.Builder(mContext, "test") 339 .setSmallIcon(android.R.drawable.sym_def_app_icon) 340 .setContentText("test") 341 .setPublicVersion(np) 342 .build(); 343 assertThat(n.containsCustomViews()).isTrue(); 344 } 345 346 @Test 347 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testContainsCustomViews_headsUp_public()348 public void testContainsCustomViews_headsUp_public() { 349 Notification np = new Notification.Builder(mContext, "test") 350 .setSmallIcon(android.R.drawable.sym_def_app_icon) 351 .setContentText("test") 352 .setCustomHeadsUpContentView(mRemoteViews) 353 .build(); 354 Notification n = new Notification.Builder(mContext, "test") 355 .setSmallIcon(android.R.drawable.sym_def_app_icon) 356 .setContentText("test") 357 .setPublicVersion(np) 358 .build(); 359 assertThat(n.containsCustomViews()).isTrue(); 360 } 361 362 @Test 363 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_noStyle()364 public void testHasPromotableStyle_noStyle() { 365 Notification n = new Notification.Builder(mContext, "test") 366 .setSmallIcon(android.R.drawable.sym_def_app_icon) 367 .setContentText("test") 368 .build(); 369 assertThat(n.hasPromotableStyle()).isTrue(); 370 } 371 372 @Test 373 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_bigText()374 public void testHasPromotableStyle_bigText() { 375 Notification n = new Notification.Builder(mContext, "test") 376 .setSmallIcon(android.R.drawable.sym_def_app_icon) 377 .setStyle(new Notification.BigTextStyle()) 378 .build(); 379 assertThat(n.hasPromotableStyle()).isTrue(); 380 } 381 382 @Test 383 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_no_bigPictureStyle()384 public void testHasPromotableStyle_no_bigPictureStyle() { 385 Notification n = new Notification.Builder(mContext, "test") 386 .setSmallIcon(android.R.drawable.sym_def_app_icon) 387 .setStyle(new Notification.BigPictureStyle()) 388 .build(); 389 assertThat(n.hasPromotableStyle()).isFalse(); 390 } 391 392 @Test 393 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_no_messagingStyle()394 public void testHasPromotableStyle_no_messagingStyle() { 395 Notification.MessagingStyle style = new Notification.MessagingStyle("self name") 396 .setGroupConversation(true) 397 .setConversationTitle("test conversation title"); 398 Notification n = new Notification.Builder(mContext, "test") 399 .setSmallIcon(android.R.drawable.sym_def_app_icon) 400 .setStyle(style) 401 .build(); 402 assertThat(n.hasPromotableStyle()).isFalse(); 403 } 404 405 @Test 406 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_no_mediaStyle()407 public void testHasPromotableStyle_no_mediaStyle() { 408 Notification n = new Notification.Builder(mContext, "test") 409 .setSmallIcon(android.R.drawable.sym_def_app_icon) 410 .setStyle(new Notification.MediaStyle()) 411 .build(); 412 assertThat(n.hasPromotableStyle()).isFalse(); 413 } 414 415 @Test 416 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_no_inboxStyle()417 public void testHasPromotableStyle_no_inboxStyle() { 418 Notification n = new Notification.Builder(mContext, "test") 419 .setSmallIcon(android.R.drawable.sym_def_app_icon) 420 .setStyle(new Notification.InboxStyle()) 421 .build(); 422 assertThat(n.hasPromotableStyle()).isFalse(); 423 } 424 425 @Test 426 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableStyle_callText()427 public void testHasPromotableStyle_callText() { 428 PendingIntent answerIntent = createPendingIntent("answer"); 429 PendingIntent declineIntent = createPendingIntent("decline"); 430 Notification.CallStyle style = Notification.CallStyle.forIncomingCall( 431 new Person.Builder().setName("A Caller").build(), 432 declineIntent, 433 answerIntent 434 ); 435 Notification n = new Notification.Builder(mContext, "test") 436 .setSmallIcon(android.R.drawable.sym_def_app_icon) 437 .setStyle(style) 438 .build(); 439 assertThat(n.hasPromotableStyle()).isTrue(); 440 } 441 442 @Test 443 @EnableFlags({Flags.FLAG_UI_RICH_ONGOING, Flags.FLAG_API_RICH_ONGOING}) testHasPromotableStyle_progress()444 public void testHasPromotableStyle_progress() { 445 Notification n = new Notification.Builder(mContext, "test") 446 .setSmallIcon(android.R.drawable.sym_def_app_icon) 447 .setStyle(new Notification.ProgressStyle()) 448 .build(); 449 assertThat(n.hasPromotableStyle()).isTrue(); 450 } 451 452 @Test 453 @EnableFlags({Flags.FLAG_UI_RICH_ONGOING}) testHasPromotableStyle_unknownStyle()454 public void testHasPromotableStyle_unknownStyle() { 455 Notification n = new Notification.Builder(mContext, "test") 456 .setSmallIcon(android.R.drawable.sym_def_app_icon) 457 .setStyle(new NotAPlatformStyle()) 458 .build(); 459 460 assertThat(n.hasPromotableStyle()).isTrue(); 461 } 462 463 @Test 464 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_bigText_bigTitle()465 public void testHasPromotableCharacteristics_bigText_bigTitle() { 466 Notification n = new Notification.Builder(mContext, "test") 467 .setSmallIcon(android.R.drawable.sym_def_app_icon) 468 .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) 469 .setColor(Color.WHITE) 470 .setColorized(true) 471 .setOngoing(true) 472 .build(); 473 assertThat(n.hasPromotableCharacteristics()).isTrue(); 474 } 475 476 @Test 477 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_bigText_normalTitle()478 public void testHasPromotableCharacteristics_bigText_normalTitle() { 479 Notification n = new Notification.Builder(mContext, "test") 480 .setSmallIcon(android.R.drawable.sym_def_app_icon) 481 .setStyle(new Notification.BigTextStyle()) 482 .setContentTitle("TITLE") 483 .setColor(Color.WHITE) 484 .setColorized(true) 485 .setOngoing(true) 486 .build(); 487 assertThat(n.hasPromotableCharacteristics()).isTrue(); 488 } 489 490 @Test 491 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_notOngoing()492 public void testHasPromotableCharacteristics_notOngoing() { 493 Notification n = new Notification.Builder(mContext, "test") 494 .setSmallIcon(android.R.drawable.sym_def_app_icon) 495 .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) 496 .setColor(Color.WHITE) 497 .setColorized(true) 498 .build(); 499 assertThat(n.hasPromotableCharacteristics()).isFalse(); 500 } 501 502 @Test 503 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_wrongStyle()504 public void testHasPromotableCharacteristics_wrongStyle() { 505 Notification n = new Notification.Builder(mContext, "test") 506 .setSmallIcon(android.R.drawable.sym_def_app_icon) 507 .setStyle(new Notification.InboxStyle()) 508 .setContentTitle("TITLE") 509 .setColor(Color.WHITE) 510 .setColorized(true) 511 .setOngoing(true) 512 .build(); 513 assertThat(n.hasPromotableCharacteristics()).isFalse(); 514 } 515 516 @Test 517 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_notColorized()518 public void testHasPromotableCharacteristics_notColorized() { 519 Notification n = new Notification.Builder(mContext, "test") 520 .setSmallIcon(android.R.drawable.sym_def_app_icon) 521 .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) 522 .setColor(Color.WHITE) 523 .setOngoing(true) 524 .build(); 525 assertThat(n.hasPromotableCharacteristics()).isFalse(); 526 } 527 528 @Test 529 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_noTitle()530 public void testHasPromotableCharacteristics_noTitle() { 531 Notification n = new Notification.Builder(mContext, "test") 532 .setSmallIcon(android.R.drawable.sym_def_app_icon) 533 .setStyle(new Notification.BigTextStyle()) 534 .setColor(Color.WHITE) 535 .setColorized(true) 536 .setOngoing(true) 537 .build(); 538 assertThat(n.hasPromotableCharacteristics()).isFalse(); 539 } 540 541 @Test 542 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_noStyle_onlyBigTitle()543 public void testHasPromotableCharacteristics_noStyle_onlyBigTitle() { 544 Bundle extras = new Bundle(); 545 extras.putString(Notification.EXTRA_TITLE_BIG, "BIG"); 546 Notification n = new Notification.Builder(mContext, "test") 547 .setSmallIcon(android.R.drawable.sym_def_app_icon) 548 .setColor(Color.WHITE) 549 .setColorized(true) 550 .setOngoing(true) 551 .addExtras(extras) 552 .build(); 553 assertThat(n.hasPromotableCharacteristics()).isFalse(); 554 } 555 556 @Test 557 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_ongoingCallStyle_notColorized()558 public void testHasPromotableCharacteristics_ongoingCallStyle_notColorized() { 559 PendingIntent intent = PendingIntent.getActivity( 560 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 561 Person person = new Person.Builder().setName("Caller").build(); 562 Notification n = new Notification.Builder(mContext, "test") 563 .setSmallIcon(android.R.drawable.sym_def_app_icon) 564 .setStyle(Notification.CallStyle.forOngoingCall(person, intent)) 565 .setColor(Color.WHITE) 566 .setOngoing(true) 567 .build(); 568 assertThat(n.hasPromotableCharacteristics()).isTrue(); 569 } 570 571 @Test 572 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_incomingCallStyle_notColorized()573 public void testHasPromotableCharacteristics_incomingCallStyle_notColorized() { 574 PendingIntent intent = PendingIntent.getActivity( 575 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 576 Person person = new Person.Builder().setName("Caller").build(); 577 Notification n = new Notification.Builder(mContext, "test") 578 .setSmallIcon(android.R.drawable.sym_def_app_icon) 579 .setStyle(Notification.CallStyle.forIncomingCall(person, intent, intent)) 580 .setColor(Color.WHITE) 581 .setOngoing(true) 582 .build(); 583 assertThat(n.hasPromotableCharacteristics()).isFalse(); 584 } 585 586 @Test 587 @EnableFlags(Flags.FLAG_UI_RICH_ONGOING) testHasPromotableCharacteristics_groupSummary()588 public void testHasPromotableCharacteristics_groupSummary() { 589 Notification n = new Notification.Builder(mContext, "test") 590 .setSmallIcon(android.R.drawable.sym_def_app_icon) 591 .setStyle(new Notification.BigTextStyle().setBigContentTitle("BIG")) 592 .setColor(Color.WHITE) 593 .setColorized(true) 594 .setOngoing(true) 595 .setGroup("someGroup") 596 .setGroupSummary(true) 597 .build(); 598 assertThat(n.hasPromotableCharacteristics()).isFalse(); 599 } 600 601 @Test 602 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) testGetShortCriticalText_noneSet()603 public void testGetShortCriticalText_noneSet() { 604 Notification n = new Notification.Builder(mContext, "test") 605 .build(); 606 607 assertSame(n.getShortCriticalText(), null); 608 } 609 610 @Test 611 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) testGetShortCriticalText_isSet()612 public void testGetShortCriticalText_isSet() { 613 Notification n = new Notification.Builder(mContext, "test") 614 .setShortCriticalText("short critical text here") 615 .build(); 616 617 assertSame(n.getShortCriticalText(), "short critical text here"); 618 } 619 620 @Test largeIconMultipleReferences_keptAfterParcelling()621 public void largeIconMultipleReferences_keptAfterParcelling() { 622 Icon originalIcon = Icon.createWithBitmap(BitmapFactory.decodeResource( 623 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); 624 625 Notification n = new Notification.Builder(mContext).setLargeIcon(originalIcon).build(); 626 assertSame(n.getLargeIcon(), originalIcon); 627 628 Notification q = writeAndReadParcelable(n); 629 assertNotSame(q.getLargeIcon(), n.getLargeIcon()); 630 631 assertTrue(q.getLargeIcon().getBitmap().sameAs(n.getLargeIcon().getBitmap())); 632 assertSame(q.getLargeIcon(), q.extras.getParcelable(EXTRA_LARGE_ICON)); 633 } 634 635 @Test largeIconReferenceInExtrasOnly_keptAfterParcelling()636 public void largeIconReferenceInExtrasOnly_keptAfterParcelling() { 637 Icon originalIcon = Icon.createWithBitmap(BitmapFactory.decodeResource( 638 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); 639 640 Notification n = new Notification.Builder(mContext).build(); 641 n.extras.putParcelable(EXTRA_LARGE_ICON, originalIcon); 642 assertSame(n.getLargeIcon(), null); 643 644 Notification q = writeAndReadParcelable(n); 645 assertSame(q.getLargeIcon(), null); 646 assertTrue(((Icon) q.extras.getParcelable(EXTRA_LARGE_ICON)).getBitmap() 647 .sameAs(originalIcon.getBitmap())); 648 } 649 650 @Test allPendingIntents_recollectedAfterReusingBuilder()651 public void allPendingIntents_recollectedAfterReusingBuilder() { 652 PendingIntent intent1 = PendingIntent.getActivity( 653 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 654 PendingIntent intent2 = PendingIntent.getActivity( 655 mContext, 0, new Intent("test2"), PendingIntent.FLAG_IMMUTABLE); 656 657 Notification.Builder builder = new Notification.Builder(mContext, "channel"); 658 builder.setContentIntent(intent1); 659 660 Parcel p = Parcel.obtain(); 661 662 Notification n1 = builder.build(); 663 n1.writeToParcel(p, 0); 664 665 builder.setContentIntent(intent2); 666 Notification n2 = builder.build(); 667 n2.writeToParcel(p, 0); 668 669 assertTrue(n2.allPendingIntents.contains(intent2)); 670 } 671 672 @Test allPendingIntents_containsCustomRemoteViews()673 public void allPendingIntents_containsCustomRemoteViews() { 674 PendingIntent intent = PendingIntent.getActivity(mContext, 0, 675 new Intent("test").setPackage(mContext.getPackageName()), 676 PendingIntent.FLAG_MUTABLE); 677 678 RemoteViews contentView = new RemoteViews(mContext.getPackageName(), 0 /* layoutId */); 679 contentView.setOnClickPendingIntent(1 /* id */, intent); 680 681 Notification.Builder builder = new Notification.Builder(mContext, "channel"); 682 builder.setCustomContentView(contentView); 683 684 Parcel p = Parcel.obtain(); 685 686 Notification n = builder.build(); 687 n.writeToParcel(p, 0); 688 689 assertTrue(n.allPendingIntents.contains(intent)); 690 } 691 692 @Test allPendingIntents_resilientToAnotherNotificationInExtras()693 public void allPendingIntents_resilientToAnotherNotificationInExtras() { 694 PendingIntent contentIntent = createPendingIntent("content"); 695 PendingIntent actionIntent = createPendingIntent("action"); 696 Notification another = new Notification.Builder(mContext, "channel").build(); 697 Bundle bundleContainingAnotherNotification = new Bundle(); 698 bundleContainingAnotherNotification.putParcelable(null, another); 699 Notification source = new Notification.Builder(mContext, "channel") 700 .setContentIntent(contentIntent) 701 .addAction(new Notification.Action.Builder(null, "action", actionIntent).build()) 702 .setExtras(bundleContainingAnotherNotification) 703 .build(); 704 705 Parcel p = Parcel.obtain(); 706 source.writeToParcel(p, 0); 707 p.setDataPosition(0); 708 Notification unparceled = new Notification(p); 709 710 assertThat(unparceled.allPendingIntents).containsExactly(contentIntent, actionIntent); 711 } 712 713 @Test allPendingIntents_alsoInPublicVersion()714 public void allPendingIntents_alsoInPublicVersion() { 715 PendingIntent contentIntent = createPendingIntent("content"); 716 PendingIntent actionIntent = createPendingIntent("action"); 717 PendingIntent publicContentIntent = createPendingIntent("publicContent"); 718 PendingIntent publicActionIntent = createPendingIntent("publicAction"); 719 Notification source = new Notification.Builder(mContext, "channel") 720 .setContentIntent(contentIntent) 721 .addAction(new Notification.Action.Builder(null, "action", actionIntent).build()) 722 .setPublicVersion(new Notification.Builder(mContext, "channel") 723 .setContentIntent(publicContentIntent) 724 .addAction(new Notification.Action.Builder( 725 null, "publicAction", publicActionIntent).build()) 726 .build()) 727 .build(); 728 729 Parcel p = Parcel.obtain(); 730 source.writeToParcel(p, 0); 731 p.setDataPosition(0); 732 Notification unparceled = new Notification(p); 733 734 assertThat(unparceled.allPendingIntents).containsExactly(contentIntent, actionIntent, 735 publicContentIntent, publicActionIntent); 736 assertThat(unparceled.publicVersion.allPendingIntents).containsExactly(publicContentIntent, 737 publicActionIntent); 738 } 739 740 @Test messagingStyle_isGroupConversation()741 public void messagingStyle_isGroupConversation() { 742 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P; 743 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name") 744 .setGroupConversation(true) 745 .setConversationTitle("test conversation title"); 746 Notification notification = new Notification.Builder(mContext, "test id") 747 .setSmallIcon(1) 748 .setContentTitle("test title") 749 .setStyle(messagingStyle) 750 .build(); 751 752 assertTrue(messagingStyle.isGroupConversation()); 753 assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION)); 754 } 755 756 @Test messagingStyle_isGroupConversation_noConversationTitle()757 public void messagingStyle_isGroupConversation_noConversationTitle() { 758 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P; 759 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name") 760 .setGroupConversation(true) 761 .setConversationTitle(null); 762 Notification notification = new Notification.Builder(mContext, "test id") 763 .setSmallIcon(1) 764 .setContentTitle("test title") 765 .setStyle(messagingStyle) 766 .build(); 767 768 assertTrue(messagingStyle.isGroupConversation()); 769 assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION)); 770 } 771 772 @Test messagingStyle_isGroupConversation_withConversationTitle_legacy()773 public void messagingStyle_isGroupConversation_withConversationTitle_legacy() { 774 // In legacy (version < P), isGroupConversation is controlled by conversationTitle. 775 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O; 776 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name") 777 .setGroupConversation(false) 778 .setConversationTitle("test conversation title"); 779 Notification notification = new Notification.Builder(mContext, "test id") 780 .setSmallIcon(1) 781 .setContentTitle("test title") 782 .setStyle(messagingStyle) 783 .build(); 784 785 assertTrue(messagingStyle.isGroupConversation()); 786 assertFalse(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION)); 787 } 788 789 @Test messagingStyle_isGroupConversation_withoutConversationTitle_legacy()790 public void messagingStyle_isGroupConversation_withoutConversationTitle_legacy() { 791 // In legacy (version < P), isGroupConversation is controlled by conversationTitle. 792 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O; 793 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name") 794 .setGroupConversation(true) 795 .setConversationTitle(null); 796 Notification notification = new Notification.Builder(mContext, "test id") 797 .setSmallIcon(1) 798 .setContentTitle("test title") 799 .setStyle(messagingStyle) 800 .build(); 801 802 assertFalse(messagingStyle.isGroupConversation()); 803 assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION)); 804 } 805 806 @Test action_builder_hasDefault()807 public void action_builder_hasDefault() { 808 Notification.Action action = makeNotificationAction(null); 809 assertEquals(Notification.Action.SEMANTIC_ACTION_NONE, action.getSemanticAction()); 810 } 811 812 @Test action_builder_setSemanticAction()813 public void action_builder_setSemanticAction() { 814 Notification.Action action = makeNotificationAction( 815 builder -> builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY)); 816 assertEquals(Notification.Action.SEMANTIC_ACTION_REPLY, action.getSemanticAction()); 817 } 818 819 @Test action_parcel()820 public void action_parcel() { 821 Notification.Action action = writeAndReadParcelable( 822 makeNotificationAction(builder -> { 823 builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_ARCHIVE); 824 builder.setAllowGeneratedReplies(true); 825 })); 826 827 assertEquals(Notification.Action.SEMANTIC_ACTION_ARCHIVE, action.getSemanticAction()); 828 assertTrue(action.getAllowGeneratedReplies()); 829 } 830 831 @Test action_clone()832 public void action_clone() { 833 Notification.Action action = makeNotificationAction( 834 builder -> builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_DELETE)); 835 assertEquals( 836 Notification.Action.SEMANTIC_ACTION_DELETE, 837 action.clone().getSemanticAction()); 838 } 839 840 @Test testBuilder_setLocusId()841 public void testBuilder_setLocusId() { 842 LocusId locusId = new LocusId("4815162342"); 843 Notification notification = new Notification.Builder(mContext, "whatever") 844 .setLocusId(locusId).build(); 845 assertEquals(locusId, notification.getLocusId()); 846 847 Notification clone = writeAndReadParcelable(notification); 848 assertEquals(locusId, clone.getLocusId()); 849 } 850 851 @Test testBuilder_setLocusId_null()852 public void testBuilder_setLocusId_null() { 853 Notification notification = new Notification.Builder(mContext, "whatever") 854 .setLocusId(null).build(); 855 assertNull(notification.getLocusId()); 856 857 Notification clone = writeAndReadParcelable(notification); 858 assertNull(clone.getLocusId()); 859 } 860 861 @Test testBuilder_getFullLengthSpanColor_returnsNullForString()862 public void testBuilder_getFullLengthSpanColor_returnsNullForString() { 863 assertThat(Notification.Builder.getFullLengthSpanColor("String")).isNull(); 864 } 865 866 @Test testBuilder_getFullLengthSpanColor_returnsNullWithPartialSpan()867 public void testBuilder_getFullLengthSpanColor_returnsNullWithPartialSpan() { 868 CharSequence text = new SpannableStringBuilder() 869 .append("text with ") 870 .append("some red", new ForegroundColorSpan(Color.RED), 871 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 872 assertThat(Notification.Builder.getFullLengthSpanColor(text)).isNull(); 873 } 874 875 @Test testBuilder_getFullLengthSpanColor_worksWithSingleSpan()876 public void testBuilder_getFullLengthSpanColor_worksWithSingleSpan() { 877 CharSequence text = new SpannableStringBuilder() 878 .append("text that is all red", new ForegroundColorSpan(Color.RED), 879 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 880 assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.RED); 881 } 882 883 @Test testBuilder_getFullLengthSpanColor_worksWithFullAndPartialSpans()884 public void testBuilder_getFullLengthSpanColor_worksWithFullAndPartialSpans() { 885 Spannable text = new SpannableString("blue text with yellow and green"); 886 text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21, 887 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 888 text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(), 889 Spanned.SPAN_INCLUSIVE_INCLUSIVE); 890 text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31, 891 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 892 assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.BLUE); 893 } 894 895 @Test testBuilder_getFullLengthSpanColor_worksWithTextAppearance()896 public void testBuilder_getFullLengthSpanColor_worksWithTextAppearance() { 897 Spannable text = new SpannableString("title text with yellow and green"); 898 text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21, 899 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 900 TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(mContext, 901 R.style.TextAppearance_DeviceDefault_Notification_Title); 902 int expectedTextColor = textAppearanceSpan.getTextColor().getDefaultColor(); 903 text.setSpan(textAppearanceSpan, 0, text.length(), 904 Spanned.SPAN_INCLUSIVE_INCLUSIVE); 905 text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31, 906 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 907 assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(expectedTextColor); 908 } 909 910 911 912 @Test testBuilder_ensureButtonFillContrast_adjustsDarker()913 public void testBuilder_ensureButtonFillContrast_adjustsDarker() { 914 int background = Color.LTGRAY; 915 int foreground = Color.LTGRAY; 916 int result = Notification.Builder.ensureButtonFillContrast(foreground, background); 917 assertContrastIsWithinRange(result, background, 1.3, 1.5); 918 assertThat(ContrastColorUtil.calculateLuminance(result)) 919 .isLessThan(ContrastColorUtil.calculateLuminance(background)); 920 } 921 922 @Test testBuilder_ensureButtonFillContrast_adjustsLighter()923 public void testBuilder_ensureButtonFillContrast_adjustsLighter() { 924 int background = Color.DKGRAY; 925 int foreground = Color.DKGRAY; 926 int result = Notification.Builder.ensureButtonFillContrast(foreground, background); 927 assertContrastIsWithinRange(result, background, 1.3, 1.5); 928 assertThat(ContrastColorUtil.calculateLuminance(result)) 929 .isGreaterThan(ContrastColorUtil.calculateLuminance(background)); 930 } 931 932 @Test testBuilder_setSilent_summaryBehavior_groupAlertChildren()933 public void testBuilder_setSilent_summaryBehavior_groupAlertChildren() { 934 Notification summaryNotif = new Notification.Builder(mContext, "channelId") 935 .setGroupSummary(true) 936 .setGroup("groupKey") 937 .setSilent(true) 938 .build(); 939 assertEquals(GROUP_ALERT_CHILDREN, summaryNotif.getGroupAlertBehavior()); 940 } 941 942 @Test testBuilder_setSilent_childBehavior_groupAlertSummary()943 public void testBuilder_setSilent_childBehavior_groupAlertSummary() { 944 Notification childNotif = new Notification.Builder(mContext, "channelId") 945 .setGroupSummary(false) 946 .setGroup("groupKey") 947 .setSilent(true) 948 .build(); 949 assertEquals(GROUP_ALERT_SUMMARY, childNotif.getGroupAlertBehavior()); 950 } 951 952 @Test 953 @DisableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_SILENT_FLAG) testBuilder_setSilent_emptyGroupKey_groupKeySilent()954 public void testBuilder_setSilent_emptyGroupKey_groupKeySilent() { 955 Notification emptyGroupKeyNotif = new Notification.Builder(mContext, "channelId") 956 .setGroup("") 957 .setSilent(true) 958 .build(); 959 assertThat(emptyGroupKeyNotif.getGroup()).isEqualTo(GROUP_KEY_SILENT); 960 assertThat(emptyGroupKeyNotif.isSilent()).isTrue(); 961 } 962 963 @Test 964 @EnableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_SILENT_FLAG) testBuilder_setSilent_flagSilent()965 public void testBuilder_setSilent_flagSilent() { 966 final String groupKey = "groupKey"; 967 Notification emptyGroupKeyNotif = new Notification.Builder(mContext, "channelId") 968 .setGroup(groupKey) 969 .setSilent(true) 970 .build(); 971 assertThat(emptyGroupKeyNotif.getGroup()).isEqualTo(groupKey); 972 assertThat(emptyGroupKeyNotif.isSilent()).isTrue(); 973 } 974 975 @Test testBuilder_setSilent_vibrateNull()976 public void testBuilder_setSilent_vibrateNull() { 977 Notification silentNotif = new Notification.Builder(mContext, "channelId") 978 .setGroup("") 979 .setSilent(true) 980 .build(); 981 982 assertNull(silentNotif.vibrate); 983 } 984 985 @Test testBuilder_setSilent_soundNull()986 public void testBuilder_setSilent_soundNull() { 987 Notification silentNotif = new Notification.Builder(mContext, "channelId") 988 .setGroup("") 989 .setSilent(true) 990 .build(); 991 992 assertNull(silentNotif.sound); 993 } 994 995 @Test testBuilder_setSilent_noDefaultSound()996 public void testBuilder_setSilent_noDefaultSound() { 997 Notification silentNotif = new Notification.Builder(mContext, "channelId") 998 .setGroup("") 999 .setSilent(true) 1000 .build(); 1001 1002 assertEquals(0, (silentNotif.defaults & DEFAULT_SOUND)); 1003 } 1004 1005 @Test testBuilder_setSilent_noDefaultVibrate()1006 public void testBuilder_setSilent_noDefaultVibrate() { 1007 Notification silentNotif = new Notification.Builder(mContext, "channelId") 1008 .setGroup("") 1009 .setSilent(true) 1010 .build(); 1011 1012 assertEquals(0, (silentNotif.defaults & DEFAULT_VIBRATE)); 1013 } 1014 1015 @Test testCallStyle_getSystemActions_forIncomingCall()1016 public void testCallStyle_getSystemActions_forIncomingCall() { 1017 PendingIntent answerIntent = createPendingIntent("answer"); 1018 PendingIntent declineIntent = createPendingIntent("decline"); 1019 Notification.CallStyle style = Notification.CallStyle.forIncomingCall( 1020 new Person.Builder().setName("A Caller").build(), 1021 declineIntent, 1022 answerIntent 1023 ); 1024 style.setBuilder(new Notification.Builder(mContext, "Channel")); 1025 1026 List<Notification.Action> actions = style.getActionsListWithSystemActions(); 1027 1028 assertEquals(2, actions.size()); 1029 assertEquals(declineIntent, actions.get(0).actionIntent); 1030 assertEquals(answerIntent, actions.get(1).actionIntent); 1031 } 1032 1033 @Test testCallStyle_getSystemActions_forOngoingCall()1034 public void testCallStyle_getSystemActions_forOngoingCall() { 1035 PendingIntent hangUpIntent = createPendingIntent("hangUp"); 1036 Notification.CallStyle style = Notification.CallStyle.forOngoingCall( 1037 new Person.Builder().setName("A Caller").build(), 1038 hangUpIntent 1039 ); 1040 style.setBuilder(new Notification.Builder(mContext, "Channel")); 1041 1042 List<Notification.Action> actions = style.getActionsListWithSystemActions(); 1043 1044 assertEquals(1, actions.size()); 1045 assertEquals(hangUpIntent, actions.get(0).actionIntent); 1046 } 1047 1048 @Test testCallStyle_getSystemActions_forIncomingCallWithOtherActions()1049 public void testCallStyle_getSystemActions_forIncomingCallWithOtherActions() { 1050 PendingIntent answerIntent = createPendingIntent("answer"); 1051 PendingIntent declineIntent = createPendingIntent("decline"); 1052 Notification.CallStyle style = Notification.CallStyle.forIncomingCall( 1053 new Person.Builder().setName("A Caller").build(), 1054 declineIntent, 1055 answerIntent 1056 ); 1057 Notification.Action actionToKeep = makeNotificationAction(null); 1058 Notification.Action actionToDrop = makeNotificationAction(null); 1059 Notification.Builder notifBuilder = new Notification.Builder(mContext, "Channel") 1060 .addAction(actionToKeep) 1061 .addAction(actionToDrop); //expect to move this action to the end 1062 style.setBuilder(notifBuilder); //add a builder with actions 1063 1064 List<Notification.Action> actions = style.getActionsListWithSystemActions(); 1065 1066 assertEquals(4, actions.size()); 1067 assertEquals(declineIntent, actions.get(0).actionIntent); 1068 assertEquals(actionToKeep, actions.get(1)); 1069 assertEquals(answerIntent, actions.get(2).actionIntent); 1070 assertEquals(actionToDrop, actions.get(3)); 1071 } 1072 1073 @Test testCallStyle_getSystemActions_forOngoingCallWithOtherActions()1074 public void testCallStyle_getSystemActions_forOngoingCallWithOtherActions() { 1075 PendingIntent hangUpIntent = createPendingIntent("hangUp"); 1076 Notification.CallStyle style = Notification.CallStyle.forOngoingCall( 1077 new Person.Builder().setName("A Caller").build(), 1078 hangUpIntent 1079 ); 1080 Notification.Action firstAction = makeNotificationAction(null); 1081 Notification.Action secondAction = makeNotificationAction(null); 1082 Notification.Builder notifBuilder = new Notification.Builder(mContext, "Channel") 1083 .addAction(firstAction) 1084 .addAction(secondAction); 1085 style.setBuilder(notifBuilder); //add a builder with actions 1086 1087 List<Notification.Action> actions = style.getActionsListWithSystemActions(); 1088 1089 assertEquals(3, actions.size()); 1090 assertEquals(hangUpIntent, actions.get(0).actionIntent); 1091 assertEquals(firstAction, actions.get(1)); 1092 assertEquals(secondAction, actions.get(2)); 1093 } 1094 1095 @Test testCallStyle_getSystemActions_dropsOldSystemActions()1096 public void testCallStyle_getSystemActions_dropsOldSystemActions() { 1097 PendingIntent hangUpIntent = createPendingIntent("decline"); 1098 Notification.CallStyle style = Notification.CallStyle.forOngoingCall( 1099 new Person.Builder().setName("A Caller").build(), 1100 hangUpIntent 1101 ); 1102 Bundle actionExtras = new Bundle(); 1103 actionExtras.putBoolean("key_action_priority", true); 1104 Notification.Action oldSystemAction = makeNotificationAction( 1105 builder -> builder.addExtras(actionExtras) 1106 ); 1107 Notification.Builder notifBuilder = new Notification.Builder(mContext, "Channel") 1108 .addAction(oldSystemAction); 1109 style.setBuilder(notifBuilder); //add a builder with actions 1110 1111 List<Notification.Action> actions = style.getActionsListWithSystemActions(); 1112 1113 assertFalse("Old versions of system actions should be dropped.", 1114 actions.contains(oldSystemAction)); 1115 } 1116 1117 @Test testBuild_ensureSmallIconIsNotTooBig_resizesIcon()1118 public void testBuild_ensureSmallIconIsNotTooBig_resizesIcon() { 1119 Icon hugeIcon = Icon.createWithBitmap( 1120 Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); 1121 Notification notification = new Notification.Builder(mContext, "Channel").setSmallIcon( 1122 hugeIcon).build(); 1123 1124 Bitmap smallNotificationIcon = notification.getSmallIcon().getBitmap(); 1125 assertThat((float) smallNotificationIcon.getWidth()).isWithin(3f).of( 1126 mContext.getResources().getDimensionPixelSize( 1127 R.dimen.notification_small_icon_size)); 1128 assertThat((float) smallNotificationIcon.getHeight()).isWithin(3f).of( 1129 mContext.getResources().getDimensionPixelSize( 1130 R.dimen.notification_small_icon_size)); 1131 } 1132 1133 @Test testBuild_ensureMessagingUserIsNotTooBig_resizesIcon()1134 public void testBuild_ensureMessagingUserIsNotTooBig_resizesIcon() { 1135 Icon hugeIcon = Icon.createWithBitmap( 1136 Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); 1137 Icon hugeMessageAvatar = Icon.createWithBitmap( 1138 Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); 1139 Icon hugeHistoricMessageAvatar = Icon.createWithBitmap( 1140 Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); 1141 1142 Notification.MessagingStyle style = new Notification.MessagingStyle( 1143 new Person.Builder().setIcon(hugeIcon).setName("A User").build()); 1144 style.addMessage(new Notification.MessagingStyle.Message("A message", 123456, 1145 new Person.Builder().setIcon(hugeMessageAvatar).setName("A Sender").build())); 1146 style.addHistoricMessage(new Notification.MessagingStyle.Message("A message", 123456, 1147 new Person.Builder().setIcon(hugeHistoricMessageAvatar).setName( 1148 "A Historic Sender").build())); 1149 Notification notification = new Notification.Builder(mContext, "Channel").setStyle( 1150 style).build(); 1151 1152 float targetSize = mContext.getResources().getDimensionPixelSize( 1153 ActivityManager.isLowRamDeviceStatic() 1154 ? R.dimen.notification_person_icon_max_size_low_ram 1155 : R.dimen.notification_person_icon_max_size); 1156 1157 Bitmap personIcon = style.getUser().getIcon().getBitmap(); 1158 assertThat((float) personIcon.getWidth()).isWithin(3f).of(targetSize); 1159 assertThat((float) personIcon.getHeight()).isWithin(3f).of(targetSize); 1160 1161 Bitmap avatarIcon = style.getMessages().get(0).getSenderPerson().getIcon().getBitmap(); 1162 assertThat((float) avatarIcon.getWidth()).isWithin(3f).of(targetSize); 1163 assertThat((float) avatarIcon.getHeight()).isWithin(3f).of(targetSize); 1164 1165 Bitmap historicAvatarIcon = style.getHistoricMessages().get( 1166 0).getSenderPerson().getIcon().getBitmap(); 1167 assertThat((float) historicAvatarIcon.getWidth()).isWithin(3f).of(targetSize); 1168 assertThat((float) historicAvatarIcon.getHeight()).isWithin(3f).of(targetSize); 1169 } 1170 1171 @Test testBuild_ensureMessagingShortcutIconIsNotTooBig_resizesIcon()1172 public void testBuild_ensureMessagingShortcutIconIsNotTooBig_resizesIcon() { 1173 Icon hugeIcon = Icon.createWithBitmap( 1174 Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); 1175 Notification.MessagingStyle style = new Notification.MessagingStyle( 1176 new Person.Builder().setName("A User").build()).setShortcutIcon(hugeIcon); 1177 1178 Notification notification = new Notification.Builder(mContext, "Channel").setStyle( 1179 style).build(); 1180 Bitmap shortcutIcon = style.getShortcutIcon().getBitmap(); 1181 1182 assertThat((float) shortcutIcon.getWidth()).isWithin(3f).of( 1183 mContext.getResources().getDimensionPixelSize( 1184 R.dimen.notification_small_icon_size)); 1185 assertThat((float) shortcutIcon.getHeight()).isWithin(3f).of( 1186 mContext.getResources().getDimensionPixelSize( 1187 R.dimen.notification_small_icon_size)); 1188 } 1189 1190 @Test 1191 @Ignore // TODO: b/329389261 - Restore or delete testColors_ensureColors_dayMode_producesValidPalette()1192 public void testColors_ensureColors_dayMode_producesValidPalette() { 1193 Notification.Colors c = new Notification.Colors(); 1194 boolean colorized = false; 1195 boolean nightMode = false; 1196 resolveColorsInNightMode(nightMode, c, Color.BLUE, colorized); 1197 assertValid(c); 1198 } 1199 1200 @Test testColors_ensureColors_nightMode_producesValidPalette()1201 public void testColors_ensureColors_nightMode_producesValidPalette() { 1202 Notification.Colors c = new Notification.Colors(); 1203 boolean colorized = false; 1204 boolean nightMode = true; 1205 resolveColorsInNightMode(nightMode, c, Color.BLUE, colorized); 1206 assertValid(c); 1207 } 1208 1209 @Test testColors_ensureColors_colorized_producesValidPalette_default()1210 public void testColors_ensureColors_colorized_producesValidPalette_default() { 1211 validateColorizedPaletteForColor(Notification.COLOR_DEFAULT); 1212 } 1213 1214 @Test testColors_ensureColors_colorized_producesValidPalette_blue()1215 public void testColors_ensureColors_colorized_producesValidPalette_blue() { 1216 validateColorizedPaletteForColor(Color.BLUE); 1217 } 1218 1219 @Test 1220 @Ignore // TODO: b/329389261 - Restore or delete testColors_ensureColors_colorized_producesValidPalette_red()1221 public void testColors_ensureColors_colorized_producesValidPalette_red() { 1222 validateColorizedPaletteForColor(Color.RED); 1223 } 1224 1225 @Test 1226 @Ignore // b/347089000 - Restore or delete testColors_ensureColors_colorized_producesValidPalette_white()1227 public void testColors_ensureColors_colorized_producesValidPalette_white() { 1228 validateColorizedPaletteForColor(Color.WHITE); 1229 } 1230 1231 @Test testColors_ensureColors_colorized_producesValidPalette_black()1232 public void testColors_ensureColors_colorized_producesValidPalette_black() { 1233 validateColorizedPaletteForColor(Color.BLACK); 1234 } 1235 1236 @Test testIsMediaNotification_nullSession_returnsFalse()1237 public void testIsMediaNotification_nullSession_returnsFalse() { 1238 // Null media session 1239 Notification.MediaStyle mediaStyle = new Notification.MediaStyle(); 1240 Notification notification = new Notification.Builder(mContext, "test id") 1241 .setStyle(mediaStyle) 1242 .build(); 1243 assertFalse(notification.isMediaNotification()); 1244 } 1245 1246 @Test testIsMediaNotification_invalidSession_returnsFalse()1247 public void testIsMediaNotification_invalidSession_returnsFalse() { 1248 // Extra was set manually to an invalid type 1249 Bundle extras = new Bundle(); 1250 extras.putParcelable(EXTRA_MEDIA_SESSION, new Intent()); 1251 Notification.MediaStyle mediaStyle = new Notification.MediaStyle(); 1252 Notification notification = new Notification.Builder(mContext, "test id") 1253 .setStyle(mediaStyle) 1254 .addExtras(extras) 1255 .build(); 1256 assertFalse(notification.isMediaNotification()); 1257 } 1258 validateColorizedPaletteForColor(int rawColor)1259 public void validateColorizedPaletteForColor(int rawColor) { 1260 Notification.Colors cDay = new Notification.Colors(); 1261 Notification.Colors cNight = new Notification.Colors(); 1262 boolean colorized = true; 1263 1264 resolveColorsInNightMode(false, cDay, rawColor, colorized); 1265 resolveColorsInNightMode(true, cNight, rawColor, colorized); 1266 1267 if (rawColor != Notification.COLOR_DEFAULT) { 1268 assertEquals(rawColor, cDay.getBackgroundColor()); 1269 assertEquals(rawColor, cNight.getBackgroundColor()); 1270 } 1271 1272 assertValid(cDay); 1273 assertValid(cNight); 1274 1275 if (rawColor != Notification.COLOR_DEFAULT) { 1276 // When a color is provided, night mode should have no effect on the notification 1277 assertEquals(cDay.getBackgroundColor(), cNight.getBackgroundColor()); 1278 assertEquals(cDay.getPrimaryTextColor(), cNight.getPrimaryTextColor()); 1279 assertEquals(cDay.getSecondaryTextColor(), cNight.getSecondaryTextColor()); 1280 assertEquals(cDay.getPrimaryAccentColor(), cNight.getPrimaryAccentColor()); 1281 assertEquals(cDay.getSecondaryAccentColor(), cNight.getSecondaryAccentColor()); 1282 assertEquals(cDay.getTertiaryAccentColor(), cNight.getTertiaryAccentColor()); 1283 assertEquals(cDay.getOnTertiaryAccentTextColor(), 1284 cNight.getOnTertiaryAccentTextColor()); 1285 assertEquals(cDay.getTertiaryFixedDimAccentColor(), 1286 cNight.getTertiaryFixedDimAccentColor()); 1287 assertEquals(cDay.getOnTertiaryFixedAccentTextColor(), 1288 cNight.getOnTertiaryFixedAccentTextColor()); 1289 assertEquals(cDay.getProtectionColor(), cNight.getProtectionColor()); 1290 assertEquals(cDay.getContrastColor(), cNight.getContrastColor()); 1291 assertEquals(cDay.getRippleAlpha(), cNight.getRippleAlpha()); 1292 } 1293 } 1294 1295 @Test testRecoverBuilder_nullExtraPeopleList_noCrash()1296 public void testRecoverBuilder_nullExtraPeopleList_noCrash() { 1297 Bundle extras = new Bundle(); 1298 extras.putParcelable(EXTRA_PEOPLE_LIST, null); 1299 1300 Notification n = new Notification.Builder(mContext, "test") 1301 .setSmallIcon(0) 1302 .addExtras(extras) 1303 .build(); 1304 Bundle fakeTypes = new Bundle(); 1305 fakeTypes.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, new Bundle()); 1306 1307 Notification.Builder.recoverBuilder(mContext, n); 1308 1309 // no crash, good 1310 } 1311 1312 @Test testVisitUris_invalidExtra_noCrash()1313 public void testVisitUris_invalidExtra_noCrash() { 1314 Notification n = new Notification.Builder(mContext, "test") 1315 .setSmallIcon(0) 1316 .build(); 1317 Bundle fakeTypes = new Bundle(); 1318 fakeTypes.putParcelable(EXTRA_LARGE_ICON_BIG, new Bundle()); 1319 fakeTypes.putParcelable(EXTRA_PICTURE_ICON, new Bundle()); 1320 fakeTypes.putParcelable(EXTRA_MESSAGING_PERSON, new Bundle()); 1321 1322 Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); 1323 n.visitUris(visitor); 1324 1325 // no crash, good 1326 } 1327 1328 @Test testRecoverBuilder_invalidExtra_noCrash()1329 public void testRecoverBuilder_invalidExtra_noCrash() { 1330 Notification n = new Notification.Builder(mContext, "test") 1331 .setSmallIcon(0) 1332 .build(); 1333 Bundle fakeTypes = new Bundle(); 1334 fakeTypes.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, new Bundle()); 1335 1336 Notification.Builder.recoverBuilder(mContext, n); 1337 1338 // no crash, good 1339 } 1340 1341 @Test testIsMediaNotification_invalidExtra_noCrash()1342 public void testIsMediaNotification_invalidExtra_noCrash() { 1343 Notification n = new Notification.Builder(mContext, "test") 1344 .setSmallIcon(0) 1345 .setStyle(new Notification.MediaStyle()) 1346 .build(); 1347 Bundle fakeTypes = new Bundle(); 1348 fakeTypes.putParcelable(EXTRA_MEDIA_SESSION, new Bundle()); 1349 1350 n.isMediaNotification(); 1351 1352 // no crash, good 1353 } 1354 1355 @Test testRestoreFromExtras_BigText_invalidExtra_noCrash()1356 public void testRestoreFromExtras_BigText_invalidExtra_noCrash() { 1357 Notification.Style style = new Notification.BigTextStyle(); 1358 Bundle fakeTypes = new Bundle(); 1359 fakeTypes.putParcelable(EXTRA_LARGE_ICON_BIG, new Bundle()); 1360 1361 1362 // no crash, good 1363 } 1364 1365 @Test testRestoreFromExtras_Messaging_invalidExtra_noCrash()1366 public void testRestoreFromExtras_Messaging_invalidExtra_noCrash() { 1367 Notification.Style style = new Notification.MessagingStyle("test"); 1368 Bundle fakeTypes = new Bundle(); 1369 fakeTypes.putParcelable(EXTRA_MESSAGING_PERSON, new Bundle()); 1370 fakeTypes.putParcelable(EXTRA_CONVERSATION_ICON, new Bundle()); 1371 1372 Notification n = new Notification.Builder(mContext, "test") 1373 .setStyle(style) 1374 .setExtras(fakeTypes) 1375 .build(); 1376 Notification.Builder.recoverBuilder(mContext, n); 1377 1378 // no crash, good 1379 } 1380 1381 @Test testRestoreFromExtras_Media_invalidExtra_noCrash()1382 public void testRestoreFromExtras_Media_invalidExtra_noCrash() { 1383 Notification.Style style = new Notification.MediaStyle(); 1384 Bundle fakeTypes = new Bundle(); 1385 fakeTypes.putParcelable(EXTRA_MEDIA_SESSION, new Bundle()); 1386 fakeTypes.putParcelable(EXTRA_MEDIA_REMOTE_INTENT, new Bundle()); 1387 1388 Notification n = new Notification.Builder(mContext, "test") 1389 .setStyle(style) 1390 .setExtras(fakeTypes) 1391 .build(); 1392 Notification.Builder.recoverBuilder(mContext, n); 1393 1394 // no crash, good 1395 } 1396 1397 @Test testRestoreFromExtras_Call_invalidExtra_noCrash()1398 public void testRestoreFromExtras_Call_invalidExtra_noCrash() { 1399 PendingIntent intent1 = PendingIntent.getActivity( 1400 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 1401 Notification.Style style = Notification.CallStyle.forIncomingCall( 1402 new Person.Builder().setName("hi").build(), intent1, intent1); 1403 1404 Bundle fakeTypes = new Bundle(); 1405 fakeTypes.putParcelable(EXTRA_CALL_PERSON, new Bundle()); 1406 fakeTypes.putParcelable(EXTRA_ANSWER_INTENT, new Bundle()); 1407 fakeTypes.putParcelable(EXTRA_DECLINE_INTENT, new Bundle()); 1408 fakeTypes.putParcelable(EXTRA_HANG_UP_INTENT, new Bundle()); 1409 1410 Notification n = new Notification.Builder(mContext, "test") 1411 .setStyle(style) 1412 .setExtras(fakeTypes) 1413 .build(); 1414 Notification.Builder.recoverBuilder(mContext, n); 1415 // no crash, good 1416 } 1417 1418 @Test testGetPictureIcon_invalidExtra_noCrash()1419 public void testGetPictureIcon_invalidExtra_noCrash() { 1420 Bundle fakeTypes = new Bundle(); 1421 fakeTypes.putParcelable(EXTRA_PICTURE, new Bundle()); 1422 fakeTypes.putParcelable(EXTRA_PICTURE_ICON, new Bundle()); 1423 1424 Notification.BigPictureStyle.getPictureIcon(fakeTypes); 1425 1426 // no crash, good 1427 } 1428 1429 @Test testWearableExtender_invalidExtra_noCrash()1430 public void testWearableExtender_invalidExtra_noCrash() { 1431 Notification n = new Notification.Builder(mContext, "test") 1432 .setSmallIcon(0) 1433 .setStyle(new Notification.MediaStyle()) 1434 .build(); 1435 Bundle fakeTypes = new Bundle(); 1436 fakeTypes.putParcelable(KEY_DISPLAY_INTENT, new Bundle()); 1437 fakeTypes.putParcelable(KEY_BACKGROUND, new Bundle()); 1438 Notification.WearableExtender extender = new Notification.WearableExtender(n); 1439 1440 // no crash, good 1441 } 1442 1443 @Test testCarExtender_invalidExtra_noCrash()1444 public void testCarExtender_invalidExtra_noCrash() { 1445 Notification n = new Notification.Builder(mContext, "test") 1446 .setSmallIcon(0) 1447 .setStyle(new Notification.MediaStyle()) 1448 .build(); 1449 Bundle fakeTypes = new Bundle(); 1450 fakeTypes.putParcelable(EXTRA_LARGE_ICON, new Bundle()); 1451 Notification.CarExtender extender = new Notification.CarExtender(n); 1452 1453 // no crash, good 1454 } 1455 1456 @Test testTvExtender_invalidExtra_noCrash()1457 public void testTvExtender_invalidExtra_noCrash() { 1458 Notification n = new Notification.Builder(mContext, "test") 1459 .setSmallIcon(0) 1460 .setStyle(new Notification.MediaStyle()) 1461 .build(); 1462 Bundle fakeTypes = new Bundle(); 1463 fakeTypes.putParcelable(EXTRA_CONTENT_INTENT, new Bundle()); 1464 fakeTypes.putParcelable(EXTRA_DELETE_INTENT, new Bundle()); 1465 Notification.TvExtender extender = new Notification.TvExtender(n); 1466 1467 // no crash, good 1468 } 1469 1470 @Test testGetUnreadConversationFromBundle_invalidExtra_noCrash()1471 public void testGetUnreadConversationFromBundle_invalidExtra_noCrash() { 1472 Bundle fakeTypes = new Bundle(); 1473 fakeTypes.putParcelable(KEY_ON_READ, new Bundle()); 1474 fakeTypes.putParcelable(KEY_ON_REPLY, new Bundle()); 1475 fakeTypes.putParcelable(KEY_REMOTE_INPUT, new Bundle()); 1476 1477 Notification n = new Notification.Builder(mContext, "test") 1478 .setExtras(fakeTypes) 1479 .build(); 1480 Notification.CarExtender extender = new Notification.CarExtender(n); 1481 1482 // no crash, good 1483 } 1484 1485 @Test testGetMessageFromBundle_invalidExtra_noCrash()1486 public void testGetMessageFromBundle_invalidExtra_noCrash() { 1487 Bundle fakeTypes = new Bundle(); 1488 fakeTypes.putParcelable(KEY_SENDER_PERSON, new Bundle()); 1489 fakeTypes.putString(KEY_TEXT, "text"); 1490 fakeTypes.putLong(KEY_TIMESTAMP, 0); 1491 fakeTypes.putParcelable(KEY_REMOTE_INPUT, new Bundle()); 1492 fakeTypes.putParcelable(KEY_DATA_URI, new Bundle()); 1493 Notification.MessagingStyle.Message.getMessageFromBundle(fakeTypes); 1494 1495 // no crash, good 1496 } 1497 1498 @Test testToBundle_getMessageFromBundle_returnsSameData()1499 public void testToBundle_getMessageFromBundle_returnsSameData() { 1500 Notification.MessagingStyle.Message message = 1501 new Notification.MessagingStyle.Message( 1502 "a", 100, new Person.Builder().setName("hi").build()); 1503 message.setData("text", Uri.parse("http://test/uri")); 1504 1505 Notification.MessagingStyle.Message convertedMessage = 1506 Notification.MessagingStyle.Message.getMessageFromBundle(message.toBundle()); 1507 1508 assertThat(convertedMessage).isNotNull(); 1509 assertThat(message.getText()).isEqualTo(convertedMessage.getText()); 1510 assertThat(message.getTimestamp()).isEqualTo(convertedMessage.getTimestamp()); 1511 assertThat(message.getExtras().size()).isEqualTo(convertedMessage.getExtras().size()); 1512 assertThat(message.getSender()).isEqualTo(convertedMessage.getSender()); 1513 assertThat(message.getSenderPerson()).isEqualTo(convertedMessage.getSenderPerson()); 1514 assertThat(message.getDataMimeType()).isEqualTo(convertedMessage.getDataMimeType()); 1515 assertThat(message.getDataUri()).isEqualTo(convertedMessage.getDataUri()); 1516 assertThat(message.isRemoteInputHistory()) 1517 .isEqualTo(convertedMessage.isRemoteInputHistory()); 1518 } 1519 1520 @Test testDoesNotStripsExtenders()1521 public void testDoesNotStripsExtenders() { 1522 Notification.Builder nb = new Notification.Builder(mContext, "channel"); 1523 nb.extend(new Notification.CarExtender().setColor(Color.RED)); 1524 nb.extend(new Notification.TvExtender().setChannelId("different channel")); 1525 nb.extend(new Notification.WearableExtender().setDismissalId("dismiss")); 1526 Notification before = nb.build(); 1527 Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before); 1528 1529 assertTrue(before == after); 1530 1531 Assert.assertEquals("different channel", 1532 new Notification.TvExtender(before).getChannelId()); 1533 Assert.assertEquals(Color.RED, new Notification.CarExtender(before).getColor()); 1534 Assert.assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId()); 1535 } 1536 1537 @Test areIconsDifferent_sameSmallIcon_false()1538 public void areIconsDifferent_sameSmallIcon_false() { 1539 Notification n1 = new Notification.Builder(mContext, "test").setSmallIcon(1).build(); 1540 Notification n2 = new Notification.Builder(mContext, "test").setSmallIcon(1).build(); 1541 1542 assertThat(Notification.areIconsDifferent(n1, n2)).isFalse(); 1543 } 1544 1545 @Test areIconsDifferent_differentSmallIcon_true()1546 public void areIconsDifferent_differentSmallIcon_true() { 1547 Notification n1 = new Notification.Builder(mContext, "test").setSmallIcon(1).build(); 1548 Notification n2 = new Notification.Builder(mContext, "test").setSmallIcon(2).build(); 1549 1550 assertThat(Notification.areIconsDifferent(n1, n2)).isTrue(); 1551 } 1552 1553 @Test areIconsDifferent_sameLargeIcon_false()1554 public void areIconsDifferent_sameLargeIcon_false() { 1555 Icon icon1 = Icon.createWithContentUri("uri"); 1556 Icon icon2 = Icon.createWithContentUri("uri"); 1557 Notification n1 = new Notification.Builder(mContext, "test") 1558 .setSmallIcon(1).setLargeIcon(icon1).build(); 1559 Notification n2 = new Notification.Builder(mContext, "test") 1560 .setSmallIcon(1).setLargeIcon(icon2).build(); 1561 1562 // Note that this will almost certainly not happen for Icons created from Bitmaps, since 1563 // their serialization/deserialization of Bitmaps (app -> system_process) results in a 1564 // different getGenerationId() value. :( 1565 assertThat(Notification.areIconsDifferent(n1, n2)).isFalse(); 1566 } 1567 1568 @Test areIconsDifferent_differentLargeIcon_true()1569 public void areIconsDifferent_differentLargeIcon_true() { 1570 Icon icon1 = Icon.createWithContentUri("uri1"); 1571 Icon icon2 = Icon.createWithContentUri("uri2"); 1572 Notification n1 = new Notification.Builder(mContext, "test") 1573 .setSmallIcon(1).setLargeIcon(icon1).build(); 1574 Notification n2 = new Notification.Builder(mContext, "test") 1575 .setSmallIcon(2).setLargeIcon(icon2).build(); 1576 1577 assertThat(Notification.areIconsDifferent(n1, n2)).isTrue(); 1578 } 1579 1580 @Test areIconsDifferent_addedLargeIcon_true()1581 public void areIconsDifferent_addedLargeIcon_true() { 1582 Icon icon = Icon.createWithContentUri("uri"); 1583 Notification n1 = new Notification.Builder(mContext, "test").setSmallIcon(1).build(); 1584 Notification n2 = new Notification.Builder(mContext, "test") 1585 .setSmallIcon(2).setLargeIcon(icon).build(); 1586 1587 assertThat(Notification.areIconsDifferent(n1, n2)).isTrue(); 1588 } 1589 1590 @Test areIconsDifferent_removedLargeIcon_true()1591 public void areIconsDifferent_removedLargeIcon_true() { 1592 Icon icon = Icon.createWithContentUri("uri"); 1593 Notification n1 = new Notification.Builder(mContext, "test") 1594 .setSmallIcon(1).setLargeIcon(icon).build(); 1595 Notification n2 = new Notification.Builder(mContext, "test").setSmallIcon(2).build(); 1596 1597 assertThat(Notification.areIconsDifferent(n1, n2)).isTrue(); 1598 } 1599 1600 @Test testStyleChangeVisiblyDifferent_noStyles()1601 public void testStyleChangeVisiblyDifferent_noStyles() { 1602 Notification.Builder n1 = new Notification.Builder(mContext, "test"); 1603 Notification.Builder n2 = new Notification.Builder(mContext, "test"); 1604 1605 assertFalse(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); 1606 } 1607 1608 @Test testStyleChangeVisiblyDifferent_noStyleToStyle()1609 public void testStyleChangeVisiblyDifferent_noStyleToStyle() { 1610 Notification.Builder n1 = new Notification.Builder(mContext, "test"); 1611 Notification.Builder n2 = new Notification.Builder(mContext, "test") 1612 .setStyle(new Notification.BigTextStyle()); 1613 1614 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); 1615 } 1616 1617 @Test testStyleChangeVisiblyDifferent_styleToNoStyle()1618 public void testStyleChangeVisiblyDifferent_styleToNoStyle() { 1619 Notification.Builder n2 = new Notification.Builder(mContext, "test"); 1620 Notification.Builder n1 = new Notification.Builder(mContext, "test") 1621 .setStyle(new Notification.BigTextStyle()); 1622 1623 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); 1624 } 1625 1626 @Test testStyleChangeVisiblyDifferent_changeStyle()1627 public void testStyleChangeVisiblyDifferent_changeStyle() { 1628 Notification.Builder n1 = new Notification.Builder(mContext, "test") 1629 .setStyle(new Notification.InboxStyle()); 1630 Notification.Builder n2 = new Notification.Builder(mContext, "test") 1631 .setStyle(new Notification.BigTextStyle()); 1632 1633 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); 1634 } 1635 1636 @Test testInboxTextChange()1637 public void testInboxTextChange() { 1638 Notification.Builder nInbox1 = new Notification.Builder(mContext, "test") 1639 .setStyle(new Notification.InboxStyle().addLine("a").addLine("b")); 1640 Notification.Builder nInbox2 = new Notification.Builder(mContext, "test") 1641 .setStyle(new Notification.InboxStyle().addLine("b").addLine("c")); 1642 1643 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nInbox1, nInbox2)); 1644 } 1645 1646 @Test testBigTextTextChange()1647 public void testBigTextTextChange() { 1648 Notification.Builder nBigText1 = new Notification.Builder(mContext, "test") 1649 .setStyle(new Notification.BigTextStyle().bigText("something")); 1650 Notification.Builder nBigText2 = new Notification.Builder(mContext, "test") 1651 .setStyle(new Notification.BigTextStyle().bigText("else")); 1652 1653 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigText1, nBigText2)); 1654 } 1655 1656 @Test testBigPictureChange()1657 public void testBigPictureChange() { 1658 Bitmap bitA = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); 1659 Bitmap bitB = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); 1660 1661 Notification.Builder nBigPic1 = new Notification.Builder(mContext, "test") 1662 .setStyle(new Notification.BigPictureStyle().bigPicture(bitA)); 1663 Notification.Builder nBigPic2 = new Notification.Builder(mContext, "test") 1664 .setStyle(new Notification.BigPictureStyle().bigPicture(bitB)); 1665 1666 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigPic1, nBigPic2)); 1667 } 1668 1669 @Test testBigPictureStyle_setExtras_pictureIconNull_noPictureIconKey()1670 public void testBigPictureStyle_setExtras_pictureIconNull_noPictureIconKey() { 1671 Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); 1672 bpStyle.bigPicture((Bitmap) null); 1673 1674 Bundle extras = new Bundle(); 1675 bpStyle.addExtras(extras); 1676 1677 assertThat(extras.containsKey(EXTRA_PICTURE_ICON)).isFalse(); 1678 } 1679 1680 @Test testBigPictureStyle_setExtras_pictureIconNull_noPictureKey()1681 public void testBigPictureStyle_setExtras_pictureIconNull_noPictureKey() { 1682 Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); 1683 bpStyle.bigPicture((Bitmap) null); 1684 1685 Bundle extras = new Bundle(); 1686 bpStyle.addExtras(extras); 1687 1688 assertThat(extras.containsKey(EXTRA_PICTURE)).isFalse(); 1689 } 1690 1691 @Test testBigPictureStyle_setExtras_pictureIconTypeBitmap_pictureIconKeyNull()1692 public void testBigPictureStyle_setExtras_pictureIconTypeBitmap_pictureIconKeyNull() { 1693 Bitmap bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); 1694 Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); 1695 bpStyle.bigPicture(bitmap); 1696 1697 Bundle extras = new Bundle(); 1698 bpStyle.addExtras(extras); 1699 1700 assertThat(extras.containsKey(EXTRA_PICTURE_ICON)).isTrue(); 1701 final Parcelable pictureIcon = extras.getParcelable(EXTRA_PICTURE_ICON); 1702 assertThat(pictureIcon).isNull(); 1703 } 1704 1705 @Test testBigPictureStyle_setExtras_pictureIconTypeIcon_pictureKeyNull()1706 public void testBigPictureStyle_setExtras_pictureIconTypeIcon_pictureKeyNull() { 1707 Icon icon = Icon.createWithResource(mContext, R.drawable.btn_plus); 1708 Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); 1709 bpStyle.bigPicture(icon); 1710 1711 Bundle extras = new Bundle(); 1712 bpStyle.addExtras(extras); 1713 1714 assertThat(extras.containsKey(EXTRA_PICTURE)).isTrue(); 1715 final Parcelable picture = extras.getParcelable(EXTRA_PICTURE); 1716 assertThat(picture).isNull(); 1717 } 1718 1719 @Test testMessagingChange_text()1720 public void testMessagingChange_text() { 1721 Notification.Builder nM1 = new Notification.Builder(mContext, "test") 1722 .setStyle(new Notification.MessagingStyle("") 1723 .addMessage(new Notification.MessagingStyle.Message( 1724 "a", 100, new Person.Builder().setName("hi").build()))); 1725 Notification.Builder nM2 = new Notification.Builder(mContext, "test") 1726 .setStyle(new Notification.MessagingStyle("") 1727 .addMessage(new Notification.MessagingStyle.Message( 1728 "a", 100, new Person.Builder().setName("hi").build())) 1729 .addMessage(new Notification.MessagingStyle.Message( 1730 "b", 100, new Person.Builder().setName("hi").build())) 1731 ); 1732 1733 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); 1734 } 1735 1736 @Test testMessagingChange_data()1737 public void testMessagingChange_data() { 1738 Notification.Builder nM1 = new Notification.Builder(mContext, "test") 1739 .setStyle(new Notification.MessagingStyle("") 1740 .addMessage(new Notification.MessagingStyle.Message( 1741 "a", 100, new Person.Builder().setName("hi").build()) 1742 .setData("text", mock(Uri.class)))); 1743 Notification.Builder nM2 = new Notification.Builder(mContext, "test") 1744 .setStyle(new Notification.MessagingStyle("") 1745 .addMessage(new Notification.MessagingStyle.Message( 1746 "a", 100, new Person.Builder().setName("hi").build()))); 1747 1748 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); 1749 } 1750 1751 @Test testMessagingChange_sender()1752 public void testMessagingChange_sender() { 1753 Person a = new Person.Builder().setName("A").build(); 1754 Person b = new Person.Builder().setName("b").build(); 1755 Notification.Builder nM1 = new Notification.Builder(mContext, "test") 1756 .setStyle(new Notification.MessagingStyle("") 1757 .addMessage(new Notification.MessagingStyle.Message("a", 100, b))); 1758 Notification.Builder nM2 = new Notification.Builder(mContext, "test") 1759 .setStyle(new Notification.MessagingStyle("") 1760 .addMessage(new Notification.MessagingStyle.Message("a", 100, a))); 1761 1762 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); 1763 } 1764 1765 @Test testMessagingChange_key()1766 public void testMessagingChange_key() { 1767 Person a = new Person.Builder().setName("hi").setKey("A").build(); 1768 Person b = new Person.Builder().setName("hi").setKey("b").build(); 1769 Notification.Builder nM1 = new Notification.Builder(mContext, "test") 1770 .setStyle(new Notification.MessagingStyle("") 1771 .addMessage(new Notification.MessagingStyle.Message("a", 100, a))); 1772 Notification.Builder nM2 = new Notification.Builder(mContext, "test") 1773 .setStyle(new Notification.MessagingStyle("") 1774 .addMessage(new Notification.MessagingStyle.Message("a", 100, b))); 1775 1776 assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); 1777 } 1778 1779 @Test testMessagingChange_ignoreTimeChange()1780 public void testMessagingChange_ignoreTimeChange() { 1781 Notification.Builder nM1 = new Notification.Builder(mContext, "test") 1782 .setStyle(new Notification.MessagingStyle("") 1783 .addMessage(new Notification.MessagingStyle.Message( 1784 "a", 100, new Person.Builder().setName("hi").build()))); 1785 Notification.Builder nM2 = new Notification.Builder(mContext, "test") 1786 .setStyle(new Notification.MessagingStyle("") 1787 .addMessage(new Notification.MessagingStyle.Message( 1788 "a", 1000, new Person.Builder().setName("hi").build())) 1789 ); 1790 1791 assertFalse(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); 1792 } 1793 1794 @Test testRemoteViews_nullChange()1795 public void testRemoteViews_nullChange() { 1796 Notification.Builder n1 = new Notification.Builder(mContext, "test") 1797 .setContent(mock(RemoteViews.class)); 1798 Notification.Builder n2 = new Notification.Builder(mContext, "test"); 1799 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1800 1801 n1 = new Notification.Builder(mContext, "test"); 1802 n2 = new Notification.Builder(mContext, "test") 1803 .setContent(mock(RemoteViews.class)); 1804 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1805 1806 n1 = new Notification.Builder(mContext, "test") 1807 .setCustomBigContentView(mock(RemoteViews.class)); 1808 n2 = new Notification.Builder(mContext, "test"); 1809 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1810 1811 n1 = new Notification.Builder(mContext, "test"); 1812 n2 = new Notification.Builder(mContext, "test") 1813 .setCustomBigContentView(mock(RemoteViews.class)); 1814 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1815 1816 n1 = new Notification.Builder(mContext, "test"); 1817 n2 = new Notification.Builder(mContext, "test"); 1818 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1819 } 1820 1821 @Test testRemoteViews_layoutChange()1822 public void testRemoteViews_layoutChange() { 1823 RemoteViews a = mock(RemoteViews.class); 1824 when(a.getLayoutId()).thenReturn(234); 1825 RemoteViews b = mock(RemoteViews.class); 1826 when(b.getLayoutId()).thenReturn(189); 1827 1828 Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); 1829 Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); 1830 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1831 1832 n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); 1833 n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); 1834 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1835 1836 n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); 1837 n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); 1838 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1839 } 1840 1841 @Test testRemoteViews_layoutSame()1842 public void testRemoteViews_layoutSame() { 1843 RemoteViews a = mock(RemoteViews.class); 1844 when(a.getLayoutId()).thenReturn(234); 1845 RemoteViews b = mock(RemoteViews.class); 1846 when(b.getLayoutId()).thenReturn(234); 1847 1848 Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); 1849 Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); 1850 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1851 1852 n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); 1853 n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); 1854 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1855 1856 n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); 1857 n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); 1858 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1859 } 1860 1861 @Test testRemoteViews_sequenceChange()1862 public void testRemoteViews_sequenceChange() { 1863 RemoteViews a = mock(RemoteViews.class); 1864 when(a.getLayoutId()).thenReturn(234); 1865 when(a.getSequenceNumber()).thenReturn(1); 1866 RemoteViews b = mock(RemoteViews.class); 1867 when(b.getLayoutId()).thenReturn(234); 1868 when(b.getSequenceNumber()).thenReturn(2); 1869 1870 Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); 1871 Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); 1872 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1873 1874 n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); 1875 n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); 1876 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1877 1878 n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); 1879 n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); 1880 assertTrue(Notification.areRemoteViewsChanged(n1, n2)); 1881 } 1882 1883 @Test testRemoteViews_sequenceSame()1884 public void testRemoteViews_sequenceSame() { 1885 RemoteViews a = mock(RemoteViews.class); 1886 when(a.getLayoutId()).thenReturn(234); 1887 when(a.getSequenceNumber()).thenReturn(1); 1888 RemoteViews b = mock(RemoteViews.class); 1889 when(b.getLayoutId()).thenReturn(234); 1890 when(b.getSequenceNumber()).thenReturn(1); 1891 1892 Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); 1893 Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); 1894 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1895 1896 n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); 1897 n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); 1898 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1899 1900 n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); 1901 n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); 1902 assertFalse(Notification.areRemoteViewsChanged(n1, n2)); 1903 } 1904 1905 @Test testActionsDifferent_null()1906 public void testActionsDifferent_null() { 1907 Notification n1 = new Notification.Builder(mContext, "test") 1908 .build(); 1909 Notification n2 = new Notification.Builder(mContext, "test") 1910 .build(); 1911 1912 assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); 1913 } 1914 1915 @Test testActionsDifferentSame()1916 public void testActionsDifferentSame() { 1917 PendingIntent intent = PendingIntent.getActivity( 1918 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 1919 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 1920 1921 Notification n1 = new Notification.Builder(mContext, "test") 1922 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) 1923 .build(); 1924 Notification n2 = new Notification.Builder(mContext, "test") 1925 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) 1926 .build(); 1927 1928 assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); 1929 } 1930 1931 @Test testActionsDifferentText()1932 public void testActionsDifferentText() { 1933 PendingIntent intent = PendingIntent.getActivity( 1934 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 1935 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 1936 1937 Notification n1 = new Notification.Builder(mContext, "test") 1938 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) 1939 .build(); 1940 Notification n2 = new Notification.Builder(mContext, "test") 1941 .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build()) 1942 .build(); 1943 1944 assertTrue(Notification.areActionsVisiblyDifferent(n1, n2)); 1945 } 1946 1947 @Test testActionsDifferentSpannables()1948 public void testActionsDifferentSpannables() { 1949 PendingIntent intent = PendingIntent.getActivity( 1950 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 1951 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 1952 1953 Notification n1 = new Notification.Builder(mContext, "test") 1954 .addAction(new Notification.Action.Builder(icon, 1955 new SpannableStringBuilder().append("test1", 1956 new StyleSpan(Typeface.BOLD), 1957 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE), 1958 intent).build()) 1959 .build(); 1960 Notification n2 = new Notification.Builder(mContext, "test") 1961 .addAction(new Notification.Action.Builder(icon, "test1", intent).build()) 1962 .build(); 1963 1964 assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); 1965 } 1966 1967 @Test testActionsDifferentNumber()1968 public void testActionsDifferentNumber() { 1969 PendingIntent intent = PendingIntent.getActivity( 1970 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 1971 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 1972 1973 Notification n1 = new Notification.Builder(mContext, "test") 1974 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) 1975 .build(); 1976 Notification n2 = new Notification.Builder(mContext, "test") 1977 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) 1978 .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build()) 1979 .build(); 1980 1981 assertTrue(Notification.areActionsVisiblyDifferent(n1, n2)); 1982 } 1983 1984 @Test testActionsDifferentIntent()1985 public void testActionsDifferentIntent() { 1986 PendingIntent intent1 = PendingIntent.getActivity( 1987 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 1988 PendingIntent intent2 = PendingIntent.getActivity( 1989 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); 1990 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 1991 1992 Notification n1 = new Notification.Builder(mContext, "test") 1993 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent1).build()) 1994 .build(); 1995 Notification n2 = new Notification.Builder(mContext, "test") 1996 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent2).build()) 1997 .build(); 1998 1999 assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); 2000 } 2001 2002 @Test testActionsIgnoresRemoteInputs()2003 public void testActionsIgnoresRemoteInputs() { 2004 PendingIntent intent = PendingIntent.getActivity( 2005 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 2006 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2007 2008 Notification n1 = new Notification.Builder(mContext, "test") 2009 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) 2010 .addRemoteInput(new RemoteInput.Builder("a") 2011 .setChoices(new CharSequence[] {"i", "m"}) 2012 .build()) 2013 .build()) 2014 .build(); 2015 Notification n2 = new Notification.Builder(mContext, "test") 2016 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) 2017 .addRemoteInput(new RemoteInput.Builder("a") 2018 .setChoices(new CharSequence[] {"t", "m"}) 2019 .build()) 2020 .build()) 2021 .build(); 2022 2023 assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); 2024 } 2025 2026 @Test testFreeformRemoteInputActionPair_noRemoteInput()2027 public void testFreeformRemoteInputActionPair_noRemoteInput() { 2028 PendingIntent intent = PendingIntent.getActivity( 2029 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 2030 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2031 Notification notification = new Notification.Builder(mContext, "test") 2032 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) 2033 .build()) 2034 .build(); 2035 Assert.assertNull(notification.findRemoteInputActionPair(false)); 2036 } 2037 2038 @Test testFreeformRemoteInputActionPair_hasRemoteInput()2039 public void testFreeformRemoteInputActionPair_hasRemoteInput() { 2040 PendingIntent intent = PendingIntent.getActivity( 2041 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 2042 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2043 2044 RemoteInput remoteInput = new RemoteInput.Builder("a").build(); 2045 2046 Notification.Action actionWithRemoteInput = 2047 new Notification.Action.Builder(icon, "TEXT 1", intent) 2048 .addRemoteInput(remoteInput) 2049 .addRemoteInput(remoteInput) 2050 .build(); 2051 2052 Notification.Action actionWithoutRemoteInput = 2053 new Notification.Action.Builder(icon, "TEXT 2", intent) 2054 .build(); 2055 2056 Notification notification = new Notification.Builder(mContext, "test") 2057 .addAction(actionWithoutRemoteInput) 2058 .addAction(actionWithRemoteInput) 2059 .build(); 2060 2061 Pair<RemoteInput, Notification.Action> remoteInputActionPair = 2062 notification.findRemoteInputActionPair(false); 2063 2064 assertNotNull(remoteInputActionPair); 2065 Assert.assertEquals(remoteInput, remoteInputActionPair.first); 2066 Assert.assertEquals(actionWithRemoteInput, remoteInputActionPair.second); 2067 } 2068 2069 @Test testFreeformRemoteInputActionPair_requestFreeform_noFreeformRemoteInput()2070 public void testFreeformRemoteInputActionPair_requestFreeform_noFreeformRemoteInput() { 2071 PendingIntent intent = PendingIntent.getActivity( 2072 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 2073 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2074 Notification notification = new Notification.Builder(mContext, "test") 2075 .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) 2076 .addRemoteInput( 2077 new RemoteInput.Builder("a") 2078 .setAllowFreeFormInput(false).build()) 2079 .build()) 2080 .build(); 2081 Assert.assertNull(notification.findRemoteInputActionPair(true)); 2082 } 2083 2084 @Test testFreeformRemoteInputActionPair_requestFreeform_hasFreeformRemoteInput()2085 public void testFreeformRemoteInputActionPair_requestFreeform_hasFreeformRemoteInput() { 2086 PendingIntent intent = PendingIntent.getActivity( 2087 mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; 2088 Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2089 2090 RemoteInput remoteInput = 2091 new RemoteInput.Builder("a").setAllowFreeFormInput(false).build(); 2092 RemoteInput freeformRemoteInput = 2093 new RemoteInput.Builder("b").setAllowFreeFormInput(true).build(); 2094 2095 Notification.Action actionWithFreeformRemoteInput = 2096 new Notification.Action.Builder(icon, "TEXT 1", intent) 2097 .addRemoteInput(remoteInput) 2098 .addRemoteInput(freeformRemoteInput) 2099 .build(); 2100 2101 Notification.Action actionWithoutFreeformRemoteInput = 2102 new Notification.Action.Builder(icon, "TEXT 2", intent) 2103 .addRemoteInput(remoteInput) 2104 .build(); 2105 2106 Notification notification = new Notification.Builder(mContext, "test") 2107 .addAction(actionWithoutFreeformRemoteInput) 2108 .addAction(actionWithFreeformRemoteInput) 2109 .build(); 2110 2111 Pair<RemoteInput, Notification.Action> remoteInputActionPair = 2112 notification.findRemoteInputActionPair(true); 2113 2114 assertNotNull(remoteInputActionPair); 2115 Assert.assertEquals(freeformRemoteInput, remoteInputActionPair.first); 2116 Assert.assertEquals(actionWithFreeformRemoteInput, remoteInputActionPair.second); 2117 } 2118 2119 // Ensures that extras in a Notification Builder can be updated. 2120 @Test testExtras_cachedExtrasOverwrittenByUserProvided()2121 public void testExtras_cachedExtrasOverwrittenByUserProvided() { 2122 Bundle extras = new Bundle(); 2123 extras.putCharSequence(EXTRA_TITLE, "test title"); 2124 extras.putCharSequence(EXTRA_SUMMARY_TEXT, "summary text"); 2125 2126 Notification.Builder builder = new Notification.Builder(mContext, "test id") 2127 .addExtras(extras); 2128 2129 Notification notification = builder.build(); 2130 assertThat(notification.extras.getCharSequence(EXTRA_TITLE).toString()).isEqualTo( 2131 "test title"); 2132 assertThat(notification.extras.getCharSequence(EXTRA_SUMMARY_TEXT).toString()).isEqualTo( 2133 "summary text"); 2134 2135 extras.putCharSequence(EXTRA_TITLE, "new title"); 2136 builder.addExtras(extras); 2137 notification = builder.build(); 2138 assertThat(notification.extras.getCharSequence(EXTRA_TITLE).toString()).isEqualTo( 2139 "new title"); 2140 assertThat(notification.extras.getCharSequence(EXTRA_SUMMARY_TEXT).toString()).isEqualTo( 2141 "summary text"); 2142 } 2143 2144 // Ensures that extras in a Notification Builder can be updated by an extender. 2145 @Test testExtras_cachedExtrasOverwrittenByExtender()2146 public void testExtras_cachedExtrasOverwrittenByExtender() { 2147 Notification.CarExtender extender = new Notification.CarExtender().setColor(1234); 2148 2149 Notification notification = new Notification.Builder(mContext, "test id") 2150 .extend(extender).build(); 2151 2152 extender.setColor(5678); 2153 2154 Notification.Builder.recoverBuilder(mContext, notification).extend(extender).build(); 2155 2156 Notification.CarExtender recoveredExtender = new Notification.CarExtender(notification); 2157 assertThat(recoveredExtender.getColor()).isEqualTo(5678); 2158 } 2159 2160 @Test 2161 @CoreCompatChangeRule.EnableCompatChanges({Notification.WEARABLE_EXTENDER_BACKGROUND_BLOCKED}) wearableBackgroundBlockEnabled_wearableBackgroundSet_valueRemainsNull()2162 public void wearableBackgroundBlockEnabled_wearableBackgroundSet_valueRemainsNull() { 2163 Notification.WearableExtender extender = new Notification.WearableExtender(); 2164 Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); 2165 extender.setBackground(bitmap); 2166 Notification notif = 2167 new Notification.Builder(mContext, "test id") 2168 .setSmallIcon(1) 2169 .setContentTitle("test_title") 2170 .extend(extender) 2171 .build(); 2172 2173 Notification.WearableExtender result = new Notification.WearableExtender(notif); 2174 Assert.assertNull(result.getBackground()); 2175 } 2176 2177 @Test 2178 @CoreCompatChangeRule.DisableCompatChanges({Notification.WEARABLE_EXTENDER_BACKGROUND_BLOCKED}) wearableBackgroundBlockDisabled_wearableBackgroundSet_valueKeepsBitmap()2179 public void wearableBackgroundBlockDisabled_wearableBackgroundSet_valueKeepsBitmap() { 2180 Notification.WearableExtender extender = new Notification.WearableExtender(); 2181 Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); 2182 extender.setBackground(bitmap); 2183 Notification notif = 2184 new Notification.Builder(mContext, "test id") 2185 .setSmallIcon(1) 2186 .setContentTitle("test_title") 2187 .extend(extender) 2188 .build(); 2189 2190 Notification.WearableExtender result = new Notification.WearableExtender(notif); 2191 Bitmap resultBitmap = result.getBackground(); 2192 assertNotNull(resultBitmap); 2193 Assert.assertEquals(bitmap, resultBitmap); 2194 } 2195 2196 @Test testGetWhen_zero()2197 public void testGetWhen_zero() { 2198 Notification n = new Notification.Builder(mContext, "test") 2199 .setWhen(0) 2200 .build(); 2201 2202 mSetFlagsRule.disableFlags(Flags.FLAG_SORT_SECTION_BY_TIME); 2203 2204 assertThat(n.getWhen()).isEqualTo(0); 2205 2206 mSetFlagsRule.enableFlags(Flags.FLAG_SORT_SECTION_BY_TIME); 2207 2208 assertThat(n.getWhen()).isEqualTo(n.creationTime); 2209 } 2210 2211 @Test testGetWhen_devProvidedNonZero()2212 public void testGetWhen_devProvidedNonZero() { 2213 Notification n = new Notification.Builder(mContext, "test") 2214 .setWhen(9) 2215 .build(); 2216 2217 mSetFlagsRule.disableFlags(Flags.FLAG_SORT_SECTION_BY_TIME); 2218 2219 assertThat(n.getWhen()).isEqualTo(9); 2220 2221 mSetFlagsRule.enableFlags(Flags.FLAG_SORT_SECTION_BY_TIME); 2222 2223 assertThat(n.getWhen()).isEqualTo(9); 2224 } 2225 2226 @Test getNotificationStyleClass_forPlatformClassName_returnsPlatformClass()2227 public void getNotificationStyleClass_forPlatformClassName_returnsPlatformClass() { 2228 final List<Class<? extends Notification.Style>> platformStyleClasses = List.of( 2229 Notification.BigTextStyle.class, Notification.BigPictureStyle.class, 2230 Notification.MessagingStyle.class, Notification.CallStyle.class, 2231 Notification.InboxStyle.class, Notification.MediaStyle.class, 2232 Notification.DecoratedCustomViewStyle.class, 2233 Notification.DecoratedMediaCustomViewStyle.class 2234 ); 2235 2236 for (Class<? extends Notification.Style> platformStyleClass : platformStyleClasses) { 2237 assertThat(Notification.getNotificationStyleClass(platformStyleClass.getName())) 2238 .isEqualTo(platformStyleClass); 2239 } 2240 } 2241 2242 @Test getNotificationStyleClass_forNotPlatformClassName_returnsNull()2243 public void getNotificationStyleClass_forNotPlatformClassName_returnsNull() { 2244 assertThat(Notification.getNotificationStyleClass(NotAPlatformStyle.class.getName())) 2245 .isNull(); 2246 } 2247 2248 @Test 2249 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_richOngoingEnabled_platformClass()2250 public void progressStyle_richOngoingEnabled_platformClass() { 2251 assertThat( 2252 Notification.getNotificationStyleClass(Notification.ProgressStyle.class.getName())) 2253 .isEqualTo(Notification.ProgressStyle.class); 2254 } 2255 2256 @Test 2257 @DisableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_richOngoingDisabled_notPlatformClass()2258 public void progressStyle_richOngoingDisabled_notPlatformClass() { 2259 assertThat( 2260 Notification.getNotificationStyleClass(Notification.ProgressStyle.class.getName())) 2261 .isNull(); 2262 } 2263 2264 @Test 2265 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onSegmentChange_visiblyDifferent()2266 public void progressStyle_onSegmentChange_visiblyDifferent() { 2267 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2268 .setStyle(new Notification.ProgressStyle() 2269 .addProgressSegment(new Notification.ProgressStyle.Segment(100)) 2270 .addProgressSegment(new Notification.ProgressStyle.Segment(50) 2271 .setColor(Color.RED))); 2272 2273 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2274 .setStyle(new Notification.ProgressStyle() 2275 .addProgressSegment(new Notification.ProgressStyle.Segment(100)) 2276 .addProgressSegment(new Notification.ProgressStyle.Segment(50) 2277 .setColor(Color.BLUE))); 2278 2279 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2280 .isTrue(); 2281 } 2282 2283 @Test 2284 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) indeterminateProgressStyle_onSegmentChange_visiblyNotDifferent()2285 public void indeterminateProgressStyle_onSegmentChange_visiblyNotDifferent() { 2286 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2287 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) 2288 .addProgressSegment(new Notification.ProgressStyle.Segment(100)) 2289 .addProgressSegment(new Notification.ProgressStyle.Segment(50) 2290 .setColor(Color.RED))); 2291 2292 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2293 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) 2294 .addProgressSegment(new Notification.ProgressStyle.Segment(100)) 2295 .addProgressSegment(new Notification.ProgressStyle.Segment(50) 2296 .setColor(Color.BLUE))); 2297 2298 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2299 .isFalse(); 2300 } 2301 2302 @Test 2303 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onStartIconChange_visiblyDifferent()2304 public void progressStyle_onStartIconChange_visiblyDifferent() { 2305 final Icon icon1 = Icon.createWithBitmap(BitmapFactory.decodeResource( 2306 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); 2307 2308 final Icon icon2 = Icon.createWithBitmap( 2309 Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2310 2311 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2312 .setStyle(new Notification.ProgressStyle().setProgressStartIcon(icon1)); 2313 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2314 .setStyle(new Notification.ProgressStyle().setProgressStartIcon(icon2)); 2315 2316 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2317 .isTrue(); 2318 } 2319 2320 @Test 2321 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onEndIconChange_visiblyDifferent()2322 public void progressStyle_onEndIconChange_visiblyDifferent() { 2323 final Icon icon1 = Icon.createWithBitmap(BitmapFactory.decodeResource( 2324 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); 2325 2326 final Icon icon2 = Icon.createWithBitmap( 2327 Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2328 2329 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2330 .setStyle(new Notification.ProgressStyle().setProgressEndIcon(icon1)); 2331 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2332 .setStyle(new Notification.ProgressStyle().setProgressEndIcon(icon2)); 2333 2334 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2335 .isTrue(); 2336 } 2337 2338 @Test 2339 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onProgressChange_visiblyDifferent()2340 public void progressStyle_onProgressChange_visiblyDifferent() { 2341 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2342 .setStyle(new Notification.ProgressStyle().setProgress(20)); 2343 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2344 .setStyle(new Notification.ProgressStyle().setProgress(21)); 2345 2346 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2347 .isTrue(); 2348 } 2349 2350 @Test 2351 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) indeterminateProgressStyle_onProgressChange_visiblyNotDifferent()2352 public void indeterminateProgressStyle_onProgressChange_visiblyNotDifferent() { 2353 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2354 .setStyle(new Notification.ProgressStyle() 2355 .setProgressIndeterminate(true).setProgress(20)); 2356 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2357 .setStyle(new Notification.ProgressStyle() 2358 .setProgressIndeterminate(true).setProgress(21)); 2359 2360 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2361 .isFalse(); 2362 } 2363 2364 @Test 2365 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onIsStyledByProgressChange_visiblyDifferent()2366 public void progressStyle_onIsStyledByProgressChange_visiblyDifferent() { 2367 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2368 .setStyle(new Notification.ProgressStyle().setStyledByProgress(true)); 2369 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2370 .setStyle(new Notification.ProgressStyle().setStyledByProgress(false)); 2371 2372 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2373 .isTrue(); 2374 } 2375 2376 @Test 2377 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) indeterminateProgressStyle_onIsStyledByProgressChange_visiblyNotDifferent()2378 public void indeterminateProgressStyle_onIsStyledByProgressChange_visiblyNotDifferent() { 2379 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2380 .setStyle(new Notification.ProgressStyle() 2381 .setProgressIndeterminate(true).setStyledByProgress(true)); 2382 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2383 .setStyle(new Notification.ProgressStyle() 2384 .setProgressIndeterminate(true).setStyledByProgress(false)); 2385 2386 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2387 .isFalse(); 2388 } 2389 2390 @Test 2391 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onProgressPointChange_visiblyDifferent()2392 public void progressStyle_onProgressPointChange_visiblyDifferent() { 2393 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2394 .setStyle(new Notification.ProgressStyle() 2395 .addProgressPoint(new Notification.ProgressStyle.Point(10))); 2396 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2397 .setStyle(new Notification.ProgressStyle() 2398 .addProgressPoint(new Notification.ProgressStyle.Point(12))); 2399 2400 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2401 .isTrue(); 2402 } 2403 2404 @Test 2405 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) indeterminateProgressStyle_onProgressPointChange_visiblyNotDifferent()2406 public void indeterminateProgressStyle_onProgressPointChange_visiblyNotDifferent() { 2407 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2408 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) 2409 .addProgressPoint(new Notification.ProgressStyle.Point(10))); 2410 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2411 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) 2412 .addProgressPoint(new Notification.ProgressStyle.Point(12))); 2413 2414 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2415 .isFalse(); 2416 } 2417 2418 @Test 2419 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onTrackerIconChange_visiblyDifferent()2420 public void progressStyle_onTrackerIconChange_visiblyDifferent() { 2421 final Icon icon1 = Icon.createWithBitmap(BitmapFactory.decodeResource( 2422 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); 2423 2424 final Icon icon2 = Icon.createWithBitmap( 2425 Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2426 2427 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2428 .setStyle(new Notification.ProgressStyle().setProgressTrackerIcon(icon1)); 2429 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2430 .setStyle(new Notification.ProgressStyle().setProgressTrackerIcon(icon2)); 2431 2432 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2433 .isTrue(); 2434 } 2435 2436 @Test 2437 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) indeterminateProgressStyle_onTrackerIconChange_visiblyNotDifferent()2438 public void indeterminateProgressStyle_onTrackerIconChange_visiblyNotDifferent() { 2439 final Icon icon1 = Icon.createWithBitmap(BitmapFactory.decodeResource( 2440 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); 2441 2442 final Icon icon2 = Icon.createWithBitmap( 2443 Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); 2444 2445 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2446 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) 2447 .setProgressTrackerIcon(icon1)); 2448 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2449 .setStyle(new Notification.ProgressStyle() 2450 .setProgressIndeterminate(true).setProgressTrackerIcon(icon2)); 2451 2452 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2453 .isFalse(); 2454 } 2455 2456 @Test 2457 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_onIndeterminateChange_visiblyDifferent()2458 public void progressStyle_onIndeterminateChange_visiblyDifferent() { 2459 final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") 2460 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true)); 2461 final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") 2462 .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(false)); 2463 2464 assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) 2465 .isTrue(); 2466 } 2467 2468 @Test 2469 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_getProgressMax_default100()2470 public void progressStyle_getProgressMax_default100() { 2471 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2472 assertThat(progressStyle.getProgressMax()).isEqualTo(100); 2473 } 2474 2475 @Test 2476 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_getProgressMax_noSegments_returnsDefault()2477 public void progressStyle_getProgressMax_noSegments_returnsDefault() { 2478 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2479 progressStyle.setProgressSegments(Collections.emptyList()); 2480 assertThat(progressStyle.getProgressMax()).isEqualTo(100); 2481 } 2482 2483 @Test 2484 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_getProgressMax_returnsSumOfSegmentLength()2485 public void progressStyle_getProgressMax_returnsSumOfSegmentLength() { 2486 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2487 progressStyle 2488 .setProgressSegments(List.of(new Notification.ProgressStyle.Segment(15), 2489 new Notification.ProgressStyle.Segment(25))) 2490 .addProgressSegment(new Notification.ProgressStyle.Segment(10)) 2491 .addProgressSegment(new Notification.ProgressStyle.Segment(20)); 2492 2493 assertThat(progressStyle.getProgressMax()).isEqualTo(70); 2494 } 2495 2496 @Test 2497 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_getProgressMax_onSetProgressSegments_resets()2498 public void progressStyle_getProgressMax_onSetProgressSegments_resets() { 2499 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2500 progressStyle 2501 .addProgressSegment(new Notification.ProgressStyle.Segment(10)) 2502 .addProgressSegment(new Notification.ProgressStyle.Segment(20)) 2503 .setProgressSegments(List.of(new Notification.ProgressStyle.Segment(15), 2504 new Notification.ProgressStyle.Segment(25))); 2505 2506 assertThat(progressStyle.getProgressMax()).isEqualTo(40); 2507 } 2508 2509 @Test 2510 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_getProgressMax_onSegmentOverflow_returnsDefault()2511 public void progressStyle_getProgressMax_onSegmentOverflow_returnsDefault() { 2512 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2513 progressStyle 2514 .addProgressSegment(new Notification.ProgressStyle.Segment(Integer.MAX_VALUE)) 2515 .addProgressSegment(new Notification.ProgressStyle.Segment(10)); 2516 2517 assertThat(progressStyle.getProgressMax()).isEqualTo(100); 2518 } 2519 2520 @Test 2521 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_getProgressMax_onSegmentLimitExceeded_returnsSumOfSegmentLength()2522 public void progressStyle_getProgressMax_onSegmentLimitExceeded_returnsSumOfSegmentLength() { 2523 // GIVEN 2524 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2525 // limit is 10 for ProgressStyle 2526 for (int i = 0; i < 30; i++) { 2527 progressStyle 2528 .addProgressSegment(new Notification.ProgressStyle.Segment(10)); 2529 } 2530 2531 // THEN 2532 assertThat(progressStyle.getProgressMax()).isEqualTo(300); 2533 } 2534 2535 @Test 2536 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_addProgressSegment_dropsInvalidSegments()2537 public void progressStyle_addProgressSegment_dropsInvalidSegments() { 2538 // GIVEN 2539 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2540 // Segments should be a positive integer. 2541 progressStyle 2542 .addProgressSegment(new Notification.ProgressStyle.Segment(0)); 2543 progressStyle 2544 .addProgressSegment(new Notification.ProgressStyle.Segment(-1)); 2545 2546 // THEN 2547 assertThat(progressStyle.getProgressSegments()).isEmpty(); 2548 } 2549 2550 @Test 2551 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_setProgressSegment_dropsInvalidSegments()2552 public void progressStyle_setProgressSegment_dropsInvalidSegments() { 2553 // GIVEN 2554 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2555 // Segments should be a positive integer. 2556 progressStyle 2557 .setProgressSegments(List.of(new Notification.ProgressStyle.Segment(0), 2558 new Notification.ProgressStyle.Segment(-1))); 2559 2560 // THEN 2561 assertThat(progressStyle.getProgressSegments()).isEmpty(); 2562 } 2563 2564 @Test 2565 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_addProgressPoint_dropsNegativePoints()2566 public void progressStyle_addProgressPoint_dropsNegativePoints() { 2567 // GIVEN 2568 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2569 // Points should not be a negative integer. 2570 progressStyle 2571 .addProgressPoint(new Notification.ProgressStyle.Point(-1)) 2572 .addProgressPoint(new Notification.ProgressStyle.Point(-100)); 2573 2574 // THEN 2575 assertThat(progressStyle.getProgressPoints()).isEmpty(); 2576 } 2577 2578 @Test 2579 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_setProgressPoint_dropsNegativePoints()2580 public void progressStyle_setProgressPoint_dropsNegativePoints() { 2581 // GIVEN 2582 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2583 // Points should not be a negative integer. 2584 progressStyle 2585 .setProgressPoints(List.of(new Notification.ProgressStyle.Point(-1), 2586 new Notification.ProgressStyle.Point(-100))); 2587 2588 // THEN 2589 assertThat(progressStyle.getProgressPoints()).isEmpty(); 2590 } 2591 2592 @Test 2593 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_addProgressPoint_dropsZeroPoints()2594 public void progressStyle_addProgressPoint_dropsZeroPoints() { 2595 // GIVEN 2596 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2597 // Points should not be a negative integer. 2598 progressStyle 2599 .addProgressPoint(new Notification.ProgressStyle.Point(0)); 2600 2601 // THEN 2602 assertThat(progressStyle.getProgressPoints()).isEmpty(); 2603 } 2604 2605 @Test 2606 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_setProgressPoint_dropsZeroPoints()2607 public void progressStyle_setProgressPoint_dropsZeroPoints() { 2608 // GIVEN 2609 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2610 // Points should not be a negative integer. 2611 progressStyle 2612 .setProgressPoints(List.of(new Notification.ProgressStyle.Point(0))); 2613 2614 // THEN 2615 assertThat(progressStyle.getProgressPoints()).isEmpty(); 2616 } 2617 2618 @Test 2619 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_createProgressModel_ignoresPointsAtMax()2620 public void progressStyle_createProgressModel_ignoresPointsAtMax() { 2621 // GIVEN 2622 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2623 progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100)); 2624 // Points should not larger than progress maximum. 2625 progressStyle 2626 .addProgressPoint(new Notification.ProgressStyle.Point(100)); 2627 2628 // THEN 2629 assertThat(progressStyle.createProgressModel(Color.BLUE, Color.RED).getPoints()).isEmpty(); 2630 } 2631 2632 @Test 2633 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_createProgressModel_ignoresPointsExceedingMax()2634 public void progressStyle_createProgressModel_ignoresPointsExceedingMax() { 2635 // GIVEN 2636 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2637 progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100)); 2638 // Points should not larger than progress maximum. 2639 progressStyle 2640 .addProgressPoint(new Notification.ProgressStyle.Point(101)) 2641 .addProgressPoint(new Notification.ProgressStyle.Point(500)); 2642 2643 // THEN 2644 assertThat(progressStyle.createProgressModel(Color.BLUE, Color.RED).getPoints()).isEmpty(); 2645 } 2646 2647 @Test 2648 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_createProgressModel_ignoresOverLimitPoints()2649 public void progressStyle_createProgressModel_ignoresOverLimitPoints() { 2650 // GIVEN 2651 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2652 progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100)); 2653 2654 // maximum 4 points are going to be rendered. 2655 progressStyle 2656 .addProgressPoint(new Notification.ProgressStyle.Point(0)) 2657 .addProgressPoint(new Notification.ProgressStyle.Point(20)) 2658 .addProgressPoint(new Notification.ProgressStyle.Point(150)) 2659 .addProgressPoint(new Notification.ProgressStyle.Point(50)) 2660 .addProgressPoint(new Notification.ProgressStyle.Point(70)) 2661 .addProgressPoint(new Notification.ProgressStyle.Point(80)) 2662 .addProgressPoint(new Notification.ProgressStyle.Point(90)) 2663 .addProgressPoint(new Notification.ProgressStyle.Point(95)) 2664 .addProgressPoint(new Notification.ProgressStyle.Point(100)); 2665 final int backgroundColor = Color.RED; 2666 final int defaultProgressColor = Color.BLUE; 2667 final int expectedProgressColor = Notification.ProgressStyle.sanitizeProgressColor( 2668 /* color = */Notification.COLOR_DEFAULT, 2669 /* bg = */backgroundColor, 2670 /* defaultColor = */defaultProgressColor); 2671 2672 // THEN 2673 assertThat(progressStyle.createProgressModel(defaultProgressColor, backgroundColor) 2674 .getPoints()).isEqualTo( 2675 List.of(new Notification.ProgressStyle.Point(20) 2676 .setColor(expectedProgressColor), 2677 new Notification.ProgressStyle.Point(50) 2678 .setColor(expectedProgressColor), 2679 new Notification.ProgressStyle.Point(70) 2680 .setColor(expectedProgressColor), 2681 new Notification.ProgressStyle.Point(80) 2682 .setColor(expectedProgressColor) 2683 ) 2684 ); 2685 } 2686 2687 @Test 2688 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_createProgressModel_mergeSegmentsOnOverflow()2689 public void progressStyle_createProgressModel_mergeSegmentsOnOverflow() { 2690 // GIVEN 2691 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2692 2693 for (int i = 0; i < 15; i++) { 2694 progressStyle 2695 .addProgressSegment(new Notification.ProgressStyle.Segment(10)); 2696 } 2697 2698 final NotificationProgressModel progressModel = progressStyle.createProgressModel( 2699 Color.BLUE, Color.RED); 2700 2701 // THEN 2702 assertThat(progressModel.getSegments().size()).isEqualTo(1); 2703 assertThat(progressModel.getProgressMax()).isEqualTo(150); 2704 } 2705 2706 @Test 2707 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_createProgressModel_useSegmentColorWhenAllMatch()2708 public void progressStyle_createProgressModel_useSegmentColorWhenAllMatch() { 2709 // GIVEN 2710 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2711 final int segmentColor = Color.YELLOW; 2712 final int defaultProgressColor = Color.BLUE; 2713 final int backgroundColor = Color.RED; 2714 // contrast ensured color for segmentColor. 2715 final int expectedSegmentColor = Notification.ProgressStyle.sanitizeProgressColor( 2716 /* color = */ segmentColor, 2717 /* bg = */ backgroundColor, 2718 /* defaultColor = */ defaultProgressColor); 2719 2720 for (int i = 0; i < 15; i++) { 2721 progressStyle 2722 .addProgressSegment(new Notification.ProgressStyle.Segment(10) 2723 .setColor(segmentColor)); 2724 } 2725 2726 final NotificationProgressModel progressModel = progressStyle.createProgressModel( 2727 defaultProgressColor, backgroundColor); 2728 2729 // THEN 2730 assertThat(progressModel.getSegments()) 2731 .isEqualTo(List.of(new Notification.ProgressStyle.Segment(150) 2732 .setColor(expectedSegmentColor))); 2733 } 2734 2735 @Test 2736 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_createProgressModel_useDefaultColorWhenAllNotMatch()2737 public void progressStyle_createProgressModel_useDefaultColorWhenAllNotMatch() { 2738 // GIVEN 2739 final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle(); 2740 final int defaultProgressColor = Color.BLUE; 2741 final int backgroundColor = Color.RED; 2742 // contrast ensured color for default progress color. 2743 final int expectedSegmentColor = Notification.ProgressStyle.sanitizeProgressColor( 2744 /* color = */ defaultProgressColor, 2745 /* bg = */ backgroundColor, 2746 /* defaultColor = */ defaultProgressColor); 2747 2748 for (int i = 0; i < 15; i++) { 2749 progressStyle 2750 .addProgressSegment(new Notification.ProgressStyle.Segment(5) 2751 .setColor(Color.BLUE)) 2752 .addProgressSegment(new Notification.ProgressStyle.Segment(5) 2753 .setColor(Color.CYAN)); 2754 } 2755 2756 final NotificationProgressModel progressModel = progressStyle.createProgressModel( 2757 defaultProgressColor, backgroundColor); 2758 2759 // THEN 2760 assertThat(progressModel.getSegments()) 2761 .isEqualTo(List.of(new Notification.ProgressStyle.Segment(150) 2762 .setColor(expectedSegmentColor))); 2763 } 2764 2765 @Test 2766 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_indeterminate_defaultValueFalse()2767 public void progressStyle_indeterminate_defaultValueFalse() { 2768 final Notification.ProgressStyle progressStyle1 = new Notification.ProgressStyle(); 2769 2770 assertThat(progressStyle1.isProgressIndeterminate()).isFalse(); 2771 } 2772 2773 @Test 2774 @EnableFlags(Flags.FLAG_API_RICH_ONGOING) progressStyle_styledByProgress_defaultValueTrue()2775 public void progressStyle_styledByProgress_defaultValueTrue() { 2776 final Notification.ProgressStyle progressStyle1 = new Notification.ProgressStyle(); 2777 2778 assertThat(progressStyle1.isStyledByProgress()).isTrue(); 2779 } assertValid(Notification.Colors c)2780 private void assertValid(Notification.Colors c) { 2781 // Assert that all colors are populated 2782 assertThat(c.getBackgroundColor()).isNotEqualTo(Notification.COLOR_INVALID); 2783 assertThat(c.getProtectionColor()).isNotEqualTo(Notification.COLOR_INVALID); 2784 assertThat(c.getPrimaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID); 2785 assertThat(c.getSecondaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID); 2786 assertThat(c.getPrimaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); 2787 assertThat(c.getSecondaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); 2788 assertThat(c.getTertiaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); 2789 assertThat(c.getOnTertiaryAccentTextColor()).isNotEqualTo(Notification.COLOR_INVALID); 2790 assertThat(c.getTertiaryFixedDimAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); 2791 assertThat(c.getOnTertiaryFixedAccentTextColor()).isNotEqualTo(Notification.COLOR_INVALID); 2792 assertThat(c.getErrorColor()).isNotEqualTo(Notification.COLOR_INVALID); 2793 assertThat(c.getContrastColor()).isNotEqualTo(Notification.COLOR_INVALID); 2794 assertThat(c.getRippleAlpha()).isAtLeast(0x00); 2795 assertThat(c.getRippleAlpha()).isAtMost(0xff); 2796 2797 // Assert that various colors have sufficient contrast with the background 2798 assertContrastIsAtLeast(c.getPrimaryTextColor(), c.getBackgroundColor(), 4.5); 2799 assertContrastIsAtLeast(c.getSecondaryTextColor(), c.getBackgroundColor(), 4.5); 2800 assertContrastIsAtLeast(c.getPrimaryAccentColor(), c.getBackgroundColor(), 4.5); 2801 assertContrastIsAtLeast(c.getErrorColor(), c.getBackgroundColor(), 4.5); 2802 assertContrastIsAtLeast(c.getContrastColor(), c.getBackgroundColor(), 4.5); 2803 2804 // These colors are only used for emphasized buttons; they do not need contrast 2805 assertContrastIsAtLeast(c.getSecondaryAccentColor(), c.getBackgroundColor(), 1); 2806 assertContrastIsAtLeast(c.getTertiaryAccentColor(), c.getBackgroundColor(), 1); 2807 assertContrastIsAtLeast(c.getTertiaryFixedDimAccentColor(), c.getBackgroundColor(), 1); 2808 2809 // The text that is used within the accent color DOES need to have contrast 2810 assertContrastIsAtLeast(c.getOnTertiaryAccentTextColor(), c.getTertiaryAccentColor(), 4.5); 2811 assertContrastIsAtLeast(c.getOnTertiaryFixedAccentTextColor(), 2812 c.getTertiaryFixedDimAccentColor(), 4.5); 2813 } 2814 resolveColorsInNightMode(boolean nightMode, Notification.Colors c, int rawColor, boolean colorized)2815 private void resolveColorsInNightMode(boolean nightMode, Notification.Colors c, int rawColor, 2816 boolean colorized) { 2817 runInNightMode(nightMode, 2818 () -> c.resolvePalette(mContext, rawColor, colorized, nightMode)); 2819 } 2820 runInNightMode(boolean nightMode, Runnable task)2821 private void runInNightMode(boolean nightMode, Runnable task) { 2822 final String initialNightMode = changeNightMode(nightMode); 2823 try { 2824 Configuration currentConfig = mContext.getResources().getConfiguration(); 2825 boolean isNightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) 2826 == Configuration.UI_MODE_NIGHT_YES; 2827 assertEquals(nightMode, isNightMode); 2828 task.run(); 2829 } finally { 2830 runShellCommand("cmd uimode night " + initialNightMode); 2831 } 2832 } 2833 2834 2835 // Change the night mode and return the previous mode changeNightMode(boolean nightMode)2836 private String changeNightMode(boolean nightMode) { 2837 final String nightModeText = runShellCommand("cmd uimode night"); 2838 final String[] nightModeSplit = nightModeText.split(":"); 2839 if (nightModeSplit.length != 2) { 2840 fail("Failed to get initial night mode value from " + nightModeText); 2841 } 2842 String previousMode = nightModeSplit[1].trim(); 2843 runShellCommand("cmd uimode night " + (nightMode ? "yes" : "no")); 2844 return previousMode; 2845 } 2846 2847 /** 2848 * Writes an arbitrary {@link Parcelable} into a {@link Parcel} using its writeToParcel 2849 * method before reading it out again to check that it was sent properly. 2850 */ writeAndReadParcelable(T original)2851 private static <T extends Parcelable> T writeAndReadParcelable(T original) { 2852 Parcel p = Parcel.obtain(); 2853 p.writeParcelable(original, /* flags */ 0); 2854 p.setDataPosition(0); 2855 return p.readParcelable(/* classLoader */ null); 2856 } 2857 2858 /** 2859 * Creates a Notification.Action by mocking initial dependencies and then applying 2860 * transformations if they're defined. 2861 */ makeNotificationAction( @ullable Consumer<Notification.Action.Builder> transformation)2862 private Notification.Action makeNotificationAction( 2863 @Nullable Consumer<Notification.Action.Builder> transformation) { 2864 Notification.Action.Builder actionBuilder = 2865 new Notification.Action.Builder(null, "Test Title", null); 2866 if (transformation != null) { 2867 transformation.accept(actionBuilder); 2868 } 2869 return actionBuilder.build(); 2870 } 2871 2872 /** 2873 * Creates a PendingIntent with the given action. 2874 */ createPendingIntent(String action)2875 private PendingIntent createPendingIntent(String action) { 2876 return PendingIntent.getActivity(mContext, 0, 2877 new Intent(action).setPackage(mContext.getPackageName()), 2878 PendingIntent.FLAG_MUTABLE); 2879 } 2880 2881 private static class NotAPlatformStyle extends Notification.Style { 2882 @Override areNotificationsVisiblyDifferent(Notification.Style other)2883 public boolean areNotificationsVisiblyDifferent(Notification.Style other) { 2884 return false; 2885 } 2886 } 2887 } 2888