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 9e7f9d22db189..23cf1d9654c4f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -363,7 +363,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen * @param activity the activity that is newly added to the Task. * @param isOnReparent whether the activity is reparented to the Task instead of new launched. * We only support to split as primary for reparented activity for now. - * @return {@code true} if the activity was placed in TaskFragment container. + * @return {@code true} if the activity has been handled, such as placed in a TaskFragment, or + * in a state that the caller shouldn't handle. */ @VisibleForTesting boolean resolveActivityToContainer(@NonNull Activity activity, boolean isOnReparent) { @@ -373,6 +374,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return true; } + if (!isOnReparent && getContainerWithActivity(activity) == null + && getInitialTaskFragmentToken(activity) != null) { + // We can't find the new launched activity in any recorded container, but it is + // currently placed in an embedded TaskFragment. This can happen in two cases: + // 1. the activity is embedded in another app. + // 2. the organizer has already requested to remove the TaskFragment. + // In either case, return true since we don't want any extra handling. + Log.d(TAG, "Activity is in a TaskFragment that is not recorded by the organizer. r=" + + activity); + return true; + } + /* * We will check the following to see if there is any embedding rule matched: * 1. Whether the new launched activity should always expand. @@ -1285,6 +1298,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return ActivityThread.currentActivityThread().getActivity(activityToken); } + /** + * Gets the token of the initial TaskFragment that embedded this activity. Do not rely on it + * after creation because the activity could be reparented. + */ + @VisibleForTesting + @Nullable + IBinder getInitialTaskFragmentToken(@NonNull Activity activity) { + final ActivityThread.ActivityClientRecord record = ActivityThread.currentActivityThread() + .getActivityClient(activity.getActivityToken()); + return record != null ? record.mInitialTaskFragmentToken : null; + } + /** * Returns {@code true} if an Activity with the provided component name should always be * expanded to occupy full task bounds. Such activity must not be put in a split. @@ -1358,8 +1383,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) { final IBinder activityToken = activity.getActivityToken(); - final IBinder initialTaskFragmentToken = ActivityThread.currentActivityThread() - .getActivityClient(activityToken).mInitialTaskFragmentToken; + final IBinder initialTaskFragmentToken = getInitialTaskFragmentToken(activity); // 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) { diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java index 7fbacbaa8761c..2fd491312f63d 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java @@ -733,6 +733,15 @@ public class SplitControllerTest { assertSplitPair(mActivity, primaryActivity); } + @Test + public void testResolveActivityToContainer_inUnknownTaskFragment() { + doReturn(new Binder()).when(mSplitController).getInitialTaskFragmentToken(mActivity); + + // No need to handle when the new launched activity is in an unknown TaskFragment. + assertTrue(mSplitController.resolveActivityToContainer(mActivity, + false /* isOnReparent */)); + } + @Test public void testGetPlaceholderOptions() { doReturn(true).when(mActivity).isResumed();