DivestOS/Patches/LineageOS-17.1/android_frameworks_base/393587.patch

174 lines
8.2 KiB
Diff
Raw Normal View History

From 27549d452e6524778c69c1e7a5e0ab6cae04750e Mon Sep 17 00:00:00 2001
From: Valentin Iftime <valiiftime@google.com>
Date: Mon, 16 Oct 2023 09:29:17 +0200
Subject: [PATCH] [BACKPORT] Prioritize system toasts
Insert toasts from system packages at the front of the queue
to ensure that apps can't spam with toast to delay system toasts from showing.
Test: atest NotificationManagerServiceTest
Bug: 293301736
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:67721fcfb3198f220c90c976f870407a0bb8d6c6)
Merged-In: I13547f853476bc88d12026c545aba9f857ce8724
Change-Id: I13547f853476bc88d12026c545aba9f857ce8724
---
.../NotificationManagerService.java | 40 +++++++++--
.../NotificationManagerServiceTest.java | 68 +++++++++++++++++++
2 files changed, 104 insertions(+), 4 deletions(-)
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e09491867f91a..d769ff8e75055 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -744,17 +744,21 @@ private void writePolicyXml(OutputStream stream, boolean forBackup, int userId)
private static final class ToastRecord
{
+ final int uid;
final int pid;
final String pkg;
+ final boolean isSystemToast;
final ITransientNotification callback;
int duration;
int displayId;
Binder token;
- ToastRecord(int pid, String pkg, ITransientNotification callback, int duration,
+ ToastRecord(int uid, int pid, String pkg, boolean isSystemToast, ITransientNotification callback, int duration,
Binder token, int displayId) {
+ this.uid = uid;
this.pid = pid;
this.pkg = pkg;
+ this.isSystemToast = isSystemToast;
this.callback = callback;
this.duration = duration;
this.token = token;
@@ -2481,10 +2485,21 @@ record = mToastQueue.get(index);
Binder token = new Binder();
mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, displayId);
- record = new ToastRecord(callingPid, pkg, callback, duration, token,
+ record = new ToastRecord(callingUid, callingPid, pkg, isSystemToast, callback, duration, token,
displayId);
- mToastQueue.add(record);
- index = mToastQueue.size() - 1;
+
+ // Insert system toasts at the front of the queue
+ int systemToastInsertIdx = mToastQueue.size();
+ if (isSystemToast) {
+ systemToastInsertIdx = getInsertIndexForSystemToastLocked();
+ }
+ if (systemToastInsertIdx < mToastQueue.size()) {
+ index = systemToastInsertIdx;
+ mToastQueue.add(index, record);
+ } else {
+ mToastQueue.add(record);
+ index = mToastQueue.size() - 1;
+ }
keepProcessAliveIfNeededLocked(callingPid);
}
// If it's at index 0, it's the current toast. It doesn't matter if it's
@@ -2500,6 +2515,23 @@ record = new ToastRecord(callingPid, pkg, callback, duration, token,
}
}
+ @GuardedBy("mToastQueue")
+ private int getInsertIndexForSystemToastLocked() {
+ // If there are other system toasts: insert after the last one
+ int idx = 0;
+ for (ToastRecord r : mToastQueue) {
+ if (idx == 0 && mIsCurrentToastShown) {
+ idx++;
+ continue;
+ }
+ if (!r.isSystemToast) {
+ return idx;
+ }
+ idx++;
+ }
+ return idx;
+ }
+
@Override
public void cancelToast(String pkg, ITransientNotification callback) {
Slog.i(TAG, "cancelToast pkg=" + pkg + " callback=" + callback);
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 bcb4c49336cf5..4a0aa7c9e8e74 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4480,6 +4480,74 @@ public void testAlwaysAllowSystemToasts() throws Exception {
assertEquals(1, mService.mToastQueue.size());
}
+ @Test
+ public void testPrioritizeSystemToasts() throws Exception {
+ // Insert non-system toasts
+ final String testPackage = "testPackageName";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = false;
+ mService.isSystemAppId = false;
+ setToastRateIsWithinQuota(true);
+ setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ INotificationManager nmService = (INotificationManager) mService.mService;
+
+ // Enqueue maximum number of toasts for test package
+ for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS; i++) {
+ nmService.enqueueTextToast(testPackage, new Binder(), "Text", 2000, 0, null);
+ }
+
+ // Enqueue system toast
+ final String testPackageSystem = "testPackageNameSystem";
+ mService.isSystemUid = true;
+ setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem, false);
+ when(mPackageManager.isPackageSuspendedForUser(testPackageSystem, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ nmService.enqueueToast(testPackageSystem, new Binder(), new TestableToastCallback(), 2000, 0);
+
+ // System toast is inserted at the front of the queue, behind current showing toast
+ assertEquals(testPackageSystem, mService.mToastQueue.get(1).pkg);
+ }
+
+ @Test
+ public void testPrioritizeSystemToasts_enqueueAfterExistingSystemToast() throws Exception {
+ // Insert system toasts
+ final String testPackageSystem1 = "testPackageNameSystem1";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = true;
+ setToastRateIsWithinQuota(true);
+ setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem1, false);
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackageSystem1, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ INotificationManager nmService = (INotificationManager) mService.mService;
+
+ // Enqueue maximum number of toasts for test package
+ for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_TOASTS; i++) {
+ nmService.enqueueTextToast(testPackageSystem1, new Binder(), "Text", 2000, 0, null);
+ }
+
+ // Enqueue another system toast
+ final String testPackageSystem2 = "testPackageNameSystem2";
+ mService.isSystemUid = true;
+ setIfPackageHasPermissionToAvoidToastRateLimiting(testPackageSystem2, false);
+ when(mPackageManager.isPackageSuspendedForUser(testPackageSystem2, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ nmService.enqueueToast(testPackageSystem2, new Binder(), new TestableToastCallback(), 2000, 0);
+
+ // System toast is inserted at the back of the queue, after the other system toasts
+ assertEquals(testPackageSystem2,
+ mService.mToastQueue.get(mService.mToastQueue.size() - 1).pkg);
+ }
+
@Test
public void testOnNotificationSmartReplySent() {
final int replyIndex = 2;