Loading core/java/android/app/INotificationManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ interface INotificationManager int getAppsBypassingDndCount(int uid); ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId); boolean isPackagePaused(String pkg); void deleteNotificationHistoryItem(String pkg, int uid, long postedTime); void silenceNotificationSound(); Loading core/java/android/app/NotificationHistory.java +20 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,26 @@ public final class NotificationHistory implements Parcelable { poolStringsFromNotifications(); } /** * Removes an individual historical notification and regenerates the string pool */ public boolean removeNotificationFromWrite(String packageName, long postedTime) { boolean removed = false; for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) { HistoricalNotification hn = mNotificationsToWrite.get(i); if (packageName.equals(hn.getPackage()) && postedTime == hn.getPostedTimeMs()) { removed = true; mNotificationsToWrite.remove(i); } } if (removed) { poolStringsFromNotifications(); } return removed; } /** * Gets pooled strings in order to write them to disk */ Loading core/tests/coretests/src/android/app/NotificationHistoryTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,40 @@ public class NotificationHistoryTest { .containsExactlyElementsIn(postRemoveExpectedEntries); } @Test public void testRemoveNotificationFromWrite() { 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 (987654323 != n.getPostedTimeMs()) { postRemoveExpectedStrings.add(n.getPackage()); postRemoveExpectedStrings.add(n.getChannelName()); postRemoveExpectedStrings.add(n.getChannelId()); postRemoveExpectedEntries.add(n); } history.addNotificationToWrite(n); } history.poolStringsFromNotifications(); assertThat(history.getNotificationsToWrite().size()).isEqualTo(10); // 1 package name and 10 unique channel names and ids assertThat(history.getPooledStringsToWrite().length).isEqualTo(21); history.removeNotificationFromWrite("pkg", 987654323); // 1 package names and 9 * 2 unique channel names and ids assertThat(history.getPooledStringsToWrite().length).isEqualTo(19); assertThat(history.getNotificationsToWrite()) .containsExactlyElementsIn(postRemoveExpectedEntries); } @Test public void testParceling() { NotificationHistory history = new NotificationHistory(); Loading services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +48 −0 Original line number Diff line number Diff line Loading @@ -170,6 +170,11 @@ public class NotificationHistoryDatabase { mFileWriteHandler.post(rpr); } public void deleteNotificationHistoryItem(String pkg, long postedTime) { RemoveNotificationRunnable rnr = new RemoveNotificationRunnable(pkg, postedTime); mFileWriteHandler.post(rnr); } public void addNotification(final HistoricalNotification notification) { synchronized (mLock) { mBuffer.addNewNotificationToWrite(notification); Loading Loading @@ -367,6 +372,49 @@ public class NotificationHistoryDatabase { } } final class RemoveNotificationRunnable implements Runnable { private String mPkg; private long mPostedTime; private NotificationHistory mNotificationHistory; public RemoveNotificationRunnable(String pkg, long postedTime) { mPkg = pkg; mPostedTime = postedTime; } @VisibleForTesting void setNotificationHistory(NotificationHistory nh) { mNotificationHistory = nh; } @Override public void run() { if (DEBUG) Slog.d(TAG, "RemovePackageRunnable"); synchronized (mLock) { // Remove from pending history mBuffer.removeNotificationFromWrite(mPkg, mPostedTime); 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.removeNotificationFromWrite(mPkg, mPostedTime)) { writeLocked(af, notificationHistory); } } catch (Exception e) { Slog.e(TAG, "Cannot clean up file on notification removal " + af.getBaseFile().getName(), e); } } } } } public static final class NotificationHistoryFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider { final static String TAG = "NotifHistoryFileDate"; Loading services/core/java/com/android/server/notification/NotificationHistoryManager.java +17 −1 Original line number Diff line number Diff line Loading @@ -130,7 +130,7 @@ public class NotificationHistoryManager { } } public void onPackageRemoved(int userId, String packageName) { public void onPackageRemoved(@UserIdInt int userId, String packageName) { synchronized (mLock) { if (!mUserUnlockedStates.get(userId, false)) { if (mHistoryEnabled.get(userId, false)) { Loading @@ -150,6 +150,22 @@ public class NotificationHistoryManager { } } public void deleteNotificationHistoryItem(String pkg, int uid, long postedTime) { 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 notif for locked/gone/disabled user " + userId); return; } userHistory.deleteNotificationHistoryItem(pkg, postedTime); } } // TODO: wire this up to AMS when power button is long pressed public void triggerWriteToDisk() { synchronized (mLock) { Loading Loading
core/java/android/app/INotificationManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ interface INotificationManager int getAppsBypassingDndCount(int uid); ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId); boolean isPackagePaused(String pkg); void deleteNotificationHistoryItem(String pkg, int uid, long postedTime); void silenceNotificationSound(); Loading
core/java/android/app/NotificationHistory.java +20 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,26 @@ public final class NotificationHistory implements Parcelable { poolStringsFromNotifications(); } /** * Removes an individual historical notification and regenerates the string pool */ public boolean removeNotificationFromWrite(String packageName, long postedTime) { boolean removed = false; for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) { HistoricalNotification hn = mNotificationsToWrite.get(i); if (packageName.equals(hn.getPackage()) && postedTime == hn.getPostedTimeMs()) { removed = true; mNotificationsToWrite.remove(i); } } if (removed) { poolStringsFromNotifications(); } return removed; } /** * Gets pooled strings in order to write them to disk */ Loading
core/tests/coretests/src/android/app/NotificationHistoryTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -233,6 +233,40 @@ public class NotificationHistoryTest { .containsExactlyElementsIn(postRemoveExpectedEntries); } @Test public void testRemoveNotificationFromWrite() { 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 (987654323 != n.getPostedTimeMs()) { postRemoveExpectedStrings.add(n.getPackage()); postRemoveExpectedStrings.add(n.getChannelName()); postRemoveExpectedStrings.add(n.getChannelId()); postRemoveExpectedEntries.add(n); } history.addNotificationToWrite(n); } history.poolStringsFromNotifications(); assertThat(history.getNotificationsToWrite().size()).isEqualTo(10); // 1 package name and 10 unique channel names and ids assertThat(history.getPooledStringsToWrite().length).isEqualTo(21); history.removeNotificationFromWrite("pkg", 987654323); // 1 package names and 9 * 2 unique channel names and ids assertThat(history.getPooledStringsToWrite().length).isEqualTo(19); assertThat(history.getNotificationsToWrite()) .containsExactlyElementsIn(postRemoveExpectedEntries); } @Test public void testParceling() { NotificationHistory history = new NotificationHistory(); Loading
services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +48 −0 Original line number Diff line number Diff line Loading @@ -170,6 +170,11 @@ public class NotificationHistoryDatabase { mFileWriteHandler.post(rpr); } public void deleteNotificationHistoryItem(String pkg, long postedTime) { RemoveNotificationRunnable rnr = new RemoveNotificationRunnable(pkg, postedTime); mFileWriteHandler.post(rnr); } public void addNotification(final HistoricalNotification notification) { synchronized (mLock) { mBuffer.addNewNotificationToWrite(notification); Loading Loading @@ -367,6 +372,49 @@ public class NotificationHistoryDatabase { } } final class RemoveNotificationRunnable implements Runnable { private String mPkg; private long mPostedTime; private NotificationHistory mNotificationHistory; public RemoveNotificationRunnable(String pkg, long postedTime) { mPkg = pkg; mPostedTime = postedTime; } @VisibleForTesting void setNotificationHistory(NotificationHistory nh) { mNotificationHistory = nh; } @Override public void run() { if (DEBUG) Slog.d(TAG, "RemovePackageRunnable"); synchronized (mLock) { // Remove from pending history mBuffer.removeNotificationFromWrite(mPkg, mPostedTime); 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.removeNotificationFromWrite(mPkg, mPostedTime)) { writeLocked(af, notificationHistory); } } catch (Exception e) { Slog.e(TAG, "Cannot clean up file on notification removal " + af.getBaseFile().getName(), e); } } } } } public static final class NotificationHistoryFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider { final static String TAG = "NotifHistoryFileDate"; Loading
services/core/java/com/android/server/notification/NotificationHistoryManager.java +17 −1 Original line number Diff line number Diff line Loading @@ -130,7 +130,7 @@ public class NotificationHistoryManager { } } public void onPackageRemoved(int userId, String packageName) { public void onPackageRemoved(@UserIdInt int userId, String packageName) { synchronized (mLock) { if (!mUserUnlockedStates.get(userId, false)) { if (mHistoryEnabled.get(userId, false)) { Loading @@ -150,6 +150,22 @@ public class NotificationHistoryManager { } } public void deleteNotificationHistoryItem(String pkg, int uid, long postedTime) { 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 notif for locked/gone/disabled user " + userId); return; } userHistory.deleteNotificationHistoryItem(pkg, postedTime); } } // TODO: wire this up to AMS when power button is long pressed public void triggerWriteToDisk() { synchronized (mLock) { Loading