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

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

Merge "Add TaskFragmentOrganizer#applyTransaction with request transition" into tm-qpr-dev

parents ff778d20 dc7cb365
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -57,6 +57,12 @@ interface ITaskFragmentOrganizerController {
     * Notifies the server that the organizer has finished handling the given transaction. The
     * server should apply the given {@link WindowContainerTransaction} for the necessary changes.
     */
    void onTransactionHandled(in ITaskFragmentOrganizer organizer, in IBinder transactionToken,
        in WindowContainerTransaction wct);
    void onTransactionHandled(in IBinder transactionToken, in WindowContainerTransaction wct,
        int transitionType, boolean shouldApplyIndependently);

    /**
     * Requests the server to apply the given {@link WindowContainerTransaction}.
     */
    void applyTransaction(in WindowContainerTransaction wct, int transitionType,
        boolean shouldApplyIndependently);
}
+105 −20
Original line number Diff line number Diff line
@@ -16,17 +16,25 @@

package android.window;

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.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_INFO_CHANGED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_VANISHED;
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.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -34,6 +42,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.SparseArray;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;

import java.util.ArrayList;
import java.util.List;
@@ -168,20 +177,110 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
     *                          {@link #onTransactionReady(TaskFragmentTransaction)}
     * @param wct               {@link WindowContainerTransaction} that the server should apply for
     *                          update of the transaction.
     * @see com.android.server.wm.WindowOrganizerController#enforceTaskPermission for permission
     * requirement.
     * @param transitionType    {@link WindowManager.TransitionType} 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
     *                                  free if there is any other active sync. If {@code false},
     *                                  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) {
            @NonNull WindowContainerTransaction wct,
            @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
        wct.setTaskFragmentOrganizer(mInterface);
        try {
            getController().onTransactionHandled(mInterface, transactionToken, wct);
            getController().onTransactionHandled(transactionToken, wct, transitionType,
                    shouldApplyIndependently);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Routes to {@link ITaskFragmentOrganizerController#applyTransaction} instead of
     * {@link IWindowOrganizerController#applyTransaction} for the different transition options.
     *
     * @see #applyTransaction(WindowContainerTransaction, int, boolean, 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 */);
    }

    /**
     * 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
     *                          transition.
     * @param shouldApplyIndependently  If {@code true}, the {@code wct} will request a new
     *                                  transition, which will be queued until the sync engine is
     *                                  free if there is any other active sync. If {@code false},
     *                                  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) {
        if (wct.isEmpty()) {
            return;
        }
        wct.setTaskFragmentOrganizer(mInterface);
        try {
            getController().applyTransaction(wct, transitionType, shouldApplyIndependently);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * 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 a TaskFragment is created and organized by this organizer.
     *
@@ -424,22 +523,8 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
        }

        // Notify the server, and the server should apply the WindowContainerTransaction.
        onTransactionHandled(transaction.getTransactionToken(), wct);
    }

    @Override
    public void applyTransaction(@NonNull WindowContainerTransaction t) {
        t.setTaskFragmentOrganizer(mInterface);
        super.applyTransaction(t);
    }

    // Suppress the lint because it is not a registration method.
    @SuppressWarnings("ExecutorRegistration")
    @Override
    public int applySyncTransaction(@NonNull WindowContainerTransaction t,
            @NonNull WindowContainerTransactionCallback callback) {
        t.setTaskFragmentOrganizer(mInterface);
        return super.applySyncTransaction(t, callback);
        onTransactionHandled(transaction.getTransactionToken(), wct, getTransitionType(wct),
                false /* shouldApplyIndependently */);
    }

    private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
+2 −4
Original line number Diff line number Diff line
@@ -763,10 +763,8 @@ public final class WindowContainerTransaction implements Parcelable {
     * @hide
     */
    @NonNull
    WindowContainerTransaction setTaskFragmentOrganizer(@NonNull ITaskFragmentOrganizer organizer) {
        if (mTaskFragmentOrganizer != null) {
            throw new IllegalStateException("Can't set multiple organizers for one transaction.");
        }
    public WindowContainerTransaction setTaskFragmentOrganizer(
            @NonNull ITaskFragmentOrganizer organizer) {
        mTaskFragmentOrganizer = organizer;
        return this;
    }
+12 −0
Original line number Diff line number Diff line
@@ -1801,6 +1801,12 @@
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/Transition.java"
    },
    "-353495930": {
      "message": "TaskFragmentTransaction changes are not collected in transition because there is an ongoing sync for applySyncTransaction().",
      "level": "WARN",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/WindowOrganizerController.java"
    },
    "-347866078": {
      "message": "Setting move animation on %s",
      "level": "VERBOSE",
@@ -2491,6 +2497,12 @@
      "group": "WM_DEBUG_ANIM",
      "at": "com\/android\/server\/wm\/WindowState.java"
    },
    "286170861": {
      "message": "Creating Pending Transition for TaskFragment: %s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/WindowOrganizerController.java"
    },
    "288485303": {
      "message": "Attempted to set remove mode to a display that does not exist: %d",
      "level": "WARN",
+34 −14
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
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.getTransitionType;
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;
@@ -109,7 +110,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    private Consumer<List<SplitInfo>> mEmbeddingCallback;
    private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
    private final Handler mHandler;
    private final Object mLock = new Object();
    final Object mLock = new Object();
    private final ActivityStartMonitor mActivityStartMonitor;

    public SplitController() {
@@ -209,8 +210,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                }
            }

            // Notify the server, and the server should apply the WindowContainerTransaction.
            mPresenter.onTransactionHandled(transaction.getTransactionToken(), wct);
            // Notify the server, and the server should apply and merge the
            // WindowContainerTransaction to the active sync to finish the TaskFragmentTransaction.
            mPresenter.onTransactionHandled(transaction.getTransactionToken(), wct,
                    getTransitionType(wct), false /* shouldApplyIndependently */);
            updateCallbackIfNecessary();
        }
    }
