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

Commit 85ec837b authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Lighten SBNs

Drop heavy objects that aren't needed for processing

Test: atest, hprof after change
Fixes: 130434362
Change-Id: I95cd6431736502b36c3aba7a2fe516253e574764
Merged-In: I95cd6431736502b36c3aba7a2fe516253e574764
parent a47236b5
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.service.notification.NotificationListenerService.Ranking.U

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityThread;
import android.app.INotificationManager;
import android.app.Notification;
@@ -71,6 +72,7 @@ import java.util.concurrent.Executors;
/**
 * Notification assistant that provides guidance on notification channel blocking
 */
@SuppressLint("OverrideAbstract")
public class Assistant extends NotificationAssistantService {
    private static final String TAG = "ExtAssistant";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -238,7 +240,7 @@ public class Assistant extends NotificationAssistantService {
        }
        mSingleThreadExecutor.submit(() -> {
            NotificationEntry entry =
                    new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
                    new NotificationEntry(getContext(), mPackageManager, sbn, channel, mSmsHelper);
            SmartActionsHelper.SmartSuggestions suggestions = mSmartActionsHelper.suggest(entry);
            if (DEBUG) {
                Log.d(TAG, String.format(
@@ -295,7 +297,7 @@ public class Assistant extends NotificationAssistantService {
            }
            Ranking ranking = getRanking(sbn.getKey(), rankingMap);
            if (ranking != null && ranking.getChannel() != null) {
                NotificationEntry entry = new NotificationEntry(mPackageManager,
                NotificationEntry entry = new NotificationEntry(getContext(), mPackageManager,
                        sbn, ranking.getChannel(), mSmsHelper);
                String key = getKey(
                        sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
+73 −3
Original line number Diff line number Diff line
@@ -28,18 +28,23 @@ import android.app.NotificationChannel;
import android.app.Person;
import android.app.RemoteInput;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioSystem;
import android.os.Build;
import android.os.Parcelable;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Objects;
import java.util.Set;

/**
 * Holds data about notifications.
@@ -47,6 +52,10 @@ import java.util.Objects;
public class NotificationEntry {
    static final String TAG = "NotificationEntry";

    // Copied from hidden definitions in Notification.TvExtender
    private static final String EXTRA_TV_EXTENDER = "android.tv.EXTENSIONS";

    private final Context mContext;
    private final StatusBarNotification mSbn;
    private final IPackageManager mPackageManager;
    private int mTargetSdkVersion = Build.VERSION_CODES.N_MR1;
@@ -60,9 +69,10 @@ public class NotificationEntry {

    private final Object mLock = new Object();

    public NotificationEntry(IPackageManager packageManager, StatusBarNotification sbn,
            NotificationChannel channel, SmsHelper smsHelper) {
        mSbn = sbn;
    public NotificationEntry(Context applicationContext, IPackageManager packageManager,
            StatusBarNotification sbn, NotificationChannel channel, SmsHelper smsHelper) {
        mContext = applicationContext;
        mSbn = cloneStatusBarNotificationLight(sbn);
        mChannel = channel;
        mPackageManager = packageManager;
        mPreChannelsNotification = isPreChannelsNotification();
@@ -71,6 +81,66 @@ public class NotificationEntry {
        mSmsHelper = smsHelper;
    }

    /** Adapted from {@code Notification.lightenPayload}. */
    @SuppressWarnings("nullness")
    private static void lightenNotificationPayload(Notification notification) {
        notification.tickerView = null;
        notification.contentView = null;
        notification.bigContentView = null;
        notification.headsUpContentView = null;
        notification.largeIcon = null;
        if (notification.extras != null && !notification.extras.isEmpty()) {
            final Set<String> keyset = notification.extras.keySet();
            final int keysetSize = keyset.size();
            final String[] keys = keyset.toArray(new String[keysetSize]);
            for (int i = 0; i < keysetSize; i++) {
                final String key = keys[i];
                if (EXTRA_TV_EXTENDER.equals(key)
                        || Notification.EXTRA_MESSAGES.equals(key)
                        || Notification.EXTRA_MESSAGING_PERSON.equals(key)
                        || Notification.EXTRA_PEOPLE_LIST.equals(key)) {
                    continue;
                }
                final Object obj = notification.extras.get(key);
                if (obj != null
                        && (obj instanceof Parcelable
                        || obj instanceof Parcelable[]
                        || obj instanceof SparseArray
                        || obj instanceof ArrayList)) {
                    notification.extras.remove(key);
                }
            }
        }
    }

    /** An interpretation of {@code Notification.cloneInto} with heavy=false. */
    private Notification cloneNotificationLight(Notification notification) {
        // We can't just use clone() here because the only way to remove the icons is with the
        // builder, which we can only create with a Context.
        Notification lightNotification =
                Notification.Builder.recoverBuilder(mContext, notification)
                        .setSmallIcon(0)
                        .setLargeIcon((Icon) null)
                        .build();
        lightenNotificationPayload(lightNotification);
        return lightNotification;
    }

    /** Adapted from {@code StatusBarNotification.cloneLight}. */
    public StatusBarNotification cloneStatusBarNotificationLight(StatusBarNotification sbn) {
        return new StatusBarNotification(
                sbn.getPackageName(),
                sbn.getOpPkg(),
                sbn.getId(),
                sbn.getTag(),
                sbn.getUid(),
                /*initialPid=*/ 0,
                /*score=*/ 0,
                cloneNotificationLight(sbn.getNotification()),
                sbn.getUser(),
                sbn.getPostTime());
    }

    private boolean isPreChannelsNotification() {
        try {
            ApplicationInfo info = mPackageManager.getApplicationInfo(
+8 −4
Original line number Diff line number Diff line
@@ -102,7 +102,8 @@ public class AgingHelperTest {
    public void testNoSnoozingOnPost() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        StatusBarNotification sbn = generateSbn(channel.getId());
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);


        mAgingHelper.onNotificationPosted(entry);
@@ -113,7 +114,8 @@ public class AgingHelperTest {
    public void testPostResetsSnooze() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        StatusBarNotification sbn = generateSbn(channel.getId());
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);


        mAgingHelper.onNotificationPosted(entry);
@@ -124,7 +126,8 @@ public class AgingHelperTest {
    public void testSnoozingOnSeen() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        StatusBarNotification sbn = generateSbn(channel.getId());
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);
        entry.setSeen();
        when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE);

@@ -137,7 +140,8 @@ public class AgingHelperTest {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
        StatusBarNotification sbn = generateSbn(channel.getId());
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);
        when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE);

        mAgingHelper.onNotificationSeen(entry);
+4 −2
Original line number Diff line number Diff line
@@ -468,8 +468,10 @@ public class AssistantTest extends ServiceTestCase<Assistant> {
    @Test
    public void testAssistantNeverIncreasesImportanceWhenSuggestingSilent() throws Exception {
        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C3, "min notif!", null);
        Adjustment adjust = mAssistant.createEnqueuedNotificationAdjustment(new NotificationEntry(
                mPackageManager, sbn, P1C3, mSmsHelper), new ArrayList<>(), new ArrayList<>());
        Adjustment adjust = mAssistant.createEnqueuedNotificationAdjustment(
                new NotificationEntry(mContext, mPackageManager, sbn, P1C3, mSmsHelper),
                new ArrayList<>(),
                new ArrayList<>());
        assertEquals(IMPORTANCE_MIN, adjust.getSignals().getInt(Adjustment.KEY_IMPORTANCE));
    }
}
+47 −21
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.media.AudioAttributes.USAGE_ALARM;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
@@ -34,6 +35,8 @@ import android.app.Person;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.os.Build;
import android.os.Process;
@@ -41,9 +44,6 @@ import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.testing.TestableContext;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -53,6 +53,9 @@ import org.mockito.MockitoAnnotations;

import java.util.ArrayList;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

@RunWith(AndroidJUnit4.class)
public class NotificationEntryTest {
    private String mPkg = "pkg";
@@ -113,7 +116,8 @@ public class NotificationEntryTest {
        people.add(new Person.Builder().setKey("mailto:testing@android.com").build());
        sbn.getNotification().extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, people);

        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);
        assertTrue(entry.involvesPeople());
    }

@@ -121,7 +125,8 @@ public class NotificationEntryTest {
    public void testNotPerson() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        StatusBarNotification sbn = generateSbn(channel.getId());
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);
        assertFalse(entry.involvesPeople());
    }

@@ -129,7 +134,8 @@ public class NotificationEntryTest {
    public void testHasPerson_matchesDefaultSmsApp() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        StatusBarNotification sbn = generateSbn(channel.getId(), DEFAULT_SMS_PACKAGE_NAME);
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);
        assertTrue(entry.involvesPeople());
    }

@@ -137,7 +143,8 @@ public class NotificationEntryTest {
    public void testHasPerson_doesntMatchDefaultSmsApp() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        StatusBarNotification sbn = generateSbn(channel.getId(), "abc");
        NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, sbn, channel, mSmsHelper);
        assertFalse(entry.involvesPeople());
    }

@@ -148,8 +155,8 @@ public class NotificationEntryTest {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setStyle(new Notification.InboxStyle())
                .build();
        NotificationEntry entry =
                new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
        assertTrue(entry.hasStyle(Notification.InboxStyle.class));
    }

@@ -160,8 +167,8 @@ public class NotificationEntryTest {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setStyle(new Notification.MessagingStyle(""))
                .build();
        NotificationEntry entry =
                new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
        assertTrue(entry.hasStyle(Notification.MessagingStyle.class));
    }

@@ -172,8 +179,8 @@ public class NotificationEntryTest {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setStyle(new Notification.BigPictureStyle())
                .build();
        NotificationEntry entry =
                new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);
        assertFalse(entry.hasStyle(Notification.InboxStyle.class));
        assertFalse(entry.hasStyle(Notification.MessagingStyle.class));
    }
@@ -184,7 +191,7 @@ public class NotificationEntryTest {
        channel.setSound(null, new AudioAttributes.Builder().setUsage(USAGE_ALARM).build());

        NotificationEntry entry = new NotificationEntry(
                mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
                mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);

        assertTrue(entry.isAudioAttributesUsage(USAGE_ALARM));
    }
@@ -193,7 +200,7 @@ public class NotificationEntryTest {
    public void testIsNotAudioAttributes() {
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
        NotificationEntry entry = new NotificationEntry(
                mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);
                mContext, mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper);

        assertFalse(entry.isAudioAttributesUsage(USAGE_ALARM));
    }
@@ -205,8 +212,8 @@ public class NotificationEntryTest {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setCategory(Notification.CATEGORY_EMAIL)
                .build();
        NotificationEntry entry =
                new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);

        assertTrue(entry.isCategory(Notification.CATEGORY_EMAIL));
        assertFalse(entry.isCategory(Notification.CATEGORY_MESSAGE));
@@ -219,8 +226,8 @@ public class NotificationEntryTest {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setFlag(FLAG_FOREGROUND_SERVICE, true)
                .build();
        NotificationEntry entry =
                new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);

        assertTrue(entry.isOngoing());
    }
@@ -232,9 +239,28 @@ public class NotificationEntryTest {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setFlag(FLAG_CAN_COLORIZE, true)
                .build();
        NotificationEntry entry =
                new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper);
        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);

        assertFalse(entry.isOngoing());
    }

    @Test
    public void testShrinkNotification() {
        Notification n = new Notification.Builder(mContext, "")
                .setLargeIcon(Icon.createWithResource(
                        mContext, android.R.drawable.alert_dark_frame))
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .build();
        n.largeIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);

        NotificationEntry entry = new NotificationEntry(
                mContext, mPackageManager, generateSbn(n), channel, mSmsHelper);

        assertNull(entry.getNotification().getSmallIcon());
        assertNull(entry.getNotification().getLargeIcon());
        assertNull(entry.getNotification().largeIcon);
        assertNull(entry.getNotification().extras.getParcelable(Notification.EXTRA_LARGE_ICON));
    }
}
Loading