summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Matías Hernández <matiashe@google.com> 2024-12-04 13:40:00 +0100
committer Matías Hernández <matiashe@google.com> 2024-12-04 13:40:00 +0100
commit357eafd4e72988ce36e2c5f97d4e554e92e66d4a (patch)
tree94999d19f0544219cc8c2f17cbb36c9646bd7380
parent11f742ec83bc4cfb7e23ab7b2a3f6e6559f01cbc (diff)
Send AZR_STATUS_CHANGED broadcasts with FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Although apps and ConditionProviderServices shouldn't be able to call setAZRStatus this early, system_server itself might, causing a crash/bootloop. Fixes: 381875093 Test: atest NotificationManagerServiceTest Flag: EXEMPT Safe bugfix Change-Id: I1af575ffb04e5bb5ac7f7609fa215b9ac525dcdf
-rw-r--r--services/core/Android.bp1
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java1
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java8
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java59
4 files changed, 67 insertions, 2 deletions
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 08206150cebb..eab335136cc2 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -157,6 +157,7 @@ java_library_static {
"android.hardware.light-V2.0-java",
"android.hardware.gnss-V2-java",
"android.hardware.vibrator-V3-java",
+ "androidx.annotation_annotation",
"app-compat-annotations",
"art_exported_aconfig_flags_lib",
"framework-tethering.stubs.module_lib",
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 15af36ba66af..39eea740a902 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2594,6 +2594,7 @@ public class NotificationManagerService extends SystemService {
intent.setPackage(pkg);
intent.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, id);
intent.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, status);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
getContext().sendBroadcastAsUser(intent, UserHandle.of(userId));
});
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index dc173b124884..95aff5652bb6 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -112,9 +112,10 @@ import android.util.SparseArray;
import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.FrameworkStatsLog;
@@ -279,6 +280,11 @@ public class ZenModeHelper {
mCallbacks.remove(callback);
}
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ public List<Callback> getCallbacks() {
+ return mCallbacks;
+ }
+
public void initZenMode() {
if (DEBUG) Log.d(TAG, "initZenMode");
synchronized (mConfigLock) {
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 90bf1d36a4ce..060269a5c9aa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -49,10 +49,14 @@ import static android.app.NotificationChannel.PROMOTIONS_ID;
import static android.app.NotificationChannel.RECS_ID;
import static android.app.NotificationChannel.SOCIAL_MEDIA_ID;
import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
+import static android.app.NotificationManager.ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED;
import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
+import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ACTIVATED;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
+import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_ID;
+import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_STATUS;
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -369,6 +373,7 @@ import java.io.FileOutputStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
@@ -11273,19 +11278,71 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
}
+ @Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void onAutomaticRuleStatusChanged_sendsBroadcastToRuleOwner() throws Exception {
+ mService.mZenModeHelper.getCallbacks().forEach(c -> c.onAutomaticRuleStatusChanged(
+ mUserId, "rule.owner.pkg", "rule_id", AUTOMATIC_RULE_STATUS_ACTIVATED));
+
+ Intent expected = new Intent(ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED)
+ .setPackage("rule.owner.pkg")
+ .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, "rule_id")
+ .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, AUTOMATIC_RULE_STATUS_ACTIVATED)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
+ verify(mContext).sendBroadcastAsUser(eqIntent(expected), eq(UserHandle.of(mUserId)));
+ }
+
private static Intent eqIntent(Intent wanted) {
return ArgumentMatchers.argThat(
new ArgumentMatcher<Intent>() {
@Override
public boolean matches(Intent argument) {
return wanted.filterEquals(argument)
- && wanted.getFlags() == argument.getFlags();
+ && wanted.getFlags() == argument.getFlags()
+ && equalBundles(wanted.getExtras(), argument.getExtras());
}
@Override
public String toString() {
return wanted.toString();
}
+
+ private boolean equalBundles(Bundle one, Bundle two) {
+ if (one == null && two == null) {
+ return true;
+ }
+ if ((one == null) != (two == null)) {
+ return false;
+ }
+ if (one.size() != two.size()) {
+ return false;
+ }
+
+ HashSet<String> setOne = new HashSet<>(one.keySet());
+ setOne.addAll(two.keySet());
+
+ for (String key : setOne) {
+ if (!one.containsKey(key) || !two.containsKey(key)) {
+ return false;
+ }
+
+ Object valueOne = one.get(key);
+ Object valueTwo = two.get(key);
+ if (valueOne instanceof Bundle
+ && valueTwo instanceof Bundle
+ && !equalBundles((Bundle) valueOne, (Bundle) valueTwo)) {
+ return false;
+ } else if (valueOne == null) {
+ if (valueTwo != null) {
+ return false;
+ }
+ } else if (!valueOne.equals(valueTwo)) {
+ return false;
+ }
+ }
+ return true;
+ }
});
}