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

Commit 165b7d6f authored by Chris Li's avatar Chris Li
Browse files

Add WCT to disable Task to enter PiP

PiP and Bubble provide a similar UX for putting a Task on the side, so
we want to disable PiP if the Task is already in Bubble.

Bug: 389158353
Flag: com.android.window.flags.disallow_bubble_to_enter_pip
Test: atest WmTests:WindowContainerTransactionTests
Test: atest WmTests:ActivityTaskManagerServiceTests
Change-Id: I386a31512ab00a4562ba2a9703273ee0968bbe77
parent 63157f31
Loading
Loading
Loading
Loading
+53 −16
Original line number Diff line number Diff line
@@ -351,20 +351,6 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * Used in conjunction with a shell-transition call (usually finishTransition). This is
     * basically a message to the transition system that a particular task should NOT go into
     * PIP even though it normally would. This is to deal with some edge-case situations where
     * Recents will "commit" the transition to go home, but then not actually go-home.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction setDoNotPip(@NonNull WindowContainerToken container) {
        final Change chg = getOrCreateChange(container.asBinder());
        chg.mChangeMask |= Change.CHANGE_FORCE_NO_PIP;
        return this;
    }

    /**
     * Resizes a container by providing a bounds in its parent coordinate.
     * This is only used by {@link TaskFragmentOrganizer}.
@@ -913,6 +899,41 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * Used in conjunction with a shell-transition call (usually finishTransition). This is
     * basically a message to the transition system that a particular task should NOT go into
     * PIP even though it normally would. This is to deal with some edge-case situations where
     * Recents will "commit" the transition to go home, but then not actually go-home.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction setDoNotPip(@NonNull WindowContainerToken container) {
        final Change chg = getOrCreateChange(container.asBinder());
        chg.mChangeMask |= Change.CHANGE_FORCE_NO_PIP;
        return this;
    }

    /**
     * Sets whether a Task or any of its children can enter picture-in-picture.
     * When {@code false}, the container and its children won't be able to enter PiP.
     *
     * Note: this is different from {@link #setDoNotPip}, which is to temporarily disable PiP during
     * finishTransition.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction setDisablePip(
            @NonNull WindowContainerToken container, boolean disablePip) {
        if (!Flags.disallowBubbleToEnterPip()) {
            throw new IllegalStateException(
                    "Flag " + Flags.FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP + " is not enabled");
        }
        final Change chg = getOrCreateChange(container.asBinder());
        chg.mChangeMask |= Change.CHANGE_DISABLE_PIP;
        chg.mDisablePip = disablePip;
        return this;
    }

    /*
     * ===========================================================================================
     * Insets
@@ -1355,6 +1376,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int CHANGE_RELATIVE_BOUNDS = 1 << 8;
        public static final int CHANGE_FORCE_EXCLUDED_FROM_RECENTS = 1 << 9;
        public static final int CHANGE_LAUNCH_NEXT_TO_BUBBLE = 1 << 10;
        public static final int CHANGE_DISABLE_PIP = 1 << 11;

        @IntDef(flag = true, prefix = { "CHANGE_" }, value = {
                CHANGE_FOCUSABLE,
@@ -1368,6 +1390,7 @@ public final class WindowContainerTransaction implements Parcelable {
                CHANGE_RELATIVE_BOUNDS,
                CHANGE_FORCE_EXCLUDED_FROM_RECENTS,
                CHANGE_LAUNCH_NEXT_TO_BUBBLE,
                CHANGE_DISABLE_PIP,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface ChangeMask {}
@@ -1379,6 +1402,7 @@ public final class WindowContainerTransaction implements Parcelable {
        private boolean mForceTranslucent = false;
        private boolean mDragResizing = false;
        private boolean mForceExcludedFromRecents = false;
        private boolean mDisablePip = false;

        private @ChangeMask int mChangeMask = 0;
        private @ActivityInfo.Config int mConfigSetMask = 0;
@@ -1404,6 +1428,8 @@ public final class WindowContainerTransaction implements Parcelable {
            mForceTranslucent = in.readBoolean();
            mDragResizing = in.readBoolean();
            mForceExcludedFromRecents = in.readBoolean();
            mLaunchNextToBubble = in.readBoolean();
            mDisablePip = in.readBoolean();
            mChangeMask = in.readInt();
            mConfigSetMask = in.readInt();
            mWindowSetMask = in.readInt();
@@ -1419,7 +1445,6 @@ public final class WindowContainerTransaction implements Parcelable {

            mWindowingMode = in.readInt();
            mActivityWindowingMode = in.readInt();
            mLaunchNextToBubble = in.readBoolean();
        }

        /**
@@ -1456,6 +1481,9 @@ public final class WindowContainerTransaction implements Parcelable {
            if ((other.mChangeMask & CHANGE_LAUNCH_NEXT_TO_BUBBLE) != 0) {
                mLaunchNextToBubble = other.mLaunchNextToBubble;
            }
            if ((other.mChangeMask & CHANGE_DISABLE_PIP) != 0) {
                mDisablePip = other.mDisablePip;
            }
            mChangeMask |= other.mChangeMask;
            if (other.mActivityWindowingMode >= WINDOWING_MODE_UNDEFINED) {
                mActivityWindowingMode = other.mActivityWindowingMode;
@@ -1546,6 +1574,11 @@ public final class WindowContainerTransaction implements Parcelable {
            return mForceExcludedFromRecents;
        }

        /** Gets whether the task is disabled to enter picture-in-picture. */
        public boolean getDisablePip() {
            return mDisablePip;
        }

        /** Gets whether the config should be sent to the client at the end of the transition. */
        public boolean getConfigAtTransitionEnd() {
            return mConfigAtTransitionEnd;
@@ -1619,6 +1652,9 @@ public final class WindowContainerTransaction implements Parcelable {
            if ((mChangeMask & CHANGE_FORCE_EXCLUDED_FROM_RECENTS) != 0) {
                sb.append("forceExcludedFromRecents:" + mForceExcludedFromRecents + ",");
            }
            if ((mChangeMask & CHANGE_DISABLE_PIP) != 0) {
                sb.append("disablePip:" + mDisablePip + ",");
            }
            if (mBoundsChangeTransaction != null) {
                sb.append("hasBoundsTransaction,");
            }
@@ -1647,6 +1683,8 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeBoolean(mForceTranslucent);
            dest.writeBoolean(mDragResizing);
            dest.writeBoolean(mForceExcludedFromRecents);
            dest.writeBoolean(mLaunchNextToBubble);
            dest.writeBoolean(mDisablePip);
            dest.writeInt(mChangeMask);
            dest.writeInt(mConfigSetMask);
            dest.writeInt(mWindowSetMask);
@@ -1661,7 +1699,6 @@ public final class WindowContainerTransaction implements Parcelable {

            dest.writeInt(mWindowingMode);
            dest.writeInt(mActivityWindowingMode);
            dest.writeBoolean(mLaunchNextToBubble);
        }

        @Override
+11 −0
Original line number Diff line number Diff line
@@ -221,3 +221,14 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "windowing_sdk"
    name: "disallow_bubble_to_enter_pip"
    description: "Prevent Bubble task to enter picture-in-picture"
    bug: "389158353"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -3190,6 +3190,14 @@ final class ActivityRecord extends WindowToken {
                && info.supportsPictureInPicture();
    }

    /**
     * Whether this activity can enter PiP now. This can be {@code false} if the system has disabled
     * this Task from entering PiP.
     */
    boolean canEnterPictureInPicture() {
        return supportsPictureInPicture() && (task == null || !task.isDisablePip());
    }

    boolean supportsFreeform() {
        return supportsFreeformInDisplayArea(getDisplayArea());
    }
@@ -3252,7 +3260,7 @@ final class ActivityRecord extends WindowToken {
     * @return whether this activity is currently allowed to enter PIP.
     */
    boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
        if (!supportsPictureInPicture()) {
        if (!canEnterPictureInPicture()) {
            return false;
        }

+38 −0
Original line number Diff line number Diff line
@@ -634,6 +634,9 @@ class Task extends TaskFragment {
    /** @see #isForceExcludedFromRecents() */
    private boolean mForceExcludedFromRecents;

    /** @see #isDisablePip() */
    private boolean mDisablePip;

    private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
            Intent _affinityIntent, String _affinity, String _rootAffinity,
            ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
@@ -4606,6 +4609,35 @@ class Task extends TaskFragment {
        mForceExcludedFromRecents = excluded;
    }

    /**
     * Whether this Task and its children are disallowed from entering picture-in-picture.
     *
     * This is different from {@link #mSupportsPictureInPicture} which is determined based on the
     * activity manifest. This flag is set by WM Shell to disable PiP for the current Task status.
     */
    boolean isDisablePip() {
        if (!Flags.disallowBubbleToEnterPip()) {
            return false;
        }
        if (mDisablePip) {
            return true;
        }
        // Check if PIP is disabled on any parent Task.
        final WindowContainer parent = getParent();
        if (parent != null && parent.asTask() != null) {
            return parent.asTask().isDisablePip();
        }
        return false;
    }

    void setDisablePip(boolean disablePip) {
        if (!Flags.disallowBubbleToEnterPip()) {
            Slog.w(TAG, "Flag " + Flags.FLAG_DISALLOW_BUBBLE_TO_ENTER_PIP + " is not enabled");
            return;
        }
        mDisablePip = disablePip;
    }

    boolean isForceHiddenForPinnedTask() {
        return (mForceHiddenFlags & FLAG_FORCE_HIDDEN_FOR_PINNED_TASK) != 0;
    }
@@ -5392,6 +5424,9 @@ class Task extends TaskFragment {
        }
        final ActivityRecord[] candidate = new ActivityRecord[1];
        topTask.forAllLeafTaskFragments(tf -> {
            if (tf.getTask().isDisablePip()) {
                return false;
            }
            // Find the top activity that may enter Pip while pausing.
            final ActivityRecord topActivity = tf.getTopNonFinishingActivity();
            if (topActivity != null && topActivity.isState(RESUMED, PAUSING)
@@ -5970,6 +6005,9 @@ class Task extends TaskFragment {
        if (mLaunchNextToBubble) {
            pw.println(prefix + "  mLaunchNextToBubble=true");
        }
        if (mDisablePip) {
            pw.println(prefix + "  mDisablePip=true");
        }
        if (mLastNonFullscreenBounds != null) {
            pw.print(prefix); pw.print("  mLastNonFullscreenBounds=");
            pw.println(mLastNonFullscreenBounds);
+2 −1
Original line number Diff line number Diff line
@@ -1383,9 +1383,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
                        // it can be moved to a new created PIP Task, so WINDOWING_MODE_PINNED is
                        // always valid for Task as long as the device supports it.
                        || (windowingMode == WINDOWING_MODE_PINNED && supportsPip);
                supportsPip &= !task.isDisablePip();
            } else if (r != null) {
                supportsFreeform = r.supportsFreeformInDisplayArea(this);
                supportsPip = r.supportsPictureInPicture();
                supportsPip = r.canEnterPictureInPicture();
                supportsMultiWindow = r.supportsMultiWindowInDisplayArea(this);
            }
        }
Loading