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

Commit 4706a5c6 authored by Chris Li's avatar Chris Li Committed by Android (Google) Code Review
Browse files

Merge "Fix ActivityEmbedding placeholder launching above fullscreen activity" into tm-qpr-dev

parents 0e7cbb04 7ed3a9c3
Loading
Loading
Loading
Loading
+58 −8
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WindowingMode;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.Rect;
import android.os.IBinder;
@@ -57,14 +58,33 @@ public final class TaskFragmentCreationParams implements Parcelable {

    /** The initial windowing mode of the TaskFragment. Inherits from parent if not set. */
    @WindowingMode
    private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
    private final int mWindowingMode;

    /**
     * The fragment token of the paired primary TaskFragment.
     * When it is set, the new TaskFragment will be positioned right above the paired TaskFragment.
     * Otherwise, the new TaskFragment will be positioned on the top of the Task by default.
     *
     * This is different from {@link WindowContainerTransaction#setAdjacentTaskFragments} as we may
     * set this when the pair of TaskFragments are stacked, while adjacent is only set on the pair
     * of TaskFragments that are in split.
     *
     * This is needed in case we need to launch a placeholder Activity to split below a transparent
     * always-expand Activity.
     */
    @Nullable
    private final IBinder mPairedPrimaryFragmentToken;

    private TaskFragmentCreationParams(
            @NonNull TaskFragmentOrganizerToken organizer,
            @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
            @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
            @NonNull IBinder ownerToken, @NonNull Rect initialBounds,
            @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken) {
        mOrganizer = organizer;
        mFragmentToken = fragmentToken;
        mOwnerToken = ownerToken;
        mInitialBounds.set(initialBounds);
        mWindowingMode = windowingMode;
        mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
    }

    @NonNull
@@ -92,12 +112,22 @@ public final class TaskFragmentCreationParams implements Parcelable {
        return mWindowingMode;
    }

    /**
     * TODO(b/232476698): remove the hide with adding CTS for this in next release.
     * @hide
     */
    @Nullable
    public IBinder getPairedPrimaryFragmentToken() {
        return mPairedPrimaryFragmentToken;
    }

    private TaskFragmentCreationParams(Parcel in) {
        mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
        mFragmentToken = in.readStrongBinder();
        mOwnerToken = in.readStrongBinder();
        mInitialBounds.readFromParcel(in);
        mWindowingMode = in.readInt();
        mPairedPrimaryFragmentToken = in.readStrongBinder();
    }

    /** @hide */
@@ -108,6 +138,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
        dest.writeStrongBinder(mOwnerToken);
        mInitialBounds.writeToParcel(dest, flags);
        dest.writeInt(mWindowingMode);
        dest.writeStrongBinder(mPairedPrimaryFragmentToken);
    }

    @NonNull
@@ -132,6 +163,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
                + " ownerToken=" + mOwnerToken
                + " initialBounds=" + mInitialBounds
                + " windowingMode=" + mWindowingMode
                + " pairedFragmentToken=" + mPairedPrimaryFragmentToken
                + "}";
    }

