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

Commit bc357abc authored by Chris Li's avatar Chris Li
Browse files

Reset embedded TaskFragment override when entering PIP

When an embedded activity is entering PIP when it is the only activity
in the Task, the whole Task will enter PIP.

When this happens, we want to reset all organizer override config so
that the activity will get the correct config. We don't want to remove
the TaskFragment because we can use it to get the windowing mode change
in organizer.

Besides that, we will disallow any further organizer override to the
TaskFragment in PIP.

Bug: 225371112
Test: atest WmTests:RootWindowContainerTests
Test: atest WmTests:TaskFragmentTest
Test: atest WmTests:TaskFragmentOrganizerControllerTest
Change-Id: I03bd679b77f7ed8a65ba5fc59723b83a4254442c
parent e87d07cc
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2481,6 +2481,12 @@ class ActivityStarter {
            if (inTaskFragment == null) {
                inTaskFragment = TaskFragment.fromTaskFragmentToken(
                        mOptions.getLaunchTaskFragmentToken(), mService);
                if (inTaskFragment != null && inTaskFragment.isEmbeddedTaskFragmentInPip()) {
                    // Do not start activity in TaskFragment in a PIP Task.
                    Slog.w(TAG, "Can not start activity in TaskFragment in PIP: "
                            + inTaskFragment);
                    inTaskFragment = null;
                }
            }
        }

+8 −3
Original line number Diff line number Diff line
@@ -190,6 +190,14 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
     * @see #mFullConfiguration
     */
    public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
        updateRequestedOverrideConfiguration(overrideConfiguration);
        // Update full configuration of this container and all its children.
        final ConfigurationContainer parent = getParent();
        onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);
    }

    /** Updates override configuration without recalculate full config. */
    void updateRequestedOverrideConfiguration(Configuration overrideConfiguration) {
        // Pre-compute this here, so we don't need to go through the entire Configuration when
        // writing to proto (which has significant cost if we write a lot of empty configurations).
        mHasOverrideConfiguration = !Configuration.EMPTY.equals(overrideConfiguration);
@@ -199,9 +207,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
                && diffRequestedOverrideMaxBounds(newBounds) != BOUNDS_CHANGE_NONE) {
            mRequestedOverrideConfiguration.windowConfiguration.setMaxBounds(newBounds);
        }
        // Update full configuration of this container and all its children.
        final ConfigurationContainer parent = getParent();
        onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);
    }

    /**
+12 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.res.Configuration.EMPTY;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -2005,7 +2006,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            // of the activity entering PIP
            r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);

            final boolean singleActivity = task.getChildCount() == 1;
            // TODO: Does it make sense to only count non-finishing activities?
            final boolean singleActivity = task.getActivityCount() == 1;
            if (singleActivity) {
                rootTask = task;

@@ -2081,6 +2083,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            // TODO(task-org): Figure-out more structured way to do this long term.
            r.setWindowingMode(intermediateWindowingMode);
            r.mWaitForEnteringPinnedMode = true;
            rootTask.forAllTaskFragments(tf -> {
                // When the Task is entering picture-in-picture, we should clear all override from
                // the client organizer, so the PIP activity can get the correct config from the
                // Task, and prevent conflict with the PipTaskOrganizer.
                if (tf.isOrganizedTaskFragment()) {
                    tf.resetAdjacentTaskFragment();
                    tf.updateRequestedOverrideConfiguration(EMPTY);
                }
            });
            rootTask.setWindowingMode(WINDOWING_MODE_PINNED);
            // Set the launch bounds for launch-into-pip Activity on the root task.
            if (r.getOptions() != null && r.getOptions().isLaunchIntoPip()) {
+8 −0
Original line number Diff line number Diff line
@@ -1380,6 +1380,14 @@ class Task extends TaskFragment {
        return getActivity(ActivityRecord::canBeTopRunning);
    }

    int getActivityCount() {
        final int[] activityCount = new int[1];
        forAllActivities(ar -> {
            activityCount[0]++;
        });
        return activityCount[0];
    }

    /**
     * Return true if any activities in this task belongs to input uid.
     */
+9 −1
Original line number Diff line number Diff line
@@ -339,7 +339,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        }
    }

    private void resetAdjacentTaskFragment() {
    void resetAdjacentTaskFragment() {
        // Reset the adjacent TaskFragment if its adjacent TaskFragment is also this TaskFragment.
        if (mAdjacentTaskFragment != null && mAdjacentTaskFragment.mAdjacentTaskFragment == this) {
            mAdjacentTaskFragment.mAdjacentTaskFragment = null;
@@ -2317,6 +2317,14 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        mMinHeight = minHeight;
    }

    /**
     * Whether this is an embedded TaskFragment in PIP Task. We don't allow any client config
     * override for such TaskFragment to prevent flight with PipTaskOrganizer.
     */
    boolean isEmbeddedTaskFragmentInPip() {
        return isOrganizedTaskFragment() && getTask() != null && getTask().inPinnedWindowingMode();
    }

    boolean shouldRemoveSelfOnLastChildRemoval() {
        return !mCreatedByOrganizer || mIsRemovalRequested;
    }
Loading