Loading services/core/java/com/android/server/notification/NotificationManagerService.java +10 −7 Original line number Diff line number Diff line Loading @@ -3796,13 +3796,13 @@ public class NotificationManagerService extends SystemService { } private void createNotificationChannelsImpl(String pkg, int uid, ParceledListSlice channelsList) { createNotificationChannelsImpl(pkg, uid, channelsList, ParceledListSlice channelsList, boolean fromTargetApp) { createNotificationChannelsImpl(pkg, uid, channelsList, fromTargetApp, ActivityTaskManager.INVALID_TASK_ID); } private void createNotificationChannelsImpl(String pkg, int uid, ParceledListSlice channelsList, int startingTaskId) { ParceledListSlice channelsList, boolean fromTargetApp, int startingTaskId) { List<NotificationChannel> channels = channelsList.getList(); final int channelsSize = channels.size(); ParceledListSlice<NotificationChannel> oldChannels = Loading @@ -3814,7 +3814,7 @@ public class NotificationManagerService extends SystemService { final NotificationChannel channel = channels.get(i); Objects.requireNonNull(channel, "channel in list is null"); needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid, channel, true /* fromTargetApp */, channel, fromTargetApp, mConditionProviders.isPackageOrComponentAllowed( pkg, UserHandle.getUserId(uid))); if (needsPolicyFileChange) { Loading Loading @@ -3850,6 +3850,7 @@ public class NotificationManagerService extends SystemService { @Override public void createNotificationChannels(String pkg, ParceledListSlice channelsList) { checkCallerIsSystemOrSameApp(pkg); boolean fromTargetApp = !isCallerSystemOrPhone(); // if not system, it's from the app int taskId = ActivityTaskManager.INVALID_TASK_ID; try { int uid = mPackageManager.getPackageUid(pkg, 0, Loading @@ -3858,14 +3859,15 @@ public class NotificationManagerService extends SystemService { } catch (RemoteException e) { // Do nothing } createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, taskId); createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, fromTargetApp, taskId); } @Override public void createNotificationChannelsForPackage(String pkg, int uid, ParceledListSlice channelsList) { enforceSystemOrSystemUI("only system can call this"); createNotificationChannelsImpl(pkg, uid, channelsList); createNotificationChannelsImpl(pkg, uid, channelsList, false /* fromTargetApp */); } @Override Loading @@ -3880,7 +3882,8 @@ public class NotificationManagerService extends SystemService { CONVERSATION_CHANNEL_ID_FORMAT, parentId, conversationId)); conversationChannel.setConversationId(parentId, conversationId); createNotificationChannelsImpl( pkg, uid, new ParceledListSlice(Arrays.asList(conversationChannel))); pkg, uid, new ParceledListSlice(Arrays.asList(conversationChannel)), false /* fromTargetApp */); mRankingHandler.requestSort(); handleSavePolicyFile(); } Loading services/core/java/com/android/server/notification/PreferencesHelper.java +2 −4 Original line number Diff line number Diff line Loading @@ -916,7 +916,7 @@ public class PreferencesHelper implements RankingConfig { throw new IllegalArgumentException("Reserved id"); } NotificationChannel existing = r.channels.get(channel.getId()); if (existing != null && fromTargetApp) { if (existing != null) { // Actually modifying an existing channel - keep most of the existing settings if (existing.isDeleted()) { // The existing channel was deleted - undelete it. Loading Loading @@ -1002,9 +1002,7 @@ public class PreferencesHelper implements RankingConfig { } if (fromTargetApp) { channel.setLockscreenVisibility(r.visibility); channel.setAllowBubbles(existing != null ? existing.getAllowBubbles() : NotificationChannel.DEFAULT_ALLOW_BUBBLE); channel.setAllowBubbles(NotificationChannel.DEFAULT_ALLOW_BUBBLE); } clearLockedFieldsLocked(channel); Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +52 −4 Original line number Diff line number Diff line Loading @@ -1101,6 +1101,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { new NotificationChannel("id", "name", IMPORTANCE_HIGH); mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); // pretend only this following part is called by the app (system permissions are required to // update the notification channel on behalf of the user above) mService.isSystemUid = false; // Recreating with a lower importance leaves channel unchanged. final NotificationChannel dupeChannel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); Loading @@ -1125,6 +1129,46 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); } @Test public void testCreateNotificationChannels_fromAppCannotSetFields() throws Exception { // Confirm that when createNotificationChannels is called from the relevant app and not // system, then it cannot set fields that can't be set by apps mService.isSystemUid = false; final NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); channel.setBypassDnd(true); channel.setAllowBubbles(true); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel))); final NotificationChannel createdChannel = mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertFalse(createdChannel.canBypassDnd()); assertFalse(createdChannel.canBubble()); } @Test public void testCreateNotificationChannels_fromSystemCanSetFields() throws Exception { // Confirm that when createNotificationChannels is called from system, // then it can set fields that can't be set by apps mService.isSystemUid = true; final NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); channel.setBypassDnd(true); channel.setAllowBubbles(true); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel))); final NotificationChannel createdChannel = mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertTrue(createdChannel.canBypassDnd()); assertTrue(createdChannel.canBubble()); } @Test public void testBlockedNotifications_suspended() throws Exception { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); Loading Loading @@ -3088,6 +3132,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testDeleteChannelGroupChecksForFgses() throws Exception { // the setup for this test requires it to seem like it's coming from the app mService.isSystemUid = false; when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) .thenReturn(singletonList(mock(AssociationInfo.class))); CountDownLatch latch = new CountDownLatch(2); Loading @@ -3100,7 +3146,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { ParceledListSlice<NotificationChannel> pls = new ParceledListSlice(ImmutableList.of(notificationChannel)); try { mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); mBinderService.createNotificationChannels(PKG, pls); } catch (RemoteException e) { throw new RuntimeException(e); } Loading @@ -3119,7 +3165,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { ParceledListSlice<NotificationChannel> pls = new ParceledListSlice(ImmutableList.of(notificationChannel)); try { mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); // Because existing channels won't have their groups overwritten when the call // is from the app, this call won't take the channel out of the group mBinderService.createNotificationChannels(PKG, pls); mBinderService.deleteNotificationChannelGroup(PKG, "group"); } catch (RemoteException e) { throw new RuntimeException(e); Loading Loading @@ -8625,7 +8673,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals("friend", friendChannel.getConversationId()); assertEquals(null, original.getConversationId()); assertEquals(original.canShowBadge(), friendChannel.canShowBadge()); assertFalse(friendChannel.canBubble()); // can't be modified by app assertEquals(original.canBubble(), friendChannel.canBubble()); // called by system assertFalse(original.getId().equals(friendChannel.getId())); assertNotNull(friendChannel.getId()); } Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +10 −7 Original line number Diff line number Diff line Loading @@ -3796,13 +3796,13 @@ public class NotificationManagerService extends SystemService { } private void createNotificationChannelsImpl(String pkg, int uid, ParceledListSlice channelsList) { createNotificationChannelsImpl(pkg, uid, channelsList, ParceledListSlice channelsList, boolean fromTargetApp) { createNotificationChannelsImpl(pkg, uid, channelsList, fromTargetApp, ActivityTaskManager.INVALID_TASK_ID); } private void createNotificationChannelsImpl(String pkg, int uid, ParceledListSlice channelsList, int startingTaskId) { ParceledListSlice channelsList, boolean fromTargetApp, int startingTaskId) { List<NotificationChannel> channels = channelsList.getList(); final int channelsSize = channels.size(); ParceledListSlice<NotificationChannel> oldChannels = Loading @@ -3814,7 +3814,7 @@ public class NotificationManagerService extends SystemService { final NotificationChannel channel = channels.get(i); Objects.requireNonNull(channel, "channel in list is null"); needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid, channel, true /* fromTargetApp */, channel, fromTargetApp, mConditionProviders.isPackageOrComponentAllowed( pkg, UserHandle.getUserId(uid))); if (needsPolicyFileChange) { Loading Loading @@ -3850,6 +3850,7 @@ public class NotificationManagerService extends SystemService { @Override public void createNotificationChannels(String pkg, ParceledListSlice channelsList) { checkCallerIsSystemOrSameApp(pkg); boolean fromTargetApp = !isCallerSystemOrPhone(); // if not system, it's from the app int taskId = ActivityTaskManager.INVALID_TASK_ID; try { int uid = mPackageManager.getPackageUid(pkg, 0, Loading @@ -3858,14 +3859,15 @@ public class NotificationManagerService extends SystemService { } catch (RemoteException e) { // Do nothing } createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, taskId); createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, fromTargetApp, taskId); } @Override public void createNotificationChannelsForPackage(String pkg, int uid, ParceledListSlice channelsList) { enforceSystemOrSystemUI("only system can call this"); createNotificationChannelsImpl(pkg, uid, channelsList); createNotificationChannelsImpl(pkg, uid, channelsList, false /* fromTargetApp */); } @Override Loading @@ -3880,7 +3882,8 @@ public class NotificationManagerService extends SystemService { CONVERSATION_CHANNEL_ID_FORMAT, parentId, conversationId)); conversationChannel.setConversationId(parentId, conversationId); createNotificationChannelsImpl( pkg, uid, new ParceledListSlice(Arrays.asList(conversationChannel))); pkg, uid, new ParceledListSlice(Arrays.asList(conversationChannel)), false /* fromTargetApp */); mRankingHandler.requestSort(); handleSavePolicyFile(); } Loading
services/core/java/com/android/server/notification/PreferencesHelper.java +2 −4 Original line number Diff line number Diff line Loading @@ -916,7 +916,7 @@ public class PreferencesHelper implements RankingConfig { throw new IllegalArgumentException("Reserved id"); } NotificationChannel existing = r.channels.get(channel.getId()); if (existing != null && fromTargetApp) { if (existing != null) { // Actually modifying an existing channel - keep most of the existing settings if (existing.isDeleted()) { // The existing channel was deleted - undelete it. Loading Loading @@ -1002,9 +1002,7 @@ public class PreferencesHelper implements RankingConfig { } if (fromTargetApp) { channel.setLockscreenVisibility(r.visibility); channel.setAllowBubbles(existing != null ? existing.getAllowBubbles() : NotificationChannel.DEFAULT_ALLOW_BUBBLE); channel.setAllowBubbles(NotificationChannel.DEFAULT_ALLOW_BUBBLE); } clearLockedFieldsLocked(channel); Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +52 −4 Original line number Diff line number Diff line Loading @@ -1101,6 +1101,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { new NotificationChannel("id", "name", IMPORTANCE_HIGH); mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); // pretend only this following part is called by the app (system permissions are required to // update the notification channel on behalf of the user above) mService.isSystemUid = false; // Recreating with a lower importance leaves channel unchanged. final NotificationChannel dupeChannel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW); Loading @@ -1125,6 +1129,46 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(IMPORTANCE_DEFAULT, createdChannel.getImportance()); } @Test public void testCreateNotificationChannels_fromAppCannotSetFields() throws Exception { // Confirm that when createNotificationChannels is called from the relevant app and not // system, then it cannot set fields that can't be set by apps mService.isSystemUid = false; final NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); channel.setBypassDnd(true); channel.setAllowBubbles(true); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel))); final NotificationChannel createdChannel = mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertFalse(createdChannel.canBypassDnd()); assertFalse(createdChannel.canBubble()); } @Test public void testCreateNotificationChannels_fromSystemCanSetFields() throws Exception { // Confirm that when createNotificationChannels is called from system, // then it can set fields that can't be set by apps mService.isSystemUid = true; final NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_DEFAULT); channel.setBypassDnd(true); channel.setAllowBubbles(true); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel))); final NotificationChannel createdChannel = mBinderService.getNotificationChannel(PKG, mContext.getUserId(), PKG, "id"); assertTrue(createdChannel.canBypassDnd()); assertTrue(createdChannel.canBubble()); } @Test public void testBlockedNotifications_suspended() throws Exception { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); Loading Loading @@ -3088,6 +3132,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testDeleteChannelGroupChecksForFgses() throws Exception { // the setup for this test requires it to seem like it's coming from the app mService.isSystemUid = false; when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) .thenReturn(singletonList(mock(AssociationInfo.class))); CountDownLatch latch = new CountDownLatch(2); Loading @@ -3100,7 +3146,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { ParceledListSlice<NotificationChannel> pls = new ParceledListSlice(ImmutableList.of(notificationChannel)); try { mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); mBinderService.createNotificationChannels(PKG, pls); } catch (RemoteException e) { throw new RuntimeException(e); } Loading @@ -3119,7 +3165,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { ParceledListSlice<NotificationChannel> pls = new ParceledListSlice(ImmutableList.of(notificationChannel)); try { mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls); // Because existing channels won't have their groups overwritten when the call // is from the app, this call won't take the channel out of the group mBinderService.createNotificationChannels(PKG, pls); mBinderService.deleteNotificationChannelGroup(PKG, "group"); } catch (RemoteException e) { throw new RuntimeException(e); Loading Loading @@ -8625,7 +8673,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals("friend", friendChannel.getConversationId()); assertEquals(null, original.getConversationId()); assertEquals(original.canShowBadge(), friendChannel.canShowBadge()); assertFalse(friendChannel.canBubble()); // can't be modified by app assertEquals(original.canBubble(), friendChannel.canBubble()); // called by system assertFalse(original.getId().equals(friendChannel.getId())); assertNotNull(friendChannel.getId()); } Loading