Loading core/java/android/service/notification/StatusBarNotification.java +27 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,33 @@ public class StatusBarNotification implements Parcelable { this.groupKey = groupKey(); } /** * @hide */ public static int getUidFromKey(@NonNull String key) { String[] parts = key.split("\\|"); if (parts.length >= 5) { try { int uid = Integer.parseInt(parts[4]); return uid; } catch (NumberFormatException e) { return -1; } } return -1; } /** * @hide */ public static String getPkgFromKey(@NonNull String key) { String[] parts = key.split("\\|"); if (parts.length >= 2) { return parts[1]; } return null; } private String key() { String sbnKey = user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid; if (overrideGroupKey != null && getNotification().isGroupSummary()) { Loading core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +23 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; Loading Loading @@ -54,6 +55,7 @@ public class StatusBarNotificationTest { private final Context mMockContext = mock(Context.class); @Mock private Context mRealContext; @Mock private PackageManager mPm; private static final String PKG = "com.example.o"; Loading @@ -78,6 +80,7 @@ public class StatusBarNotificationTest { InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); when(mPm.getApplicationLabel(any())).thenReturn(""); mRealContext = InstrumentationRegistry.getContext(); } Loading Loading @@ -217,6 +220,26 @@ public class StatusBarNotificationTest { assertEquals(pkg, resultContext.getPackageName()); } @Test public void testGetUidFromKey() { StatusBarNotification sbn = getNotification("pkg", null, "channel"); assertEquals(UID, StatusBarNotification.getUidFromKey(sbn.getKey())); sbn.setOverrideGroupKey("addsToKey"); assertEquals(UID, StatusBarNotification.getUidFromKey(sbn.getKey())); } @Test public void testGetPkgFromKey() { StatusBarNotification sbn = getNotification("pkg", null, "channel"); assertEquals("pkg", StatusBarNotification.getPkgFromKey(sbn.getKey())); sbn.setOverrideGroupKey("addsToKey"); assertEquals("pkg", StatusBarNotification.getPkgFromKey(sbn.getKey())); } private StatusBarNotification getNotification(String pkg, String group, String channelId) { return getNotification(pkg, getNotificationBuilder(group, channelId)); } Loading services/core/java/com/android/server/notification/NotificationManagerService.java +33 −23 Original line number Diff line number Diff line Loading @@ -3544,11 +3544,7 @@ public class NotificationManagerService extends SystemService { "canNotifyAsPackage for uid " + uid); } if (mEnableAppSettingMigration) { return mPermissionHelper.hasPermission(uid); } else { return mPreferencesHelper.getImportance(pkg, uid) != IMPORTANCE_NONE; } return areNotificationsEnabledForPackageInt(pkg, uid); } /** Loading Loading @@ -6732,13 +6728,30 @@ public class NotificationManagerService extends SystemService { // blocked apps if (isBlocked(r, mUsageStats)) { boolean isBlocked = !areNotificationsEnabledForPackageInt(pkg, uid); synchronized (mNotificationLock) { isBlocked |= isRecordBlockedLocked(r); } if (isBlocked) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); } mUsageStats.registerBlocked(r); return false; } return true; } private boolean areNotificationsEnabledForPackageInt(String pkg, int uid) { if (mEnableAppSettingMigration) { return mPermissionHelper.hasPermission(uid); } else { return mPreferencesHelper.getImportance(pkg, uid) != IMPORTANCE_NONE; } } protected int getNotificationCount(String pkg, int userId, int excludedId, String excludedTag) { int count = 0; Loading Loading @@ -6767,24 +6780,15 @@ public class NotificationManagerService extends SystemService { return count; } protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) { if (isBlocked(r)) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); } usageStats.registerBlocked(r); return true; } return false; } private boolean isBlocked(NotificationRecord r) { /** * Checks whether a notification is banned at a group or channel level or if the NAS or system * has blocked the notification. */ @GuardedBy("mNotificationLock") boolean isRecordBlockedLocked(NotificationRecord r) { final String pkg = r.getSbn().getPackageName(); final int callingUid = r.getSbn().getUid(); return mPreferencesHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup()) || mPreferencesHelper.getImportance(pkg, callingUid) == NotificationManager.IMPORTANCE_NONE || r.getImportance() == NotificationManager.IMPORTANCE_NONE; } Loading Loading @@ -7095,6 +7099,9 @@ public class NotificationManagerService extends SystemService { @Override public void run() { String pkg = StatusBarNotification.getPkgFromKey(key); int uid = StatusBarNotification.getUidFromKey(key); boolean appBanned = !areNotificationsEnabledForPackageInt(pkg, uid); synchronized (mNotificationLock) { try { NotificationRecord r = null; Loading @@ -7111,8 +7118,11 @@ public class NotificationManagerService extends SystemService { return; } if (isBlocked(r)) { Slog.i(TAG, "notification blocked by assistant request"); if (appBanned || isRecordBlockedLocked(r)) { mUsageStats.registerBlocked(r); if (DBG) { Slog.e(TAG, "Suppressing notification from package " + pkg); } return; } Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +37 −6 Original line number Diff line number Diff line Loading @@ -182,7 +182,6 @@ import android.util.TypedXmlSerializer; import android.util.Xml; import android.widget.RemoteViews; import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import com.android.internal.app.IAppOpsService; Loading Loading @@ -1040,7 +1039,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(channel); // isBlocked is only used for user blocking, not app suspension assertFalse(mService.isBlocked(r, mUsageStats)); assertFalse(mService.isRecordBlockedLocked(r)); } @Test Loading @@ -1050,8 +1049,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_NONE); NotificationRecord r = generateNotificationRecord(channel); assertTrue(mService.isBlocked(r, mUsageStats)); verify(mUsageStats, times(1)).registerBlocked(eq(r)); assertTrue(mService.isRecordBlockedLocked(r)); mBinderService.createNotificationChannels( PKG, new ParceledListSlice(Arrays.asList(channel))); Loading Loading @@ -1148,8 +1146,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationManager.IMPORTANCE_HIGH); channel.setGroup("something"); NotificationRecord r = generateNotificationRecord(channel); assertTrue(mService.isBlocked(r, mUsageStats)); verify(mUsageStats, times(1)).registerBlocked(eq(r)); assertTrue(mService.isRecordBlockedLocked(r)); } @Test Loading Loading @@ -1286,6 +1283,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { verify(mUsageStats, never()).registerPostedByApp(any()); } @Test public void testBlockedNotifications_blockedByUser() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); NotificationRecord r = generateNotificationRecord(channel); mService.addEnqueuedNotification(r); when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(IMPORTANCE_NONE); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(r.getKey()); runnable.run(); waitForIdle(); verify(mUsageStats).registerBlocked(any()); verify(mUsageStats, never()).registerPostedByApp(any()); } @Test public void testEnqueueNotification_appBlocked() throws Exception { mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); mBinderService.enqueueNotificationWithTag(PKG, PKG, "testEnqueueNotification_appBlocked", 0, generateNotificationRecord(null).getNotification(), 0); waitForIdle(); verify(mWorkerHandler, never()).post( any(NotificationManagerService.EnqueueNotificationRunnable.class)); } @Test public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { mBinderService.enqueueNotificationWithTag(PKG, PKG, Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +33 −0 Original line number Diff line number Diff line Loading @@ -630,4 +630,37 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase { verify(mPreferencesHelper, never()).getImportance(anyString(), anyInt()); verify(mPreferencesHelper, never()).getNotificationChannelsBypassingDnd(PKG, mUid); } @Test public void testBlockedNotifications_blockedByUser() throws Exception { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); NotificationRecord r = generateNotificationRecord(channel); mService.addEnqueuedNotification(r); when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(r.getKey()); runnable.run(); waitForIdle(); verify(mUsageStats).registerBlocked(any()); verify(mUsageStats, never()).registerPostedByApp(any()); } @Test public void testEnqueueNotification_appBlocked() throws Exception { when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); mBinderService.enqueueNotificationWithTag(PKG, PKG, "testEnqueueNotification_appBlocked", 0, generateNotificationRecord(null).getNotification(), 0); waitForIdle(); verify(mWorkerHandler, never()).post( any(NotificationManagerService.EnqueueNotificationRunnable.class)); } } Loading
core/java/android/service/notification/StatusBarNotification.java +27 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,33 @@ public class StatusBarNotification implements Parcelable { this.groupKey = groupKey(); } /** * @hide */ public static int getUidFromKey(@NonNull String key) { String[] parts = key.split("\\|"); if (parts.length >= 5) { try { int uid = Integer.parseInt(parts[4]); return uid; } catch (NumberFormatException e) { return -1; } } return -1; } /** * @hide */ public static String getPkgFromKey(@NonNull String key) { String[] parts = key.split("\\|"); if (parts.length >= 2) { return parts[1]; } return null; } private String key() { String sbnKey = user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid; if (overrideGroupKey != null && getNotification().isGroupSummary()) { Loading
core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +23 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; Loading Loading @@ -54,6 +55,7 @@ public class StatusBarNotificationTest { private final Context mMockContext = mock(Context.class); @Mock private Context mRealContext; @Mock private PackageManager mPm; private static final String PKG = "com.example.o"; Loading @@ -78,6 +80,7 @@ public class StatusBarNotificationTest { InstrumentationRegistry.getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); when(mPm.getApplicationLabel(any())).thenReturn(""); mRealContext = InstrumentationRegistry.getContext(); } Loading Loading @@ -217,6 +220,26 @@ public class StatusBarNotificationTest { assertEquals(pkg, resultContext.getPackageName()); } @Test public void testGetUidFromKey() { StatusBarNotification sbn = getNotification("pkg", null, "channel"); assertEquals(UID, StatusBarNotification.getUidFromKey(sbn.getKey())); sbn.setOverrideGroupKey("addsToKey"); assertEquals(UID, StatusBarNotification.getUidFromKey(sbn.getKey())); } @Test public void testGetPkgFromKey() { StatusBarNotification sbn = getNotification("pkg", null, "channel"); assertEquals("pkg", StatusBarNotification.getPkgFromKey(sbn.getKey())); sbn.setOverrideGroupKey("addsToKey"); assertEquals("pkg", StatusBarNotification.getPkgFromKey(sbn.getKey())); } private StatusBarNotification getNotification(String pkg, String group, String channelId) { return getNotification(pkg, getNotificationBuilder(group, channelId)); } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +33 −23 Original line number Diff line number Diff line Loading @@ -3544,11 +3544,7 @@ public class NotificationManagerService extends SystemService { "canNotifyAsPackage for uid " + uid); } if (mEnableAppSettingMigration) { return mPermissionHelper.hasPermission(uid); } else { return mPreferencesHelper.getImportance(pkg, uid) != IMPORTANCE_NONE; } return areNotificationsEnabledForPackageInt(pkg, uid); } /** Loading Loading @@ -6732,13 +6728,30 @@ public class NotificationManagerService extends SystemService { // blocked apps if (isBlocked(r, mUsageStats)) { boolean isBlocked = !areNotificationsEnabledForPackageInt(pkg, uid); synchronized (mNotificationLock) { isBlocked |= isRecordBlockedLocked(r); } if (isBlocked) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); } mUsageStats.registerBlocked(r); return false; } return true; } private boolean areNotificationsEnabledForPackageInt(String pkg, int uid) { if (mEnableAppSettingMigration) { return mPermissionHelper.hasPermission(uid); } else { return mPreferencesHelper.getImportance(pkg, uid) != IMPORTANCE_NONE; } } protected int getNotificationCount(String pkg, int userId, int excludedId, String excludedTag) { int count = 0; Loading Loading @@ -6767,24 +6780,15 @@ public class NotificationManagerService extends SystemService { return count; } protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) { if (isBlocked(r)) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); } usageStats.registerBlocked(r); return true; } return false; } private boolean isBlocked(NotificationRecord r) { /** * Checks whether a notification is banned at a group or channel level or if the NAS or system * has blocked the notification. */ @GuardedBy("mNotificationLock") boolean isRecordBlockedLocked(NotificationRecord r) { final String pkg = r.getSbn().getPackageName(); final int callingUid = r.getSbn().getUid(); return mPreferencesHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup()) || mPreferencesHelper.getImportance(pkg, callingUid) == NotificationManager.IMPORTANCE_NONE || r.getImportance() == NotificationManager.IMPORTANCE_NONE; } Loading Loading @@ -7095,6 +7099,9 @@ public class NotificationManagerService extends SystemService { @Override public void run() { String pkg = StatusBarNotification.getPkgFromKey(key); int uid = StatusBarNotification.getUidFromKey(key); boolean appBanned = !areNotificationsEnabledForPackageInt(pkg, uid); synchronized (mNotificationLock) { try { NotificationRecord r = null; Loading @@ -7111,8 +7118,11 @@ public class NotificationManagerService extends SystemService { return; } if (isBlocked(r)) { Slog.i(TAG, "notification blocked by assistant request"); if (appBanned || isRecordBlockedLocked(r)) { mUsageStats.registerBlocked(r); if (DBG) { Slog.e(TAG, "Suppressing notification from package " + pkg); } return; } Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +37 −6 Original line number Diff line number Diff line Loading @@ -182,7 +182,6 @@ import android.util.TypedXmlSerializer; import android.util.Xml; import android.widget.RemoteViews; import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import com.android.internal.app.IAppOpsService; Loading Loading @@ -1040,7 +1039,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(channel); // isBlocked is only used for user blocking, not app suspension assertFalse(mService.isBlocked(r, mUsageStats)); assertFalse(mService.isRecordBlockedLocked(r)); } @Test Loading @@ -1050,8 +1049,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_NONE); NotificationRecord r = generateNotificationRecord(channel); assertTrue(mService.isBlocked(r, mUsageStats)); verify(mUsageStats, times(1)).registerBlocked(eq(r)); assertTrue(mService.isRecordBlockedLocked(r)); mBinderService.createNotificationChannels( PKG, new ParceledListSlice(Arrays.asList(channel))); Loading Loading @@ -1148,8 +1146,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationManager.IMPORTANCE_HIGH); channel.setGroup("something"); NotificationRecord r = generateNotificationRecord(channel); assertTrue(mService.isBlocked(r, mUsageStats)); verify(mUsageStats, times(1)).registerBlocked(eq(r)); assertTrue(mService.isRecordBlockedLocked(r)); } @Test Loading Loading @@ -1286,6 +1283,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { verify(mUsageStats, never()).registerPostedByApp(any()); } @Test public void testBlockedNotifications_blockedByUser() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); NotificationRecord r = generateNotificationRecord(channel); mService.addEnqueuedNotification(r); when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(IMPORTANCE_NONE); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(r.getKey()); runnable.run(); waitForIdle(); verify(mUsageStats).registerBlocked(any()); verify(mUsageStats, never()).registerPostedByApp(any()); } @Test public void testEnqueueNotification_appBlocked() throws Exception { mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); mBinderService.enqueueNotificationWithTag(PKG, PKG, "testEnqueueNotification_appBlocked", 0, generateNotificationRecord(null).getNotification(), 0); waitForIdle(); verify(mWorkerHandler, never()).post( any(NotificationManagerService.EnqueueNotificationRunnable.class)); } @Test public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { mBinderService.enqueueNotificationWithTag(PKG, PKG, Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +33 −0 Original line number Diff line number Diff line Loading @@ -630,4 +630,37 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase { verify(mPreferencesHelper, never()).getImportance(anyString(), anyInt()); verify(mPreferencesHelper, never()).getNotificationChannelsBypassingDnd(PKG, mUid); } @Test public void testBlockedNotifications_blockedByUser() throws Exception { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); NotificationRecord r = generateNotificationRecord(channel); mService.addEnqueuedNotification(r); when(mPermissionHelper.hasPermission(anyInt())).thenReturn(false); NotificationManagerService.PostNotificationRunnable runnable = mService.new PostNotificationRunnable(r.getKey()); runnable.run(); waitForIdle(); verify(mUsageStats).registerBlocked(any()); verify(mUsageStats, never()).registerPostedByApp(any()); } @Test public void testEnqueueNotification_appBlocked() throws Exception { when(mPermissionHelper.hasPermission(mUid)).thenReturn(false); mBinderService.enqueueNotificationWithTag(PKG, PKG, "testEnqueueNotification_appBlocked", 0, generateNotificationRecord(null).getNotification(), 0); waitForIdle(); verify(mWorkerHandler, never()).post( any(NotificationManagerService.EnqueueNotificationRunnable.class)); } }