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

Commit 4dd6d513 authored by Mady Mellor's avatar Mady Mellor
Browse files

Handle non-visually-interruptive updates better in bubbles

1) If its a non-visual update to an existing bubble don't
   alter the bubble order or show a flyout
2) If its a non-visual update to a bubble in the overflow
   don't promote that content out of the overflow

Test: BubbleControllerTest
Bug: 162975422
Bug: 163608157
Change-Id: I6d8e67028a5aacf1a23acdbfaeb0fa8a50f829a6
parent 19893112
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -285,6 +285,15 @@ class Bubble implements BubbleViewProvider {
        mInflateSynchronously = inflateSynchronously;
    }

    /**
     * Sets whether this bubble is considered visually interruptive. Normally pulled from the
     * {@link NotificationEntry}, this method is purely for testing.
     */
    @VisibleForTesting
    void setVisuallyInterruptiveForTest(boolean visuallyInterruptive) {
        mIsVisuallyInterruptive = visuallyInterruptive;
    }

    /**
     * Starts a task to inflate & load any necessary information to display a bubble.
     *
@@ -411,6 +420,7 @@ class Bubble implements BubbleViewProvider {
            } else if (mIntent != null && entry.getBubbleMetadata().getIntent() == null) {
                // Was an intent bubble now it's a shortcut bubble... still unregister the listener
                mIntent.unregisterCancelListener(mIntentCancelListener);
                mIntentActive = false;
                mIntent = null;
            }
            mDeleteIntent = entry.getBubbleMetadata().getDeleteIntent();
+13 −4
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.bubbles.animation.StackAnimationController;
import com.android.systemui.bubbles.dagger.BubbleModule;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.model.SysUiState;
@@ -407,7 +406,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            if (bubble.getBubbleIntent() == null) {
                return;
            }
            if (bubble.isIntentActive()) {
            if (bubble.isIntentActive()
                    || mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
                bubble.setPendingIntentCanceled();
                return;
            }
@@ -1120,9 +1120,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
            notif.setInterruption();
        }
        if (!notif.getRanking().visuallyInterruptive()
                && (notif.getBubbleMetadata() != null
                    && !notif.getBubbleMetadata().getAutoExpandBubble())
                && mBubbleData.hasOverflowBubbleWithKey(notif.getKey())) {
            // Update the bubble but don't promote it out of overflow
            Bubble b = mBubbleData.getOverflowBubbleWithKey(notif.getKey());
            b.setEntry(notif);
        } else {
            Bubble bubble = mBubbleData.getOrCreateBubble(notif, null /* persistedBubble */);
            inflateAndAdd(bubble, suppressFlyout, showInShade);
        }
    }

    void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
        // Lazy init stack view when a bubble is created
+4 −3
Original line number Diff line number Diff line
@@ -277,7 +277,8 @@ public class BubbleData {
        } else {
            // Updates an existing bubble
            bubble.setSuppressFlyout(suppressFlyout);
            doUpdate(bubble);
            // If there is no flyout, we probably shouldn't show the bubble at the top
            doUpdate(bubble, !suppressFlyout /* reorder */);
        }

        if (bubble.shouldAutoExpand()) {
@@ -431,12 +432,12 @@ public class BubbleData {
        }
    }

    private void doUpdate(Bubble bubble) {
    private void doUpdate(Bubble bubble, boolean reorder) {
        if (DEBUG_BUBBLE_DATA) {
            Log.d(TAG, "doUpdate: " + bubble);
        }
        mStateChange.updatedBubble = bubble;
        if (!isExpanded()) {
        if (!isExpanded() && reorder) {
            int prevPos = mBubbles.indexOf(bubble);
            mBubbles.remove(bubble);
            mBubbles.add(0, bubble);
+23 −0
Original line number Diff line number Diff line
@@ -999,6 +999,29 @@ public class BubbleControllerTest extends SysuiTestCase {
        verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry());
    }


    /**
     * Verifies that when a non visually interruptive update occurs for a bubble in the overflow,
     * the that bubble does not get promoted from the overflow.
     */
    @Test
    public void test_notVisuallyInterruptive_updateOverflowBubble_notAdded() {
        // Setup
        mBubbleController.updateBubble(mRow.getEntry());
        mBubbleController.updateBubble(mRow2.getEntry());
        assertTrue(mBubbleController.hasBubbles());

        // Overflow it
        mBubbleData.dismissBubbleWithKey(mRow.getEntry().getKey(),
                BubbleController.DISMISS_USER_GESTURE);
        assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getEntry().getKey())).isFalse();
        assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey())).isTrue();

        // Test
        mBubbleController.updateBubble(mRow.getEntry());
        assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getEntry().getKey())).isFalse();
    }

    /**
     * Sets the bubble metadata flags for this entry. These ]flags are normally set by
     * NotificationManagerService when the notification is sent, however, these tests do not
+26 −0
Original line number Diff line number Diff line
@@ -512,6 +512,26 @@ public class BubbleDataTest extends SysuiTestCase {
        assertSelectionChangedTo(mBubbleA1);
    }

    /**
     * Verifies that when a non visually interruptive update occurs, that the selection does not
     * change.
     */
    @Test
    public void test_notVisuallyInterruptive_updateBubble_selectionDoesntChange() {
        // Setup
        sendUpdatedEntryAtTime(mEntryA1, 1000);
        sendUpdatedEntryAtTime(mEntryB1, 2000);
        sendUpdatedEntryAtTime(mEntryB2, 3000);
        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
        mBubbleData.setListener(mListener);

        assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA2);

        // Test
        sendUpdatedEntryAtTime(mEntryB1, 5000, false /* isVisuallyInterruptive */);
        assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA2);
    }

    /**
     * Verifies that a request to expand the stack has no effect if there are no bubbles.
     */
@@ -883,9 +903,15 @@ public class BubbleDataTest extends SysuiTestCase {
    }

    private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime) {
        sendUpdatedEntryAtTime(entry, postTime, true /* visuallyInterruptive */);
    }

    private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime,
            boolean visuallyInterruptive) {
        setPostTime(entry, postTime);
        // BubbleController calls this:
        Bubble b = mBubbleData.getOrCreateBubble(entry, null /* persistedBubble */);
        b.setVisuallyInterruptiveForTest(visuallyInterruptive);
        // And then this
        mBubbleData.notificationEntryUpdated(b, false /* suppressFlyout*/,
                true /* showInShade */);