@@ -159,6 +191,9 @@ public final class TaskFragmentCreationParams implements Parcelable {
        @WindowingMode
        private int mWindowingMode = WINDOWING_MODE_UNDEFINED;

        @Nullable
        private IBinder mPairedPrimaryFragmentToken;

        public Builder(@NonNull TaskFragmentOrganizerToken organizer,
                @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
            mOrganizer = organizer;
@@ -180,14 +215,29 @@ public final class TaskFragmentCreationParams implements Parcelable {
            return this;
        }

        /**
         * Sets the fragment token of the paired primary TaskFragment.
         * When it is set, the new TaskFragment will be positioned right above the paired
         * TaskFragment. Otherwise, the new TaskFragment will be positioned on the top of the Task
         * by default.
         *
         * This is needed in case we need to launch a placeholder Activity to split below a
         * transparent always-expand Activity.
         *
         * TODO(b/232476698): remove the hide with adding CTS for this in next release.
         * @hide
         */
        @NonNull
        public Builder setPairedPrimaryFragmentToken(@Nullable IBinder fragmentToken) {
            mPairedPrimaryFragmentToken = fragmentToken;
            return this;
        }

        /** Constructs the options to create TaskFragment with. */
        @NonNull
        public TaskFragmentCreationParams build() {
            final TaskFragmentCreationParams result = new TaskFragmentCreationParams(
                    mOrganizer, mFragmentToken, mOwnerToken);
            result.mInitialBounds.set(mInitialBounds);
            result.mWindowingMode = mWindowingMode;
            return result;
            return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
                    mInitialBounds, mWindowingMode, mPairedPrimaryFragmentToken);
        }
    }
}
+27 −32
Original line number Diff line number Diff line
@@ -133,8 +133,18 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
        }

        // Create a TaskFragment for the secondary activity.
        createTaskFragmentAndStartActivity(wct, secondaryFragmentToken, ownerToken,
                secondaryFragmentBounds, windowingMode, activityIntent,
        final TaskFragmentCreationParams fragmentOptions = new TaskFragmentCreationParams.Builder(
                getOrganizerToken(), secondaryFragmentToken, ownerToken)
                .setInitialBounds(secondaryFragmentBounds)
                .setWindowingMode(windowingMode)
                // Make sure to set the paired fragment token so that the new TaskFragment will be
                // positioned right above the paired TaskFragment.
                // This is needed in case we need to launch a placeholder Activity to split below a
                // transparent always-expand Activity.
                .setPairedPrimaryFragmentToken(launchingFragmentToken)
                .build();
        createTaskFragment(wct, fragmentOptions);
        wct.startActivityInTaskFragment(secondaryFragmentToken, ownerToken, activityIntent,
                activityOptions);

        // Set adjacent to each other so that the containers below will be invisible.
@@ -173,8 +183,21 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
     */
    void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
            @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
        final TaskFragmentCreationParams fragmentOptions =
                createFragmentOptions(fragmentToken, ownerToken, bounds, windowingMode);
        final TaskFragmentCreationParams fragmentOptions = new TaskFragmentCreationParams.Builder(
                getOrganizerToken(), fragmentToken, ownerToken)
                .setInitialBounds(bounds)
                .setWindowingMode(windowingMode)
                .build();
        createTaskFragment(wct, fragmentOptions);
    }

    void createTaskFragment(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentCreationParams fragmentOptions) {
        if (mFragmentInfos.containsKey(fragmentOptions.getFragmentToken())) {
            throw new IllegalArgumentException(
                    "There is an existing TaskFragment with fragmentToken="
                            + fragmentOptions.getFragmentToken());
        }
        wct.createTaskFragment(fragmentOptions);
    }

@@ -189,18 +212,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
        wct.reparentActivityToTaskFragment(fragmentToken, activity.getActivityToken());
    }

    /**
     * @param ownerToken The token of the activity that creates this task fragment. It does not
     *                   have to be a child of this task fragment, but must belong to the same task.
     */
    private void createTaskFragmentAndStartActivity(@NonNull WindowContainerTransaction wct,
            @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect bounds,
            @WindowingMode int windowingMode, @NonNull Intent activityIntent,
            @Nullable Bundle activityOptions) {
        createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
        wct.startActivityInTaskFragment(fragmentToken, ownerToken, activityIntent, activityOptions);
    }

    void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
            @NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
        WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
