Cleanup TaskFragmentOrganizer#applyTransaction

Replace the existing usage with the overload method, which is introduced
to sync TaskFragmentOrganizer with other transition.

Introduced TaskFragmentTransitionType to avoid exposing Shell transition
API to CTS.

Bug: 232476698
Test: pass existing
Change-Id: I666b9ee6b6076766513b97e675fdbaa002428601
This commit is contained in:
Chris Li
2022-12-05 22:45:23 +08:00
parent 765e03a592
commit 55e086c2ec
7 changed files with 160 additions and 118 deletions

View File

@@ -3429,14 +3429,20 @@ package android.window {
public class TaskFragmentOrganizer extends android.window.WindowOrganizer { public class TaskFragmentOrganizer extends android.window.WindowOrganizer {
ctor public TaskFragmentOrganizer(@NonNull java.util.concurrent.Executor); 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 java.util.concurrent.Executor getExecutor();
method @NonNull public android.window.TaskFragmentOrganizerToken getOrganizerToken(); 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 public void onTransactionReady(@NonNull android.window.TaskFragmentTransaction);
method @CallSuper public void registerOrganizer(); method @CallSuper public void registerOrganizer();
method @CallSuper public void unregisterOrganizer(); 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_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_TASK_FRAGMENT_INFO = "task_fragment_info";
field public static final String KEY_ERROR_CALLBACK_THROWABLE = "fragment_throwable"; 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 { public final class TaskFragmentOrganizerToken implements android.os.Parcelable {
@@ -3558,8 +3564,8 @@ package android.window {
public class WindowOrganizer { public class WindowOrganizer {
ctor public 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(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) 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 void applyTransaction(@NonNull android.window.WindowContainerTransaction);
} }
@UiContext public abstract class WindowProviderService extends android.app.Service { @UiContext public abstract class WindowProviderService extends android.app.Service {

View File

@@ -20,22 +20,20 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN; 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.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.TestApi; import android.annotation.TestApi;
import android.app.WindowConfiguration;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationDefinition;
import android.view.WindowManager; import android.view.WindowManager;
import java.util.List; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor; 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"; 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) * Creates a {@link Bundle} with an exception, operation type and TaskFragmentInfo (if any)
* that can be passed to {@link ITaskFragmentOrganizer#onTaskFragmentError}. * that can be passed to {@link ITaskFragmentOrganizer#onTaskFragmentError}.
@@ -155,7 +199,7 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
* {@link #onTransactionReady(TaskFragmentTransaction)} * {@link #onTransactionReady(TaskFragmentTransaction)}
* @param wct {@link WindowContainerTransaction} that the server should apply for * @param wct {@link WindowContainerTransaction} that the server should apply for
* update of the transaction. * 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. * transition.
* @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new * @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
* transition, which will be queued until the sync engine is * 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. * the {@code wct} will be directly applied to the active sync.
* @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission * @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
* for permission enforcement. * for permission enforcement.
* @hide
*/ */
public void onTransactionHandled(@NonNull IBinder transactionToken, public void onTransactionHandled(@NonNull IBinder transactionToken,
@NonNull WindowContainerTransaction wct, @NonNull WindowContainerTransaction wct,
@WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) { @TaskFragmentTransitionType int transitionType, boolean shouldApplyIndependently) {
wct.setTaskFragmentOrganizer(mInterface); wct.setTaskFragmentOrganizer(mInterface);
try { try {
getController().onTransactionHandled(transactionToken, wct, transitionType, getController().onTransactionHandled(transactionToken, wct, transitionType,
@@ -178,22 +221,19 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
} }
/** /**
* Routes to {@link ITaskFragmentOrganizerController#applyTransaction} instead of * Must use {@link #applyTransaction(WindowContainerTransaction, int, boolean)} instead.
* {@link IWindowOrganizerController#applyTransaction} for the different transition options.
*
* @see #applyTransaction(WindowContainerTransaction, int, boolean) * @see #applyTransaction(WindowContainerTransaction, int, boolean)
*/ */
@Override @Override
public void applyTransaction(@NonNull WindowContainerTransaction wct) { public void applyTransaction(@NonNull WindowContainerTransaction wct) {
// TODO(b/207070762) doing so to keep CTS compatibility. Remove in the next release. throw new RuntimeException("Not allowed!");
applyTransaction(wct, getTransitionType(wct), false /* shouldApplyIndependently */);
} }
/** /**
* Requests the server to apply the given {@link WindowContainerTransaction}. * Requests the server to apply the given {@link WindowContainerTransaction}.
* *
* @param wct {@link WindowContainerTransaction} to apply. * @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. * transition.
* @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new * @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
* transition, which will be queued until the sync engine is * 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. * the {@code wct} will be directly applied to the active sync.
* @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission * @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
* for permission enforcement. * for permission enforcement.
* @hide
*/ */
public void applyTransaction(@NonNull WindowContainerTransaction wct, public void applyTransaction(@NonNull WindowContainerTransaction wct,
@WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) { @TaskFragmentTransitionType int transitionType, boolean shouldApplyIndependently) {
if (wct.isEmpty()) { if (wct.isEmpty()) {
return; 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 * Called when the transaction is ready so that the organizer can update the TaskFragments based
* on the changes in transaction. * on the changes in transaction.
@@ -266,7 +262,7 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) { public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
// Notify the server to finish the transaction. // Notify the server to finish the transaction.
onTransactionHandled(transaction.getTransactionToken(), new WindowContainerTransaction(), onTransactionHandled(transaction.getTransactionToken(), new WindowContainerTransaction(),
TRANSIT_NONE, false /* shouldApplyIndependently */); TASK_FRAGMENT_TRANSIT_NONE, false /* shouldApplyIndependently */);
} }
private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() { private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {

View File

@@ -40,14 +40,11 @@ public class WindowOrganizer {
* Apply multiple WindowContainer operations at once. * Apply multiple WindowContainer operations at once.
* *
* Note that using this API requires the caller to hold * Note that using this API requires the caller to hold
* {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
* {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
* created by itself.
* *
* @param t The transaction to apply. * @param t The transaction to apply.
*/ */
@RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS, @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
conditional = true)
public void applyTransaction(@NonNull WindowContainerTransaction t) { public void applyTransaction(@NonNull WindowContainerTransaction t) {
try { try {
if (!t.isEmpty()) { if (!t.isEmpty()) {
@@ -62,9 +59,7 @@ public class WindowOrganizer {
* Apply multiple WindowContainer operations at once. * Apply multiple WindowContainer operations at once.
* *
* Note that using this API requires the caller to hold * Note that using this API requires the caller to hold
* {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
* {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
* created by itself.
* *
* @param t The transaction to apply. * @param t The transaction to apply.
* @param callback This transaction will use the synchronization scheme described in * @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. * @return An ID for the sync operation which will later be passed to transactionReady callback.
* This lets the caller differentiate overlapping sync operations. * This lets the caller differentiate overlapping sync operations.
*/ */
@RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS, @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
conditional = true)
public int applySyncTransaction(@NonNull WindowContainerTransaction t, public int applySyncTransaction(@NonNull WindowContainerTransaction t,
@NonNull WindowContainerTransactionCallback callback) { @NonNull WindowContainerTransactionCallback callback) {
try { try {

View File

@@ -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_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY; 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_OP_TYPE;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO; 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.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_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED; 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_ERROR;
@@ -340,7 +340,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
container.setInfo(wct, taskFragmentInfo); container.setInfo(wct, taskFragmentInfo);
if (container.isFinished()) { if (container.isFinished()) {
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else { } else {
// Update with the latest Task configuration. // 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. // 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 // Instead, the original split should be cleanup, and the dependent may be
// expanded to fullscreen. // expanded to fullscreen.
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
cleanupForEnterPip(wct, container); cleanupForEnterPip(wct, container);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (taskFragmentInfo.isTaskClearedForReuse()) { } else if (taskFragmentInfo.isTaskClearedForReuse()) {
// Do not finish the dependents if this TaskFragment was cleared due to // Do not finish the dependents if this TaskFragment was cleared due to
// launching activity in the Task. // launching activity in the Task.
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (taskFragmentInfo.isClearedForReorderActivityToFront()) { } else if (taskFragmentInfo.isClearedForReorderActivityToFront()) {
// Do not finish the dependents if this TaskFragment was cleared to reorder // Do not finish the dependents if this TaskFragment was cleared to reorder
// the launching Activity to front of the Task. // the launching Activity to front of the Task.
mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} else if (!container.isWaitingActivityAppear()) { } else if (!container.isWaitingActivityAppear()) {
// Do not finish the container before the expected activity appear until // Do not finish the container before the expected activity appear until
// timeout. // timeout.
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */);
} }
} else if (wasInPip && isInPip) { } else if (wasInPip && isInPip) {
@@ -585,7 +591,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
container.setInfo(wct, taskFragmentInfo); container.setInfo(wct, taskFragmentInfo);
container.clearPendingAppearedActivities(); container.clearPendingAppearedActivities();
if (container.isEmpty()) { if (container.isEmpty()) {
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} }
break; break;
@@ -1000,7 +1007,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@GuardedBy("mLock") @GuardedBy("mLock")
void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct, void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container) { @NonNull TaskFragmentContainer container) {
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
} }
@@ -1563,7 +1571,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// (not resumed yet). // (not resumed yet).
if (isOnCreated || primaryActivity.isResumed()) { if (isOnCreated || primaryActivity.isResumed()) {
// Only set trigger type if the launch happens in foreground. // Only set trigger type if the launch happens in foreground.
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_OPEN); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
return null; return null;
} }
final ActivityOptions options = ActivityOptions.makeBasic(); final ActivityOptions options = ActivityOptions.makeBasic();
@@ -1591,7 +1600,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return false; return false;
} }
mTransactionManager.getCurrentTransactionRecord().setOriginType(TRANSIT_CLOSE); mTransactionManager.getCurrentTransactionRecord()
.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
mPresenter.cleanupContainer(wct, splitContainer.getSecondaryContainer(), mPresenter.cleanupContainer(wct, splitContainer.getSecondaryContainer(),
false /* shouldFinishDependent */); false /* shouldFinishDependent */);
return true; return true;
@@ -1891,7 +1901,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
synchronized (mLock) { synchronized (mLock) {
final TransactionRecord transactionRecord = mTransactionManager final TransactionRecord transactionRecord = mTransactionManager
.startNewTransaction(); .startNewTransaction();
transactionRecord.setOriginType(TRANSIT_OPEN); transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
SplitController.this.onActivityCreated(transactionRecord.getTransaction(), SplitController.this.onActivityCreated(transactionRecord.getTransaction(),
activity); activity);
// The WCT should be applied and merged to the activity launch transition. // The WCT should be applied and merged to the activity launch transition.
@@ -1980,7 +1990,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
synchronized (mLock) { synchronized (mLock) {
final TransactionRecord transactionRecord = mTransactionManager final TransactionRecord transactionRecord = mTransactionManager
.startNewTransaction(); .startNewTransaction();
transactionRecord.setOriginType(TRANSIT_OPEN); transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
final WindowContainerTransaction wct = transactionRecord.getTransaction(); final WindowContainerTransaction wct = transactionRecord.getTransaction();
final TaskFragmentContainer launchedInTaskFragment; final TaskFragmentContainer launchedInTaskFragment;
if (launchingActivity != null) { if (launchingActivity != null) {

View File

@@ -16,12 +16,12 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.view.WindowManager.TRANSIT_CHANGE; import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_NONE; import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_NONE;
import android.os.IBinder; import android.os.IBinder;
import android.view.WindowManager.TransitionType;
import android.window.TaskFragmentOrganizer; import android.window.TaskFragmentOrganizer;
import android.window.TaskFragmentOrganizer.TaskFragmentTransitionType;
import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -122,8 +122,8 @@ class TransactionManager {
* @see #setOriginType(int) * @see #setOriginType(int)
* @see #getTransactionTransitionType() * @see #getTransactionTransitionType()
*/ */
@TransitionType @TaskFragmentTransitionType
private int mOriginType = TRANSIT_NONE; private int mOriginType = TASK_FRAGMENT_TRANSIT_NONE;
TransactionRecord(@Nullable IBinder taskFragmentTransactionToken) { TransactionRecord(@Nullable IBinder taskFragmentTransactionToken) {
mTaskFragmentTransactionToken = taskFragmentTransactionToken; mTaskFragmentTransactionToken = taskFragmentTransactionToken;
@@ -136,12 +136,12 @@ class TransactionManager {
} }
/** /**
* Sets the {@link TransitionType} that triggers this transaction. If there are multiple * Sets the {@link TaskFragmentTransitionType} that triggers this transaction. If there are
* calls, only the first call will be respected as the "origin" type. * multiple calls, only the first call will be respected as the "origin" type.
*/ */
void setOriginType(@TransitionType int type) { void setOriginType(@TaskFragmentTransitionType int type) {
ensureCurrentTransaction(); ensureCurrentTransaction();
if (mOriginType != TRANSIT_NONE) { if (mOriginType != TASK_FRAGMENT_TRANSIT_NONE) {
// Skip if the origin type has already been set. // Skip if the origin type has already been set.
return; 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}. * current {@link WindowContainerTransaction}.
*/ */
@VisibleForTesting @VisibleForTesting
@TransitionType @TaskFragmentTransitionType
int getTransactionTransitionType() { int getTransactionTransitionType() {
// Use TRANSIT_CHANGE as default if there is not opening/closing window. // Use TASK_FRAGMENT_TRANSIT_CHANGE as default if there is not opening/closing window.
return mOriginType != TRANSIT_NONE ? mOriginType : TRANSIT_CHANGE; return mOriginType != TASK_FRAGMENT_TRANSIT_NONE
? mOriginType
: TASK_FRAGMENT_TRANSIT_CHANGE;
} }
} }
} }

View File

@@ -16,9 +16,9 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.view.WindowManager.TRANSIT_CHANGE; import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE; import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN; import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_OPEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
@@ -86,27 +86,29 @@ public class TransactionManagerTest {
@Test @Test
public void testSetTransactionOriginType() { public void testSetTransactionOriginType() {
// Return TRANSIT_CHANGE if there is no trigger type set. // Return TASK_FRAGMENT_TRANSIT_CHANGE if there is no trigger type set.
TransactionRecord transactionRecord = mTransactionManager.startNewTransaction(); TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
assertEquals(TRANSIT_CHANGE, transactionRecord.getTransactionTransitionType()); assertEquals(TASK_FRAGMENT_TRANSIT_CHANGE,
transactionRecord.getTransactionTransitionType());
// Return the first set type. // Return the first set type.
mTransactionManager.getCurrentTransactionRecord().abort(); mTransactionManager.getCurrentTransactionRecord().abort();
transactionRecord = mTransactionManager.startNewTransaction(); transactionRecord = mTransactionManager.startNewTransaction();
transactionRecord.setOriginType(TRANSIT_OPEN); transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_OPEN);
assertEquals(TRANSIT_OPEN, transactionRecord.getTransactionTransitionType()); assertEquals(TASK_FRAGMENT_TRANSIT_OPEN, transactionRecord.getTransactionTransitionType());
transactionRecord.setOriginType(TRANSIT_CLOSE); transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
assertEquals(TRANSIT_OPEN, transactionRecord.getTransactionTransitionType()); assertEquals(TASK_FRAGMENT_TRANSIT_OPEN, transactionRecord.getTransactionTransitionType());
// Reset when #startNewTransaction(). // Reset when #startNewTransaction().
transactionRecord.abort(); transactionRecord.abort();
transactionRecord = mTransactionManager.startNewTransaction(); transactionRecord = mTransactionManager.startNewTransaction();
assertEquals(TRANSIT_CHANGE, transactionRecord.getTransactionTransitionType()); assertEquals(TASK_FRAGMENT_TRANSIT_CHANGE,
transactionRecord.getTransactionTransitionType());
} }
@Test @Test

View File

@@ -19,9 +19,16 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.DEFAULT_DISPLAY;
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.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE; import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE; import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
import static android.window.TaskFragmentOrganizer.getTransitionType; import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CHANGE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_CLOSE;
import static android.window.TaskFragmentOrganizer.TASK_FRAGMENT_TRANSIT_NONE;
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_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED; 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_ERROR;
@@ -581,7 +588,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment); mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mTransaction.startActivityInTaskFragment( mTransaction.startActivityInTaskFragment(
mFragmentToken, ownerActivity.token, new Intent(), null /* activityOptions */); mFragmentToken, ownerActivity.token, new Intent(), null /* activityOptions */);
mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_OPEN,
false /* shouldApplyIndependently */);
// Not allowed because TaskFragment is not organized by the caller organizer. // Not allowed because TaskFragment is not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction); assertApplyTransactionDisallowed(mTransaction);
@@ -602,7 +610,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
.build(); .build();
mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment); mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token); mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token);
mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */);
// Not allowed because TaskFragment is not organized by the caller organizer. // Not allowed because TaskFragment is not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction); assertApplyTransactionDisallowed(mTransaction);
@@ -628,7 +637,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
.build(); .build();
mWindowOrganizerController.mLaunchTaskFragments.put(fragmentToken2, taskFragment2); mWindowOrganizerController.mLaunchTaskFragments.put(fragmentToken2, taskFragment2);
mTransaction.setAdjacentTaskFragments(mFragmentToken, fragmentToken2, null /* params */); mTransaction.setAdjacentTaskFragments(mFragmentToken, fragmentToken2, null /* params */);
mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */);
// Not allowed because TaskFragments are not organized by the caller organizer. // Not allowed because TaskFragments are not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction); assertApplyTransactionDisallowed(mTransaction);
@@ -661,7 +671,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
.build(); .build();
mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment); mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
mTransaction.requestFocusOnTaskFragment(mFragmentToken); mTransaction.requestFocusOnTaskFragment(mFragmentToken);
mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */);
// Not allowed because TaskFragment is not organized by the caller organizer. // Not allowed because TaskFragment is not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction); assertApplyTransactionDisallowed(mTransaction);
@@ -729,7 +740,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final ActivityRecord activity = createActivityRecord(task); final ActivityRecord activity = createActivityRecord(task);
// Skip manipulate the SurfaceControl. // Skip manipulate the SurfaceControl.
doNothing().when(activity).setDropInputMode(anyInt()); doNothing().when(activity).setDropInputMode(anyInt());
mOrganizer.applyTransaction(mTransaction); mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */);
mTaskFragment = new TaskFragmentBuilder(mAtm) mTaskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task) .setParentTask(task)
.setFragmentToken(mFragmentToken) .setFragmentToken(mFragmentToken)
@@ -830,8 +842,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken); createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
mController.onTransactionHandled(new Binder(), mTransaction, mController.onTransactionHandled(new Binder(), mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
getTransitionType(mTransaction), false /* shouldApplyIndependently */); false /* shouldApplyIndependently */);
// Nothing should happen as the organizer is not registered. // Nothing should happen as the organizer is not registered.
assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken)); assertNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
@@ -1379,12 +1391,31 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final IBinder transactionToken = tokenCaptor.getValue(); final IBinder transactionToken = tokenCaptor.getValue();
final WindowContainerTransaction wct = wctCaptor.getValue(); final WindowContainerTransaction wct = wctCaptor.getValue();
wct.setTaskFragmentOrganizer(mIOrganizer); wct.setTaskFragmentOrganizer(mIOrganizer);
mController.onTransactionHandled(transactionToken, wct, getTransitionType(wct), mController.onTransactionHandled(transactionToken, wct, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */); false /* shouldApplyIndependently */);
verify(mTransitionController).continueTransitionReady(); verify(mTransitionController).continueTransitionReady();
} }
@Test
public void testWindowOrganizerApplyTransaction_throwException() {
// Not allow to use #applyTransaction(WindowContainerTransaction).
assertThrows(RuntimeException.class, () -> mOrganizer.applyTransaction(mTransaction));
// Allow to use the overload method.
mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */);
}
@Test
public void testTaskFragmentTransitionType() {
// 1-1 relationship with WindowManager.TransitionType
assertEquals(TRANSIT_NONE, TASK_FRAGMENT_TRANSIT_NONE);
assertEquals(TRANSIT_OPEN, TASK_FRAGMENT_TRANSIT_OPEN);
assertEquals(TRANSIT_CLOSE, TASK_FRAGMENT_TRANSIT_CLOSE);
assertEquals(TRANSIT_CHANGE, TASK_FRAGMENT_TRANSIT_CHANGE);
}
/** /**
* Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls * Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
* {@link WindowOrganizerController#applyTransaction(WindowContainerTransaction)} to apply the * {@link WindowOrganizerController#applyTransaction(WindowContainerTransaction)} to apply the
@@ -1406,13 +1437,14 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
/** Asserts that applying the given transaction will throw a {@link SecurityException}. */ /** Asserts that applying the given transaction will throw a {@link SecurityException}. */
private void assertApplyTransactionDisallowed(WindowContainerTransaction t) { private void assertApplyTransactionDisallowed(WindowContainerTransaction t) {
assertThrows(SecurityException.class, () -> assertThrows(SecurityException.class, () ->
mController.applyTransaction(t, getTransitionType(t), mController.applyTransaction(t, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */)); false /* shouldApplyIndependently */));
} }
/** Asserts that applying the given transaction will not throw any exception. */ /** Asserts that applying the given transaction will not throw any exception. */
private void assertApplyTransactionAllowed(WindowContainerTransaction t) { private void assertApplyTransactionAllowed(WindowContainerTransaction t) {
mController.applyTransaction(t, getTransitionType(t), false /* shouldApplyIndependently */); mController.applyTransaction(t, TASK_FRAGMENT_TRANSIT_CHANGE,
false /* shouldApplyIndependently */);
} }
/** Asserts that there will be a transaction for TaskFragment appeared. */ /** Asserts that there will be a transaction for TaskFragment appeared. */