From 198282aea1128a1f9e87c5e54379b1b6a815649a Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Tue, 20 Aug 2019 16:08:42 -0400 Subject: [PATCH] Limit the number of Notif Channels per app Fixes: 139111963 Test: atest Change-Id: I0f0d442e9f5cc5bb1d73a638e00726807ef9fb48 (cherry picked from commit c29370a294cd2aec9536d97e81f74931396b6fd9) --- .../server/notification/PreferencesHelper.java | 16 +++++++ .../server/notification/PreferencesHelperTest.java | 49 ++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 7b45a1b1997c..669dce7160cd 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 @@ public class PreferencesHelper implements RankingConfig { 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 @@ public class PreferencesHelper implements RankingConfig { // noop } } + boolean skipWarningLogged = false; PackagePreferences r = getOrCreatePackagePreferencesLocked(name, uid, XmlUtils.readIntAttribute( @@ -225,6 +229,14 @@ public class PreferencesHelper implements RankingConfig { } // 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 @@ public class PreferencesHelper implements RankingConfig { 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 8f8b746b59d4..365cd80c88c7 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_MAX; 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 @@ public class PreferencesHelperTest extends UiServiceTestCase { 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 = "\n" + + "\n" + + "" + + "" + + "" + + ""; + 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)); + } } -- 2.11.0