mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
174 lines
8.2 KiB
Diff
174 lines
8.2 KiB
Diff
|
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;
|