Merge "Don't applyReady immediately when create empty TaskFragment" into main
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index d6fc01a..a7eb444 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -329,15 +329,7 @@
deferred);
wctApplied.meet();
if (needsSetReady) {
- // TODO(b/294925498): Remove this once we have accurate ready
- // tracking.
- if (hasActivityLaunch(wct) && !mService.mRootWindowContainer
- .allPausedActivitiesComplete()) {
- // WCT is launching an activity, so we need to wait for its
- // lifecycle events.
- return;
- }
- nextTransition.setAllReady();
+ setAllReadyIfNeeded(nextTransition, wct);
}
});
return nextTransition.getToken();
@@ -390,7 +382,7 @@
}
}
- private static boolean hasActivityLaunch(WindowContainerTransaction wct) {
+ private static boolean hasActivityLaunch(@NonNull WindowContainerTransaction wct) {
for (int i = 0; i < wct.getHierarchyOps().size(); ++i) {
if (wct.getHierarchyOps().get(i).getType() == HIERARCHY_OP_TYPE_LAUNCH_TASK) {
return true;
@@ -399,6 +391,46 @@
return false;
}
+ private boolean isCreatedTaskFragmentReady(@NonNull WindowContainerTransaction wct) {
+ for (int i = 0; i < wct.getHierarchyOps().size(); ++i) {
+ final WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i);
+ if (op.getType() != HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION
+ || op.getTaskFragmentOperation().getOpType()
+ != OP_TYPE_CREATE_TASK_FRAGMENT) {
+ continue;
+ }
+ final IBinder tfToken = op.getTaskFragmentOperation()
+ .getTaskFragmentCreationParams().getFragmentToken();
+ final TaskFragment taskFragment = getTaskFragment(tfToken);
+ if (taskFragment != null && !taskFragment.isReadyToTransit()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void setAllReadyIfNeeded(@NonNull Transition transition,
+ @NonNull WindowContainerTransaction wct) {
+ // TODO(b/294925498): Remove this once we have accurate ready tracking.
+ if (hasActivityLaunch(wct) && !mService.mRootWindowContainer
+ .allPausedActivitiesComplete()) {
+ // WCT is launching an activity, so we need to wait for its
+ // lifecycle events.
+ return;
+ }
+ if (!isCreatedTaskFragmentReady(wct)) {
+ // When the organizer intercepts a #startActivity, it will create an empty TaskFragment
+ // for that specific incoming starting activity. We don't want to set all ready here,
+ // because we requires that #startActivity to be included in this transition, and NOT be
+ // in its own transition.
+ // TODO(b/232042367): explicitly ensure the #startActivity and this transaction are in
+ // the same transition instead of relying on this possible racing condition.
+ return;
+ }
+
+ transition.setAllReady();
+ }
+
@Override
public int startLegacyTransition(int type, @NonNull RemoteAnimationAdapter adapter,
@NonNull IWindowContainerTransactionCallback callback,
@@ -529,7 +561,7 @@
}
mTransitionController.requestStartTransition(transition, null /* startTask */,
remoteTransition, null /* displayChange */);
- transition.setAllReady();
+ setAllReadyIfNeeded(transition, wct);
};
mTransitionController.startCollectOrQueue(transition, doApply);
} finally {