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

Commit a625b94d authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Clean up settings and history for deleted convos

Test: atest
Fixes: 149556404
Change-Id: I998ecf39b794b4b3b3daca44875f9754797e0187
parent 8ac64bc0
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -383,6 +383,26 @@ public final class NotificationHistory implements Parcelable {
        return removed;
    }

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

        return removed;
    }

    /**
     * Gets pooled strings in order to write them to disk
     */
+38 −0
Original line number Diff line number Diff line
@@ -288,6 +288,44 @@ public class NotificationHistoryTest {
                .containsExactlyElementsIn(postRemoveExpectedEntries);
    }

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

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

            if (i != 2) {
                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 conversation id that will be removed
        history.addNotificationToWrite(getHistoricalNotification("pkg", 2));

        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.removeConversationFromWrite("pkg", "convo2");

        // 1 package names and 9 * 2 unique channel names and ids and 4 conversation ids
        assertThat(history.getPooledStringsToWrite().length).isEqualTo(23);
        assertThat(history.getNotificationsToWrite())
                .containsExactlyElementsIn(postRemoveExpectedEntries);
    }

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

    public void deleteConversation(String pkg, String conversationId) {
        RemoveConversationRunnable rcr = new RemoveConversationRunnable(pkg, conversationId);
        mFileWriteHandler.post(rcr);
    }

    public void addNotification(final HistoricalNotification notification) {
        synchronized (mLock) {
            mBuffer.addNewNotificationToWrite(notification);
@@ -396,7 +401,7 @@ public class NotificationHistoryDatabase {

        @Override
        public void run() {
            if (DEBUG) Slog.d(TAG, "RemovePackageRunnable");
            if (DEBUG) Slog.d(TAG, "RemoveNotificationRunnable");
            synchronized (mLock) {
                // Remove from pending history
                mBuffer.removeNotificationFromWrite(mPkg, mPostedTime);
@@ -422,6 +427,49 @@ public class NotificationHistoryDatabase {
        }
    }

    final class RemoveConversationRunnable implements Runnable {
        private String mPkg;
        private String mConversationId;
        private NotificationHistory mNotificationHistory;

        public RemoveConversationRunnable(String pkg, String conversationId) {
            mPkg = pkg;
            mConversationId = conversationId;
        }

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

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

                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.removeConversationFromWrite(mPkg, mConversationId)) {
                            writeLocked(af, notificationHistory);
                        }
                    } catch (Exception e) {
                        Slog.e(TAG, "Cannot clean up file on conversation removal "
                                + af.getBaseFile().getName(), e);
                    }
                }
            }
        }
    }

    public static final class NotificationHistoryFileAttrProvider implements
            NotificationHistoryDatabase.FileAttrProvider {
        final static String TAG = "NotifHistoryFileDate";
+16 −0
Original line number Diff line number Diff line
@@ -166,6 +166,22 @@ public class NotificationHistoryManager {
        }
    }

    public void deleteConversation(String pkg, int uid, String conversationId) {
        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 conversation for locked/gone/disabled user "
                        + userId);
                return;
            }
            userHistory.deleteConversation(pkg, conversationId);
        }
    }

    // TODO: wire this up to AMS when power button is long pressed
    public void triggerWriteToDisk() {
        synchronized (mLock) {
+16 −0
Original line number Diff line number Diff line
@@ -5655,6 +5655,22 @@ public class NotificationManagerService extends SystemService {
        mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground));
    }

    public void onConversationRemoved(String pkg, int uid, String conversationId) {
        checkCallerIsSystem();
        Preconditions.checkStringNotEmpty(pkg);
        Preconditions.checkStringNotEmpty(conversationId);

        mHistoryManager.deleteConversation(pkg, uid, conversationId);
        List<String> deletedChannelIds =
                mPreferencesHelper.deleteConversation(pkg, uid, conversationId);
        for (String channelId : deletedChannelIds) {
            cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
                    UserHandle.getUserId(uid), REASON_CHANNEL_BANNED,
                    null);
        }
        handleSavePolicyFile();
    }

    @VisibleForTesting
    protected void fixNotification(Notification notification, String pkg, String tag, int id,
            int userId) throws NameNotFoundException {
Loading