Loading core/java/android/app/INotificationManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ interface INotificationManager boolean areChannelsBypassingDnd(); ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int uid); ParceledListSlice getPackagesBypassingDnd(int userId); List<String> getPackagesWithAnyChannels(int userId); boolean isPackagePaused(String pkg); void deleteNotificationHistoryItem(String pkg, int uid, long postedTime); boolean isPermissionFixed(String pkg, int userId); Loading core/java/android/app/notification.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -307,6 +307,16 @@ flag { } } flag { name: "nm_binder_perf_get_apps_with_channels" namespace: "systemui" description: "Use a single binder call to get the set of apps with channels for a user" bug: "362981561" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "no_sbnholder" namespace: "systemui" Loading services/core/java/com/android/server/notification/NotificationManagerService.java +15 −0 Original line number Diff line number Diff line Loading @@ -5247,6 +5247,21 @@ public class NotificationManagerService extends SystemService { return mPreferencesHelper.areChannelsBypassingDnd(); } @Override @FlaggedApi(android.app.Flags.FLAG_NM_BINDER_PERF_GET_APPS_WITH_CHANNELS) public List<String> getPackagesWithAnyChannels(int userId) throws RemoteException { checkCallerIsSystem(); UserHandle user = UserHandle.of(userId); List<String> packages = mPreferencesHelper.getPackagesWithAnyChannels(userId); for (int i = packages.size() - 1; i >= 0; i--) { String pkg = packages.get(i); if (!areNotificationsEnabledForPackage(pkg, getUidForPackageAndUser(pkg, user))) { packages.remove(i); } } return packages; } @Override public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException { boolean packagesChanged = false; Loading services/core/java/com/android/server/notification/PreferencesHelper.java +23 −0 Original line number Diff line number Diff line Loading @@ -2005,6 +2005,29 @@ public class PreferencesHelper implements RankingConfig { return bypassing; } /** * Gets all apps for this user that have a nonzero number of channels. This count does not * include deleted channels. */ @FlaggedApi(android.app.Flags.FLAG_NM_BINDER_PERF_GET_APPS_WITH_CHANNELS) public @NonNull List<String> getPackagesWithAnyChannels(@UserIdInt int userId) { List<String> pkgs = new ArrayList<>(); synchronized (mLock) { for (PackagePreferences p : mPackagePreferences.values()) { if (UserHandle.getUserId(p.uid) != userId) { continue; } for (NotificationChannel c : p.channels.values()) { if (!c.isDeleted()) { pkgs.add(p.pkg); break; } } } } return pkgs; } /** * True for pre-O apps that only have the default channel, or pre O apps that have no * channels yet. This method will create the default channel for pre-O apps that don't have it. Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -5384,6 +5384,42 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { anyInt()); } @Test public void testGetPackagesWithChannels_blocked() throws Exception { // While we mostly rely on the PreferencesHelper implementation of channels, we filter in // NMS so that we do not return blocked packages. // Three packages; all under user 1. // pkg2 is blocked, but pkg1 and pkg3 are not. String pkg1 = "com.package.one", pkg2 = "com.package.two", pkg3 = "com.package.three"; int uid1 = UserHandle.getUid(1, 111); int uid2 = UserHandle.getUid(1, 222); int uid3 = UserHandle.getUid(1, 333); when(mPackageManager.getPackageUid(eq(pkg1), anyLong(), anyInt())).thenReturn(uid1); when(mPackageManager.getPackageUid(eq(pkg2), anyLong(), anyInt())).thenReturn(uid2); when(mPackageManager.getPackageUid(eq(pkg3), anyLong(), anyInt())).thenReturn(uid3); when(mPermissionHelper.hasPermission(uid1)).thenReturn(true); when(mPermissionHelper.hasPermission(uid2)).thenReturn(false); when(mPermissionHelper.hasPermission(uid3)).thenReturn(true); NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT); NotificationChannel channel2 = new NotificationChannel("id3", "name3", NotificationManager.IMPORTANCE_DEFAULT); NotificationChannel channel3 = new NotificationChannel("id4", "name3", NotificationManager.IMPORTANCE_DEFAULT); mService.mPreferencesHelper.createNotificationChannel(pkg1, uid1, channel1, true, false, uid1, false); mService.mPreferencesHelper.createNotificationChannel(pkg2, uid2, channel2, true, false, uid2, false); mService.mPreferencesHelper.createNotificationChannel(pkg3, uid3, channel3, true, false, uid3, false); // Output should contain only the package with notification permissions (1, 3). enableInteractAcrossUsers(); assertThat(mBinderService.getPackagesWithAnyChannels(1)).containsExactly(pkg1, pkg3); } @Test public void testHasCompanionDevice_failure() throws Exception { when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( Loading Loading
core/java/android/app/INotificationManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ interface INotificationManager boolean areChannelsBypassingDnd(); ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int uid); ParceledListSlice getPackagesBypassingDnd(int userId); List<String> getPackagesWithAnyChannels(int userId); boolean isPackagePaused(String pkg); void deleteNotificationHistoryItem(String pkg, int uid, long postedTime); boolean isPermissionFixed(String pkg, int userId); Loading
core/java/android/app/notification.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -307,6 +307,16 @@ flag { } } flag { name: "nm_binder_perf_get_apps_with_channels" namespace: "systemui" description: "Use a single binder call to get the set of apps with channels for a user" bug: "362981561" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "no_sbnholder" namespace: "systemui" Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +15 −0 Original line number Diff line number Diff line Loading @@ -5247,6 +5247,21 @@ public class NotificationManagerService extends SystemService { return mPreferencesHelper.areChannelsBypassingDnd(); } @Override @FlaggedApi(android.app.Flags.FLAG_NM_BINDER_PERF_GET_APPS_WITH_CHANNELS) public List<String> getPackagesWithAnyChannels(int userId) throws RemoteException { checkCallerIsSystem(); UserHandle user = UserHandle.of(userId); List<String> packages = mPreferencesHelper.getPackagesWithAnyChannels(userId); for (int i = packages.size() - 1; i >= 0; i--) { String pkg = packages.get(i); if (!areNotificationsEnabledForPackage(pkg, getUidForPackageAndUser(pkg, user))) { packages.remove(i); } } return packages; } @Override public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException { boolean packagesChanged = false; Loading
services/core/java/com/android/server/notification/PreferencesHelper.java +23 −0 Original line number Diff line number Diff line Loading @@ -2005,6 +2005,29 @@ public class PreferencesHelper implements RankingConfig { return bypassing; } /** * Gets all apps for this user that have a nonzero number of channels. This count does not * include deleted channels. */ @FlaggedApi(android.app.Flags.FLAG_NM_BINDER_PERF_GET_APPS_WITH_CHANNELS) public @NonNull List<String> getPackagesWithAnyChannels(@UserIdInt int userId) { List<String> pkgs = new ArrayList<>(); synchronized (mLock) { for (PackagePreferences p : mPackagePreferences.values()) { if (UserHandle.getUserId(p.uid) != userId) { continue; } for (NotificationChannel c : p.channels.values()) { if (!c.isDeleted()) { pkgs.add(p.pkg); break; } } } } return pkgs; } /** * True for pre-O apps that only have the default channel, or pre O apps that have no * channels yet. This method will create the default channel for pre-O apps that don't have it. Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -5384,6 +5384,42 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { anyInt()); } @Test public void testGetPackagesWithChannels_blocked() throws Exception { // While we mostly rely on the PreferencesHelper implementation of channels, we filter in // NMS so that we do not return blocked packages. // Three packages; all under user 1. // pkg2 is blocked, but pkg1 and pkg3 are not. String pkg1 = "com.package.one", pkg2 = "com.package.two", pkg3 = "com.package.three"; int uid1 = UserHandle.getUid(1, 111); int uid2 = UserHandle.getUid(1, 222); int uid3 = UserHandle.getUid(1, 333); when(mPackageManager.getPackageUid(eq(pkg1), anyLong(), anyInt())).thenReturn(uid1); when(mPackageManager.getPackageUid(eq(pkg2), anyLong(), anyInt())).thenReturn(uid2); when(mPackageManager.getPackageUid(eq(pkg3), anyLong(), anyInt())).thenReturn(uid3); when(mPermissionHelper.hasPermission(uid1)).thenReturn(true); when(mPermissionHelper.hasPermission(uid2)).thenReturn(false); when(mPermissionHelper.hasPermission(uid3)).thenReturn(true); NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT); NotificationChannel channel2 = new NotificationChannel("id3", "name3", NotificationManager.IMPORTANCE_DEFAULT); NotificationChannel channel3 = new NotificationChannel("id4", "name3", NotificationManager.IMPORTANCE_DEFAULT); mService.mPreferencesHelper.createNotificationChannel(pkg1, uid1, channel1, true, false, uid1, false); mService.mPreferencesHelper.createNotificationChannel(pkg2, uid2, channel2, true, false, uid2, false); mService.mPreferencesHelper.createNotificationChannel(pkg3, uid3, channel3, true, false, uid3, false); // Output should contain only the package with notification permissions (1, 3). enableInteractAcrossUsers(); assertThat(mBinderService.getPackagesWithAnyChannels(1)).containsExactly(pkg1, pkg3); } @Test public void testHasCompanionDevice_failure() throws Exception { when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( Loading