Loading services/core/java/com/android/server/notification/NotificationManagerService.java +17 −7 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ public class NotificationManagerService extends SystemService { static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION; static final int INVALID_UID = -1; static final boolean ENABLE_BLOCKED_TOASTS = true; Loading Loading @@ -4699,6 +4699,12 @@ public class NotificationManagerService extends SystemService { // ensure opPkg is delegate if does not match pkg int uid = resolveNotificationUid(opPkg, pkg, callingUid, userId); if (uid == INVALID_UID) { Slog.w(TAG, opPkg + ":" + callingUid + " trying to cancel notification " + "for nonexistent pkg " + pkg + " in user " + userId); return; } // if opPkg is not the same as pkg, make sure the notification given was posted // by opPkg if (!Objects.equals(pkg, opPkg)) { Loading Loading @@ -4743,6 +4749,11 @@ public class NotificationManagerService extends SystemService { // as "pkg" final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId); if (notificationUid == INVALID_UID) { throw new SecurityException("Caller " + opPkg + ":" + callingUid + " trying to post for invalid pkg " + pkg + " in user " + incomingUserId); } checkRestrictedCategories(notification); // Fix the notification as best we can. Loading Loading @@ -5063,8 +5074,7 @@ public class NotificationManagerService extends SystemService { } @VisibleForTesting int resolveNotificationUid(String callingPkg, String targetPkg, int callingUid, int userId) { int resolveNotificationUid(String callingPkg, String targetPkg, int callingUid, int userId) { if (userId == UserHandle.USER_ALL) { userId = USER_SYSTEM; } Loading @@ -5075,16 +5085,16 @@ public class NotificationManagerService extends SystemService { return callingUid; } int targetUid = -1; int targetUid = INVALID_UID; try { targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId); } catch (NameNotFoundException e) { /* ignore */ /* ignore, handled by caller */ } // posted from app A on behalf of app B if (targetUid != -1 && (isCallerAndroid(callingPkg, callingUid) if (isCallerAndroid(callingPkg, callingUid) || mPreferencesHelper.isDelegateAllowed( targetPkg, targetUid, callingPkg, callingUid))) { targetPkg, targetUid, callingPkg, callingUid)) { return targetUid; } Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +35 −6 Original line number Diff line number Diff line Loading @@ -181,12 +181,6 @@ import java.util.function.Consumer; @RunWithLooper public class NotificationManagerServiceTest extends UiServiceTestCase { private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; private static final String CLEAR_DEVICE_CONFIG_KEY_CMD = "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " " + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE; private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD = "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " " + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE; private final int mUid = Binder.getCallingUid(); private TestableNotificationManagerService mService; Loading Loading @@ -4039,6 +4033,41 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0)); } @Test public void testPostFromAndroidForNonExistentPackage() throws Exception { final String notReal = "NOT REAL"; when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow( PackageManager.NameNotFoundException.class); ApplicationInfo ai = new ApplicationInfo(); ai.uid = -1; when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai); final StatusBarNotification sbn = generateNotificationRecord(null).sbn; try { mInternalService.enqueueNotification(notReal, "android", 0, 0, "tag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); fail("can't post notifications for nonexistent packages, even if you exist"); } catch (SecurityException e) { // yay } } @Test public void testCancelFromAndroidForNonExistentPackage() throws Exception { final String notReal = "NOT REAL"; when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( PackageManager.NameNotFoundException.class); ApplicationInfo ai = new ApplicationInfo(); ai.uid = -1; when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai); // unlike the post case, ignore instead of throwing final StatusBarNotification sbn = generateNotificationRecord(null).sbn; mInternalService.cancelNotification(notReal, "android", 0, 0, "tag", sbn.getId(), sbn.getUserId()); } @Test public void testResolveNotificationUid_delegateNotAllowed() throws Exception { when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123); Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +17 −7 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ public class NotificationManagerService extends SystemService { static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION; static final int INVALID_UID = -1; static final boolean ENABLE_BLOCKED_TOASTS = true; Loading Loading @@ -4699,6 +4699,12 @@ public class NotificationManagerService extends SystemService { // ensure opPkg is delegate if does not match pkg int uid = resolveNotificationUid(opPkg, pkg, callingUid, userId); if (uid == INVALID_UID) { Slog.w(TAG, opPkg + ":" + callingUid + " trying to cancel notification " + "for nonexistent pkg " + pkg + " in user " + userId); return; } // if opPkg is not the same as pkg, make sure the notification given was posted // by opPkg if (!Objects.equals(pkg, opPkg)) { Loading Loading @@ -4743,6 +4749,11 @@ public class NotificationManagerService extends SystemService { // as "pkg" final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId); if (notificationUid == INVALID_UID) { throw new SecurityException("Caller " + opPkg + ":" + callingUid + " trying to post for invalid pkg " + pkg + " in user " + incomingUserId); } checkRestrictedCategories(notification); // Fix the notification as best we can. Loading Loading @@ -5063,8 +5074,7 @@ public class NotificationManagerService extends SystemService { } @VisibleForTesting int resolveNotificationUid(String callingPkg, String targetPkg, int callingUid, int userId) { int resolveNotificationUid(String callingPkg, String targetPkg, int callingUid, int userId) { if (userId == UserHandle.USER_ALL) { userId = USER_SYSTEM; } Loading @@ -5075,16 +5085,16 @@ public class NotificationManagerService extends SystemService { return callingUid; } int targetUid = -1; int targetUid = INVALID_UID; try { targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId); } catch (NameNotFoundException e) { /* ignore */ /* ignore, handled by caller */ } // posted from app A on behalf of app B if (targetUid != -1 && (isCallerAndroid(callingPkg, callingUid) if (isCallerAndroid(callingPkg, callingUid) || mPreferencesHelper.isDelegateAllowed( targetPkg, targetUid, callingPkg, callingUid))) { targetPkg, targetUid, callingPkg, callingUid)) { return targetUid; } Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +35 −6 Original line number Diff line number Diff line Loading @@ -181,12 +181,6 @@ import java.util.function.Consumer; @RunWithLooper public class NotificationManagerServiceTest extends UiServiceTestCase { private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; private static final String CLEAR_DEVICE_CONFIG_KEY_CMD = "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " " + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE; private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD = "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " " + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE; private final int mUid = Binder.getCallingUid(); private TestableNotificationManagerService mService; Loading Loading @@ -4039,6 +4033,41 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0)); } @Test public void testPostFromAndroidForNonExistentPackage() throws Exception { final String notReal = "NOT REAL"; when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow( PackageManager.NameNotFoundException.class); ApplicationInfo ai = new ApplicationInfo(); ai.uid = -1; when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai); final StatusBarNotification sbn = generateNotificationRecord(null).sbn; try { mInternalService.enqueueNotification(notReal, "android", 0, 0, "tag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); fail("can't post notifications for nonexistent packages, even if you exist"); } catch (SecurityException e) { // yay } } @Test public void testCancelFromAndroidForNonExistentPackage() throws Exception { final String notReal = "NOT REAL"; when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow( PackageManager.NameNotFoundException.class); ApplicationInfo ai = new ApplicationInfo(); ai.uid = -1; when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai); // unlike the post case, ignore instead of throwing final StatusBarNotification sbn = generateNotificationRecord(null).sbn; mInternalService.cancelNotification(notReal, "android", 0, 0, "tag", sbn.getId(), sbn.getUserId()); } @Test public void testResolveNotificationUid_delegateNotAllowed() throws Exception { when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123); Loading