From 5c8e246f55ec93fb18391e538c9a1614e37c939d Mon Sep 17 00:00:00 2001 From: Jernej Virag Date: Mon, 24 Jan 2022 18:01:14 +0000 Subject: [PATCH] Limit the maximum size of small notification icons Right now, the size of small notification icons is unbounded and can cause big memory usage spikes (easily measured as 50MB+). This limits the maximum size of small icon when its set as a bitmap. Bug:193720474 Bug:209044537 Test: manual via test app Test: atest NotificationTest Change-Id: I684fe29d5b473d86280035e00298c8e59f47dbb7 --- core/java/android/app/Notification.java | 12 ++++++++++++ core/res/res/values/dimens.xml | 4 ++++ core/res/res/values/symbols.xml | 2 ++ .../src/android/app/NotificationTest.java | 17 +++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 779552f1bbed4..d57c288165d50 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -6712,6 +6712,18 @@ public class Notification implements Parcelable return; } boolean isLowRam = ActivityManager.isLowRamDeviceStatic(); + + if (mSmallIcon != null + // Only bitmap icons can be downscaled. + && (mSmallIcon.getType() == Icon.TYPE_BITMAP + || mSmallIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP)) { + Resources resources = context.getResources(); + int maxSize = resources.getDimensionPixelSize( + isLowRam ? R.dimen.notification_small_icon_size_low_ram + : R.dimen.notification_small_icon_size); + mSmallIcon.scaleDownIfNecessary(maxSize, maxSize); + } + if (mLargeIcon != null || largeIcon != null) { Resources resources = context.getResources(); Class style = getNotificationStyle(); diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 3f08e4b9d9ad0..d374b74aa947c 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -755,6 +755,8 @@ 120dp 800dp + + 48dp 284dp @@ -779,6 +781,8 @@ 0.5 + + @dimen/notification_small_icon_size 208dp diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4d8f9a2aa1d5a..8a12375b5ccdc 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3561,6 +3561,7 @@ + @@ -3569,6 +3570,7 @@ + diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index 37cf514e92eae..e6d23643e8c03 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -39,6 +39,7 @@ import android.content.Intent; import android.content.LocusId; import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.Icon; @@ -503,6 +504,22 @@ public class NotificationTest { .isGreaterThan(ContrastColorUtil.calculateLuminance(background)); } + @Test + public void testBuild_ensureSmallIconIsNotTooBig_resizesIcon() { + Icon hugeIcon = Icon.createWithBitmap( + Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); + Notification notification = new Notification.Builder(mContext, "Channel").setSmallIcon( + hugeIcon).build(); + + Bitmap smallNotificationIcon = notification.getSmallIcon().getBitmap(); + assertThat(smallNotificationIcon.getWidth()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_small_icon_size)); + assertThat(smallNotificationIcon.getHeight()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_small_icon_size)); + } + @Test public void testColors_ensureColors_dayMode_producesValidPalette() { Notification.Colors c = new Notification.Colors();