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

Commit 8ae2f4fc authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "Create a root task for bubble" into main

parents 71ea965e 3a6e7472
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -596,6 +596,7 @@ public class ActivityOptions extends ComponentOptions {
    private boolean mIsEligibleForLegacyPermissionPrompt;
    private boolean mRemoveWithTaskOrganizer;
    private boolean mLaunchedFromBubble;
    // TODO(b/407669465): remove it once migrated to the new approach
    private boolean mLaunchNextToBubble;
    private boolean mTransientLaunch;
    private PictureInPictureParams mLaunchIntoPipParams;
+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.bubbles

import android.window.WindowContainerToken
import com.android.wm.shell.shared.bubbles.BubbleBarLocation
import java.util.Collections

@@ -51,4 +52,8 @@ class FakeBubbleExpandedViewManager(var bubbleBar: Boolean = false, var expanded
    override fun hideCurrentInputMethod() {}

    override fun updateBubbleBarLocation(location: BubbleBarLocation, source: Int) {}

    override fun getAppBubbleRootTaskToken(): WindowContainerToken? {
        return null
    }
}
+20 −0
Original line number Diff line number Diff line
@@ -52,6 +52,26 @@ public class BubbleAnythingFlagHelper {
                && Flags.enableCreateAnyBubble());
    }

    /** Whether creating a root task to manage the bubble tasks in the Core. */
    public static boolean enableRootTaskForBubble() {
        // This is needed to prevent tasks being hidden and re-parented to TDA when move-to-back.
        if (!enableCreateAnyBubbleWithForceExcludedFromRecents()) {
            return false;
        }

        // This is needed to allow the activity behind the root task remains in RESUMED state.
        if (!com.android.window.flags.Flags.enableSeeThroughTaskFragments()) {
            return false;
        }

        // This is needed to allow the leaf task can be started in expected bounds.
        if (!com.android.window.flags.Flags.respectLeafTaskBounds()) {
            return false;
        }

        return com.android.window.flags.Flags.rootTaskForBubble();
    }

    /** Whether the overall bubble anything feature is enabled. */
    public static boolean enableBubbleAnything() {
        return Flags.enableBubbleAnything();
+26 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.bubbles;

import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED;
import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
@@ -231,6 +232,7 @@ public class BubbleController implements ConfigurationChangeListener,
    private final BubbleData mBubbleData;
    @Nullable private BubbleStackView mStackView;
    @Nullable private BubbleBarLayerView mLayerView;
    @Nullable private ActivityManager.RunningTaskInfo mAppBubbleRootTaskInfo;
    private BubbleIconFactory mBubbleIconFactory;
    private final BubblePositioner mBubblePositioner;
    private Bubbles.SysuiProxy mSysuiProxy;
@@ -563,6 +565,25 @@ public class BubbleController implements ConfigurationChangeListener,
                Slog.e(TAG, "Failed to register Bubble multitasking delegate.", e);
            }
        }

        if (BubbleAnythingFlagHelper.enableRootTaskForBubble()) {
            // Create a root-task in WM Core. The app bubble tasks will be positioned as the leaf
            // tasks under this root-task.
            // The app bubble should be dismissed with proper transition (such as need to convert
            // it to fullscreen) if the bubble task is no longer be a leaf task under this leaf
            // task.
            mTaskOrganizer.createRootTask(mContext.getDisplayId(), WINDOWING_MODE_MULTI_WINDOW,
                    new ShellTaskOrganizer.TaskListener() {
                        @Override
                        public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
                                SurfaceControl leash) {
                            if (mAppBubbleRootTaskInfo != null) {
                                return;
                            }
                            mAppBubbleRootTaskInfo = taskInfo;
                        }
                    });
        }
    }

    private ExternalInterfaceBinder createExternalInterface() {
@@ -2723,6 +2744,11 @@ public class BubbleController implements ConfigurationChangeListener,
        return mLayerView;
    }

    @Nullable
    public ActivityManager.RunningTaskInfo getAppBubbleRootTaskInfo() {
        return mAppBubbleRootTaskInfo;
    }

    /**
     * Returns the id of the display to which the current Bubble view is attached if it is currently
     * showing, {@link INVALID_DISPLAY} otherwise.
+14 −2
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.window.ScreenCapture;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.annotation.Nullable;
@@ -250,15 +251,26 @@ public class BubbleExpandedView extends LinearLayout {
                                // Needs to be mutable for the fillInIntent
                                PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
                                /* options= */ null);
                        final WindowContainerToken rootToken = mManager.getAppBubbleRootTaskToken();
                        if (rootToken != null) {
                            options.setLaunchRootTask(rootToken);
                        } else {
                            options.setLaunchNextToBubble(true /* launchNextToBubble */);
                        }
                        mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
                    } else if (!mIsOverflow && isShortcutBubble) {
                        ProtoLog.v(WM_SHELL_BUBBLES, "startingShortcutBubble=%s", getBubbleKey());
                        if (mBubble.isChat()) {
                            options.setLaunchedFromBubble(true);
                            options.setApplyActivityFlagsForBubbles(true);
                        } else {
                            final WindowContainerToken rootToken =
                                    mManager.getAppBubbleRootTaskToken();
                            if (rootToken != null) {
                                options.setLaunchRootTask(rootToken);
                            } else {
                                options.setLaunchNextToBubble(true /* launchNextToBubble */);
                            }
                            options.setApplyMultipleTaskFlagForShortcut(true);
                        }
                        mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
Loading