From 31f403284e2b2fa88cca68974b2ad902dca01521 Mon Sep 17 00:00:00 2001 From: Julia Tuttle <juliatuttle@google.com> Date: Mon, 18 Dec 2023 13:13:21 -0500 Subject: [PATCH] BigPictureStyle: set unused big picture extra to null ag/24426105 changed BigPictureStyle so that whichever of EXTRA_PICTURE or EXTRA_PICTURE_ICON wasn't set to the big picture would be *removed* instead of set to null. This was an app-visible behavior change, and turned out to break one of our own tests, b/315128763. Since it has the potential to affect apps that interact with notifications, I'm modifying it to preserve the old null value behavior, while leaving the other bitmap expiration work in that change alone. Bug: 290381858 Bug: 315128763 Test: atest NotificationTest Test: atest NotificationManagerServiceTest Flag: NA (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:297baf11fc11c065f9661efc3dd253c0c332c803) Merged-In: Ifef48da0ba6c0314dffef9ac04e5018bfb85b91b Change-Id: Ifef48da0ba6c0314dffef9ac04e5018bfb85b91b --- core/java/android/app/Notification.java | 7 +++--- .../src/android/app/NotificationTest.java | 24 ++++++++++++------- .../NotificationManagerService.java | 13 ++++++---- .../NotificationManagerServiceTest.java | 9 +++++-- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 013bcddbb7f3..7454e52b50ef 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -7702,11 +7702,12 @@ public class Notification implements Parcelable } else if (mPictureIcon.getType() == Icon.TYPE_BITMAP) { // If the icon contains a bitmap, use the old extra so that listeners which look // for that extra can still find the picture. Don't include the new extra in - // that case, to avoid duplicating data. + // that case, to avoid duplicating data. Leave the unused extra set to null to avoid + // crashing apps that came to expect it to be present but null. extras.putParcelable(EXTRA_PICTURE, mPictureIcon.getBitmap()); - extras.remove(EXTRA_PICTURE_ICON); + extras.putParcelable(EXTRA_PICTURE_ICON, null); } else { - extras.remove(EXTRA_PICTURE); + extras.putParcelable(EXTRA_PICTURE, null); extras.putParcelable(EXTRA_PICTURE_ICON, mPictureIcon); } } diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index 1577d9c1c1ab..5b0502da1bdf 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -1244,29 +1244,33 @@ public class NotificationTest { } @Test - public void testBigPictureStyle_setExtras_pictureIconNull_noPictureIconKey() { + public void testBigPictureStyle_setExtras_pictureIconNull_pictureIconKeyNull() { Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); bpStyle.bigPicture((Bitmap) null); Bundle extras = new Bundle(); bpStyle.addExtras(extras); - assertThat(extras.containsKey(EXTRA_PICTURE_ICON)).isFalse(); + assertThat(extras.containsKey(EXTRA_PICTURE_ICON)).isTrue(); + final Parcelable pictureIcon = extras.getParcelable(EXTRA_PICTURE_ICON); + assertThat(pictureIcon).isNull(); } @Test - public void testBigPictureStyle_setExtras_pictureIconNull_noPictureKey() { + public void testBigPictureStyle_setExtras_pictureIconNull_pictureKeyNull() { Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); bpStyle.bigPicture((Bitmap) null); Bundle extras = new Bundle(); bpStyle.addExtras(extras); - assertThat(extras.containsKey(EXTRA_PICTURE)).isFalse(); + assertThat(extras.containsKey(EXTRA_PICTURE)).isTrue(); + final Parcelable picture = extras.getParcelable(EXTRA_PICTURE); + assertThat(picture).isNull(); } @Test - public void testBigPictureStyle_setExtras_pictureIconTypeBitmap_noPictureIconKey() { + public void testBigPictureStyle_setExtras_pictureIconTypeBitmap_pictureIconKeyNull() { Bitmap bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); bpStyle.bigPicture(bitmap); @@ -1274,11 +1278,13 @@ public class NotificationTest { Bundle extras = new Bundle(); bpStyle.addExtras(extras); - assertThat(extras.containsKey(EXTRA_PICTURE_ICON)).isFalse(); + assertThat(extras.containsKey(EXTRA_PICTURE_ICON)).isTrue(); + final Parcelable pictureIcon = extras.getParcelable(EXTRA_PICTURE_ICON); + assertThat(pictureIcon).isNull(); } @Test - public void testBigPictureStyle_setExtras_pictureIconTypeIcon_noPictureKey() { + public void testBigPictureStyle_setExtras_pictureIconTypeIcon_pictureKeyNull() { Icon icon = Icon.createWithResource(mContext, R.drawable.btn_plus); Notification.BigPictureStyle bpStyle = new Notification.BigPictureStyle(); bpStyle.bigPicture(icon); @@ -1286,7 +1292,9 @@ public class NotificationTest { Bundle extras = new Bundle(); bpStyle.addExtras(extras); - assertThat(extras.containsKey(EXTRA_PICTURE)).isFalse(); + assertThat(extras.containsKey(EXTRA_PICTURE)).isTrue(); + final Parcelable picture = extras.getParcelable(EXTRA_PICTURE); + assertThat(picture).isNull(); } @Test diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index e7ae61072db4..6b956e2ae9d7 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6985,12 +6985,14 @@ public class NotificationManagerService extends SystemService { return false; } - final boolean hasBitmap = n.extras.containsKey(Notification.EXTRA_PICTURE); + final boolean hasBitmap = n.extras.containsKey(Notification.EXTRA_PICTURE) + && n.extras.getParcelable(Notification.EXTRA_PICTURE) != null; if (hasBitmap) { return true; } - final boolean hasIcon = n.extras.containsKey(Notification.EXTRA_PICTURE_ICON); + final boolean hasIcon = n.extras.containsKey(Notification.EXTRA_PICTURE_ICON) + && n.extras.getParcelable(Notification.EXTRA_PICTURE_ICON) != null; if (hasIcon) { return true; } @@ -7006,9 +7008,10 @@ public class NotificationManagerService extends SystemService { if (!isBigPictureWithBitmapOrIcon(r.getNotification())) { return; } - // Remove Notification object's reference to picture bitmap or URI - r.getNotification().extras.remove(Notification.EXTRA_PICTURE); - r.getNotification().extras.remove(Notification.EXTRA_PICTURE_ICON); + // Remove Notification object's reference to picture bitmap or URI. Leave the extras set to + // null to avoid crashing apps that came to expect them to be present but null. + r.getNotification().extras.putParcelable(Notification.EXTRA_PICTURE, null); + r.getNotification().extras.putParcelable(Notification.EXTRA_PICTURE_ICON, null); // Make Notification silent r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 776189eeb7c3..b93fffcb1869 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -11978,7 +11978,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { /* isImageBitmap= */ true, /* isExpired= */ true); addRecordAndRemoveBitmaps(record); - assertThat(record.getNotification().extras.containsKey(EXTRA_PICTURE)).isFalse(); + assertThat(record.getNotification().extras.containsKey(EXTRA_PICTURE)).isTrue(); + final Parcelable picture = record.getNotification().extras.getParcelable(EXTRA_PICTURE); + assertThat(picture).isNull(); } @Test @@ -12012,7 +12014,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { /* isImageBitmap= */ false, /* isExpired= */ true); addRecordAndRemoveBitmaps(record); - assertThat(record.getNotification().extras.containsKey(EXTRA_PICTURE_ICON)).isFalse(); + assertThat(record.getNotification().extras.containsKey(EXTRA_PICTURE_ICON)).isTrue(); + final Parcelable pictureIcon = + record.getNotification().extras.getParcelable(EXTRA_PICTURE_ICON); + assertThat(pictureIcon).isNull(); } @Test -- GitLab