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

Commit bb23cbcb authored by Mady Mellor's avatar Mady Mellor
Browse files

Fix an issue where the bubble wasn't opening

If a bubble had been dismissed, but the notif was still visible,
when the user clicks on that notif, the onNotificationClick event
can occur before onNotificationBubbleChanged.

This means that we might remove/cancel a notification that is
about to become a bubble, so when onNotificationBubbleChanged is
called there isn't a record to create the bubble with.

This CL fixes this by skipping the removal if it's a bubble notif
where the bubble has been dismissed & the notif canBubble.

Test: atest NotificationManagerServiceTest
Bug: 189149153
Bug: 183732510
Change-Id: I366c3a317fb6d4c38e7547c31ff9d47dc9b4846e
parent e1d07010
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -6815,12 +6815,14 @@ public class NotificationManagerService extends SystemService {
                        mUsageStats.registerClickedByUser(r);
                    }

                    if (mReason == REASON_LISTENER_CANCEL
                            && r.getNotification().isBubbleNotification()) {
                    if ((mReason == REASON_LISTENER_CANCEL
                            && r.getNotification().isBubbleNotification())
                            || (mReason == REASON_CLICK && r.canBubble()
                            && r.isFlagBubbleRemoved())) {
                        boolean isBubbleSuppressed = r.getNotification().getBubbleMetadata() != null
                                && r.getNotification().getBubbleMetadata().isBubbleSuppressed();
                        mNotificationDelegate.onBubbleNotificationSuppressionChanged(
                                r.getKey(), true /* suppressed */, isBubbleSuppressed);
                                r.getKey(), true /* notifSuppressed */, isBubbleSuppressed);
                        return;
                    }

+41 −0
Original line number Diff line number Diff line
@@ -7223,6 +7223,47 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                mNotificationRecordLogger.event(0));
    }

    /**
     * When something is bubble'd and the bubble is dismissed, but the notification is still
     * visible, clicking on the notification shouldn't auto-cancel it because clicking on
     * it will produce a bubble.
     */
    @Test
    public void testNotificationBubbles_bubbleStays_whenClicked_afterBubbleDismissed()
            throws Exception {
        setUpPrefsForBubbles(PKG, mUid,
                true /* global */,
                BUBBLE_PREFERENCE_ALL /* app */,
                true /* channel */);

        // GIVEN a notification that has the auto cancels flag (cancel on click) and is a bubble
        final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
        nr.getSbn().getNotification().flags |= FLAG_BUBBLE | FLAG_AUTO_CANCEL;
        nr.setAllowBubble(true);
        mService.addNotification(nr);

        // And the bubble is dismissed
        mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(),
                false /* isBubble */, 0 /* bubbleFlags */);
        waitForIdle();
        assertTrue(nr.isFlagBubbleRemoved());

        // WHEN we click the notification
        final NotificationVisibility nv = NotificationVisibility.obtain(nr.getKey(), 1, 2, true);
        mService.mNotificationDelegate.onNotificationClick(mUid, Binder.getCallingPid(),
                nr.getKey(), nv);
        waitForIdle();

        // THEN the bubble should still exist
        StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
        assertEquals(1, notifsAfter.length);

        // Check we got the click log
        assertEquals(1, mNotificationRecordLogger.numCalls());
        assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLICKED,
                mNotificationRecordLogger.event(0));
    }

    @Test
    public void testLoadDefaultApprovedServices_emptyResources() {
        TestableResources tr = mContext.getOrCreateTestableResources();