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

Commit f20b2ecd authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "Clean up settings and history for deleted convos"

parents 1ed2833b a625b94d
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