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

Commit 1c7b6944 authored by Ioana Alexandru's avatar Ioana Alexandru
Browse files

Implement caching in NotifIconStyleProvider

Bug: 371174789
Test: PreparationCoordinatorTest
Flag: android.app.notifications_redesign_app_icons
Change-Id: I796ef12168432b5483fc6955db41c0b893301bff
parent b6cf4489
Loading
Loading
Loading
Loading
+52 −3
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.notification.collection.render.GroupMember
import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import com.android.systemui.statusbar.notification.row.icon.AppIconProvider;
import com.android.systemui.statusbar.notification.row.icon.NotificationIconStyleProvider;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
import com.android.systemui.util.settings.SecureSettings;

@@ -119,13 +120,13 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
    @Mock private IStatusBarService mService;
    @Mock private BindEventManagerImpl mBindEventManagerImpl;
    @Mock private AppIconProvider mAppIconProvider;
    @Mock private NotificationIconStyleProvider mNotificationIconStyleProvider;
    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
    @Mock private SensitiveNotificationProtectionController mSensitiveNotifProtectionController;
    @Mock private Handler mHandler;
    @Mock private SecureSettings mSecureSettings;
    @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
    @Mock
    HighPriorityProvider mHighPriorityProvider;
    @Mock HighPriorityProvider mHighPriorityProvider;
    private SectionStyleProvider mSectionStyleProvider;
    @Mock private UserTracker mUserTracker;
    @Mock private GroupMembershipManager mGroupMembershipManager;
@@ -170,6 +171,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
                mService,
                mBindEventManagerImpl,
                mAppIconProvider,
                mNotificationIconStyleProvider,
                TEST_CHILD_BIND_CUTOFF,
                TEST_MAX_GROUP_DELAY);

