Merge "Adds bulk getChannelsBypassingDnd call to NMS" into main
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 5bc0ddc..e2bee64 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -122,6 +122,7 @@
boolean onlyHasDefaultChannel(String pkg, int uid);
boolean areChannelsBypassingDnd();
ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int uid);
+ List<String> getPackagesBypassingDnd(int userId, boolean includeConversationChannels);
boolean isPackagePaused(String pkg);
void deleteNotificationHistoryItem(String pkg, int uid, long postedTime);
boolean isPermissionFixed(String pkg, int userId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4023e52..b436c8b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -225,6 +225,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.LauncherApps;
import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
@@ -4536,6 +4537,34 @@
}
@Override
+ public List<String> getPackagesBypassingDnd(int userId,
+ boolean includeConversationChannels) {
+ checkCallerIsSystem();
+
+ final ArraySet<String> packageNames = new ArraySet<>();
+
+ for (int user : mUm.getProfileIds(userId, false)) {
+ List<PackageInfo> pkgs = mPackageManagerClient.getInstalledPackagesAsUser(0, user);
+ for (PackageInfo pi : pkgs) {
+ String pkg = pi.packageName;
+ // If any NotificationChannel for this package is bypassing, the
+ // package is considered bypassing.
+ for (NotificationChannel channel : getNotificationChannelsBypassingDnd(pkg,
+ pi.applicationInfo.uid).getList()) {
+ // Skips non-demoted conversation channels.
+ if (!includeConversationChannels
+ && !TextUtils.isEmpty(channel.getConversationId())
+ && !channel.isDemoted()) {
+ continue;
+ }
+ packageNames.add(pkg);
+ }
+ }
+ }
+ return new ArrayList<String>(packageNames);
+ }
+
+ @Override
public boolean areChannelsBypassingDnd() {
if (android.app.Flags.modesApi()) {
return mZenModeHelper.getConsolidatedNotificationPolicy().allowPriorityChannels()
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 f07e5bc..398dc281 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -208,6 +208,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.LauncherApps;
import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
@@ -12072,6 +12073,127 @@
}
@Test
+ public void testGetPackagesBypassingDnd_empty() throws RemoteException {
+ mService.setPreferencesHelper(mPreferencesHelper);
+ List<String> result = mBinderService.getPackagesBypassingDnd(mUserId, true);
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void testGetPackagesBypassingDnd_excludeConversationChannels() throws RemoteException {
+ mService.setPreferencesHelper(mPreferencesHelper);
+
+ // Set packages
+ PackageInfo pkg0 = new PackageInfo();
+ pkg0.packageName = "pkg0";
+ pkg0.applicationInfo = new ApplicationInfo();
+ pkg0.applicationInfo.uid = mUid;
+ PackageInfo pkg1 = new PackageInfo();
+ pkg1.packageName = "pkg1";
+ pkg1.applicationInfo = new ApplicationInfo();
+ pkg1.applicationInfo.uid = mUid;
+ PackageInfo pkg2 = new PackageInfo();
+ pkg2.packageName = "pkg2";
+ pkg2.applicationInfo = new ApplicationInfo();
+ pkg2.applicationInfo.uid = mUid;
+
+ when(mPackageManagerClient.getInstalledPackagesAsUser(0, mUserId))
+ .thenReturn(List.of(pkg0, pkg1, pkg2));
+
+ // Conversation channels
+ NotificationChannel nc0 = new NotificationChannel("id0", "id0",
+ NotificationManager.IMPORTANCE_HIGH);
+ nc0.setConversationId("parentChannel", "conversationId");
+
+ // Demoted conversation channel
+ NotificationChannel nc1 = new NotificationChannel("id1", "id1",
+ NotificationManager.IMPORTANCE_HIGH);
+ nc1.setConversationId("parentChannel", "conversationId");
+ nc1.setDemoted(true);
+
+ // Non-conversation channels
+ NotificationChannel nc2 = new NotificationChannel("id2", "id2",
+ NotificationManager.IMPORTANCE_HIGH);
+ NotificationChannel nc3 = new NotificationChannel("id3", "id3",
+ NotificationManager.IMPORTANCE_HIGH);
+
+ ParceledListSlice<NotificationChannel> pls0 =
+ new ParceledListSlice(ImmutableList.of(nc0));
+ ParceledListSlice<NotificationChannel> pls1 =
+ new ParceledListSlice(ImmutableList.of(nc1));
+ ParceledListSlice<NotificationChannel> pls2 =
+ new ParceledListSlice(ImmutableList.of(nc2, nc3));
+
+ when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg0", mUid))
+ .thenReturn(pls0);
+ when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg1", mUid))
+ .thenReturn(pls1);
+ when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg2", mUid))
+ .thenReturn(pls2);
+
+ List<String> result = mBinderService.getPackagesBypassingDnd(mUserId, false);
+
+ assertThat(result).containsExactly("pkg1", "pkg2");
+ }
+
+ @Test
+ public void testGetPackagesBypassingDnd_includeConversationChannels() throws RemoteException {
+ mService.setPreferencesHelper(mPreferencesHelper);
+
+ // Set packages
+ PackageInfo pkg0 = new PackageInfo();
+ pkg0.packageName = "pkg0";
+ pkg0.applicationInfo = new ApplicationInfo();
+ pkg0.applicationInfo.uid = mUid;
+ PackageInfo pkg1 = new PackageInfo();
+ pkg1.packageName = "pkg1";
+ pkg1.applicationInfo = new ApplicationInfo();
+ pkg1.applicationInfo.uid = mUid;
+ PackageInfo pkg2 = new PackageInfo();
+ pkg2.packageName = "pkg2";
+ pkg2.applicationInfo = new ApplicationInfo();
+ pkg2.applicationInfo.uid = mUid;
+
+ when(mPackageManagerClient.getInstalledPackagesAsUser(0, mUserId))
+ .thenReturn(List.of(pkg0, pkg1, pkg2));
+
+ // Conversation channels
+ NotificationChannel nc0 = new NotificationChannel("id0", "id0",
+ NotificationManager.IMPORTANCE_HIGH);
+ nc0.setConversationId("parentChannel", "conversationId");
+
+ // Demoted conversation channel
+ NotificationChannel nc1 = new NotificationChannel("id1", "id1",
+ NotificationManager.IMPORTANCE_HIGH);
+ nc1.setConversationId("parentChannel", "conversationId");
+ nc1.setDemoted(true);
+
+ // Non-conversation channels
+ NotificationChannel nc2 = new NotificationChannel("id2", "id2",
+ NotificationManager.IMPORTANCE_HIGH);
+ NotificationChannel nc3 = new NotificationChannel("id3", "id3",
+ NotificationManager.IMPORTANCE_HIGH);
+
+ ParceledListSlice<NotificationChannel> pls0 =
+ new ParceledListSlice(ImmutableList.of(nc0));
+ ParceledListSlice<NotificationChannel> pls1 =
+ new ParceledListSlice(ImmutableList.of(nc1));
+ ParceledListSlice<NotificationChannel> pls2 =
+ new ParceledListSlice(ImmutableList.of(nc2, nc3));
+
+ when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg0", mUid))
+ .thenReturn(pls0);
+ when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg1", mUid))
+ .thenReturn(pls1);
+ when(mPreferencesHelper.getNotificationChannelsBypassingDnd("pkg2", mUid))
+ .thenReturn(pls2);
+
+ List<String> result = mBinderService.getPackagesBypassingDnd(mUserId, true);
+
+ assertThat(result).containsExactly("pkg0", "pkg1", "pkg2");
+ }
+
+ @Test
public void testMatchesCallFilter_noPermissionShouldThrow() throws Exception {
// set the testable NMS to not system uid/appid
mService.isSystemUid = false;