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

Commit 59609424 authored by Kevin Han's avatar Kevin Han
Browse files

Add init/cleanup hooks to notif listeners.

As we refactor more state out of NotificationEntry, we need a place to
initialize/delete this state in its respective manager. Add/remove is
not appropriate for this as some add callbacks will call into other
managers which may have not had a chance to initialize their state yet
since we have no guarantee of ordering.

So instead, we break out a init and cleanup callback from add and
remove respectively where listeners can use it to do any initialization.

Test: atest NotifCollectionTest
Change-Id: If2233f8f4058c91dcf3d6ede61deae656e47c728
parent ffcdce33
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -92,8 +92,8 @@ import javax.inject.Singleton;
 * {@link #addNotificationLifetimeExtender(NotifLifetimeExtender)}).
 *
 * Interested parties can register listeners
 * ({@link #addCollectionListener(NotifCollectionListener)}) to be informed when notifications are
 * added, updated, or removed.
 * ({@link #addCollectionListener(NotifCollectionListener)}) to be informed when notifications
 * events occur.
 */
@MainThread
@Singleton
@@ -230,6 +230,8 @@ public class NotifCollection implements Dumpable {

            entry = new NotificationEntry(sbn, ranking);
            mNotificationSet.put(sbn.getKey(), entry);
            dispatchOnEntryInit(entry);

            if (rankingMap != null) {
                applyRanking(rankingMap);
            }
@@ -297,6 +299,7 @@ public class NotifCollection implements Dumpable {
            }

            dispatchOnEntryRemoved(entry, reason, dismissedByUserStats != null /* removedByUser */);
            dispatchOnEntryCleanUp(entry);
        }

        rebuildList();
@@ -378,6 +381,14 @@ public class NotifCollection implements Dumpable {
        return ranking;
    }

    private void dispatchOnEntryInit(NotificationEntry entry) {
        mAmDispatchingToOtherCode = true;
        for (NotifCollectionListener listener : mNotifCollectionListeners) {
            listener.onEntryInit(entry);
        }
        mAmDispatchingToOtherCode = false;
    }

    private void dispatchOnEntryAdded(NotificationEntry entry) {
        mAmDispatchingToOtherCode = true;
        for (NotifCollectionListener listener : mNotifCollectionListeners) {
@@ -413,6 +424,14 @@ public class NotifCollection implements Dumpable {
        mAmDispatchingToOtherCode = false;
    }

    private void dispatchOnEntryCleanUp(NotificationEntry entry) {
        mAmDispatchingToOtherCode = true;
        for (NotifCollectionListener listener : mNotifCollectionListeners) {
            listener.onEntryCleanUp(entry);
        }
        mAmDispatchingToOtherCode = false;
    }

    private final BatchableNotificationHandler mNotifHandler = new BatchableNotificationHandler() {
        @Override
        public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+2 −1
Original line number Diff line number Diff line
@@ -90,7 +90,8 @@ public class NotifPipeline {
    }

    /**
     * Registers a listener to be informed when notifications are added, removed or updated.
     * Registers a listener to be informed when there is a notification entry event such as an add,
     * update, or remove.
     */
    public void addCollectionListener(NotifCollectionListener listener) {
        mNotifCollection.addCollectionListener(listener);
+24 −2
Original line number Diff line number Diff line
@@ -18,14 +18,24 @@ package com.android.systemui.statusbar.notification.collection.notifcollection;

import android.service.notification.NotificationListenerService;

import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;

/**
 * Listener interface for {@link NotifCollection}.
 * Listener interface for {@link NotificationEntry} events.
 */
public interface NotifCollectionListener {
    /**
     * Called whenever a new {@link NotificationEntry} is initialized. This should be used for
     * initializing any decorated state tied to the notification.
     *
     * Do not reference other registered {@link NotifCollectionListener} implementations here as
     * there is no guarantee of order and they may not have had a chance to initialize yet. Instead,
     * use {@link #onEntryAdded} which is called after all initialization.
     */
    default void onEntryInit(NotificationEntry entry) {
    }

    /**
     * Called whenever a notification with a new key is posted.
     */
@@ -50,6 +60,18 @@ public interface NotifCollectionListener {
            boolean removedByUser) {
    }

    /**
     * Called whenever a {@link NotificationEntry} is considered deleted. This should be used for
     * cleaning up any state tied to the notification.
     *
     * This is the deletion parallel of {@link #onEntryInit} and similarly means that you cannot
     * expect other {@link NotifCollectionListener} implementations to still have valid state for
     * the entry during this call. Instead, use {@link #onEntryRemoved} which will be called before
     * deletion.
     */
    default void onEntryCleanUp(NotificationEntry entry) {
    }

    /**
     * Called whenever the RankingMap is updated by system server. By the time this listener is
     * called, the Rankings of all entries will have been updated.
+12 −2
Original line number Diff line number Diff line
@@ -139,9 +139,10 @@ public class NotifCollectionTest extends SysuiTestCase {
                        .setRank(4747));

        // THEN the listener is notified
        verify(mCollectionListener).onEntryAdded(mEntryCaptor.capture());

        verify(mCollectionListener).onEntryInit(mEntryCaptor.capture());
        NotificationEntry entry = mEntryCaptor.getValue();

        verify(mCollectionListener).onEntryAdded(entry);
        assertEquals(notif1.key, entry.getKey());
        assertEquals(notif1.sbn, entry.getSbn());
        assertEquals(notif1.ranking, entry.getRanking());
@@ -236,6 +237,7 @@ public class NotifCollectionTest extends SysuiTestCase {

        // THEN the listener is notified
        verify(mCollectionListener).onEntryRemoved(entry, REASON_APP_CANCEL, false);
        verify(mCollectionListener).onEntryCleanUp(entry);
        assertEquals(notif.sbn, entry.getSbn());
        assertEquals(notif.ranking, entry.getRanking());
    }
@@ -605,6 +607,10 @@ public class NotifCollectionTest extends SysuiTestCase {
    private static class RecordingCollectionListener implements NotifCollectionListener {
        private final Map<String, NotificationEntry> mLastSeenEntries = new ArrayMap<>();

        @Override
        public void onEntryInit(NotificationEntry entry) {
        }

        @Override
        public void onEntryAdded(NotificationEntry entry) {
            mLastSeenEntries.put(entry.getKey(), entry);
@@ -618,6 +624,10 @@ public class NotifCollectionTest extends SysuiTestCase {
        public void onEntryRemoved(NotificationEntry entry, int reason, boolean removedByUser) {
        }

        @Override
        public void onEntryCleanUp(NotificationEntry entry) {
        }

        public NotificationEntry getEntry(String key) {
            if (!mLastSeenEntries.containsKey(key)) {
                throw new RuntimeException("Key not found: " + key);