@@ -226,7 +228,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase {

    @Test
    @EnableFlags(Flags.FLAG_NOTIFICATIONS_REDESIGN_APP_ICONS)
    public void testPurgesCache() {
    public void testPurgesAppIconProviderCache() {
        // GIVEN a notification list
        NotificationEntry entry1 = getNotificationEntryBuilder().setPkg("1").build();
        NotificationEntry entry2 = getNotificationEntryBuilder().setPkg("2").build();
@@ -271,6 +273,53 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
        assertEquals(expectedList, actualList);
    }

    @Test
    @EnableFlags(Flags.FLAG_NOTIFICATIONS_REDESIGN_APP_ICONS)
    public void testPurgesNotificationIconStyleProviderCache() {
        // GIVEN a notification list
        NotificationEntry entry1 = getNotificationEntryBuilder().setPkg("1").build();
        NotificationEntry entry2 = getNotificationEntryBuilder().setPkg("2").build();
        NotificationEntry entry2bis = getNotificationEntryBuilder().setPkg("2").build();
        NotificationEntry entry3 = getNotificationEntryBuilder().setPkg("3").build();

        String groupKey1 = "group1";
        NotificationEntry summary =
                getNotificationEntryBuilder()
                        .setPkg(groupKey1)
                        .setGroup(mContext, groupKey1)
                        .setGroupSummary(mContext, true)
                        .build();
        NotificationEntry child1 = getNotificationEntryBuilder().setGroup(mContext, groupKey1)
                .setPkg(groupKey1).build();
        NotificationEntry child2 = getNotificationEntryBuilder().setGroup(mContext, groupKey1)
                .setPkg(groupKey1).build();
        GroupEntry groupWithSummaryAndChildren = getGroupEntryBuilder().setKey(groupKey1)
                .setSummary(summary).addChild(child1).addChild(child2).build();

        String groupKey2 = "group2";
        NotificationEntry summary2 =
                getNotificationEntryBuilder()
                        .setPkg(groupKey2)
                        .setGroup(mContext, groupKey2)
                        .setGroupSummary(mContext, true)
                        .build();
        GroupEntry summaryOnlyGroup = getGroupEntryBuilder().setKey(groupKey2)
                .setSummary(summary2).build();

        // WHEN onBeforeTransformGroup is called
        mBeforeTransformGroupsListener.onBeforeTransformGroups(
                List.of(entry1, entry2, entry2bis, entry3,
                        groupWithSummaryAndChildren, summaryOnlyGroup));

        // THEN purge should be called
        ArgumentCaptor<Collection<String>> argumentCaptor = ArgumentCaptor.forClass(List.class);
        verify(mNotificationIconStyleProvider).purgeCache(argumentCaptor.capture());
        List<String> actualList = argumentCaptor.getValue().stream().sorted().toList();
        List<String> expectedList = Stream.of("1", "2", "3", "group1", "group2")
                .sorted().toList();
        assertEquals(expectedList, actualList);
    }

    @Test
    public void testInflatesNewNotification() {
        // WHEN there is a new notification
+10 −2
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.systemui.statusbar.notification.collection.render.NotifViewCo
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager.NotifInflationErrorListener;
import com.android.systemui.statusbar.notification.row.icon.AppIconProvider;
import com.android.systemui.statusbar.notification.row.icon.NotificationIconStyleProvider;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;

@@ -110,6 +111,7 @@ public class PreparationCoordinator implements Coordinator {
    private final long mMaxGroupInflationDelay;
    private final BindEventManagerImpl mBindEventManager;
    private final AppIconProvider mAppIconProvider;
    private final NotificationIconStyleProvider mNotificationIconStyleProvider;

    @Inject
    public PreparationCoordinator(
@@ -120,7 +122,8 @@ public class PreparationCoordinator implements Coordinator {
            NotifUiAdjustmentProvider adjustmentProvider,
            IStatusBarService service,
            BindEventManagerImpl bindEventManager,
            AppIconProvider appIconProvider) {
            AppIconProvider appIconProvider,
            NotificationIconStyleProvider notificationIconStyleProvider) {
        this(
                logger,
                notifInflater,
@@ -130,6 +133,7 @@ public class PreparationCoordinator implements Coordinator {
                service,
                bindEventManager,
                appIconProvider,
                notificationIconStyleProvider,
                CHILD_BIND_CUTOFF,
                MAX_GROUP_INFLATION_DELAY);
    }
@@ -144,6 +148,7 @@ public class PreparationCoordinator implements Coordinator {
            IStatusBarService service,
            BindEventManagerImpl bindEventManager,
            AppIconProvider appIconProvider,
            NotificationIconStyleProvider notificationIconStyleProvider,
            int childBindCutoff,
            long maxGroupInflationDelay) {
        mLogger = logger;
@@ -156,6 +161,7 @@ public class PreparationCoordinator implements Coordinator {
        mMaxGroupInflationDelay = maxGroupInflationDelay;
        mBindEventManager = bindEventManager;
        mAppIconProvider = appIconProvider;
        mNotificationIconStyleProvider = notificationIconStyleProvider;
    }

    @Override
@@ -274,7 +280,9 @@ public class PreparationCoordinator implements Coordinator {
    };

    private void purgeCaches(Collection<ListEntry> entries) {
        mAppIconProvider.purgeCache(/* wantedPackages = */ getPackages(entries));
        Set<String> wantedPackages = getPackages(entries);
        mAppIconProvider.purgeCache(wantedPackages);
        mNotificationIconStyleProvider.purgeCache(wantedPackages);
    }

    /**
+25 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.pm.ApplicationInfo
import android.service.notification.StatusBarNotification
import android.util.Log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.collection.NotifCollectionCache
import dagger.Module
import dagger.Provides
import javax.inject.Inject
@@ -33,15 +34,30 @@ import javax.inject.Provider
 * notifications.
 */
interface NotificationIconStyleProvider {
    /**
     * Determines whether the [notification] should display the app icon instead of the small icon.
     * This can result in a binder call, and therefore should only be called from the background.
     */
    @WorkerThread
    fun shouldShowAppIcon(notification: StatusBarNotification, context: Context): Boolean

    /**
     * Mark all the entries in the cache that are NOT in [wantedPackages] to be cleared. If they're
     * still not needed on the next call of this method (made after a timeout of 1s, in case they
     * happen more frequently than that), they will be purged. This can be done from any thread.
     */
    fun purgeCache(wantedPackages: Collection<String>)
}

@SysUISingleton
class NotificationIconStyleProviderImpl @Inject constructor() : NotificationIconStyleProvider {
    private val cache = NotifCollectionCache<Boolean>()

    override fun shouldShowAppIcon(notification: StatusBarNotification, context: Context): Boolean {
        val packageContext = notification.getPackageContext(context)
        return !belongsToHeadlessSystemApp(packageContext)
        return cache.getOrFetch(notification.packageName) {
            !belongsToHeadlessSystemApp(packageContext)
        }
    }

    @WorkerThread
@@ -62,6 +78,10 @@ class NotificationIconStyleProviderImpl @Inject constructor() : NotificationIcon
            return false
        }
    }

    override fun purgeCache(wantedPackages: Collection<String>) {
        cache.purge(wantedPackages)
    }
}

class NoOpIconStyleProvider : NotificationIconStyleProvider {
@@ -73,6 +93,10 @@ class NoOpIconStyleProvider : NotificationIconStyleProvider {
        Log.wtf(TAG, "NoOpIconStyleProvider should not be used anywhere.")
        return true
    }

    override fun purgeCache(wantedPackages: Collection<String>) {
        Log.wtf(TAG, "NoOpIconStyleProvider should not be used anywhere.")
    }
}

@Module