From fbc61bfcc75fc78616d485af40287f74a0f27551 Mon Sep 17 00:00:00 2001 From: Tavi Date: Mon, 3 Jun 2024 14:39:12 -0400 Subject: [PATCH] 17.1: reconcile picks Signed-off-by: Tavi --- .../android_frameworks_base/393587.patch | 173 ++++++++++++++++++ .../android_frameworks_base/393588.patch | 101 ++++++++++ Scripts/LineageOS-17.1/Patch.sh | 2 + 3 files changed, 276 insertions(+) create mode 100644 Patches/LineageOS-17.1/android_frameworks_base/393587.patch create mode 100644 Patches/LineageOS-17.1/android_frameworks_base/393588.patch diff --git a/Patches/LineageOS-17.1/android_frameworks_base/393587.patch b/Patches/LineageOS-17.1/android_frameworks_base/393587.patch new file mode 100644 index 00000000..5f374638 --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/393587.patch @@ -0,0 +1,173 @@ +From 27549d452e6524778c69c1e7a5e0ab6cae04750e Mon Sep 17 00:00:00 2001 +From: Valentin Iftime +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; diff --git a/Patches/LineageOS-17.1/android_frameworks_base/393588.patch b/Patches/LineageOS-17.1/android_frameworks_base/393588.patch new file mode 100644 index 00000000..cf4e43ba --- /dev/null +++ b/Patches/LineageOS-17.1/android_frameworks_base/393588.patch @@ -0,0 +1,101 @@ +From 9a28c009d937e060bb5c10034cb5370129b8ce81 Mon Sep 17 00:00:00 2001 +From: Jan Tomljanovic +Date: Fri, 6 Nov 2020 11:28:09 +0000 +Subject: [PATCH] Don't try to show the current toast again while it's showing. + +By doing this we avoid a few bad things: + - mechanism that hides the current toast by trying to show it again + - delaying the call to hide and remove the current toast from the queue + when it's duration expires (which in the case of repeated calls can + delay this indefinitely) + +Test: atest NotificationManagerServiceTest +Test: atest android.widget.cts.ToastTest +Bug: 167672740 +Change-Id: Ie4953109314113efae49fa0c5e0c236e6e0dbb23 +--- + .../NotificationManagerService.java | 13 ++++++++++ + .../NotificationManagerServiceTest.java | 26 +++++++++++++++++++ + 2 files changed, 39 insertions(+) + +diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java +index d769ff8e75055..7b1c0ac27ab30 100755 +--- a/services/core/java/com/android/server/notification/NotificationManagerService.java ++++ b/services/core/java/com/android/server/notification/NotificationManagerService.java +@@ -437,6 +437,10 @@ public class NotificationManagerService extends SystemService { + + private KeyguardManager mKeyguardManager; + ++ // True if the toast that's on top of the queue is being shown at the moment. ++ @GuardedBy("mToastQueue") ++ private boolean mIsCurrentToastShown = false; ++ + // The last key in this list owns the hardware. + ArrayList mLights = new ArrayList<>(); + +@@ -6482,12 +6486,17 @@ public void run() { + + @GuardedBy("mToastQueue") + void showNextToastLocked() { ++ if (mIsCurrentToastShown) { ++ return; // Don't show the same toast twice. ++ } ++ + ToastRecord record = mToastQueue.get(0); + while (record != null) { + if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback); + try { + record.callback.show(record.token); + scheduleDurationReachedLocked(record); ++ mIsCurrentToastShown = true; + return; + } catch (RemoteException e) { + Slog.w(TAG, "Object died trying to show notification " + record.callback +@@ -6519,6 +6528,10 @@ void cancelToastLocked(int index) { + // the list anyway + } + ++ if (index == 0) { ++ mIsCurrentToastShown = false; ++ } ++ + ToastRecord lastToast = mToastQueue.remove(index); + + mWindowManagerInternal.removeWindowToken(lastToast.token, false /* removeWindows */, +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 4a0aa7c9e8e74..0e8cea43063b9 100755 +--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java ++++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +@@ -4415,6 +4415,32 @@ public void testAllowForegroundToasts() throws Exception { + } + + @Test ++ public void testDontCallShowToastAgainOnTheSameTextToast() throws Exception { ++ final String testPackage = "testPackageName"; ++ assertEquals(0, mService.mToastQueue.size()); ++ mService.isSystemUid = false; ++ ++ // package is not suspended ++ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) ++ .thenReturn(false); ++ ++ setAppInForegroundForToasts(mUid, true); ++ ++ Binder token = new Binder(); ++ INotificationManager nmService = (INotificationManager) mService.mService; ++ ++ // first time trying to show the toast, showToast gets called ++ nmService.enqueueTextToast(testPackage, token, "Text", 2000, 0, null); ++ verify(mStatusBar, times(1)) ++ .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any()); ++ ++ // second time trying to show the same toast, showToast isn't called again (total number of ++ // invocations stays at one) ++ nmService.enqueueTextToast(testPackage, token, "Text", 2000, 0, null); ++ verify(mStatusBar, times(1)) ++ .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any()); ++ } ++ + public void testDisallowToastsFromSuspendedPackages() throws Exception { + final String testPackage = "testPackageName"; + assertEquals(0, mService.mToastQueue.size()); diff --git a/Scripts/LineageOS-17.1/Patch.sh b/Scripts/LineageOS-17.1/Patch.sh index 4c96ead3..d05fe1da 100644 --- a/Scripts/LineageOS-17.1/Patch.sh +++ b/Scripts/LineageOS-17.1/Patch.sh @@ -292,6 +292,8 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/391912.patch"; #Q_asb_2024-03 D applyPatch "$DOS_PATCHES/android_frameworks_base/391913.patch"; #Q_asb_2024-03 Close AccountManagerService.session after timeout. applyPatch "$DOS_PATCHES/android_frameworks_base/392204.patch"; #Q_asb_2024-04 isUserInLockDown can be true when there are other strong auth requirements applyPatch "$DOS_PATCHES/android_frameworks_base/392205.patch"; #Q_asb_2024-04 Fix security vulnerability that creates user with no restrictions when accountOptions are too long. +applyPatch "$DOS_PATCHES/android_frameworks_base/393587.patch"; #Q_asb_2024-05 Prioritize system toasts +applyPatch "$DOS_PATCHES/android_frameworks_base/393588.patch"; #Q_asb_2024-05 Don't try to show the current toast again while it's showing. #applyPatch "$DOS_PATCHES/android_frameworks_base/272645.patch"; #ten-bt-sbc-hd-dualchannel: Add CHANNEL_MODE_DUAL_CHANNEL constant (ValdikSS) #applyPatch "$DOS_PATCHES/android_frameworks_base/272646-forwardport.patch"; #ten-bt-sbc-hd-dualchannel: Add Dual Channel into Bluetooth Audio Channel Mode developer options menu (ValdikSS) #applyPatch "$DOS_PATCHES/android_frameworks_base/272647.patch"; #ten-bt-sbc-hd-dualchannel: Allow SBC as HD audio codec in Bluetooth device configuration (ValdikSS)