Loading services/core/java/com/android/server/notification/NotificationManagerService.java +36 −10 Original line number Diff line number Diff line Loading @@ -3082,11 +3082,36 @@ public class NotificationManagerService extends SystemService { private void sendRegisteredOnlyBroadcast(Intent baseIntent) { int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true); if (Flags.nmBinderPerfReduceZenBroadcasts()) { for (int userId : userIds) { Context userContext = getContext().createContextAsUser(UserHandle.of(userId), 0); String[] dndPackages = mConditionProviders.getAllowedPackages(userId) .toArray(new String[0]); // We send the broadcast to all DND packages in the second step, so leave them out // of this first broadcast for *running* receivers. That ensures each package only // receives it once. Intent registeredOnlyIntent = new Intent(baseIntent) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); userContext.sendBroadcastMultiplePermissions(registeredOnlyIntent, /* receiverPermissions= */ new String[0], /* excludedPermissions= */ new String[0], /* excludedPackages= */ dndPackages); for (String pkg : dndPackages) { Intent pkgIntent = new Intent(baseIntent).setPackage(pkg) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); userContext.sendBroadcast(pkgIntent); } } } else { Intent intent = new Intent(baseIntent).addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); for (int userId : userIds) { getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), null); } // explicitly send the broadcast to all DND packages, even if they aren't currently running // explicitly send the broadcast to all DND packages, even if they aren't currently // running for (int userId : userIds) { for (String pkg : mConditionProviders.getAllowedPackages(userId)) { Intent pkgIntent = new Intent(baseIntent).setPackage(pkg).setFlags( Loading @@ -3095,6 +3120,7 @@ public class NotificationManagerService extends SystemService { } } } } @Override public void onBootPhase(int phase) { Loading services/core/java/com/android/server/notification/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -187,3 +187,13 @@ flag { description: "Enables sound uri with vibration source in notification channel" bug: "351975435" } flag { name: "nm_binder_perf_reduce_zen_broadcasts" namespace: "systemui" description: "Don't send duplicate zen-related (policy changed, etc) broadcasts" bug: "324376849" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +73 −1 Original line number Diff line number Diff line Loading @@ -644,6 +644,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { doNothing().when(mContext).sendBroadcast(any(), anyString()); doNothing().when(mContext).sendBroadcastAsUser(any(), any()); doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); doNothing().when(mContext).sendBroadcastMultiplePermissions(any(), any(), any(), any()); doReturn(mContext).when(mContext).createContextAsUser(eq(mUser), anyInt()); TestableContentResolver cr = mock(TestableContentResolver.class); when(mContext.getContentResolver()).thenReturn(cr); doNothing().when(cr).registerContentObserver(any(), anyBoolean(), any(), anyInt()); Loading Loading @@ -11235,7 +11238,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test public void onZenModeChanged_sendsBroadcasts() throws Exception { @DisableFlags(Flags.FLAG_NM_BINDER_PERF_REDUCE_ZEN_BROADCASTS) public void onZenModeChanged_sendsBroadcasts_oldBehavior() throws Exception { when(mAmi.getCurrentUserId()).thenReturn(100); when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102}); when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() { Loading Loading @@ -11287,6 +11291,74 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102))); } @Test @EnableFlags(Flags.FLAG_NM_BINDER_PERF_REDUCE_ZEN_BROADCASTS) public void onZenModeChanged_sendsBroadcasts() throws Exception { when(mAmi.getCurrentUserId()).thenReturn(100); when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102}); when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() { @Override public List<String> answer(InvocationOnMock invocation) { int userId = invocation.getArgument(0); switch (userId) { case 100: return Lists.newArrayList("a", "b", "c"); case 101: return Lists.newArrayList(); case 102: return Lists.newArrayList("b"); default: throw new IllegalArgumentException( "Why would you ask for packages of userId " + userId + "?"); } } }); Context context100 = mock(Context.class); doReturn(context100).when(mContext).createContextAsUser(eq(UserHandle.of(100)), anyInt()); Context context101 = mock(Context.class); doReturn(context101).when(mContext).createContextAsUser(eq(UserHandle.of(101)), anyInt()); Context context102 = mock(Context.class); doReturn(context102).when(mContext).createContextAsUser(eq(UserHandle.of(102)), anyInt()); mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null, "testing!", false); waitForIdle(); // Verify broadcasts per user: registered receivers first, then DND packages. InOrder inOrder = inOrder(context100, context101, context102); inOrder.verify(context100).sendBroadcastMultiplePermissions( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(new String[0]), eq(new String[0]), eq(new String[] {"a", "b", "c"})); inOrder.verify(context100).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("a") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); inOrder.verify(context100).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("b") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); inOrder.verify(context100).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("c") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); inOrder.verify(context101).sendBroadcastMultiplePermissions( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(new String[0]), eq(new String[0]), eq(new String[] {})); inOrder.verify(context102).sendBroadcastMultiplePermissions( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(new String[0]), eq(new String[0]), eq(new String[] {"b"})); inOrder.verify(context102).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("b") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); } @Test @EnableFlags(android.app.Flags.FLAG_MODES_API) public void onAutomaticRuleStatusChanged_sendsBroadcastToRuleOwner() throws Exception { Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +36 −10 Original line number Diff line number Diff line Loading @@ -3082,11 +3082,36 @@ public class NotificationManagerService extends SystemService { private void sendRegisteredOnlyBroadcast(Intent baseIntent) { int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true); if (Flags.nmBinderPerfReduceZenBroadcasts()) { for (int userId : userIds) { Context userContext = getContext().createContextAsUser(UserHandle.of(userId), 0); String[] dndPackages = mConditionProviders.getAllowedPackages(userId) .toArray(new String[0]); // We send the broadcast to all DND packages in the second step, so leave them out // of this first broadcast for *running* receivers. That ensures each package only // receives it once. Intent registeredOnlyIntent = new Intent(baseIntent) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); userContext.sendBroadcastMultiplePermissions(registeredOnlyIntent, /* receiverPermissions= */ new String[0], /* excludedPermissions= */ new String[0], /* excludedPackages= */ dndPackages); for (String pkg : dndPackages) { Intent pkgIntent = new Intent(baseIntent).setPackage(pkg) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); userContext.sendBroadcast(pkgIntent); } } } else { Intent intent = new Intent(baseIntent).addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); for (int userId : userIds) { getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), null); } // explicitly send the broadcast to all DND packages, even if they aren't currently running // explicitly send the broadcast to all DND packages, even if they aren't currently // running for (int userId : userIds) { for (String pkg : mConditionProviders.getAllowedPackages(userId)) { Intent pkgIntent = new Intent(baseIntent).setPackage(pkg).setFlags( Loading @@ -3095,6 +3120,7 @@ public class NotificationManagerService extends SystemService { } } } } @Override public void onBootPhase(int phase) { Loading
services/core/java/com/android/server/notification/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -187,3 +187,13 @@ flag { description: "Enables sound uri with vibration source in notification channel" bug: "351975435" } flag { name: "nm_binder_perf_reduce_zen_broadcasts" namespace: "systemui" description: "Don't send duplicate zen-related (policy changed, etc) broadcasts" bug: "324376849" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +73 −1 Original line number Diff line number Diff line Loading @@ -644,6 +644,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { doNothing().when(mContext).sendBroadcast(any(), anyString()); doNothing().when(mContext).sendBroadcastAsUser(any(), any()); doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); doNothing().when(mContext).sendBroadcastMultiplePermissions(any(), any(), any(), any()); doReturn(mContext).when(mContext).createContextAsUser(eq(mUser), anyInt()); TestableContentResolver cr = mock(TestableContentResolver.class); when(mContext.getContentResolver()).thenReturn(cr); doNothing().when(cr).registerContentObserver(any(), anyBoolean(), any(), anyInt()); Loading Loading @@ -11235,7 +11238,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test public void onZenModeChanged_sendsBroadcasts() throws Exception { @DisableFlags(Flags.FLAG_NM_BINDER_PERF_REDUCE_ZEN_BROADCASTS) public void onZenModeChanged_sendsBroadcasts_oldBehavior() throws Exception { when(mAmi.getCurrentUserId()).thenReturn(100); when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102}); when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() { Loading Loading @@ -11287,6 +11291,74 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102))); } @Test @EnableFlags(Flags.FLAG_NM_BINDER_PERF_REDUCE_ZEN_BROADCASTS) public void onZenModeChanged_sendsBroadcasts() throws Exception { when(mAmi.getCurrentUserId()).thenReturn(100); when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102}); when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() { @Override public List<String> answer(InvocationOnMock invocation) { int userId = invocation.getArgument(0); switch (userId) { case 100: return Lists.newArrayList("a", "b", "c"); case 101: return Lists.newArrayList(); case 102: return Lists.newArrayList("b"); default: throw new IllegalArgumentException( "Why would you ask for packages of userId " + userId + "?"); } } }); Context context100 = mock(Context.class); doReturn(context100).when(mContext).createContextAsUser(eq(UserHandle.of(100)), anyInt()); Context context101 = mock(Context.class); doReturn(context101).when(mContext).createContextAsUser(eq(UserHandle.of(101)), anyInt()); Context context102 = mock(Context.class); doReturn(context102).when(mContext).createContextAsUser(eq(UserHandle.of(102)), anyInt()); mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null, "testing!", false); waitForIdle(); // Verify broadcasts per user: registered receivers first, then DND packages. InOrder inOrder = inOrder(context100, context101, context102); inOrder.verify(context100).sendBroadcastMultiplePermissions( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(new String[0]), eq(new String[0]), eq(new String[] {"a", "b", "c"})); inOrder.verify(context100).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("a") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); inOrder.verify(context100).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("b") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); inOrder.verify(context100).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("c") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); inOrder.verify(context101).sendBroadcastMultiplePermissions( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(new String[0]), eq(new String[0]), eq(new String[] {})); inOrder.verify(context102).sendBroadcastMultiplePermissions( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(new String[0]), eq(new String[0]), eq(new String[] {"b"})); inOrder.verify(context102).sendBroadcast( eqIntent(new Intent(ACTION_INTERRUPTION_FILTER_CHANGED) .setPackage("b") .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT))); } @Test @EnableFlags(android.app.Flags.FLAG_MODES_API) public void onAutomaticRuleStatusChanged_sendsBroadcastToRuleOwner() throws Exception {