Loading libs/WindowManager/Shell/res/values/config.xml +1 −1 Original line number Diff line number Diff line Loading @@ -113,6 +113,6 @@ <bool name="config_dimNonImeAttachedSide">true</bool> <!-- Components support to launch multiple instances into split-screen --> <string-array name="config_componentsSupportMultiInstancesSplit"> <string-array name="config_appsSupportMultiInstancesSplit"> </string-array> </resources> libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +48 −45 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; import static android.view.Display.DEFAULT_DISPLAY; Loading Loading @@ -98,7 +97,6 @@ import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Executor; Loading Loading @@ -171,7 +169,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private final IconProvider mIconProvider; private final Optional<RecentTasksController> mRecentTasksOptional; private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler; private final String[] mMultiInstancesComponents; private final String[] mAppsSupportMultiInstances; @VisibleForTesting StageCoordinator mStageCoordinator; Loading Loading @@ -221,8 +219,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, // TODO(255224696): Remove the config once having a way for client apps to opt-in // multi-instances split. mMultiInstancesComponents = mContext.getResources() .getStringArray(R.array.config_componentsSupportMultiInstancesSplit); mAppsSupportMultiInstances = mContext.getResources() .getStringArray(R.array.config_appsSupportMultiInstancesSplit); } @VisibleForTesting Loading Loading @@ -261,8 +259,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator = stageCoordinator; mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this); shellInit.addInitCallback(this::onInit, this); mMultiInstancesComponents = mContext.getResources() .getStringArray(R.array.config_componentsSupportMultiInstancesSplit); mAppsSupportMultiInstances = mContext.getResources() .getStringArray(R.array.config_appsSupportMultiInstancesSplit); } public SplitScreen asSplitScreen() { Loading Loading @@ -529,7 +527,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) { Intent fillInIntent = null; if (launchSameComponentAdjacently(pendingIntent, splitPosition, taskId)) { if (launchSameAppAdjacently(pendingIntent, taskId)) { if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) { fillInIntent = new Intent(); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); Loading @@ -556,7 +554,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) { Intent fillInIntent = null; if (launchSameComponentAdjacently(pendingIntent, splitPosition, taskId)) { if (launchSameAppAdjacently(pendingIntent, taskId)) { if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) { fillInIntent = new Intent(); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); Loading @@ -578,7 +576,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) { Intent fillInIntent1 = null; Intent fillInIntent2 = null; if (launchSameComponentAdjacently(pendingIntent1, pendingIntent2)) { if (launchSameAppAdjacently(pendingIntent1, pendingIntent2)) { if (supportMultiInstancesSplit(pendingIntent1.getIntent().getComponent())) { fillInIntent1 = new Intent(); fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); Loading Loading @@ -613,7 +611,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, if (fillInIntent == null) fillInIntent = new Intent(); fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION); if (launchSameComponentAdjacently(intent, position, INVALID_TASK_ID)) { if (launchSameAppAdjacently(position, intent)) { final ComponentName launching = intent.getIntent().getComponent(); if (supportMultiInstancesSplit(launching)) { // To prevent accumulating large number of instances in the background, reuse task Loading Loading @@ -647,47 +645,52 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.startIntent(intent, fillInIntent, position, options); } /** Returns {@code true} if it's launching the same component on both sides of the split. */ private boolean launchSameComponentAdjacently(@Nullable PendingIntent pendingIntent, @SplitPosition int position, int taskId) { if (pendingIntent == null || pendingIntent.getIntent() == null) return false; final ComponentName launchingActivity = pendingIntent.getIntent().getComponent(); if (launchingActivity == null) return false; if (taskId != INVALID_TASK_ID) { final ActivityManager.RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(taskId); if (taskInfo != null) { return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity); @Nullable private String getPackageName(Intent intent) { if (intent == null || intent.getComponent() == null) { return null; } return false; return intent.getComponent().getPackageName(); } if (!isSplitScreenVisible()) { // Split screen is not yet activated, check if the current top running task is valid to // split together. final ActivityManager.RunningTaskInfo topRunningTask = mRecentTasksOptional private boolean launchSameAppAdjacently(@SplitPosition int position, PendingIntent pendingIntent) { ActivityManager.RunningTaskInfo adjacentTaskInfo = null; if (isSplitScreenVisible()) { adjacentTaskInfo = getTaskInfo(SplitLayout.reversePosition(position)); } else { adjacentTaskInfo = mRecentTasksOptional .map(recentTasks -> recentTasks.getTopRunningTask()).orElse(null); if (topRunningTask != null && isValidToEnterSplitScreen(topRunningTask)) { return Objects.equals(topRunningTask.baseIntent.getComponent(), launchingActivity); if (!isValidToEnterSplitScreen(adjacentTaskInfo)) { return false; } } if (adjacentTaskInfo == null) { return false; } // Compare to the adjacent side of the split to determine if this is launching the same // component adjacently. final ActivityManager.RunningTaskInfo pairedTaskInfo = getTaskInfo(SplitLayout.reversePosition(position)); final ComponentName pairedActivity = pairedTaskInfo != null ? pairedTaskInfo.baseIntent.getComponent() : null; return Objects.equals(launchingActivity, pairedActivity); final String targetPackageName = getPackageName(pendingIntent.getIntent()); final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent); return targetPackageName != null && targetPackageName.equals(adjacentPackageName); } private boolean launchSameAppAdjacently(PendingIntent pendingIntent, int taskId) { final ActivityManager.RunningTaskInfo adjacentTaskInfo = mTaskOrganizer.getRunningTaskInfo(taskId); if (adjacentTaskInfo == null) { return false; } final String targetPackageName = getPackageName(pendingIntent.getIntent()); final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent); return targetPackageName != null && targetPackageName.equals(adjacentPackageName); } private boolean launchSameComponentAdjacently(PendingIntent pendingIntent1, private boolean launchSameAppAdjacently(PendingIntent pendingIntent1, PendingIntent pendingIntent2) { return Objects.equals(pendingIntent1.getIntent().getComponent(), pendingIntent2.getIntent().getComponent()); final String targetPackageName = getPackageName(pendingIntent1.getIntent()); final String adjacentPackageName = getPackageName(pendingIntent2.getIntent()); return targetPackageName != null && targetPackageName.equals(adjacentPackageName); } @VisibleForTesting Loading @@ -695,9 +698,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, boolean supportMultiInstancesSplit(@Nullable ComponentName launching) { if (launching == null) return false; final String componentName = launching.flattenToString(); for (int i = 0; i < mMultiInstancesComponents.length; i++) { if (mMultiInstancesComponents[i].equals(componentName)) { final String packageName = launching.getPackageName(); for (int i = 0; i < mAppsSupportMultiInstances.length; i++) { if (mAppsSupportMultiInstances[i].equals(packageName)) { return true; } } Loading Loading
libs/WindowManager/Shell/res/values/config.xml +1 −1 Original line number Diff line number Diff line Loading @@ -113,6 +113,6 @@ <bool name="config_dimNonImeAttachedSide">true</bool> <!-- Components support to launch multiple instances into split-screen --> <string-array name="config_componentsSupportMultiInstancesSplit"> <string-array name="config_appsSupportMultiInstancesSplit"> </string-array> </resources>
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +48 −45 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; import static android.view.Display.DEFAULT_DISPLAY; Loading Loading @@ -98,7 +97,6 @@ import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Executor; Loading Loading @@ -171,7 +169,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private final IconProvider mIconProvider; private final Optional<RecentTasksController> mRecentTasksOptional; private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler; private final String[] mMultiInstancesComponents; private final String[] mAppsSupportMultiInstances; @VisibleForTesting StageCoordinator mStageCoordinator; Loading Loading @@ -221,8 +219,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, // TODO(255224696): Remove the config once having a way for client apps to opt-in // multi-instances split. mMultiInstancesComponents = mContext.getResources() .getStringArray(R.array.config_componentsSupportMultiInstancesSplit); mAppsSupportMultiInstances = mContext.getResources() .getStringArray(R.array.config_appsSupportMultiInstancesSplit); } @VisibleForTesting Loading Loading @@ -261,8 +259,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator = stageCoordinator; mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this); shellInit.addInitCallback(this::onInit, this); mMultiInstancesComponents = mContext.getResources() .getStringArray(R.array.config_componentsSupportMultiInstancesSplit); mAppsSupportMultiInstances = mContext.getResources() .getStringArray(R.array.config_appsSupportMultiInstancesSplit); } public SplitScreen asSplitScreen() { Loading Loading @@ -529,7 +527,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) { Intent fillInIntent = null; if (launchSameComponentAdjacently(pendingIntent, splitPosition, taskId)) { if (launchSameAppAdjacently(pendingIntent, taskId)) { if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) { fillInIntent = new Intent(); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); Loading @@ -556,7 +554,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) { Intent fillInIntent = null; if (launchSameComponentAdjacently(pendingIntent, splitPosition, taskId)) { if (launchSameAppAdjacently(pendingIntent, taskId)) { if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) { fillInIntent = new Intent(); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); Loading @@ -578,7 +576,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) { Intent fillInIntent1 = null; Intent fillInIntent2 = null; if (launchSameComponentAdjacently(pendingIntent1, pendingIntent2)) { if (launchSameAppAdjacently(pendingIntent1, pendingIntent2)) { if (supportMultiInstancesSplit(pendingIntent1.getIntent().getComponent())) { fillInIntent1 = new Intent(); fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); Loading Loading @@ -613,7 +611,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, if (fillInIntent == null) fillInIntent = new Intent(); fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION); if (launchSameComponentAdjacently(intent, position, INVALID_TASK_ID)) { if (launchSameAppAdjacently(position, intent)) { final ComponentName launching = intent.getIntent().getComponent(); if (supportMultiInstancesSplit(launching)) { // To prevent accumulating large number of instances in the background, reuse task Loading Loading @@ -647,47 +645,52 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.startIntent(intent, fillInIntent, position, options); } /** Returns {@code true} if it's launching the same component on both sides of the split. */ private boolean launchSameComponentAdjacently(@Nullable PendingIntent pendingIntent, @SplitPosition int position, int taskId) { if (pendingIntent == null || pendingIntent.getIntent() == null) return false; final ComponentName launchingActivity = pendingIntent.getIntent().getComponent(); if (launchingActivity == null) return false; if (taskId != INVALID_TASK_ID) { final ActivityManager.RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(taskId); if (taskInfo != null) { return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity); @Nullable private String getPackageName(Intent intent) { if (intent == null || intent.getComponent() == null) { return null; } return false; return intent.getComponent().getPackageName(); } if (!isSplitScreenVisible()) { // Split screen is not yet activated, check if the current top running task is valid to // split together. final ActivityManager.RunningTaskInfo topRunningTask = mRecentTasksOptional private boolean launchSameAppAdjacently(@SplitPosition int position, PendingIntent pendingIntent) { ActivityManager.RunningTaskInfo adjacentTaskInfo = null; if (isSplitScreenVisible()) { adjacentTaskInfo = getTaskInfo(SplitLayout.reversePosition(position)); } else { adjacentTaskInfo = mRecentTasksOptional .map(recentTasks -> recentTasks.getTopRunningTask()).orElse(null); if (topRunningTask != null && isValidToEnterSplitScreen(topRunningTask)) { return Objects.equals(topRunningTask.baseIntent.getComponent(), launchingActivity); if (!isValidToEnterSplitScreen(adjacentTaskInfo)) { return false; } } if (adjacentTaskInfo == null) { return false; } // Compare to the adjacent side of the split to determine if this is launching the same // component adjacently. final ActivityManager.RunningTaskInfo pairedTaskInfo = getTaskInfo(SplitLayout.reversePosition(position)); final ComponentName pairedActivity = pairedTaskInfo != null ? pairedTaskInfo.baseIntent.getComponent() : null; return Objects.equals(launchingActivity, pairedActivity); final String targetPackageName = getPackageName(pendingIntent.getIntent()); final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent); return targetPackageName != null && targetPackageName.equals(adjacentPackageName); } private boolean launchSameAppAdjacently(PendingIntent pendingIntent, int taskId) { final ActivityManager.RunningTaskInfo adjacentTaskInfo = mTaskOrganizer.getRunningTaskInfo(taskId); if (adjacentTaskInfo == null) { return false; } final String targetPackageName = getPackageName(pendingIntent.getIntent()); final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent); return targetPackageName != null && targetPackageName.equals(adjacentPackageName); } private boolean launchSameComponentAdjacently(PendingIntent pendingIntent1, private boolean launchSameAppAdjacently(PendingIntent pendingIntent1, PendingIntent pendingIntent2) { return Objects.equals(pendingIntent1.getIntent().getComponent(), pendingIntent2.getIntent().getComponent()); final String targetPackageName = getPackageName(pendingIntent1.getIntent()); final String adjacentPackageName = getPackageName(pendingIntent2.getIntent()); return targetPackageName != null && targetPackageName.equals(adjacentPackageName); } @VisibleForTesting Loading @@ -695,9 +698,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, boolean supportMultiInstancesSplit(@Nullable ComponentName launching) { if (launching == null) return false; final String componentName = launching.flattenToString(); for (int i = 0; i < mMultiInstancesComponents.length; i++) { if (mMultiInstancesComponents[i].equals(componentName)) { final String packageName = launching.getPackageName(); for (int i = 0; i < mAppsSupportMultiInstances.length; i++) { if (mAppsSupportMultiInstances[i].equals(packageName)) { return true; } } Loading