Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c8e246f authored by Jernej Virag's avatar Jernej Virag
Browse files

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
parent 2b2ddee2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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<? extends Style> style = getNotificationStyle();
+4 −0
Original line number Diff line number Diff line
@@ -755,6 +755,8 @@
    <dimen name="item_touch_helper_swipe_escape_velocity">120dp</dimen>
    <dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>

    <!-- The maximum size of the small notification icon. -->
    <dimen name="notification_small_icon_size">48dp</dimen>
    <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined by the maximum notification height -->
    <dimen name="notification_custom_view_max_image_height">284dp</dimen>
    <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined a maximum notification width -->
@@ -779,6 +781,8 @@
    <!-- The alpha of a disabled notification button -->
    <item type="dimen" format="float" name="notification_action_disabled_alpha">0.5</item>

    <!-- The maximum size of the small notification icon on low memory devices. -->
    <dimen name="notification_small_icon_size_low_ram">@dimen/notification_small_icon_size</dimen>
    <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
    <dimen name="notification_custom_view_max_image_height_low_ram">208dp</dimen>
    <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
+2 −0
Original line number Diff line number Diff line
@@ -3561,6 +3561,7 @@
  <java-symbol type="style" name="Theme.DeviceDefault.Autofill.Save" />
  <java-symbol type="style" name="Theme.DeviceDefault.Light.Autofill.Save" />

  <java-symbol type="dimen" name="notification_small_icon_size"/>
  <java-symbol type="dimen" name="notification_big_picture_max_height"/>
  <java-symbol type="dimen" name="notification_big_picture_max_width"/>
  <java-symbol type="dimen" name="notification_right_icon_size"/>
@@ -3569,6 +3570,7 @@
  <java-symbol type="dimen" name="notification_custom_view_max_image_height"/>
  <java-symbol type="dimen" name="notification_custom_view_max_image_width"/>

  <java-symbol type="dimen" name="notification_small_icon_size_low_ram"/>
  <java-symbol type="dimen" name="notification_big_picture_max_height_low_ram"/>
  <java-symbol type="dimen" name="notification_big_picture_max_width_low_ram"/>
  <java-symbol type="dimen" name="notification_right_icon_size_low_ram"/>
+17 −0
Original line number Diff line number Diff line
@@ -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();