Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58d89b49 authored by Valentin Iftime's avatar Valentin Iftime Committed by Iavor-Valentin Iftime
Browse files

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.
 Also increase Clipboard paste warning toasts length to LENGTH_LONG.

Test: atest NotificationManagerServiceTest
Bug: 293301736

Change-Id: I13547f853476bc88d12026c545aba9f857ce8724
Merged-In: I13547f853476bc88d12026c545aba9f857ce8724
parent 22454204
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1109,7 +1109,7 @@ public class ClipboardService extends SystemService {
                        getContext().getString(R.string.pasted_from_clipboard, callingAppLabel);
                Slog.i(TAG, message);
                Toast.makeText(
                        getContext(), UiThread.get().getLooper(), message, Toast.LENGTH_SHORT)
                        getContext(), UiThread.get().getLooper(), message, Toast.LENGTH_LONG)
                        .show();
            } catch (PackageManager.NameNotFoundException e) {
                // do nothing
+30 −2
Original line number Diff line number Diff line
@@ -3315,8 +3315,19 @@ public class NotificationManagerService extends SystemService {
                                null /* options */);
                        record = getToastRecord(callingUid, callingPid, pkg, isSystemToast, token,
                                text, callback, duration, windowToken, displayId, textCallback);
                        // 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;
                        }
                        keepProcessAliveForToastIfNeededLocked(callingPid);
                    }
                    // If it's at index 0, it's the current toast.  It doesn't matter if it's
@@ -3332,6 +3343,23 @@ public class NotificationManagerService extends SystemService {
            }
        }
        @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;
        }
        private boolean checkCanEnqueueToast(String pkg, int callingUid,
                boolean isAppRenderedToast, boolean isSystemToast) {
            final boolean isPackageSuspended = isPackagePaused(pkg);
+68 −0
Original line number Diff line number Diff line
@@ -6839,6 +6839,74 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        assertEquals(NotificationManagerService.MAX_PACKAGE_TOASTS, 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);
    }

    private void setAppInForegroundForToasts(int uid, boolean inForeground) {
        int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE;
        when(mActivityManager.getUidImportance(mUid)).thenReturn(importance);