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

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

Merge "Cleanup TaskFragmentOrganizer#applyTransaction"

parents e1be0c9e 55e086c2
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -3433,14 +3433,20 @@ package android.window {

  public class TaskFragmentOrganizer extends android.window.WindowOrganizer {
    ctor public TaskFragmentOrganizer(@NonNull java.util.concurrent.Executor);
    method public void applyTransaction(@NonNull android.window.WindowContainerTransaction, int, boolean);
    method @NonNull public java.util.concurrent.Executor getExecutor();
    method @NonNull public android.window.TaskFragmentOrganizerToken getOrganizerToken();
    method public void onTransactionHandled(@NonNull android.os.IBinder, @NonNull android.window.WindowContainerTransaction, int, boolean);
    method public void onTransactionReady(@NonNull android.window.TaskFragmentTransaction);
    method @CallSuper public void registerOrganizer();
    method @CallSuper public void unregisterOrganizer();
    field public static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";
    field public static final String KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO = "task_fragment_info";
    field public static final String KEY_ERROR_CALLBACK_THROWABLE = "fragment_throwable";
    field public static final int TASK_FRAGMENT_TRANSIT_CHANGE = 6; // 0x6
    field public static final int TASK_FRAGMENT_TRANSIT_CLOSE = 2; // 0x2
    field public static final int TASK_FRAGMENT_TRANSIT_NONE = 0; // 0x0
    field public static final int TASK_FRAGMENT_TRANSIT_OPEN = 1; // 0x1
  }

  public final class TaskFragmentOrganizerToken implements android.os.Parcelable {
@@ -3562,8 +3568,8 @@ package android.window {

  public class WindowOrganizer {
    ctor public WindowOrganizer();
    method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
    method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public void applyTransaction(@NonNull android.window.WindowContainerTransaction);
    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void applyTransaction(@NonNull android.window.WindowContainerTransaction);
  }

  @UiContext public abstract class WindowProviderService extends android.app.Service {
+56 −60
Original line number Diff line number Diff line
@@ -20,22 +20,20 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;

import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.WindowConfiguration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;

import java.util.List;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;

/**
@@ -62,6 +60,52 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
     */
    public static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";

    /**
     * No change set.
     */
    @WindowManager.TransitionType
    @TaskFragmentTransitionType
    public static final int TASK_FRAGMENT_TRANSIT_NONE = TRANSIT_NONE;

    /**
     * A window that didn't exist before has been created and made visible.
     */
    @WindowManager.TransitionType
    @TaskFragmentTransitionType
    public static final int TASK_FRAGMENT_TRANSIT_OPEN = TRANSIT_OPEN;

    /**
     * A window that was visible no-longer exists (was finished or destroyed).
     */
    @WindowManager.TransitionType
    @TaskFragmentTransitionType
    public static final int TASK_FRAGMENT_TRANSIT_CLOSE = TRANSIT_CLOSE;

    /**
     * A window is visible before and after but changes in some way (eg. it resizes or changes
     * windowing-mode).
     */
    @WindowManager.TransitionType
    @TaskFragmentTransitionType
    public static final int TASK_FRAGMENT_TRANSIT_CHANGE = TRANSIT_CHANGE;

    /**
     * Introduced a sub set of {@link WindowManager.TransitionType} for the types that are used for
     * TaskFragment transition.
     *
     * Doing this instead of exposing {@link WindowManager.TransitionType} because we want to keep
     * the Shell transition API hidden until it comes fully stable.
     * @hide
     */
    @IntDef(prefix = { "TASK_FRAGMENT_TRANSIT_" }, value = {
            TASK_FRAGMENT_TRANSIT_NONE,
            TASK_FRAGMENT_TRANSIT_OPEN,
            TASK_FRAGMENT_TRANSIT_CLOSE,
            TASK_FRAGMENT_TRANSIT_CHANGE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TaskFragmentTransitionType {}

    /**
     * Creates a {@link Bundle} with an exception, operation type and TaskFragmentInfo (if any)
     * that can be passed to {@link ITaskFragmentOrganizer#onTaskFragmentError}.
@@ -155,7 +199,7 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
     *                          {@link #onTransactionReady(TaskFragmentTransaction)}
     * @param wct               {@link WindowContainerTransaction} that the server should apply for
     *                          update of the transaction.
     * @param transitionType    {@link WindowManager.TransitionType} if it needs to start a
     * @param transitionType    {@link TaskFragmentTransitionType} if it needs to start a
     *                          transition.
     * @param shouldApplyIndependently  If {@code true}, the {@code wct} will request a new
     *                                  transition, which will be queued until the sync engine is
@@ -163,11 +207,10 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
     *                                  the {@code wct} will be directly applied to the active sync.
     * @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
     * for permission enforcement.
     * @hide
     */
    public void onTransactionHandled(@NonNull IBinder transactionToken,
            @NonNull WindowContainerTransaction wct,
            @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
            @TaskFragmentTransitionType int transitionType, boolean shouldApplyIndependently) {
        wct.setTaskFragmentOrganizer(mInterface);
        try {
            getController().onTransactionHandled(transactionToken, wct, transitionType,
@@ -178,22 +221,19 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
    }

    /**
     * Routes to {@link ITaskFragmentOrganizerController#applyTransaction} instead of
     * {@link IWindowOrganizerController#applyTransaction} for the different transition options.
     *
     * Must use {@link #applyTransaction(WindowContainerTransaction, int, boolean)} instead.
     * @see #applyTransaction(WindowContainerTransaction, int, boolean)
     */
    @Override
    public void applyTransaction(@NonNull WindowContainerTransaction wct) {
        // TODO(b/207070762) doing so to keep CTS compatibility. Remove in the next release.
        applyTransaction(wct, getTransitionType(wct), false /* shouldApplyIndependently */);
        throw new RuntimeException("Not allowed!");
    }

    /**
     * Requests the server to apply the given {@link WindowContainerTransaction}.
     *
     * @param wct   {@link WindowContainerTransaction} to apply.
     * @param transitionType    {@link WindowManager.TransitionType} if it needs to start a
     * @param transitionType    {@link TaskFragmentTransitionType} if it needs to start a
     *                          transition.
     * @param shouldApplyIndependently  If {@code true}, the {@code wct} will request a new
     *                                  transition, which will be queued until the sync engine is
@@ -201,10 +241,9 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
     *                                  the {@code wct} will be directly applied to the active sync.
     * @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
     * for permission enforcement.
     * @hide
     */
    public void applyTransaction(@NonNull WindowContainerTransaction wct,
            @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
            @TaskFragmentTransitionType int transitionType, boolean shouldApplyIndependently) {
        if (wct.isEmpty()) {
            return;
        }
@@ -216,49 +255,6 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
        }
    }

    /**
     * Gets the default {@link WindowManager.TransitionType} based on the requested
     * {@link WindowContainerTransaction}.
     * @hide
     */
    // TODO(b/207070762): let Extensions to set the transition type instead.
    @WindowManager.TransitionType
    public static int getTransitionType(@NonNull WindowContainerTransaction wct) {
        if (wct.isEmpty()) {
            return TRANSIT_NONE;
        }
        for (WindowContainerTransaction.Change change : wct.getChanges().values()) {
            if ((change.getWindowSetMask() & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0) {
                // Treat as TRANSIT_CHANGE when there is TaskFragment resizing.
                return TRANSIT_CHANGE;
            }
        }
        boolean containsCreatingTaskFragment = false;
        boolean containsDeleteTaskFragment = false;
        final List<WindowContainerTransaction.HierarchyOp> ops = wct.getHierarchyOps();
        for (int i = ops.size() - 1; i >= 0; i--) {
            final int type = ops.get(i).getType();
            if (type == HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT) {
                // Treat as TRANSIT_CHANGE when there is activity reparent.
                return TRANSIT_CHANGE;
            }
            if (type == HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT) {
                containsCreatingTaskFragment = true;
            } else if (type == HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT) {
                containsDeleteTaskFragment = true;
            }
        }
        if (containsCreatingTaskFragment) {
            return TRANSIT_OPEN;
        }
        if (containsDeleteTaskFragment) {
            return TRANSIT_CLOSE;
        }

        // Use TRANSIT_CHANGE as default.
        return TRANSIT_CHANGE;
    }

    /**
     * Called when the transaction is ready so that the organizer can update the TaskFragments based
     * on the changes in transaction.
@@ -266,7 +262,7 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
    public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
        // Notify the server to finish the transaction.
        onTransactionHandled(transaction.getTransactionToken(), new WindowContainerTransaction(),
                TRANSIT_NONE, false /* shouldApplyIndependently */);
                TASK_FRAGMENT_TRANSIT_NONE, false /* shouldApplyIndependently */);
    }

    private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
+4 −10
Original line number Diff line number Diff line
@@ -40,14 +40,11 @@ public class WindowOrganizer {
     * Apply multiple WindowContainer operations at once.
     *
     * Note that using this API requires the caller to hold
     * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using
     * {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
     * created by itself.
     * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
     *
     * @param t The transaction to apply.
     */
    @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
            conditional = true)
    @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
    public void applyTransaction(@NonNull WindowContainerTransaction t) {
        try {
            if (!t.isEmpty()) {
@@ -62,9 +59,7 @@ public class WindowOrganizer {
     * Apply multiple WindowContainer operations at once.
     *
     * Note that using this API requires the caller to hold
     * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using
     * {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
     * created by itself.
     * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
     *
     * @param t The transaction to apply.
     * @param callback This transaction will use the synchronization scheme described in
@@ -73,8 +68,7 @@ public class WindowOrganizer {
     * @return An ID for the sync operation which will later be passed to transactionReady callback.
     *         This lets the caller differentiate overlapping sync operations.
     */
    @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
            conditional = true)
    @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
    public int applySyncTransaction(@NonNull WindowContainerTransaction t,
            @NonNull WindowContainerTransactionCallback callback) {
        try {
+22 −12
Original line number Diff line number Diff line
@@ -20,11 +20,11 @@ import static android.app.ActivityManager.START_SUCCESS;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CLOSE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_OPEN;
import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
@@ -340,7 +340,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen

        container.setInfo(wct, taskFragmentInfo);
        if (container.isFinished()) {
            mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
            mTransactionManager.getCurrentTransactionRecord()
                    .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
            mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
        } else {
            // Update with the latest Task configuration.
@@ -376,22 +377,27 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                // Do not finish the dependents if the last activity is reparented to PiP.
                // Instead, the original split should be cleanup, and the dependent may be
                // expanded to fullscreen.
                mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
                mTransactionManager.getCurrentTransactionRecord()
                        .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
                cleanupForEnterPip(wct, container);
                mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
            } else if (taskFragmentInfo.isTaskClearedForReuse()) {
                // Do not finish the dependents if this TaskFragment was cleared due to
                // launching activity in the Task.
                mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
                mTransactionManager.getCurrentTransactionRecord()
                        .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
                mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
            } else if (taskFragmentInfo.isClearedForReorderActivityToFront()) {
                // Do not finish the dependents if this TaskFragment was cleared to reorder
                // the launching Activity to front of the Task.
                mTransactionManager.getCurrentTransactionRecord()
                        .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
                mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
            } else if (!container.isWaitingActivityAppear()) {
                // Do not finish the container before the expected activity appear until
                // timeout.
                mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
                mTransactionManager.getCurrentTransactionRecord()
                        .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
                mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */);
            }
        } else if (wasInPip && isInPip) {
@@ -585,7 +591,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                container.setInfo(wct, taskFragmentInfo);
                container.clearPendingAppearedActivities();
                if (container.isEmpty()) {
                    mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
                    mTransactionManager.getCurrentTransactionRecord()
                            .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
                    mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
                }
                break;
@@ -1000,7 +1007,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    @GuardedBy("mLock")
    void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container) {
        mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
        mTransactionManager.getCurrentTransactionRecord()
                .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
        mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
    }

@@ -1566,7 +1574,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        // (not resumed yet).
        if (isOnCreated || primaryActivity.isResumed()) {
            // Only set trigger type if the launch happens in foreground.
            mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_OPEN);
            mTransactionManager.getCurrentTransactionRecord()
                    .setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
            return null;
        }
        final ActivityOptions options = ActivityOptions.makeBasic();
@@ -1594,7 +1603,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            return false;
        }

        mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE);
        mTransactionManager.getCurrentTransactionRecord()
                .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
        mPresenter.cleanupContainer(wct, splitContainer.getSecondaryContainer(),
                false /* shouldFinishDependent */);
        return true;
@@ -1894,7 +1904,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            synchronized (mLock) {
                final TransactionRecord transactionRecord = mTransactionManager
                        .startNewTransaction();
                transactionRecord.setOriginType(TRANSIT_OPEN);
                transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
                SplitController.this.onActivityCreated(transactionRecord.getTransaction(),
                        activity);
                // The WCT should be applied and merged to the activity launch transition.
@@ -1983,7 +1993,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            synchronized (mLock) {
                final TransactionRecord transactionRecord = mTransactionManager
                        .startNewTransaction();
                transactionRecord.setOriginType(TRANSIT_OPEN);
                transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
                final WindowContainerTransaction wct = transactionRecord.getTransaction();
                final TaskFragmentContainer launchedInTaskFragment;
                if (launchingActivity != null) {
+15 −13
Original line number Diff line number Diff line
@@ -16,12 +16,12 @@

package androidx.window.extensions.embedding;

import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CHANGE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_NONE;

import android.os.IBinder;
import android.view.WindowManager.TransitionType;
import android.window.TaskFragmentOrganizer;
import android.window.TaskFragmentOrganizer.TaskFragmentTransitionType;
import android.window.WindowContainerTransaction;

import androidx.annotation.NonNull;
@@ -122,8 +122,8 @@ class TransactionManager {
         * @see #setOriginType(int)
         * @see #getTransactionTransitionType()
         */
        @TransitionType
        private int mOriginType = TRANSIT_NONE;
        @TaskFragmentTransitionType
        private int mOriginType = TASK_FRAGMENT_TRANSIT_NONE;

        TransactionRecord(@Nullable IBinder taskFragmentTransactionToken) {
            mTaskFragmentTransactionToken = taskFragmentTransactionToken;
@@ -136,12 +136,12 @@ class TransactionManager {
        }

        /**
         * Sets the {@link TransitionType} that triggers this transaction. If there are multiple
         * calls, only the first call will be respected as the "origin" type.
         * Sets the {@link TaskFragmentTransitionType} that triggers this transaction. If there are
         * multiple calls, only the first call will be respected as the "origin" type.
         */
        void setOriginType(@TransitionType int type) {
        void setOriginType(@TaskFragmentTransitionType int type) {
            ensureCurrentTransaction();
            if (mOriginType != TRANSIT_NONE) {
            if (mOriginType != TASK_FRAGMENT_TRANSIT_NONE) {
                // Skip if the origin type has already been set.
                return;
            }
@@ -188,14 +188,16 @@ class TransactionManager {
        }

        /**
         * Gets the {@link TransitionType} that we will request transition with for the
         * Gets the {@link TaskFragmentTransitionType} that we will request transition with for the
         * current {@link WindowContainerTransaction}.
         */
        @VisibleForTesting
        @TransitionType
        @TaskFragmentTransitionType
        int getTransactionTransitionType() {
            // Use TRANSIT_CHANGE as default if there is not opening/closing window.
            return mOriginType != TRANSIT_NONE ? mOriginType : TRANSIT_CHANGE;
            // Use TASK_FRAGMENT_TRANSIT_CHANGE as default if there is not opening/closing window.
            return mOriginType != TASK_FRAGMENT_TRANSIT_NONE
                    ? mOriginType
                    : TASK_FRAGMENT_TRANSIT_CHANGE;
        }
    }
}
Loading