From 92361f2abef1d25c74f8c311e125e7579ba21fcb Mon Sep 17 00:00:00 2001 From: Jan Tomljanovic Date: Tue, 12 Jan 2021 17:11:02 +0000 Subject: [PATCH] Collect data for blocked toasts due to rate limiting. We're using compat change that will report that the change was accessed only when a toast was blocked due to rate limting. We can use these stats to observe how much of an impact this feature has and on which apps. Test: manually observed that the log message appears Bug: 174840628 Change-Id: I0cc0c76f48b392cbdaf87363248a683ae3150cf3 --- .../NotificationManagerService.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4ab827908e347..ab5238f1ddbf7 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -154,6 +154,7 @@ import android.app.usage.UsageStatsManagerInternal; import android.companion.ICompanionDeviceManager; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; +import android.compat.annotation.LoggingOnly; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; @@ -250,6 +251,7 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.compat.IPlatformCompat; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceIdSequence; @@ -446,6 +448,17 @@ public class NotificationManagerService extends SystemService { @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R) private static final long NOTIFICATION_TRAMPOLINE_BLOCK = 167676448L; + /** + * Rate limit showing toasts, on a per package basis. + * + * It limits the number of {@link android.widget.Toast#show()} calls to prevent overburdening + * the user with too many toasts in a limited time. Any attempt to show more toasts than allowed + * in a certain time frame will result in the toast being discarded. + */ + @ChangeId + @LoggingOnly + private static final long RATE_LIMIT_TOASTS = 174840628L; + private IActivityManager mAm; private ActivityTaskManagerInternal mAtm; private ActivityManager mActivityManager; @@ -466,6 +479,7 @@ public class NotificationManagerService extends SystemService { private UriGrantsManagerInternal mUgmInternal; private RoleObserver mRoleObserver; private UserManager mUm; + private IPlatformCompat mPlatformCompat; private ShortcutHelper mShortcutHelper; final IBinder mForegroundToken = new Binder(); @@ -1988,6 +2002,8 @@ public class NotificationManagerService extends SystemService { mDeviceIdleManager = getContext().getSystemService(DeviceIdleManager.class); mDpm = dpm; mUm = userManager; + mPlatformCompat = IPlatformCompat.Stub.asInterface( + ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mUiHandler = new Handler(UiThread.get().getLooper()); String[] extractorNames; @@ -7412,6 +7428,7 @@ public class NotificationManagerService extends SystemService { private boolean tryShowToast(ToastRecord record, boolean rateLimitingEnabled, boolean isWithinQuota) { if (rateLimitingEnabled && !isWithinQuota) { + reportCompatRateLimitingToastsChange(record.uid); Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the " + "following toast was blocked and discarded: " + record); return false; @@ -7424,6 +7441,19 @@ public class NotificationManagerService extends SystemService { return record.show(); } + /** Reports rate limiting toasts compat change (used when the toast was blocked). */ + private void reportCompatRateLimitingToastsChange(int uid) { + final long id = Binder.clearCallingIdentity(); + try { + mPlatformCompat.reportChangeByUid(RATE_LIMIT_TOASTS, uid); + } catch (RemoteException e) { + Slog.e(TAG, "Unexpected exception while reporting toast was blocked due to rate" + + " limiting", e); + } finally { + Binder.restoreCallingIdentity(id); + } + } + @GuardedBy("mToastQueue") void cancelToastLocked(int index) { ToastRecord record = mToastQueue.get(index);