Loading core/java/android/app/INotificationManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ interface INotificationManager void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); void createNotificationChannels(String pkg, in ParceledListSlice channelsList); void createNotificationChannelsForPackage(String pkg, int uid, in ParceledListSlice channelsList); ParceledListSlice getConversations(boolean onlyImportant); ParceledListSlice getConversationsForPackage(String pkg, int uid); ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted); NotificationChannelGroup getNotificationChannelGroupForPackage(String groupId, String pkg, int uid); Loading core/java/android/service/notification/ConversationChannelWrapper.java +26 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ public final class ConversationChannelWrapper implements Parcelable { private CharSequence mGroupLabel; private CharSequence mParentChannelLabel; private ShortcutInfo mShortcutInfo; private String mPkg; private int mUid; public ConversationChannelWrapper() {} Loading @@ -41,6 +43,8 @@ public final class ConversationChannelWrapper implements Parcelable { mGroupLabel = in.readCharSequence(); mParentChannelLabel = in.readCharSequence(); mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader()); mPkg = in.readStringNoHelper(); mUid = in.readInt(); } @Override Loading @@ -49,6 +53,8 @@ public final class ConversationChannelWrapper implements Parcelable { dest.writeCharSequence(mGroupLabel); dest.writeCharSequence(mParentChannelLabel); dest.writeParcelable(mShortcutInfo, flags); dest.writeStringNoHelper(mPkg); dest.writeInt(mUid); } @Override Loading Loading @@ -103,6 +109,22 @@ public final class ConversationChannelWrapper implements Parcelable { mShortcutInfo = shortcutInfo; } public String getPkg() { return mPkg; } public void setPkg(String pkg) { mPkg = pkg; } public int getUid() { return mUid; } public void setUid(int uid) { mUid = uid; } @Override public boolean equals(Object o) { if (this == o) return true; Loading @@ -111,12 +133,14 @@ public final class ConversationChannelWrapper implements Parcelable { return Objects.equals(getNotificationChannel(), that.getNotificationChannel()) && Objects.equals(getGroupLabel(), that.getGroupLabel()) && Objects.equals(getParentChannelLabel(), that.getParentChannelLabel()) && Objects.equals(getShortcutInfo(), that.getShortcutInfo()); Objects.equals(getShortcutInfo(), that.getShortcutInfo()) && Objects.equals(getPkg(), that.getPkg()) && getUid() == that.getUid(); } @Override public int hashCode() { return Objects.hash(getNotificationChannel(), getGroupLabel(), getParentChannelLabel(), getShortcutInfo()); getShortcutInfo(), getPkg(), getUid()); } } services/core/java/com/android/server/notification/NotificationManagerService.java +21 −0 Original line number Diff line number Diff line Loading @@ -3439,6 +3439,27 @@ public class NotificationManagerService extends SystemService { return mPreferencesHelper.getBlockedChannelCount(pkg, uid); } @Override public ParceledListSlice<ConversationChannelWrapper> getConversations( boolean onlyImportant) { enforceSystemOrSystemUI("getConversations"); ArrayList<ConversationChannelWrapper> conversations = mPreferencesHelper.getConversations(onlyImportant); for (ConversationChannelWrapper conversation : conversations) { LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery() .setPackage(conversation.getPkg()) .setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED) .setShortcutIds(Arrays.asList( conversation.getNotificationChannel().getConversationId())); List<ShortcutInfo> shortcuts = mLauncherAppsService.getShortcuts( query, UserHandle.of(UserHandle.getUserId(conversation.getUid()))); if (shortcuts != null && !shortcuts.isEmpty()) { conversation.setShortcutInfo(shortcuts.get(0)); } } return new ParceledListSlice<>(conversations); } @Override public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage( String pkg, int uid, boolean includeDeleted) { Loading services/core/java/com/android/server/notification/PreferencesHelper.java +40 −0 Original line number Diff line number Diff line Loading @@ -1186,6 +1186,44 @@ public class PreferencesHelper implements RankingConfig { return groups; } public ArrayList<ConversationChannelWrapper> getConversations(boolean onlyImportant) { synchronized (mPackagePreferences) { ArrayList<ConversationChannelWrapper> conversations = new ArrayList<>(); for (PackagePreferences p : mPackagePreferences.values()) { int N = p.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = p.channels.valueAt(i); if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted() && (nc.isImportantConversation() || !onlyImportant)) { ConversationChannelWrapper conversation = new ConversationChannelWrapper(); conversation.setPkg(p.pkg); conversation.setUid(p.uid); conversation.setNotificationChannel(nc); conversation.setParentChannelLabel( p.channels.get(nc.getParentChannelId()).getName()); boolean blockedByGroup = false; if (nc.getGroup() != null) { NotificationChannelGroup group = p.groups.get(nc.getGroup()); if (group != null) { if (group.isBlocked()) { blockedByGroup = true; } else { conversation.setGroupLabel(group.getName()); } } } if (!blockedByGroup) { conversations.add(conversation); } } } } return conversations; } } public ArrayList<ConversationChannelWrapper> getConversations(String pkg, int uid) { Objects.requireNonNull(pkg); synchronized (mPackagePreferences) { Loading @@ -1199,6 +1237,8 @@ public class PreferencesHelper implements RankingConfig { final NotificationChannel nc = r.channels.valueAt(i); if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted()) { ConversationChannelWrapper conversation = new ConversationChannelWrapper(); conversation.setPkg(r.pkg); conversation.setUid(r.uid); conversation.setNotificationChannel(nc); conversation.setParentChannelLabel( r.channels.get(nc.getParentChannelId()).getName()); Loading services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { private static final int UID_N_MR1 = 0; private static final UserHandle USER = UserHandle.of(0); private static final int UID_O = 1111; private static final int UID_P = 2222; private static final String SYSTEM_PKG = "android"; private static final int SYSTEM_UID = 1000; private static final UserHandle USER2 = UserHandle.of(10); Loading Loading @@ -141,9 +142,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { upgrade.targetSdkVersion = Build.VERSION_CODES.O; when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy); when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getApplicationInfoAsUser(eq(PKG_P), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getApplicationInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getPackageUidAsUser(eq(PKG_N_MR1), anyInt())).thenReturn(UID_N_MR1); when(mPm.getPackageUidAsUser(eq(PKG_O), anyInt())).thenReturn(UID_O); when(mPm.getPackageUidAsUser(eq(PKG_P), anyInt())).thenReturn(UID_P); when(mPm.getPackageUidAsUser(eq(SYSTEM_PKG), anyInt())).thenReturn(SYSTEM_UID); PackageInfo info = mock(PackageInfo.class); info.signatures = new Signature[] {mock(Signature.class)}; Loading Loading @@ -2944,6 +2947,92 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertNotNull(mHelper.getNotificationChannel(PKG_O, UID_O, "id", true)); } @Test public void testGetConversations_all() { String convoId = "convo"; NotificationChannel messages = new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); NotificationChannel calls = new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); NotificationChannel p = new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); NotificationChannel channel = new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); channel.setConversationId(messages.getId(), convoId); mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); NotificationChannel diffConvo = new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); diffConvo.setConversationId(p.getId(), "different convo"); mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false); NotificationChannel channel2 = new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); channel2.setConversationId(calls.getId(), convoId); channel2.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); List<ConversationChannelWrapper> convos = mHelper.getConversations(false); assertEquals(3, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); assertTrue(conversationWrapperContainsChannel(convos, diffConvo)); assertTrue(conversationWrapperContainsChannel(convos, channel2)); } @Test public void testGetConversations_onlyImportant() { String convoId = "convo"; NotificationChannel messages = new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); NotificationChannel calls = new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); NotificationChannel p = new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); NotificationChannel channel = new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); channel.setConversationId(messages.getId(), convoId); channel.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); NotificationChannel diffConvo = new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); diffConvo.setConversationId(p.getId(), "different convo"); diffConvo.setImportantConversation(true); mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false); NotificationChannel channel2 = new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); channel2.setConversationId(calls.getId(), convoId); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); List<ConversationChannelWrapper> convos = mHelper.getConversations(true); assertEquals(2, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); assertTrue(conversationWrapperContainsChannel(convos, diffConvo)); assertFalse(conversationWrapperContainsChannel(convos, channel2)); } private boolean conversationWrapperContainsChannel(List<ConversationChannelWrapper> list, NotificationChannel expected) { for (ConversationChannelWrapper ccw : list) { if (ccw.getNotificationChannel().equals(expected)) { return true; } } return false; } @Test public void testGetConversations_invalidPkg() { assertThat(mHelper.getConversations("bad", 1)).isEmpty(); Loading Loading
core/java/android/app/INotificationManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ interface INotificationManager void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); void createNotificationChannels(String pkg, in ParceledListSlice channelsList); void createNotificationChannelsForPackage(String pkg, int uid, in ParceledListSlice channelsList); ParceledListSlice getConversations(boolean onlyImportant); ParceledListSlice getConversationsForPackage(String pkg, int uid); ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted); NotificationChannelGroup getNotificationChannelGroupForPackage(String groupId, String pkg, int uid); Loading
core/java/android/service/notification/ConversationChannelWrapper.java +26 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ public final class ConversationChannelWrapper implements Parcelable { private CharSequence mGroupLabel; private CharSequence mParentChannelLabel; private ShortcutInfo mShortcutInfo; private String mPkg; private int mUid; public ConversationChannelWrapper() {} Loading @@ -41,6 +43,8 @@ public final class ConversationChannelWrapper implements Parcelable { mGroupLabel = in.readCharSequence(); mParentChannelLabel = in.readCharSequence(); mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader()); mPkg = in.readStringNoHelper(); mUid = in.readInt(); } @Override Loading @@ -49,6 +53,8 @@ public final class ConversationChannelWrapper implements Parcelable { dest.writeCharSequence(mGroupLabel); dest.writeCharSequence(mParentChannelLabel); dest.writeParcelable(mShortcutInfo, flags); dest.writeStringNoHelper(mPkg); dest.writeInt(mUid); } @Override Loading Loading @@ -103,6 +109,22 @@ public final class ConversationChannelWrapper implements Parcelable { mShortcutInfo = shortcutInfo; } public String getPkg() { return mPkg; } public void setPkg(String pkg) { mPkg = pkg; } public int getUid() { return mUid; } public void setUid(int uid) { mUid = uid; } @Override public boolean equals(Object o) { if (this == o) return true; Loading @@ -111,12 +133,14 @@ public final class ConversationChannelWrapper implements Parcelable { return Objects.equals(getNotificationChannel(), that.getNotificationChannel()) && Objects.equals(getGroupLabel(), that.getGroupLabel()) && Objects.equals(getParentChannelLabel(), that.getParentChannelLabel()) && Objects.equals(getShortcutInfo(), that.getShortcutInfo()); Objects.equals(getShortcutInfo(), that.getShortcutInfo()) && Objects.equals(getPkg(), that.getPkg()) && getUid() == that.getUid(); } @Override public int hashCode() { return Objects.hash(getNotificationChannel(), getGroupLabel(), getParentChannelLabel(), getShortcutInfo()); getShortcutInfo(), getPkg(), getUid()); } }
services/core/java/com/android/server/notification/NotificationManagerService.java +21 −0 Original line number Diff line number Diff line Loading @@ -3439,6 +3439,27 @@ public class NotificationManagerService extends SystemService { return mPreferencesHelper.getBlockedChannelCount(pkg, uid); } @Override public ParceledListSlice<ConversationChannelWrapper> getConversations( boolean onlyImportant) { enforceSystemOrSystemUI("getConversations"); ArrayList<ConversationChannelWrapper> conversations = mPreferencesHelper.getConversations(onlyImportant); for (ConversationChannelWrapper conversation : conversations) { LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery() .setPackage(conversation.getPkg()) .setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED) .setShortcutIds(Arrays.asList( conversation.getNotificationChannel().getConversationId())); List<ShortcutInfo> shortcuts = mLauncherAppsService.getShortcuts( query, UserHandle.of(UserHandle.getUserId(conversation.getUid()))); if (shortcuts != null && !shortcuts.isEmpty()) { conversation.setShortcutInfo(shortcuts.get(0)); } } return new ParceledListSlice<>(conversations); } @Override public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage( String pkg, int uid, boolean includeDeleted) { Loading
services/core/java/com/android/server/notification/PreferencesHelper.java +40 −0 Original line number Diff line number Diff line Loading @@ -1186,6 +1186,44 @@ public class PreferencesHelper implements RankingConfig { return groups; } public ArrayList<ConversationChannelWrapper> getConversations(boolean onlyImportant) { synchronized (mPackagePreferences) { ArrayList<ConversationChannelWrapper> conversations = new ArrayList<>(); for (PackagePreferences p : mPackagePreferences.values()) { int N = p.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = p.channels.valueAt(i); if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted() && (nc.isImportantConversation() || !onlyImportant)) { ConversationChannelWrapper conversation = new ConversationChannelWrapper(); conversation.setPkg(p.pkg); conversation.setUid(p.uid); conversation.setNotificationChannel(nc); conversation.setParentChannelLabel( p.channels.get(nc.getParentChannelId()).getName()); boolean blockedByGroup = false; if (nc.getGroup() != null) { NotificationChannelGroup group = p.groups.get(nc.getGroup()); if (group != null) { if (group.isBlocked()) { blockedByGroup = true; } else { conversation.setGroupLabel(group.getName()); } } } if (!blockedByGroup) { conversations.add(conversation); } } } } return conversations; } } public ArrayList<ConversationChannelWrapper> getConversations(String pkg, int uid) { Objects.requireNonNull(pkg); synchronized (mPackagePreferences) { Loading @@ -1199,6 +1237,8 @@ public class PreferencesHelper implements RankingConfig { final NotificationChannel nc = r.channels.valueAt(i); if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted()) { ConversationChannelWrapper conversation = new ConversationChannelWrapper(); conversation.setPkg(r.pkg); conversation.setUid(r.uid); conversation.setNotificationChannel(nc); conversation.setParentChannelLabel( r.channels.get(nc.getParentChannelId()).getName()); Loading
services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { private static final int UID_N_MR1 = 0; private static final UserHandle USER = UserHandle.of(0); private static final int UID_O = 1111; private static final int UID_P = 2222; private static final String SYSTEM_PKG = "android"; private static final int SYSTEM_UID = 1000; private static final UserHandle USER2 = UserHandle.of(10); Loading Loading @@ -141,9 +142,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { upgrade.targetSdkVersion = Build.VERSION_CODES.O; when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy); when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getApplicationInfoAsUser(eq(PKG_P), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getApplicationInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getPackageUidAsUser(eq(PKG_N_MR1), anyInt())).thenReturn(UID_N_MR1); when(mPm.getPackageUidAsUser(eq(PKG_O), anyInt())).thenReturn(UID_O); when(mPm.getPackageUidAsUser(eq(PKG_P), anyInt())).thenReturn(UID_P); when(mPm.getPackageUidAsUser(eq(SYSTEM_PKG), anyInt())).thenReturn(SYSTEM_UID); PackageInfo info = mock(PackageInfo.class); info.signatures = new Signature[] {mock(Signature.class)}; Loading Loading @@ -2944,6 +2947,92 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertNotNull(mHelper.getNotificationChannel(PKG_O, UID_O, "id", true)); } @Test public void testGetConversations_all() { String convoId = "convo"; NotificationChannel messages = new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); NotificationChannel calls = new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); NotificationChannel p = new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); NotificationChannel channel = new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); channel.setConversationId(messages.getId(), convoId); mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); NotificationChannel diffConvo = new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); diffConvo.setConversationId(p.getId(), "different convo"); mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false); NotificationChannel channel2 = new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); channel2.setConversationId(calls.getId(), convoId); channel2.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); List<ConversationChannelWrapper> convos = mHelper.getConversations(false); assertEquals(3, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); assertTrue(conversationWrapperContainsChannel(convos, diffConvo)); assertTrue(conversationWrapperContainsChannel(convos, channel2)); } @Test public void testGetConversations_onlyImportant() { String convoId = "convo"; NotificationChannel messages = new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); NotificationChannel calls = new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); NotificationChannel p = new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); NotificationChannel channel = new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); channel.setConversationId(messages.getId(), convoId); channel.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); NotificationChannel diffConvo = new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); diffConvo.setConversationId(p.getId(), "different convo"); diffConvo.setImportantConversation(true); mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false); NotificationChannel channel2 = new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); channel2.setConversationId(calls.getId(), convoId); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); List<ConversationChannelWrapper> convos = mHelper.getConversations(true); assertEquals(2, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); assertTrue(conversationWrapperContainsChannel(convos, diffConvo)); assertFalse(conversationWrapperContainsChannel(convos, channel2)); } private boolean conversationWrapperContainsChannel(List<ConversationChannelWrapper> list, NotificationChannel expected) { for (ConversationChannelWrapper ccw : list) { if (ccw.getNotificationChannel().equals(expected)) { return true; } } return false; } @Test public void testGetConversations_invalidPkg() { assertThat(mHelper.getConversations("bad", 1)).isEmpty(); Loading