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

Commit ec78f61c authored by Yuri Lin's avatar Yuri Lin Committed by Automerger Merge Worker
Browse files

Merge "Remove notification channels from history when they're deleted." into sc-dev am: 285d2b4a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14053424

Change-Id: I6d545de64e128efc09e4940bfe19c7f301c015cb
parents 377db02c 285d2b4a
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -403,6 +403,26 @@ public final class NotificationHistory implements Parcelable {
        return removed;
    }

    /**
     * Removes all notifications from a channel and regenerates the string pool
     */
    public boolean removeChannelFromWrite(String packageName, String channelId) {
        boolean removed = false;
        for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
            HistoricalNotification hn = mNotificationsToWrite.get(i);
            if (packageName.equals(hn.getPackage())
                    && Objects.equals(channelId, hn.getChannelId())) {
                removed = true;
                mNotificationsToWrite.remove(i);
            }
        }
        if (removed) {
            poolStringsFromNotifications();
        }

        return removed;
    }

    /**
     * Gets pooled strings in order to write them to disk
     */
+44 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@@ -326,6 +328,48 @@ public class NotificationHistoryTest {
                .containsExactlyElementsIn(postRemoveExpectedEntries);
    }

    @Test
    public void testRemoveChannelFromWrite() {
        NotificationHistory history = new NotificationHistory();

        List<HistoricalNotification> postRemoveExpectedEntries = new ArrayList<>();
        Set<String> postRemoveExpectedStrings = new HashSet<>();
        for (int i = 1; i <= 10; i++) {
            HistoricalNotification n = getHistoricalNotification("pkg", i);

            // Remove channel numbers 5 and 6
            if (i != 5 && i != 6) {
                postRemoveExpectedStrings.add(n.getPackage());
                postRemoveExpectedStrings.add(n.getChannelName());
                postRemoveExpectedStrings.add(n.getChannelId());
                if (n.getConversationId() != null) {
                    postRemoveExpectedStrings.add(n.getConversationId());
                }
                postRemoveExpectedEntries.add(n);
            }

            history.addNotificationToWrite(n);
        }
        // add second notification with the same channel id that will also be removed
        history.addNotificationToWrite(getHistoricalNotification("pkg", 6));

        history.poolStringsFromNotifications();

        assertThat(history.getNotificationsToWrite().size()).isEqualTo(11);
        // 1 package name and 20 unique channel names and ids and 5 conversation ids
        assertThat(history.getPooledStringsToWrite().length).isEqualTo(26);

        history.removeChannelFromWrite("pkg", "channelId5");
        history.removeChannelFromWrite("pkg", "channelId6");

        // 1 package names and 8 * 2 unique channel names and ids and 4 conversation ids
        assertThat(history.getPooledStringsToWrite().length).isEqualTo(21);
        assertThat(Arrays.asList(history.getPooledStringsToWrite()))
                .containsExactlyElementsIn(postRemoveExpectedStrings);
        assertThat(history.getNotificationsToWrite())
                .containsExactlyElementsIn(postRemoveExpectedEntries);
    }

    @Test
    public void testParceling() {
        NotificationHistory history = new NotificationHistory();
+48 −0
Original line number Diff line number Diff line
@@ -175,6 +175,11 @@ public class NotificationHistoryDatabase {
        mFileWriteHandler.post(rcr);
    }

    public void deleteNotificationChannel(String pkg, String channelId) {
        RemoveChannelRunnable rcr = new RemoveChannelRunnable(pkg, channelId);
        mFileWriteHandler.post(rcr);
    }

    public void addNotification(final HistoricalNotification notification) {
        synchronized (mLock) {
            mBuffer.addNewNotificationToWrite(notification);
@@ -505,4 +510,47 @@ public class NotificationHistoryDatabase {
            }
        }
    }

    final class RemoveChannelRunnable implements Runnable {
        private String mPkg;
        private String mChannelId;
        private NotificationHistory mNotificationHistory;

        RemoveChannelRunnable(String pkg, String channelId) {
            mPkg = pkg;
            mChannelId = channelId;
        }

        @VisibleForTesting
        void setNotificationHistory(NotificationHistory nh) {
            mNotificationHistory = nh;
        }

        @Override
        public void run() {
            if (DEBUG) Slog.d(TAG, "RemoveChannelRunnable");
            synchronized (mLock) {
                // Remove from pending history
                mBuffer.removeChannelFromWrite(mPkg, mChannelId);

                Iterator<AtomicFile> historyFileItr = mHistoryFiles.iterator();
                while (historyFileItr.hasNext()) {
                    final AtomicFile af = historyFileItr.next();
                    try {
                        NotificationHistory notificationHistory = mNotificationHistory != null
                                ? mNotificationHistory
                                : new NotificationHistory();
                        readLocked(af, notificationHistory,
                                new NotificationHistoryFilter.Builder().build());
                        if (notificationHistory.removeChannelFromWrite(mPkg, mChannelId)) {
                            writeLocked(af, notificationHistory);
                        }
                    } catch (Exception e) {
                        Slog.e(TAG, "Cannot clean up file on channel removal "
                                + af.getBaseFile().getName(), e);
                    }
                }
            }
        }
    }
}
+16 −0
Original line number Diff line number Diff line
@@ -183,6 +183,22 @@ public class NotificationHistoryManager {
        }
    }

    public void deleteNotificationChannel(String pkg, int uid, String channelId) {
        synchronized (mLock) {
            int userId = UserHandle.getUserId(uid);
            final NotificationHistoryDatabase userHistory =
                    getUserHistoryAndInitializeIfNeededLocked(userId);
            // TODO: it shouldn't be possible to delete a notification entry while the user is
            // locked but we should handle it
            if (userHistory == null) {
                Slog.w(TAG, "Attempted to remove channel for locked/gone/disabled user "
                        + userId);
                return;
            }
            userHistory.deleteNotificationChannel(pkg, channelId);
        }
    }

    public void triggerWriteToDisk() {
        synchronized (mLock) {
            final int userCount = mUserState.size();
+1 −0
Original line number Diff line number Diff line
@@ -3625,6 +3625,7 @@ public class NotificationManagerService extends SystemService {
            cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
                    callingUser, REASON_CHANNEL_REMOVED, null);
            mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, channelId);
            mHistoryManager.deleteNotificationChannel(pkg, callingUid, channelId);
            mListeners.notifyNotificationChannelChanged(pkg,
                    UserHandle.getUserHandleForUid(callingUid),
                    mPreferencesHelper.getNotificationChannel(pkg, callingUid, channelId, true),
Loading