diff options
| author | 2020-09-25 14:19:52 +0000 | |
|---|---|---|
| committer | 2020-09-25 14:19:52 +0000 | |
| commit | ce302adbc6dbe9b20d109b297ae4785f3bfd00b5 (patch) | |
| tree | d8d06ae2c7419b506727dda3e02b0ba6712ece3a | |
| parent | 343552e1fc3e5f86eb169280d55442cb7146352a (diff) | |
| parent | 2b381875386871085a0c4511aa51934b6c077be4 (diff) | |
Merge "Bulk process shortcut removals"
12 files changed, 81 insertions, 60 deletions
diff --git a/core/java/android/app/NotificationHistory.java b/core/java/android/app/NotificationHistory.java index 59dc9991c832..55fff8b2f074 100644 --- a/core/java/android/app/NotificationHistory.java +++ b/core/java/android/app/NotificationHistory.java @@ -22,12 +22,10 @@ import android.graphics.drawable.Icon; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import android.util.Slog; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -387,12 +385,13 @@ public final class NotificationHistory implements Parcelable { /** * Removes all notifications from a conversation and regenerates the string pool */ - public boolean removeConversationFromWrite(String packageName, String conversationId) { + public boolean removeConversationsFromWrite(String packageName, Set<String> conversationIds) { 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())) { + && hn.getConversationId() != null + && conversationIds.contains(hn.getConversationId())) { removed = true; mNotificationsToWrite.remove(i); } diff --git a/core/tests/coretests/src/android/app/NotificationHistoryTest.java b/core/tests/coretests/src/android/app/NotificationHistoryTest.java index c9510918e555..7fa16130f25c 100644 --- a/core/tests/coretests/src/android/app/NotificationHistoryTest.java +++ b/core/tests/coretests/src/android/app/NotificationHistoryTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import android.app.NotificationHistory.HistoricalNotification; import android.graphics.drawable.Icon; import android.os.Parcel; -import android.util.Slog; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -31,6 +30,7 @@ import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; +import java.util.Set; @RunWith(AndroidJUnit4.class) public class NotificationHistoryTest { @@ -297,7 +297,7 @@ public class NotificationHistoryTest { for (int i = 1; i <= 10; i++) { HistoricalNotification n = getHistoricalNotification("pkg", i); - if (i != 2) { + if (i != 2 && i != 4) { postRemoveExpectedStrings.add(n.getPackage()); postRemoveExpectedStrings.add(n.getChannelName()); postRemoveExpectedStrings.add(n.getChannelId()); @@ -318,10 +318,10 @@ public class NotificationHistoryTest { // 1 package name and 20 unique channel names and ids and 5 conversation ids assertThat(history.getPooledStringsToWrite().length).isEqualTo(26); - history.removeConversationFromWrite("pkg", "convo2"); + history.removeConversationsFromWrite("pkg", Set.of("convo2", "convo4")); - // 1 package names and 9 * 2 unique channel names and ids and 4 conversation ids - assertThat(history.getPooledStringsToWrite().length).isEqualTo(23); + // 1 package names and 8 * 2 unique channel names and ids and 3 conversation ids + assertThat(history.getPooledStringsToWrite().length).isEqualTo(20); assertThat(history.getNotificationsToWrite()) .containsExactlyElementsIn(postRemoveExpectedEntries); } diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java index 18da33ce19e0..7257f522221f 100644 --- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java @@ -40,15 +40,12 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.LinkedList; -import java.util.concurrent.TimeUnit; +import java.util.Set; /** * Provides an interface to write and query for notification history data for a user from a Protocol @@ -173,8 +170,8 @@ public class NotificationHistoryDatabase { mFileWriteHandler.post(rnr); } - public void deleteConversation(String pkg, String conversationId) { - RemoveConversationRunnable rcr = new RemoveConversationRunnable(pkg, conversationId); + public void deleteConversations(String pkg, Set<String> conversationIds) { + RemoveConversationRunnable rcr = new RemoveConversationRunnable(pkg, conversationIds); mFileWriteHandler.post(rcr); } @@ -467,12 +464,12 @@ public class NotificationHistoryDatabase { final class RemoveConversationRunnable implements Runnable { private String mPkg; - private String mConversationId; + private Set<String> mConversationIds; private NotificationHistory mNotificationHistory; - public RemoveConversationRunnable(String pkg, String conversationId) { + public RemoveConversationRunnable(String pkg, Set<String> conversationIds) { mPkg = pkg; - mConversationId = conversationId; + mConversationIds = conversationIds; } @VisibleForTesting @@ -482,10 +479,10 @@ public class NotificationHistoryDatabase { @Override public void run() { - if (DEBUG) Slog.d(TAG, "RemoveConversationRunnable " + mPkg + " " + mConversationId); + if (DEBUG) Slog.d(TAG, "RemoveConversationRunnable " + mPkg + " " + mConversationIds); synchronized (mLock) { // Remove from pending history - mBuffer.removeConversationFromWrite(mPkg, mConversationId); + mBuffer.removeConversationsFromWrite(mPkg, mConversationIds); Iterator<AtomicFile> historyFileItr = mHistoryFiles.iterator(); while (historyFileItr.hasNext()) { @@ -496,7 +493,8 @@ public class NotificationHistoryDatabase { : new NotificationHistory(); readLocked(af, notificationHistory, new NotificationHistoryFilter.Builder().build()); - if(notificationHistory.removeConversationFromWrite(mPkg, mConversationId)) { + if (notificationHistory.removeConversationsFromWrite( + mPkg, mConversationIds)) { writeLocked(af, notificationHistory); } } catch (Exception e) { diff --git a/services/core/java/com/android/server/notification/NotificationHistoryManager.java b/services/core/java/com/android/server/notification/NotificationHistoryManager.java index 69a7ce90f1c6..cf3530bfe7fc 100644 --- a/services/core/java/com/android/server/notification/NotificationHistoryManager.java +++ b/services/core/java/com/android/server/notification/NotificationHistoryManager.java @@ -38,12 +38,12 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.FunctionalUtils; import com.android.server.IoThread; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * Keeps track of per-user notification histories. @@ -167,7 +167,7 @@ public class NotificationHistoryManager { } } - public void deleteConversation(String pkg, int uid, String conversationId) { + public void deleteConversations(String pkg, int uid, Set<String> conversationIds) { synchronized (mLock) { int userId = UserHandle.getUserId(uid); final NotificationHistoryDatabase userHistory = @@ -179,7 +179,7 @@ public class NotificationHistoryManager { + userId); return; } - userHistory.deleteConversation(pkg, conversationId); + userHistory.deleteConversations(pkg, conversationIds); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java index c301cd2339ec..affdcea1960b 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java +++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java @@ -19,6 +19,8 @@ package com.android.server.notification; import android.app.Notification; import android.app.NotificationChannel; +import java.util.Set; + public interface NotificationManagerInternal { NotificationChannel getNotificationChannel(String pkg, int uid, String channelId); void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid, @@ -28,5 +30,5 @@ public interface NotificationManagerInternal { void removeForegroundServiceFlagFromNotification(String pkg, int notificationId, int userId); - void onConversationRemoved(String pkg, int uid, String conversationId); + void onConversationRemoved(String pkg, int uid, Set<String> shortcuts); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 79882dab48a1..b4c98e06a442 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -5605,8 +5605,8 @@ public class NotificationManagerService extends SystemService { } @Override - public void onConversationRemoved(String pkg, int uid, String conversationId) { - onConversationRemovedInternal(pkg, uid, conversationId); + public void onConversationRemoved(String pkg, int uid, Set<String> shortcuts) { + onConversationRemovedInternal(pkg, uid, shortcuts); } @GuardedBy("mNotificationLock") @@ -5835,14 +5835,13 @@ public class NotificationManagerService extends SystemService { mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground)); } - private void onConversationRemovedInternal(String pkg, int uid, String conversationId) { + private void onConversationRemovedInternal(String pkg, int uid, Set<String> shortcuts) { checkCallerIsSystem(); Preconditions.checkStringNotEmpty(pkg); - Preconditions.checkStringNotEmpty(conversationId); - mHistoryManager.deleteConversation(pkg, uid, conversationId); + mHistoryManager.deleteConversations(pkg, uid, shortcuts); List<String> deletedChannelIds = - mPreferencesHelper.deleteConversation(pkg, uid, conversationId); + mPreferencesHelper.deleteConversations(pkg, uid, shortcuts); for (String channelId : deletedChannelIds) { cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true, UserHandle.getUserId(uid), REASON_CHANNEL_BANNED, diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 9cf9545d889a..bdf98f41cbbc 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -79,6 +79,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class PreferencesHelper implements RankingConfig { @@ -1428,7 +1429,8 @@ public class PreferencesHelper implements RankingConfig { } } - public @NonNull List<String> deleteConversation(String pkg, int uid, String conversationId) { + public @NonNull List<String> deleteConversations(String pkg, int uid, + Set<String> conversationIds) { synchronized (mPackagePreferences) { List<String> deletedChannelIds = new ArrayList<>(); PackagePreferences r = getPackagePreferencesLocked(pkg, uid); @@ -1438,7 +1440,8 @@ public class PreferencesHelper implements RankingConfig { int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); - if (conversationId.equals(nc.getConversationId())) { + if (nc.getConversationId() != null + && conversationIds.contains(nc.getConversationId())) { nc.setDeleted(true); LogMaker lm = getChannelLog(nc, pkg); lm.setType( diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java index 4d1129567ca6..52fec339e331 100644 --- a/services/people/java/com/android/server/people/data/DataManager.java +++ b/services/people/java/com/android/server/people/data/DataManager.java @@ -74,6 +74,7 @@ import com.android.server.notification.ShortcutHelper; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -757,14 +758,16 @@ public class DataManager { Slog.e(TAG, "Package not found: " + packageName, e); } PackageData packageData = getPackage(packageName, user.getIdentifier()); + Set<String> shortcutIds = new HashSet<>(); for (ShortcutInfo shortcutInfo : shortcuts) { if (packageData != null) { packageData.deleteDataForConversation(shortcutInfo.getId()); } - if (uid != Process.INVALID_UID) { - mNotificationManagerInternal.onConversationRemoved( - shortcutInfo.getPackage(), uid, shortcutInfo.getId()); - } + shortcutIds.add(shortcutInfo.getId()); + } + if (uid != Process.INVALID_UID) { + mNotificationManagerInternal.onConversationRemoved( + packageName, uid, shortcutIds); } }); } diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java index b2f7abbf84df..0a6cd51c3cc5 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java @@ -623,17 +623,19 @@ public final class DataManagerTest { } @Test - public void testShortcutDeleted() { + public void testShortcutsDeleted() { mDataManager.onUserUnlocked(USER_ID_PRIMARY); ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc1", buildPerson()); ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc2", buildPerson()); + ShortcutInfo shortcut3 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc3", + buildPerson()); mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME, - Arrays.asList(shortcut1, shortcut2), UserHandle.of(USER_ID_PRIMARY)); + Arrays.asList(shortcut1, shortcut2, shortcut3), UserHandle.of(USER_ID_PRIMARY)); mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME, - Collections.singletonList(shortcut1), UserHandle.of(USER_ID_PRIMARY)); + List.of(shortcut1, shortcut3), UserHandle.of(USER_ID_PRIMARY)); List<ConversationInfo> conversations = getConversationsInPrimary(); @@ -641,7 +643,7 @@ public final class DataManagerTest { assertEquals("sc2", conversations.get(0).getShortcutId()); verify(mNotificationManagerInternal) - .onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, "sc1"); + .onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, Set.of("sc1", "sc3")); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java index a2d987fb0a8d..f6d6624d7e1c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java @@ -44,15 +44,13 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.mockito.internal.matchers.Not; import java.io.File; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.Set; @RunWith(AndroidJUnit4.class) public class NotificationHistoryDatabaseTest extends UiServiceTestCase { @@ -309,22 +307,22 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { public void testRemoveConversationRunnable() throws Exception { NotificationHistory nh = mock(NotificationHistory.class); NotificationHistoryDatabase.RemoveConversationRunnable rcr = - mDataBase.new RemoveConversationRunnable("pkg", "convo"); + mDataBase.new RemoveConversationRunnable("pkg", Set.of("convo", "another")); rcr.setNotificationHistory(nh); AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); mDataBase.mHistoryFiles.addLast(af); - when(nh.removeConversationFromWrite("pkg", "convo")).thenReturn(true); + when(nh.removeConversationsFromWrite("pkg", Set.of("convo", "another"))).thenReturn(true); mDataBase.mBuffer = mock(NotificationHistory.class); rcr.run(); - verify(mDataBase.mBuffer).removeConversationFromWrite("pkg", "convo"); + verify(mDataBase.mBuffer).removeConversationsFromWrite("pkg",Set.of("convo", "another")); verify(af).openRead(); - verify(nh).removeConversationFromWrite("pkg", "convo"); + verify(nh).removeConversationsFromWrite("pkg",Set.of("convo", "another")); verify(af).startWrite(); } @@ -332,22 +330,22 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { public void testRemoveConversationRunnable_noChanges() throws Exception { NotificationHistory nh = mock(NotificationHistory.class); NotificationHistoryDatabase.RemoveConversationRunnable rcr = - mDataBase.new RemoveConversationRunnable("pkg", "convo"); + mDataBase.new RemoveConversationRunnable("pkg", Set.of("convo")); rcr.setNotificationHistory(nh); AtomicFile af = mock(AtomicFile.class); when(af.getBaseFile()).thenReturn(new File(mRootDir, "af")); mDataBase.mHistoryFiles.addLast(af); - when(nh.removeConversationFromWrite("pkg", "convo")).thenReturn(false); + when(nh.removeConversationsFromWrite("pkg", Set.of("convo"))).thenReturn(false); mDataBase.mBuffer = mock(NotificationHistory.class); rcr.run(); - verify(mDataBase.mBuffer).removeConversationFromWrite("pkg", "convo"); + verify(mDataBase.mBuffer).removeConversationsFromWrite("pkg", Set.of("convo")); verify(af).openRead(); - verify(nh).removeConversationFromWrite("pkg", "convo"); + verify(nh).removeConversationsFromWrite("pkg", Set.of("convo")); verify(af, never()).startWrite(); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java index 2341c10a9c91..a0293b7ad12a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryManagerTest.java @@ -47,6 +47,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; +import java.util.Set; @RunWith(AndroidJUnit4.class) @@ -365,15 +366,15 @@ public class NotificationHistoryManagerTest extends UiServiceTestCase { @Test public void testDeleteConversation_userUnlocked() { String pkg = "pkg"; - String convo = "convo"; + Set<String> convos = Set.of("convo", "another"); NotificationHistoryDatabase userHistory = mock(NotificationHistoryDatabase.class); mHistoryManager.onUserUnlocked(USER_SYSTEM); mHistoryManager.replaceNotificationHistoryDatabase(USER_SYSTEM, userHistory); - mHistoryManager.deleteConversation(pkg, 1, convo); + mHistoryManager.deleteConversations(pkg, 1, convos); - verify(userHistory, times(1)).deleteConversation(pkg, convo); + verify(userHistory, times(1)).deleteConversations(pkg, convos); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 0be1bf3fe5c2..3e779a9b2435 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -127,6 +127,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.ThreadLocalRandom; @SmallTest @@ -3502,8 +3503,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { } @Test - public void testDeleteConversation() { + public void testDeleteConversations() { String convoId = "convo"; + String convoIdC = "convoC"; NotificationChannel messages = new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); @@ -3526,10 +3528,16 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setConversationId(calls.getId(), convoId); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); + NotificationChannel channel3 = + new NotificationChannel("C person msgs", "msgs from C", IMPORTANCE_DEFAULT); + channel3.setConversationId(messages.getId(), convoIdC); + mHelper.createNotificationChannel(PKG_O, UID_O, channel3, true, false); + assertEquals(channel, mHelper.getNotificationChannel(PKG_O, UID_O, channel.getId(), false)); assertEquals(channel2, mHelper.getNotificationChannel(PKG_O, UID_O, channel2.getId(), false)); - assertEquals(2, mHelper.deleteConversation(PKG_O, UID_O, convoId).size()); + List<String> deleted = mHelper.deleteConversations(PKG_O, UID_O, Set.of(convoId, convoIdC)); + assertEquals(3, deleted.size()); assertEquals(messages, mHelper.getNotificationChannel(PKG_O, UID_O, messages.getId(), false)); @@ -3542,7 +3550,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertEquals(channel2, mHelper.getNotificationChannel(PKG_O, UID_O, channel2.getId(), true)); - assertEquals(7, mLogger.getCalls().size()); + assertEquals(9, mLogger.getCalls().size()); assertEquals( NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED, mLogger.get(0).event); // Channel messages @@ -3563,12 +3571,20 @@ public class PreferencesHelperTest extends UiServiceTestCase { mLogger.get(4).event); // Channel channel2 - Conversation A person calls assertEquals( NotificationChannelLogger.NotificationChannelEvent + .NOTIFICATION_CHANNEL_CONVERSATION_CREATED, + mLogger.get(5).event); // Channel channel3 - Conversation C person msgs + assertEquals( + NotificationChannelLogger.NotificationChannelEvent + .NOTIFICATION_CHANNEL_CONVERSATION_DELETED, + mLogger.get(6).event); // Delete Channel channel - Conversation A person msgs + assertEquals( + NotificationChannelLogger.NotificationChannelEvent .NOTIFICATION_CHANNEL_CONVERSATION_DELETED, - mLogger.get(5).event); // Delete Channel channel - Conversation A person msgs + mLogger.get(7).event); // Delete Channel channel2 - Conversation A person calls assertEquals( NotificationChannelLogger.NotificationChannelEvent .NOTIFICATION_CHANNEL_CONVERSATION_DELETED, - mLogger.get(6).event); // Delete Channel channel2 - Conversation A person calls + mLogger.get(8).event); // Delete Channel channel3 - Conversation C person msgs } @Test |