@@ -238,22 +249,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
        wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
    }

    TaskFragmentCreationParams createFragmentOptions(@NonNull IBinder fragmentToken,
            @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
        if (mFragmentInfos.containsKey(fragmentToken)) {
            throw new IllegalArgumentException(
                    "There is an existing TaskFragment with fragmentToken=" + fragmentToken);
        }

        return new TaskFragmentCreationParams.Builder(
                getOrganizerToken(),
                fragmentToken,
                ownerToken)
                .setInitialBounds(bounds)
                .setWindowingMode(windowingMode)
                .build();
    }

    void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
            @Nullable Rect bounds) {
        if (!mFragmentInfos.containsKey(fragmentToken)) {
+7 −4
Original line number Diff line number Diff line
@@ -1218,14 +1218,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity,
            @NonNull Activity activityInTask, int taskId) {
        return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
                activityInTask, taskId);
                activityInTask, taskId, null /* pairedPrimaryContainer */);
    }

    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
            @NonNull Activity activityInTask, int taskId) {
        return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
                activityInTask, taskId);
                activityInTask, taskId, null /* pairedPrimaryContainer */);
    }

    /**
@@ -1237,10 +1237,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     * @param activityInTask            activity in the same Task so that we can get the Task bounds
     *                                  if needed.
     * @param taskId                    parent Task of the new TaskFragment.
     * @param pairedPrimaryContainer    the paired primary {@link TaskFragmentContainer}. When it is
     *                                  set, the new container will be added right above it.
     */
    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
            @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId) {
            @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId,
            @Nullable TaskFragmentContainer pairedPrimaryContainer) {
        if (activityInTask == null) {
            throw new IllegalArgumentException("activityInTask must not be null,");
        }
@@ -1249,7 +1252,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        }
        final TaskContainer taskContainer = mTaskContainers.get(taskId);
        final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
                pendingAppearedIntent, taskContainer, this);
                pendingAppearedIntent, taskContainer, this, pairedPrimaryContainer);
        return container;
    }

+15 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.util.Size;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.window.TaskFragmentCreationParams;
import android.window.WindowContainerTransaction;

import androidx.annotation.GuardedBy;
@@ -307,10 +308,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        }

        final int taskId = primaryContainer.getTaskId();
        final TaskFragmentContainer secondaryContainer = mController.newContainer(activityIntent,
                launchingActivity, taskId);
        final int windowingMode = mController.getTaskContainer(taskId)
                .getWindowingModeForSplitTaskFragment(primaryRectBounds);
        final TaskFragmentContainer secondaryContainer = mController.newContainer(
                null /* pendingAppearedActivity */, activityIntent, launchingActivity, taskId,
                // Pass in the primary container to make sure it is added right above the primary.
                primaryContainer);
        final TaskContainer taskContainer = mController.getTaskContainer(taskId);
        final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
                primaryRectBounds);
        mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
                rule, splitAttributes);
        startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
@@ -412,17 +416,18 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
    }

    @Override
    void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
            @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
        final TaskFragmentContainer container = mController.getContainer(fragmentToken);
    void createTaskFragment(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentCreationParams fragmentOptions) {
        final TaskFragmentContainer container = mController.getContainer(
                fragmentOptions.getFragmentToken());
        if (container == null) {
            throw new IllegalStateException(
                    "Creating a task fragment that is not registered with controller.");
        }

        container.setLastRequestedBounds(bounds);
        container.setLastRequestedWindowingMode(windowingMode);
        super.createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
        container.setLastRequestedBounds(fragmentOptions.getInitialBounds());
        container.setLastRequestedWindowingMode(fragmentOptions.getWindowingMode());
        super.createTaskFragment(wct, fragmentOptions);
    }

    @Override
+13 −2
Original line number Diff line number Diff line
@@ -118,10 +118,12 @@ class TaskFragmentContainer {
    /**
     * Creates a container with an existing activity that will be re-parented to it in a window
     * container transaction.
     * @param pairedPrimaryContainer    when it is set, the new container will be add right above it
     */
    TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
            @Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
            @NonNull SplitController controller) {
            @NonNull SplitController controller,
            @Nullable TaskFragmentContainer pairedPrimaryContainer) {
        if ((pendingAppearedActivity == null && pendingAppearedIntent == null)
                || (pendingAppearedActivity != null && pendingAppearedIntent != null)) {
            throw new IllegalArgumentException(
@@ -130,7 +132,16 @@ class TaskFragmentContainer {
        mController = controller;
        mToken = new Binder("TaskFragmentContainer");
        mTaskContainer = taskContainer;
        if (pairedPrimaryContainer != null) {
            if (pairedPrimaryContainer.getTaskContainer() != taskContainer) {
                throw new IllegalArgumentException(
                        "pairedPrimaryContainer must be in the same Task");
            }
            final int primaryIndex = taskContainer.mContainers.indexOf(pairedPrimaryContainer);
            taskContainer.mContainers.add(primaryIndex + 1, this);
        } else {
            taskContainer.mContainers.add(this);
        }
        if (pendingAppearedActivity != null) {
            addPendingAppearedActivity(pendingAppearedActivity);
        }
Loading