diff options
3 files changed, 152 insertions, 0 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 5bc0ddc48c8b..e2bee64cbb7b 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -122,6 +122,7 @@ interface INotificationManager 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 4023e52e3b13..b436c8b42edf 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.ApplicationInfo; 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 @@ public class NotificationManagerService extends SystemService { } @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 f07e5bca4f70..398dc28121fa 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.ApplicationInfo; 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 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @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; |