Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21db01d2 authored by Jerry Chang's avatar Jerry Chang
Browse files

Update to check package name for multi-instnaces split

Update to check package name to determine whether it is launching the
same app adjacently or not instead of checking component name. This is
to cover more cases when the running task was started from a different
component with its app icon.

Bug: 255224696
Test: atest WMShellUnitTests
Test: check with the repro steps in bug.
Change-Id: I135d6cf518cda603484824dfae61290672f443c7
parent 5e432142
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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>
+48 −45
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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;
@@ -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
@@ -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() {
@@ -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);
@@ -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);
@@ -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);
@@ -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
@@ -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
@@ -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;
            }
        }