summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/INotificationManager.aidl1
-rw-r--r--core/java/android/app/notification.aconfig10
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java15
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java23
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java36
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java61
6 files changed, 146 insertions, 0 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 6fedcbe50f30..b9255ecaf1b6 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -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);
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index a10b6ff39a37..9d8ab03982e6 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -308,6 +308,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"
description: "removes sbnholder from NLS"
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8242eeb7a3fe..09c8b5ba823e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5248,6 +5248,21 @@ public class NotificationManagerService extends SystemService {
}
@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;
checkCallerIsSystem();
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index a171ffc2ed98..3974c839fd38 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -2006,6 +2006,29 @@ public class PreferencesHelper implements RankingConfig {
}
/**
+ * 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.
* Should never be true for O+ targeting apps, but that's enforced on boot/when an app
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 3ec41fd673b1..858dd3a605d8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5385,6 +5385,42 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@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(
new IllegalArgumentException());
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 3f26cd9258af..640de174ba20 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -3096,6 +3096,67 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void getPackagesWithAnyChannels_noChannels() {
+ assertThat(mHelper.getPackagesWithAnyChannels(UserHandle.getUserId(UID_O))).isEmpty();
+ }
+
+ @Test
+ public void getPackagesWithAnyChannels_someChannels() {
+ // 2 channels under PKG_N_MR1, 1 under PKG_O
+ NotificationChannel channel1 = new NotificationChannel("1", "something",
+ IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false, UID_N_MR1,
+ false);
+ NotificationChannel channel2 = new NotificationChannel("2", "another", IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false, UID_N_MR1,
+ false);
+
+ NotificationChannel other = new NotificationChannel("3", "still another",
+ IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(PKG_O, UID_O, other, true, false, UID_O, false);
+
+ assertThat(mHelper.getPackagesWithAnyChannels(USER.getIdentifier())).containsExactly(
+ PKG_N_MR1, PKG_O);
+ }
+
+ @Test
+ public void getPackagesWithAnyChannels_onlyDeleted() {
+ NotificationChannel channel1 = new NotificationChannel("1", "something",
+ IMPORTANCE_DEFAULT);
+ channel1.setDeleted(true);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel1, true, false, UID_O,
+ false);
+ NotificationChannel channel2 = new NotificationChannel("2", "another", IMPORTANCE_DEFAULT);
+ channel2.setDeleted(true);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false, UID_O,
+ false);
+
+ assertThat(mHelper.getPackagesWithAnyChannels(UserHandle.getUserId(UID_O))).isEmpty();
+ }
+
+ @Test
+ public void getPackagesWithAnyChannels_distinguishesUsers() throws Exception {
+ // Set a package up for both users 0 and 10
+ String pkgName = "test.package";
+ int uid0 = UserHandle.getUid(0, 1234);
+ int uid10 = UserHandle.getUid(10, 1234);
+ setUpPackageWithUid(pkgName, uid0);
+ setUpPackageWithUid(pkgName, uid10);
+
+ // but only user 10 has channels
+ NotificationChannel channel1 = new NotificationChannel("1", "something",
+ IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(pkgName, uid10, channel1, true, false, uid10,
+ false);
+ NotificationChannel channel2 = new NotificationChannel("2", "another", IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(pkgName, uid10, channel2, true, false, uid10,
+ false);
+
+ assertThat(mHelper.getPackagesWithAnyChannels(0)).isEmpty();
+ assertThat(mHelper.getPackagesWithAnyChannels(10)).containsExactly(pkgName);
+ }
+
+ @Test
public void testOnlyHasDefaultChannel() throws Exception {
assertTrue(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1));
assertFalse(mHelper.onlyHasDefaultChannel(PKG_O, UID_O));