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

Commit 3b9ef3fe authored by Mady Mellor's avatar Mady Mellor
Browse files

Allow floating tasks to be shown as bubbles (behind a sysui flag)

Special "app bubble" that is ordered at the front of the list unless
something else was selected. This is guarded behind the flag to
enable floating tasks, and a new flag to allow floating tasks to be
bubbles.

Test: manual  - enable the flags and create a floating task
             => floating task appears in a bubble
Bug: 237678727
Change-Id: Ibf66e8bae07800b5f64598c9b50de7a7995d09e6
parent 027ea363
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ import java.util.concurrent.Executor;
public class Bubble implements BubbleViewProvider {
    private static final String TAG = "Bubble";

    public static final String KEY_APP_BUBBLE = "key_app_bubble";

    private final String mKey;
    @Nullable
    private final String mGroupKey;
@@ -163,6 +165,14 @@ public class Bubble implements BubbleViewProvider {
    @Nullable
    private PendingIntent mDeleteIntent;

    /**
     * Used only for a special bubble in the stack that has the key {@link #KEY_APP_BUBBLE}.
     * There can only be one of these bubbles in the stack and this intent will be populated for
     * that bubble.
     */
    @Nullable
    private Intent mAppIntent;

    /**
     * Create a bubble with limited information based on given {@link ShortcutInfo}.
     * Note: Currently this is only being used when the bubble is persisted to disk.
@@ -192,6 +202,22 @@ public class Bubble implements BubbleViewProvider {
        mBubbleMetadataFlagListener = listener;
    }

    public Bubble(Intent intent,
            UserHandle user,
            Executor mainExecutor) {
        mKey = KEY_APP_BUBBLE;
        mGroupKey = null;
        mLocusId = null;
        mFlags = 0;
        mUser = user;
        mShowBubbleUpdateDot = false;
        mMainExecutor = mainExecutor;
        mTaskId = INVALID_TASK_ID;
        mAppIntent = intent;
        mDesiredHeight = Integer.MAX_VALUE;
        mPackageName = intent.getPackage();
    }

    @VisibleForTesting(visibility = PRIVATE)
    public Bubble(@NonNull final BubbleEntry entry,
            final Bubbles.BubbleMetadataFlagListener listener,
@@ -417,6 +443,9 @@ public class Bubble implements BubbleViewProvider {

        mShortcutInfo = info.shortcutInfo;
        mAppName = info.appName;
        if (mTitle == null) {
            mTitle = mAppName;
        }
        mFlyoutMessage = info.flyoutMessage;

        mBadgeBitmap = info.badgeBitmap;
@@ -520,7 +549,7 @@ public class Bubble implements BubbleViewProvider {
     * @return the last time this bubble was updated or accessed, whichever is most recent.
     */
    long getLastActivity() {
        return Math.max(mLastUpdated, mLastAccessed);
        return isAppBubble() ? Long.MAX_VALUE : Math.max(mLastUpdated, mLastAccessed);
    }

    /**
@@ -719,6 +748,15 @@ public class Bubble implements BubbleViewProvider {
        return mDeleteIntent;
    }

    @Nullable
    Intent getAppBubbleIntent() {
        return mAppIntent;
    }

    boolean isAppBubble() {
        return KEY_APP_BUBBLE.equals(mKey);
    }

    Intent getSettingsIntent(final Context context) {
        final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
        intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
+14 −0
Original line number Diff line number Diff line
@@ -1016,6 +1016,20 @@ public class BubbleController implements ConfigurationChangeListener {
        }
    }

    /**
     * Adds a bubble for a specific intent. These bubbles are <b>not</b> backed by a notification
     * and remain until the user dismisses the bubble or bubble stack. Only one intent bubble
     * is supported at a time.
     *
     * @param intent the intent to display in the bubble expanded view.
     */
    public void addAppBubble(Intent intent) {
        if (intent == null || intent.getPackage() == null) return;
        Bubble b = new Bubble(intent, UserHandle.of(mCurrentUserId), mMainExecutor);
        b.setShouldAutoExpand(true);
        inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
    }

    /**
     * Fills the overflow bubbles by loading them from disk.
     */
+13 −5
Original line number Diff line number Diff line
@@ -224,15 +224,23 @@ public class BubbleExpandedView extends LinearLayout {
                try {
                    options.setTaskAlwaysOnTop(true);
                    options.setLaunchedFromBubble(true);
                    if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
                        options.setApplyActivityFlagsForBubbles(true);
                        mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
                                options, launchBounds);
                    } else {

                    Intent fillInIntent = new Intent();
                    // Apply flags to make behaviour match documentLaunchMode=always.
                    fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
                    fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);

                    if (mBubble.isAppBubble()) {
                        PendingIntent pi = PendingIntent.getActivity(mContext, 0,
                                mBubble.getAppBubbleIntent(),
                                PendingIntent.FLAG_MUTABLE,
                                null);
                        mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
                    } else if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
                        options.setApplyActivityFlagsForBubbles(true);
                        mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
                                options, launchBounds);
                    } else {
                        if (mBubble != null) {
                            mBubble.setIntentActive();
                        }
+2 −0
Original line number Diff line number Diff line
@@ -591,6 +591,7 @@ public abstract class WMShellBaseModule {
            ShellInit shellInit,
            ShellController shellController,
            ShellCommandHandler shellCommandHandler,
            Optional<BubbleController> bubbleController,
            WindowManager windowManager,
            ShellTaskOrganizer organizer,
            TaskViewTransitions taskViewTransitions,
@@ -602,6 +603,7 @@ public abstract class WMShellBaseModule {
                    shellInit,
                    shellController,
                    shellCommandHandler,
                    bubbleController,
                    windowManager,
                    organizer,
                    taskViewTransitions,
+25 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TaskViewTransitions;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -54,6 +55,7 @@ import com.android.wm.shell.sysui.ShellInit;

import java.io.PrintWriter;
import java.util.Objects;
import java.util.Optional;

/**
 * Entry point for creating and managing floating tasks.
@@ -70,6 +72,8 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont

    public static final boolean FLOATING_TASKS_ENABLED =
            SystemProperties.getBoolean("persist.wm.debug.floating_tasks", false);
    public static final boolean SHOW_FLOATING_TASKS_AS_BUBBLES =
            SystemProperties.getBoolean("persist.wm.debug.floating_tasks_as_bubbles", false);

    @VisibleForTesting
    static final int SMALLEST_SCREEN_WIDTH_DP_TO_BE_TABLET = 600;
@@ -82,6 +86,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
    private Context mContext;
    private ShellController mShellController;
    private ShellCommandHandler mShellCommandHandler;
    private @Nullable BubbleController mBubbleController;
    private WindowManager mWindowManager;
    private ShellTaskOrganizer mTaskOrganizer;
    private TaskViewTransitions mTaskViewTransitions;
@@ -111,6 +116,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
            ShellInit shellInit,
            ShellController shellController,
            ShellCommandHandler shellCommandHandler,
            Optional<BubbleController> bubbleController,
            WindowManager windowManager,
            ShellTaskOrganizer organizer,
            TaskViewTransitions transitions,
@@ -120,6 +126,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
        mContext = context;
        mShellController = shellController;
        mShellCommandHandler = shellCommandHandler;
        mBubbleController = bubbleController.get();
        mWindowManager = windowManager;
        mTaskOrganizer = organizer;
        mTaskViewTransitions = transitions;
@@ -187,6 +194,22 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
        return true;
    }

    /** Returns true if the task was or should be shown as a bubble. */
    private boolean maybeShowTaskAsBubble(Intent intent) {
        if (SHOW_FLOATING_TASKS_AS_BUBBLES && mBubbleController != null) {
            removeFloatingLayer();
            if (intent.getPackage() != null) {
                mBubbleController.addAppBubble(intent);
                ProtoLog.d(WM_SHELL_FLOATING_APPS, "showing floating task as bubble: %s", intent);
            } else {
                ProtoLog.d(WM_SHELL_FLOATING_APPS,
                        "failed to show floating task as bubble: %s; unknown package", intent);
            }
            return true;
        }
        return false;
    }

    /**
     * Shows, stashes, or un-stashes the floating task depending on state:
     * - If there is no floating task for this intent, it shows this the provided task.
@@ -195,6 +218,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
     */
    public void showOrSetStashed(Intent intent) {
        if (!canShowTask(intent)) return;
        if (maybeShowTaskAsBubble(intent)) return;

        addFloatingLayer();

@@ -215,6 +239,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
     */
    public void showTask(Intent intent) {
        if (!canShowTask(intent)) return;
        if (maybeShowTaskAsBubble(intent)) return;

        addFloatingLayer();

Loading