summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Tomljanovic <jtomljanovic@google.com>2020-11-06 11:28:09 +0000
committerJan Tomljanovic <jtomljanovic@google.com>2020-11-10 14:27:08 +0000
commitea90e9501b7925338f3e61fa8ea1b5d0902a53bb (patch)
tree6beb5ed95e9d4bc684c28b969f548e7fbd7886c3
parent85b41414abedcddf94fb0afa3a57f83bbecd2a33 (diff)
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
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java13
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java53
2 files changed, 66 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1516cded50a6..1e2898b91a27 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -494,6 +494,10 @@ public class NotificationManagerService extends SystemService {
final ArrayList<ToastRecord> mToastQueue = new ArrayList<>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
+ // 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<String> mLights = new ArrayList<>();
@@ -7297,10 +7301,15 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mToastQueue")
void showNextToastLocked() {
+ if (mIsCurrentToastShown) {
+ return; // Don't show the same toast twice.
+ }
+
ToastRecord record = mToastQueue.get(0);
while (record != null) {
if (record.show()) {
scheduleDurationReachedLocked(record);
+ mIsCurrentToastShown = true;
return;
}
int index = mToastQueue.indexOf(record);
@@ -7316,6 +7325,10 @@ public class NotificationManagerService extends SystemService {
ToastRecord record = mToastQueue.get(index);
record.hide();
+ if (index == 0) {
+ mIsCurrentToastShown = false;
+ }
+
ToastRecord lastToast = mToastQueue.remove(index);
mWindowManagerInternal.removeWindowToken(lastToast.windowToken, 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 87aaba2b164a..70d3f988f1f7 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4923,6 +4923,32 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testDontCallShowToastAgainOnTheSameCustomToast() 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();
+ ITransientNotification callback = mock(ITransientNotification.class);
+ INotificationManager nmService = (INotificationManager) mService.mService;
+
+ // first time trying to show the toast, showToast gets called
+ nmService.enqueueToast(testPackage, token, callback, 2000, 0);
+ verify(callback, times(1)).show(any());
+
+ // second time trying to show the same toast, showToast isn't called again (total number of
+ // invocations stays at one)
+ nmService.enqueueToast(testPackage, token, callback, 2000, 0);
+ verify(callback, times(1)).show(any());
+ }
+
+ @Test
public void testAllowForegroundTextToasts() throws Exception {
final String testPackage = "testPackageName";
assertEquals(0, mService.mToastQueue.size());
@@ -4959,6 +4985,33 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@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());
+ }
+
+ @Test
public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws
Exception {
final String testPackage = "testPackageName";