diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 8caff23539c31..b49b289d44c0a 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -2599,6 +2599,12 @@ "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "743418423": { + "message": "Sending TaskFragment error exception=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_ORGANIZER", + "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java" + }, "744171317": { "message": " SKIP: %s", "level": "VERBOSE", diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java index 5b379c0db52b8..c4ec4627f6cb8 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java @@ -708,10 +708,24 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } final Activity launchingActivity = (Activity) who; + if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { + setLaunchingInSameContainer(launchingActivity, intent, options); + } + + return super.onStartActivity(who, intent, options); + } + + /** + * Returns {@code true} if the activity that is going to be started via the + * {@code intent} should be paired with the {@code launchingActivity} and is set to be + * launched in an empty side container. + */ + private boolean setLaunchingToSideContainer(Activity launchingActivity, Intent intent, + Bundle options) { final ExtensionSplitPairRule splitPairRule = getSplitRule( launchingActivity.getComponentName(), intent.getComponent(), getSplitRules()); if (splitPairRule == null) { - return super.onStartActivity(who, intent, options); + return false; } // Create a new split with an empty side container @@ -722,8 +736,52 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // dedicated container. options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN, secondaryContainer.getTaskFragmentToken()); + return true; + } - return super.onStartActivity(who, intent, options); + /** + * Checks if the activity that is going to be started via the {@code intent} should be + * paired with the existing top activity which is currently paired with the + * {@code launchingActivity}. If so, set the activity to be launched in the same + * container of the {@code launchingActivity}. + */ + private void setLaunchingInSameContainer(Activity launchingActivity, Intent intent, + Bundle options) { + final TaskFragmentContainer launchingContainer = getContainerWithActivity( + launchingActivity.getActivityToken()); + if (launchingContainer == null) { + return; + } + + final SplitContainer splitContainer = getActiveSplitForContainer(launchingContainer); + if (splitContainer == null) { + return; + } + + if (splitContainer.getSecondaryContainer() != launchingContainer) { + return; + } + + // The launching activity is on the secondary container. Retrieve the primary + // activity from the other container. + Activity primaryActivity = + splitContainer.getPrimaryContainer().getTopNonFinishingActivity(); + if (primaryActivity == null) { + return; + } + + final ExtensionSplitPairRule splitPairRule = getSplitRule( + primaryActivity.getComponentName(), intent.getComponent(), getSplitRules()); + if (splitPairRule == null) { + return; + } + + // Amend the request to let the WM know that the activity should be placed in the + // dedicated container. This is necessary for the case that the activity is started + // into a new Task, or new Task will be escaped from the current host Task and be + // displayed in fullscreen. + options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN, + launchingContainer.getTaskFragmentToken()); } } } diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 96860a23d3cf8..690f67c25cfe0 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -199,6 +199,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception) { + ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, + "Sending TaskFragment error exception=%s", exception.toString()); final Bundle exceptionBundle = putExceptionInBundle(exception); try { organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); @@ -313,6 +315,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception) { validateAndGetState(organizer); + Slog.w(TAG, "onTaskFragmentError ", exception); PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(organizer, errorCallbackToken, exception, PendingTaskFragmentEvent.EVENT_ERROR); mPendingTaskFragmentEvents.add(pendingEvent);