Limit the number of Notif Channels per app
Fixes: 139111963
Test: atest
Change-Id: I0f0d442e9f5cc5bb1d73a638e00726807ef9fb48
(cherry picked from commit c29370a294cd2aec9536d97e81f74931396b6fd9)
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 7b45a1b..669dce7 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -73,6 +73,9 @@
private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":";
@VisibleForTesting
+ static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
+
+ @VisibleForTesting
static final String TAG_RANKING = "ranking";
private static final String TAG_PACKAGE = "package";
private static final String TAG_CHANNEL = "channel";
@@ -179,6 +182,7 @@
// noop
}
}
+ boolean skipWarningLogged = false;
PackagePreferences r = getOrCreatePackagePreferencesLocked(name, uid,
XmlUtils.readIntAttribute(
@@ -225,6 +229,14 @@
}
// Channels
if (TAG_CHANNEL.equals(tagName)) {
+ if (r.channels.size() >= NOTIFICATION_CHANNEL_COUNT_LIMIT) {
+ if (!skipWarningLogged) {
+ Slog.w(TAG, "Skipping further channels for " + r.pkg
+ + "; app has too many");
+ skipWarningLogged = true;
+ }
+ continue;
+ }
String id = parser.getAttributeValue(null, ATT_ID);
String channelName = parser.getAttributeValue(null, ATT_NAME);
int channelImportance = XmlUtils.readIntAttribute(
@@ -690,6 +702,10 @@
return needsPolicyFileChange;
}
+ if (r.channels.size() >= NOTIFICATION_CHANNEL_COUNT_LIMIT) {
+ throw new IllegalStateException("Limit exceed; cannot create more channels");
+ }
+
needsPolicyFileChange = true;
if (channel.getImportance() < IMPORTANCE_NONE
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 8f8b746..365cd80 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -22,6 +22,8 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
+
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.fail;
@@ -2690,4 +2692,51 @@
assertFalse(mHelper.areBubblesAllowed(PKG_O, UID_O));
verify(mHandler, times(1)).requestSort();
}
+
+ @Test
+ public void testTooManyChannels() {
+ for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) {
+ NotificationChannel channel = new NotificationChannel(String.valueOf(i),
+ String.valueOf(i), NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true);
+ }
+ try {
+ NotificationChannel channel = new NotificationChannel(
+ String.valueOf(NOTIFICATION_CHANNEL_COUNT_LIMIT),
+ String.valueOf(NOTIFICATION_CHANNEL_COUNT_LIMIT),
+ NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true);
+ fail("Allowed to create too many notification channels");
+ } catch (IllegalStateException e) {
+ // great
+ }
+ }
+
+ @Test
+ public void testTooManyChannels_xml() throws Exception {
+ String extraChannel = "EXTRA";
+ String extraChannel1 = "EXTRA1";
+
+ // create first... many... directly so we don't need a big xml blob in this test
+ for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) {
+ NotificationChannel channel = new NotificationChannel(String.valueOf(i),
+ String.valueOf(i), NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true);
+ }
+
+ final String xml = "<ranking version=\"1\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
+ + "<channel id=\"" + extraChannel + "\" name=\"hi\" importance=\"3\"/>"
+ + "<channel id=\"" + extraChannel1 + "\" name=\"hi\" importance=\"3\"/>"
+ + "</package>"
+ + "</ranking>";
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel, true));
+ assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel1, true));
+ }
}