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

Commit 116a6e04 authored by Mady Mellor's avatar Mady Mellor Committed by Automerger Merge Worker
Browse files

Merge "Fix launching bubbles from widgets" into sc-dev am: faee2e6b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14940550

Change-Id: Ib0a1d09296d050e400e0f61f14f08f0724e908e3
parents 1ef16dd8 faee2e6b
Loading
Loading
Loading
Loading
+51 −1
Original line number Diff line number Diff line
@@ -373,6 +373,13 @@ public class BubbleController {
                        return;
                    }
                }
                for (Bubble b : mBubbleData.getOverflowBubbles()) {
                    if (task.taskId == b.getTaskId()) {
                        promoteBubbleFromOverflow(b);
                        mBubbleData.setExpanded(true);
                        return;
                    }
                }
            }
        });

@@ -824,7 +831,35 @@ public class BubbleController {
        setIsBubble(bubble, true /* isBubble */);
    }

    @VisibleForTesting
    /**
     * Expands and selects the provided bubble as long as it already exists in the stack or the
     * overflow.
     *
     * This is currently only used when opening a bubble via clicking on a conversation widget.
     */
    public void expandStackAndSelectBubble(Bubble b) {
        if (b == null) {
            return;
        }
        if (mBubbleData.hasBubbleInStackWithKey(b.getKey())) {
            // already in the stack
            mBubbleData.setSelectedBubble(b);
            mBubbleData.setExpanded(true);
        } else if (mBubbleData.hasOverflowBubbleWithKey(b.getKey())) {
            // promote it out of the overflow
            promoteBubbleFromOverflow(b);
        }
    }

    /**
     * Expands and selects a bubble based on the provided {@link BubbleEntry}. If no bubble
     * exists for this entry, and it is able to bubble, a new bubble will be created.
     *
     * This is the method to use when opening a bubble via a notification or in a state where
     * the device might not be unlocked.
     *
     * @param entry the entry to use for the bubble.
     */
    public void expandStackAndSelectBubble(BubbleEntry entry) {
        if (mIsStatusBarShade) {
            mNotifEntryToExpandOnShadeUnlock = null;
@@ -1391,6 +1426,21 @@ public class BubbleController {
            });
        }

        @Override
        public void expandStackAndSelectBubble(Bubble bubble) {
            mMainExecutor.execute(() -> {
                BubbleController.this.expandStackAndSelectBubble(bubble);
            });
        }

        @Override
        @Nullable
        public Bubble getBubbleWithShortcutId(String shortcutId) {
            return mMainExecutor.executeBlockingForResult(() -> {
                return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId);
            }, Bubble.class);
        }

        @Override
        public void onTaskbarChanged(Bundle b) {
            mMainExecutor.execute(() -> {
+29 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.LocusId;
import android.content.pm.ShortcutInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -874,6 +875,34 @@ public class BubbleData {
        return b;
    }

    /** @return any bubble (in the stack or the overflow) that matches the provided shortcutId. */
    @Nullable
    Bubble getAnyBubbleWithShortcutId(String shortcutId) {
        if (TextUtils.isEmpty(shortcutId)) {
            return null;
        }
        for (int i = 0; i < mBubbles.size(); i++) {
            Bubble bubble = mBubbles.get(i);
            String bubbleShortcutId = bubble.getShortcutInfo() != null
                    ? bubble.getShortcutInfo().getId()
                    : bubble.getMetadataShortcutId();
            if (shortcutId.equals(bubbleShortcutId)) {
                return bubble;
            }
        }

        for (int i = 0; i < mOverflowBubbles.size(); i++) {
            Bubble bubble = mOverflowBubbles.get(i);
            String bubbleShortcutId = bubble.getShortcutInfo() != null
                    ? bubble.getShortcutInfo().getId()
                    : bubble.getMetadataShortcutId();
            if (shortcutId.equals(bubbleShortcutId)) {
                return bubble;
            }
        }
        return null;
    }

    @VisibleForTesting(visibility = PRIVATE)
    @Nullable
    public Bubble getBubbleInStackWithKey(String key) {
+13 −0
Original line number Diff line number Diff line
@@ -118,6 +118,19 @@ public interface Bubbles {
     */
    void expandStackAndSelectBubble(BubbleEntry entry);

    /**
     * Request the stack expand if needed, then select the specified Bubble as current.
     *
     * @param bubble the bubble to be selected
     */
    void expandStackAndSelectBubble(Bubble bubble);

    /**
     * @return a bubble that matches the provided shortcutId, if one exists.
     */
    @Nullable
    Bubble getBubbleWithShortcutId(String shortcutId);

    /** Called for any taskbar changes. */
    void onTaskbarChanged(Bundle b);

+46 −9
Original line number Diff line number Diff line
@@ -35,9 +35,11 @@ import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.people.PeopleSpaceUtils;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubble;

import java.util.Optional;

@@ -53,14 +55,35 @@ public class LaunchConversationActivity extends Activity {
    private final UserManager mUserManager;
    private boolean mIsForTesting;
    private IStatusBarService mIStatusBarService;
    private CommandQueue mCommandQueue;
    private Bubble mBubble;
    private NotificationEntry mEntryToBubble;

    @Inject
    public LaunchConversationActivity(NotificationEntryManager notificationEntryManager,
            Optional<BubblesManager> bubblesManagerOptional, UserManager userManager) {
            Optional<BubblesManager> bubblesManagerOptional, UserManager userManager,
            CommandQueue commandQueue) {
        super();
        mNotificationEntryManager = notificationEntryManager;
        mBubblesManagerOptional = bubblesManagerOptional;
        mUserManager = userManager;
        mCommandQueue = commandQueue;
        mCommandQueue.addCallback(new CommandQueue.Callbacks() {
            // (b/190833924) Wait for the app transition to finish before showing the bubble,
            // opening the bubble while the transition is happening can mess with the placement
            // of the  bubble's surface.
            @Override
            public void appTransitionFinished(int displayId) {
                if (mBubblesManagerOptional.isPresent()) {
                    if (mBubble != null) {
                        mBubblesManagerOptional.get().expandStackAndSelectBubble(mBubble);
                    } else if (mEntryToBubble != null) {
                        mBubblesManagerOptional.get().expandStackAndSelectBubble(mEntryToBubble);
                    }
                }
                mCommandQueue.removeCallback(this);
            }
        });
    }

    @Override
@@ -95,15 +118,29 @@ public class LaunchConversationActivity extends Activity {
                    return;
                }

                // We can potentially bubble without a notification, so rather than rely on
                // notificationKey here (which could be null if there's no notification or if the
                // bubble is suppressing the notification), so we'll use the shortcutId for lookups.
                // This misses one specific case: a bubble that was never opened & still has a
                // visible notification, but the bubble was dismissed & aged out of the overflow.
                // So it wouldn't exist in the stack or overflow to be looked up BUT the notif entry
                // would still exist & be bubbleable. So if we don't get a bubble from the
                // shortcutId, fallback to notificationKey if it exists.
                if (mBubblesManagerOptional.isPresent()) {
                    mBubble = mBubblesManagerOptional.get().getBubbleWithShortcutId(tileId);
                    NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(
                            notificationKey);
                if (entry != null && entry.canBubble() && mBubblesManagerOptional.isPresent()) {
                    if (DEBUG) Log.d(TAG, "Open bubble for conversation");
                    mBubblesManagerOptional.get().expandStackAndSelectBubble(entry);
                    if (mBubble != null || (entry != null && entry.canBubble())) {
                        mEntryToBubble = entry;
                        if (DEBUG) {
                            Log.d(TAG,
                                    "Opening bubble: " + mBubble  + ", entry: " + mEntryToBubble);
                        }
                        // Just opt-out and don't cancel the notification for bubbles.
                        finish();
                        return;
                    }
                }

                if (mIStatusBarService == null) {
                    mIStatusBarService = IStatusBarService.Stub.asInterface(
+17 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.wm.shell.bubbles.Bubble;
import com.android.wm.shell.bubbles.BubbleEntry;
import com.android.wm.shell.bubbles.Bubbles;

@@ -657,6 +658,22 @@ public class BubblesManager implements Dumpable {
        mBubbles.expandStackAndSelectBubble(notifToBubbleEntry(entry));
    }

    /**
     * Request the stack expand if needed, then select the specified Bubble as current.
     *
     * @param bubble the bubble to be selected
     */
    public void expandStackAndSelectBubble(Bubble bubble) {
        mBubbles.expandStackAndSelectBubble(bubble);
    }

    /**
     * @return a bubble that matches the provided shortcutId, if one exists.
     */
    public Bubble getBubbleWithShortcutId(String shortcutId) {
        return mBubbles.getBubbleWithShortcutId(shortcutId);
    }

    /** See {@link NotifCallback}. */
    public void addNotifCallback(NotifCallback callback) {
        mCallbacks.add(callback);
Loading