diff options
| author | 2022-03-29 22:19:51 -0400 | |
|---|---|---|
| committer | 2022-04-01 13:31:30 -0400 | |
| commit | d8659858914ba6d66885b4a8202f4876a054463e (patch) | |
| tree | ed04f41987e6e3c78f87665aadf9ab5eb1ee26b3 | |
| parent | 39c6eaa64ddfbe5eb772a6dc8f6ea5b6b29437f1 (diff) | |
Send Split Info Callback before Activity#onCreate
The onTaskFragmentInfo callback from the server
triggered by the creation of a new activity may not
reach the client before Activity#onCreate is called
because of undeterministic IPC call order. However, the
application should get a split info update that includes
the newly launched activity before the Activity#onCreate
is called for that activity so that the application
knows that the activity will be in a split, which may
influence UI decisions.
Bug: b/218791665 b/200303250
Test: atest ActivityEmbeddingLaunchTests
Change-Id: If69c077db8ca390d41446e1329a448b3dd074293
3 files changed, 42 insertions, 4 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 418ff0e7263a..c7d62530a43d 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -602,14 +602,22 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return null; } + private void updateCallbackIfNecessary() { + updateCallbackIfNecessary(true /* deferCallbackUntilAllActivitiesCreated */); + } + /** * Notifies listeners about changes to split states if necessary. + * + * @param deferCallbackUntilAllActivitiesCreated boolean to indicate whether the split info + * callback should be deferred until all the + * organized activities have been created. */ - private void updateCallbackIfNecessary() { + private void updateCallbackIfNecessary(boolean deferCallbackUntilAllActivitiesCreated) { if (mEmbeddingCallback == null) { return; } - if (!allActivitiesCreated()) { + if (deferCallbackUntilAllActivitiesCreated && !allActivitiesCreated()) { return; } List<SplitInfo> currentSplitStates = getActiveSplitStates(); @@ -825,6 +833,36 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @Override + public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) { + final IBinder activityToken = activity.getActivityToken(); + final IBinder initialTaskFragmentToken = ActivityThread.currentActivityThread() + .getActivityClient(activityToken).mInitialTaskFragmentToken; + // If the activity is not embedded, then it will not have an initial task fragment token + // so no further action is needed. + if (initialTaskFragmentToken == null) { + return; + } + for (int i = mTaskContainers.size() - 1; i >= 0; i--) { + final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i) + .mContainers; + for (int j = containers.size() - 1; j >= 0; j--) { + final TaskFragmentContainer container = containers.get(j); + if (!container.hasActivity(activityToken) + && container.getTaskFragmentToken().equals(initialTaskFragmentToken)) { + // The onTaskFragmentInfoChanged callback containing this activity has not + // reached the client yet, so add the activity to the pending appeared + // activities and send a split info callback to the client before + // {@link Activity#onCreate} is called. + container.addPendingAppearedActivity(activity); + updateCallbackIfNecessary( + false /* deferCallbackUntilAllActivitiesCreated */); + return; + } + } + } + } + + @Override public void onActivityPostCreated(Activity activity, Bundle savedInstanceState) { // Calling after Activity#onCreate is complete to allow the app launch something // first. In case of a configured placeholder activity we want to make sure diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java index e49af41d4eac..9a12669f078a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java @@ -120,7 +120,7 @@ class TaskFragmentContainer { } ActivityStack toActivityStack() { - return new ActivityStack(collectActivities(), mInfo.getRunningActivityCount() == 0); + return new ActivityStack(collectActivities(), isEmpty()); } void addPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) { diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 23df429c3f24..cf32457211af 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -2264,7 +2264,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { mFragmentToken, mRemoteToken.toWindowContainerToken(), getConfiguration(), - getChildCount() == 0, + runningActivityCount[0] == 0, runningActivityCount[0], isVisible(), childActivities, |