@@ -221,6 +224,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     * @param wct   The {@link WindowContainerTransaction} to make any changes with if needed.
     * @param taskFragmentInfo  Info of the TaskFragment that is created.
     */
    // Suppress GuardedBy warning because lint ask to mark this method as
    // @GuardedBy(container.mController.mLock), which is mLock itself
    @SuppressWarnings("GuardedBy")
    @VisibleForTesting
    @GuardedBy("mLock")
    void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
@@ -245,6 +251,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     * @param wct   The {@link WindowContainerTransaction} to make any changes with if needed.
     * @param taskFragmentInfo  Info of the TaskFragment that is changed.
     */
    // Suppress GuardedBy warning because lint ask to mark this method as
    // @GuardedBy(container.mController.mLock), which is mLock itself
    @SuppressWarnings("GuardedBy")
    @VisibleForTesting
    @GuardedBy("mLock")
    void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
@@ -430,6 +439,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     *                          transaction operation.
     * @param exception             exception from the server side.
     */
    // Suppress GuardedBy warning because lint ask to mark this method as
    // @GuardedBy(container.mController.mLock), which is mLock itself
    @SuppressWarnings("GuardedBy")
    @VisibleForTesting
    @GuardedBy("mLock")
    void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
@@ -869,24 +881,24 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     * Called when we have been waiting too long for the TaskFragment to become non-empty after
     * creation.
     */
    @GuardedBy("mLock")
    void onTaskFragmentAppearEmptyTimeout(@NonNull TaskFragmentContainer container) {
        synchronized (mLock) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        onTaskFragmentAppearEmptyTimeout(wct, container);
            mPresenter.applyTransaction(wct);
        }
        // Can be applied independently as a timeout callback.
        mPresenter.applyTransaction(wct, getTransitionType(wct),
                true /* shouldApplyIndependently */);
    }

    /**
     * Called when we have been waiting too long for the TaskFragment to become non-empty after
     * creation.
     */
    @GuardedBy("mLock")
    void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container) {
        synchronized (mLock) {
        mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
    }
    }

    /**
     * When we are trying to handle a new activity Intent, returns the {@link TaskFragmentContainer}
@@ -1714,7 +1726,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            synchronized (mLock) {
                final WindowContainerTransaction wct = new WindowContainerTransaction();
                SplitController.this.onActivityCreated(wct, activity);
                mPresenter.applyTransaction(wct);
                // The WCT should be applied and merged to the activity launch transition.
                mPresenter.applyTransaction(wct, getTransitionType(wct),
                        false /* shouldApplyIndependently */);
            }
        }

@@ -1723,7 +1737,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            synchronized (mLock) {
                final WindowContainerTransaction wct = new WindowContainerTransaction();
                SplitController.this.onActivityConfigurationChanged(wct, activity);
                mPresenter.applyTransaction(wct);
                // The WCT should be applied and merged to the Task change transition so that the
                // placeholder is launched in the same transition.
                mPresenter.applyTransaction(wct, getTransitionType(wct),
                        false /* shouldApplyIndependently */);
            }
        }

@@ -1775,7 +1792,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                final TaskFragmentContainer launchedInTaskFragment = resolveStartActivityIntent(wct,
                        taskId, intent, launchingActivity);
                if (launchedInTaskFragment != null) {
                    mPresenter.applyTransaction(wct);
                    // Make sure the WCT is applied immediately instead of being queued so that the
                    // TaskFragment will be ready before activity attachment.
                    mPresenter.applyTransaction(wct, getTransitionType(wct),
                            false /* shouldApplyIndependently */);
                    // Amend the request to let the WM know that the activity should be placed in
                    // the dedicated container.
                    options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
Loading