only rate limit notification updates

Updates to progress bars are the main culprit in system
performance events caused by apps spamming the notification
service. Rate-limiting only updates allows us to set a lower
threshold wihtout the owrry of mistakenly dropping bursts of
notifications being quickly posted after a network sync.

Also reduce logspam caused by the rate-limit events.

Bug: 30132961
Change-Id: I49acda6a2831204da45e899ddd3d62d571d7174b
This commit is contained in:
Chris Wren
2016-08-04 11:24:42 -04:00
parent 3c2587f26e
commit a61f179c3d
2 changed files with 24 additions and 20 deletions

View File

@@ -312,8 +312,8 @@ public class NotificationManager
try {
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
copy, idOut, user.getIdentifier());
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
if (localLOGV && id != idOut[0]) {
Log.v(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();

View File

@@ -180,7 +180,7 @@ public class NotificationManagerService extends SystemService {
= SystemProperties.getBoolean("debug.child_notifs", true);
static final int MAX_PACKAGE_NOTIFICATIONS = 50;
static final float DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE = 50f;
static final float DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE = 10f;
// message codes
static final int MESSAGE_TIMEOUT = 2;
@@ -2538,20 +2538,32 @@ public class NotificationManagerService extends SystemService {
mUsageStats.registerEnqueuedByApp(pkg);
if (pkg == null || notification == null) {
throw new IllegalArgumentException("null not allowed: pkg=" + pkg
+ " id=" + id + " notification=" + notification);
}
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
user);
// Limit the number of notifications that any given package except the android
// package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemNotification && !isNotificationFromListener) {
synchronized (mNotificationList) {
final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
if (appEnqueueRate > mMaxPackageEnqueueRate) {
mUsageStats.registerOverRateQuota(pkg);
final long now = SystemClock.elapsedRealtime();
if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
+ ". Shedding events. package=" + pkg);
mLastOverRateLogTime = now;
if(mNotificationsByKey.get(n.getKey()) != null) {
// this is an update, rate limit updates only
final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg);
if (appEnqueueRate > mMaxPackageEnqueueRate) {
mUsageStats.registerOverRateQuota(pkg);
final long now = SystemClock.elapsedRealtime();
if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) {
Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate
+ ". Shedding events. package=" + pkg);
mLastOverRateLogTime = now;
}
return;
}
return;
}
int count = 0;
@@ -2574,11 +2586,6 @@ public class NotificationManagerService extends SystemService {
}
}
if (pkg == null || notification == null) {
throw new IllegalArgumentException("null not allowed: pkg=" + pkg
+ " id=" + id + " notification=" + notification);
}
// Whitelist pending intents.
if (notification.allPendingIntents != null) {
final int intentCount = notification.allPendingIntents.size();
@@ -2601,9 +2608,6 @@ public class NotificationManagerService extends SystemService {
Notification.PRIORITY_MAX);
// setup local book-keeping
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
user);
final NotificationRecord r = new NotificationRecord(getContext(), n);
mHandler.post(new EnqueueNotificationRunnable(userId, r));