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

Commit e7cf038b authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge changes I23104038,Ic664739b into main

* changes:
  Add a signal for the contents of the overflow going from empty to not
  Switch app bubble overflow removals to a dismiss / cancel
parents 9a461698 5a165f73
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@ public class BubbleController implements ConfigurationChangeListener,
         * the pointer might need to be updated.
         */
        void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer);
        /** Called when the bubble overflow empty state changes, used to show/hide the overflow. */
        void bubbleOverflowChanged(boolean hasBubbles);
    }

    private final Context mContext;
@@ -1401,7 +1403,7 @@ public class BubbleController implements ConfigurationChangeListener,
            Bubble b = mBubbleData.getOverflowBubbleWithKey(appBubbleKey);
            if (b != null) {
                // It's in the overflow, so remove it & reinflate
                mBubbleData.removeOverflowBubble(b);
                mBubbleData.dismissBubbleWithKey(appBubbleKey, Bubbles.DISMISS_NOTIF_CANCEL);
            } else {
                // App bubble does not exist, lets add and expand it
                b = Bubble.createAppBubble(intent, user, icon, mMainExecutor);
@@ -1844,6 +1846,11 @@ public class BubbleController implements ConfigurationChangeListener,
            }

        }

        @Override
        public void bubbleOverflowChanged(boolean hasBubbles) {
            // TODO (b/334175587): tell stack view to hide / show the overflow
        }
    };

    /** When bubbles are in the bubble bar, this will be used to notify bubble bar views. */
