summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Matías Hernández <matiashe@google.com> 2024-12-30 05:56:55 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2024-12-30 05:56:55 -0800
commit5e15c15179aab7f5bd9bef9f260f87320f8521a6 (patch)
tree6ce2d5829952050f550f14c4a3e3583881b6471d
parent2d598a12bee7ba31ea9f523b093bc9f4ae154ccf (diff)
parenta6d46200becfa6af0b11bb7df58009dc55f3fb75 (diff)
Merge "Stop duplicate broadcasts to registered receivers in zen-access packages" into main
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java46
-rw-r--r--services/core/java/com/android/server/notification/flags.aconfig10
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java74
3 files changed, 119 insertions, 11 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index eeae6166873a..f50e8aa7eb7b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3082,16 +3082,42 @@ public class NotificationManagerService extends SystemService {
private void sendRegisteredOnlyBroadcast(Intent baseIntent) {
int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true);
- 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
- for (int userId : userIds) {
- for (String pkg : mConditionProviders.getAllowedPackages(userId)) {
- Intent pkgIntent = new Intent(baseIntent).setPackage(pkg).setFlags(
- Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- getContext().sendBroadcastAsUser(pkgIntent, UserHandle.of(userId));
+ 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
+ for (int userId : userIds) {
+ for (String pkg : mConditionProviders.getAllowedPackages(userId)) {
+ Intent pkgIntent = new Intent(baseIntent).setPackage(pkg).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ getContext().sendBroadcastAsUser(pkgIntent, UserHandle.of(userId));
+ }
}
}
}
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index 65a38ae1fcde..f15c23e110a4 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -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
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 bcda2c0662ca..301165f8151d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -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());
@@ -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>>() {
@@ -11288,6 +11292,74 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@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 {
mService.mZenModeHelper.getCallbacks().forEach(c -> c.onAutomaticRuleStatusChanged(