@@ -1875,6 +1882,11 @@ public class BubbleController implements ConfigurationChangeListener,
            // Nothing to do for order changes, these are handled by launcher / in the bubble bar.
        }

        @Override
        public void bubbleOverflowChanged(boolean hasBubbles) {
            // Nothing to do for our views, handled by launcher / in the bubble bar.
        }

        @Override
        public void suppressionChanged(Bubble bubble, boolean isSuppressed) {
            if (mLayerView != null) {
@@ -1914,7 +1926,7 @@ public class BubbleController implements ConfigurationChangeListener,
            ProtoLog.d(WM_SHELL_BUBBLES, "mBubbleDataListener#applyUpdate:"
                    + " added=%s removed=%b updated=%s orderChanged=%b expansionChanged=%b"
                    + " expanded=%b selectionChanged=%b selected=%s"
                    + " suppressed=%s unsupressed=%s shouldShowEducation=%b",
                    + " suppressed=%s unsupressed=%s shouldShowEducation=%b showOverflowChanged=%b",
                    update.addedBubble != null ? update.addedBubble.getKey() : "null",
                    !update.removedBubbles.isEmpty(),
                    update.updatedBubble != null ? update.updatedBubble.getKey() : "null",
@@ -1923,13 +1935,17 @@ public class BubbleController implements ConfigurationChangeListener,
                    update.selectedBubble != null ? update.selectedBubble.getKey() : "null",
                    update.suppressedBubble != null ? update.suppressedBubble.getKey() : "null",
                    update.unsuppressedBubble != null ? update.unsuppressedBubble.getKey() : "null",
                    update.shouldShowEducation);
                    update.shouldShowEducation, update.showOverflowChanged);

            ensureBubbleViewsAndWindowCreated();

            // Lazy load overflow bubbles from disk
            loadOverflowBubblesFromDisk();

            if (update.showOverflowChanged) {
                mBubbleViewCallback.bubbleOverflowChanged(!update.overflowBubbles.isEmpty());
            }

            // If bubbles in the overflow have a dot, make sure the overflow shows a dot
            updateOverflowButtonDot();

+10 −15
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ public class BubbleData {
        boolean suppressedSummaryChanged;
        boolean expanded;
        boolean shouldShowEducation;
        boolean showOverflowChanged;
        @Nullable BubbleViewProvider selectedBubble;
        @Nullable Bubble addedBubble;
        @Nullable Bubble updatedBubble;
@@ -109,7 +110,8 @@ public class BubbleData {
                    || suppressedBubble != null
                    || unsuppressedBubble != null
                    || suppressedSummaryChanged
                    || suppressedSummaryGroup != null;
                    || suppressedSummaryGroup != null
                    || showOverflowChanged;
        }

        void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) {
@@ -410,6 +412,9 @@ public class BubbleData {
            if (bubbleToReturn != null) {
                // Promoting from overflow
                mOverflowBubbles.remove(bubbleToReturn);
                if (mOverflowBubbles.isEmpty()) {
                    mStateChange.showOverflowChanged = true;
                }
            } else if (mPendingBubbles.containsKey(key)) {
                // Update while it was pending
                bubbleToReturn = mPendingBubbles.get(key);
@@ -496,19 +501,6 @@ public class BubbleData {
        dispatchPendingChanges();
    }

    /**
     * Explicitly removes a bubble from the overflow, if it exists.
     *
     * @param bubble the bubble to remove.
     */
    public void removeOverflowBubble(Bubble bubble) {
        if (bubble == null) return;
        if (mOverflowBubbles.remove(bubble)) {
            mStateChange.removedOverflowBubble = bubble;
            dispatchPendingChanges();
        }
    }

    /**
     * Adds a group key indicating that the summary for this group should be suppressed.
     *
@@ -683,7 +675,6 @@ public class BubbleData {
        if (indexToRemove == -1) {
            if (hasOverflowBubbleWithKey(key)
                    && shouldRemoveHiddenBubble) {

                Bubble b = getOverflowBubbleWithKey(key);
                ProtoLog.d(WM_SHELL_BUBBLES, "doRemove - cancel overflow bubble=%s", key);
                if (b != null) {
@@ -693,6 +684,7 @@ public class BubbleData {
                mOverflowBubbles.remove(b);
                mStateChange.bubbleRemoved(b, reason);
                mStateChange.removedOverflowBubble = b;
                mStateChange.showOverflowChanged = mOverflowBubbles.isEmpty();
            }
            if (hasSuppressedBubbleWithKey(key) && shouldRemoveHiddenBubble) {
                Bubble b = getSuppressedBubbleWithKey(key);
@@ -792,6 +784,9 @@ public class BubbleData {
        }
        ProtoLog.d(WM_SHELL_BUBBLES, "overflowBubble=%s", bubble.getKey());
        mLogger.logOverflowAdd(bubble, reason);
        if (mOverflowBubbles.isEmpty()) {
            mStateChange.showOverflowChanged = true;
        }
        mOverflowBubbles.remove(bubble);
        mOverflowBubbles.add(0, bubble);
        mStateChange.addedOverflowBubble = bubble;
+45 −17
Original line number Diff line number Diff line
@@ -1192,23 +1192,6 @@ public class BubbleDataTest extends ShellTestCase {
        assertThat(mBubbleData.getBubbleInStackWithKey(appBubbleKey)).isNull();
    }

    @Test
    public void test_removeOverflowBubble() {
        sendUpdatedEntryAtTime(mEntryA1, 2000);
        mBubbleData.setListener(mListener);

        mBubbleData.dismissBubbleWithKey(mEntryA1.getKey(), Bubbles.DISMISS_USER_GESTURE);
        verifyUpdateReceived();
        assertOverflowChangedTo(ImmutableList.of(mBubbleA1));

        mBubbleData.removeOverflowBubble(mBubbleA1);
        verifyUpdateReceived();

        BubbleData.Update update = mUpdateCaptor.getValue();
        assertThat(update.removedOverflowBubble).isEqualTo(mBubbleA1);
        assertOverflowChangedTo(ImmutableList.of());
    }

    @Test
    public void test_getInitialStateForBubbleBar_includesInitialBubblesAndPosition() {
        sendUpdatedEntryAtTime(mEntryA1, 1000);
@@ -1235,6 +1218,51 @@ public class BubbleDataTest extends ShellTestCase {
        assertExpandedChangedTo(true);
    }

    @Test
    public void testShowOverflowChanged_hasOverflowBubbles() {
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
        sendUpdatedEntryAtTime(mEntryA1, 1000);
        mBubbleData.setListener(mListener);

        mBubbleData.dismissBubbleWithKey(mEntryA1.getKey(), Bubbles.DISMISS_USER_GESTURE);
        verifyUpdateReceived();
        assertThat(mUpdateCaptor.getValue().showOverflowChanged).isTrue();
        assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();
    }

    @Test
    public void testShowOverflowChanged_false_hasOverflowBubbles() {
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
        sendUpdatedEntryAtTime(mEntryA1, 1000);
        sendUpdatedEntryAtTime(mEntryA2, 1000);
        mBubbleData.setListener(mListener);

        // First overflowed causes change event
        mBubbleData.dismissBubbleWithKey(mEntryA1.getKey(), Bubbles.DISMISS_USER_GESTURE);
        verifyUpdateReceived();
        assertThat(mUpdateCaptor.getValue().showOverflowChanged).isTrue();
        assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();

        // Second overflow does not
        mBubbleData.dismissBubbleWithKey(mEntryA2.getKey(), Bubbles.DISMISS_USER_GESTURE);
        verifyUpdateReceived();
        assertThat(mUpdateCaptor.getValue().showOverflowChanged).isFalse();
    }

    @Test
    public void testShowOverflowChanged_noOverflowBubbles() {
        sendUpdatedEntryAtTime(mEntryA1, 1000);
        mBubbleData.dismissBubbleWithKey(mEntryA1.getKey(), Bubbles.DISMISS_USER_GESTURE);
        assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();
        mBubbleData.setListener(mListener);

        mBubbleData.dismissBubbleWithKey(mEntryA1.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);

        verifyUpdateReceived();
        assertThat(mUpdateCaptor.getValue().showOverflowChanged).isTrue();
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
    }

    private void verifyUpdateReceived() {
        verify(mListener).applyUpdate(mUpdateCaptor.capture());
        reset(mListener);