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

Commit c583cc01 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Enhance error handling logic to restore split-screen" into tm-qpr-dev

parents 55b31cdc a7931fda
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -500,7 +500,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
                    || (taskInfo.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME
                    && taskInfo.isVisible);
            final boolean focusTaskChanged = (mLastFocusedTaskInfo == null
                    || mLastFocusedTaskInfo.taskId != taskInfo.taskId) && isFocusedOrHome;
                    || mLastFocusedTaskInfo.taskId != taskInfo.taskId
                    || mLastFocusedTaskInfo.getWindowingMode() != taskInfo.getWindowingMode())
                    && isFocusedOrHome;
            if (focusTaskChanged) {
                for (int i = 0; i < mFocusListeners.size(); i++) {
                    mFocusListeners.valueAt(i).onFocusTaskChanged(taskInfo);
+12 −20
Original line number Diff line number Diff line
@@ -24,8 +24,6 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;

import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
@@ -64,7 +62,6 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -102,7 +99,7 @@ import java.util.concurrent.Executor;
 */
// TODO(b/198577848): Implement split screen flicker test to consolidate CUJ of split screen.
public class SplitScreenController implements DragAndDropPolicy.Starter,
        RemoteCallable<SplitScreenController>, ShellTaskOrganizer.FocusListener {
        RemoteCallable<SplitScreenController> {
    private static final String TAG = SplitScreenController.class.getSimpleName();

    public static final int EXIT_REASON_UNKNOWN = 0;
@@ -150,8 +147,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    // outside the bounds of the roots by being reparented into a higher level fullscreen container
    private SurfaceControl mSplitTasksContainerLayer;

    private ActivityManager.RunningTaskInfo mFocusingTaskInfo;

    public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
            SyncTransactionQueue syncQueue, Context context,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
@@ -173,7 +168,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        mLogger = new SplitscreenEventLogger();
        mIconProvider = iconProvider;
        mRecentTasksOptional = recentTasks;
        mTaskOrganizer.addFocusListener(this);
    }

    public SplitScreen asSplitScreen() {
@@ -190,11 +184,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        return mMainExecutor;
    }

    @Override
    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
        mFocusingTaskInfo = taskInfo;
    }

    public void onOrganizerRegistered() {
        if (mStageCoordinator == null) {
            // TODO: Multi-display
@@ -213,6 +202,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        return mStageCoordinator;
    }

    public ActivityManager.RunningTaskInfo getFocusingTaskInfo() {
        return mStageCoordinator.getFocusingTaskInfo();
    }

    public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
        return mStageCoordinator.isValidToEnterSplitScreen(taskInfo);
    }

    @Nullable
    public ActivityManager.RunningTaskInfo getTaskInfo(@SplitPosition int splitPosition) {
        if (!isSplitScreenVisible() || splitPosition == SPLIT_POSITION_UNDEFINED) {
@@ -228,12 +225,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                && mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
    }

    public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
        return taskInfo.supportsMultiWindow
                && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
                && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
    }

    public @SplitPosition int getSplitPosition(int taskId) {
        return mStageCoordinator.getSplitPosition(taskId);
    }
@@ -470,8 +461,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            return Objects.equals(launchingActivity, pairedActivity);
        }

        if (mFocusingTaskInfo != null && isValidToEnterSplitScreen(mFocusingTaskInfo)) {
            return Objects.equals(mFocusingTaskInfo.baseIntent.getComponent(), launchingActivity);
        final ActivityManager.RunningTaskInfo taskInfo = getFocusingTaskInfo();
        if (taskInfo != null && isValidToEnterSplitScreen(taskInfo)) {
            return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity);
        }

        return false;
+37 −7
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;

import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
@@ -98,6 +100,7 @@ import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -138,7 +141,7 @@ import java.util.Optional;
 */
public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        DisplayController.OnDisplaysChangedListener, Transitions.TransitionHandler,
        ShellTaskOrganizer.TaskListener {
        ShellTaskOrganizer.TaskListener, ShellTaskOrganizer.FocusListener {

    private static final String TAG = StageCoordinator.class.getSimpleName();

@@ -176,6 +179,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private final Rect mTempRect1 = new Rect();
    private final Rect mTempRect2 = new Rect();

    private ActivityManager.RunningTaskInfo mFocusingTaskInfo;

    /**
     * A single-top root task which the split divider attached to.
     */
@@ -255,6 +260,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mDisplayController.addDisplayWindowListener(this);
        mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
        transitions.addHandler(this);
        mTaskOrganizer.addFocusListener(this);
    }

    @VisibleForTesting
@@ -1226,6 +1232,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                }
            }
        } else if (isSideStage && !mMainStage.isActive()) {
            if (mFocusingTaskInfo != null && !isValidToEnterSplitScreen(mFocusingTaskInfo)) {
                final WindowContainerTransaction wct = new WindowContainerTransaction();
                mSideStage.removeAllTasks(wct, true);
                wct.reorder(mRootTaskInfo.token, false /* onTop */);
                mTaskOrganizer.applyTransaction(wct);
                Slog.i(TAG, "cancel entering split screen, reason = "
                        + exitReasonToString(EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW));
            } else {
                final WindowContainerTransaction wct = new WindowContainerTransaction();
                mSplitLayout.init();
                prepareEnterSplitScreen(wct);
@@ -1233,6 +1247,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                mSyncQueue.runInSync(t ->
                        updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */));
            }
        }
        if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) {
            mShouldUpdateRecents = true;
            updateRecentTasksSplitPair();
@@ -1246,6 +1261,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
    }

    boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
        return taskInfo.supportsMultiWindow
                && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
                && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
    }

    ActivityManager.RunningTaskInfo getFocusingTaskInfo() {
        return mFocusingTaskInfo;
    }

    @Override
    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
        mFocusingTaskInfo = taskInfo;
    }

    @Override
    public void onSnappedToDismiss(boolean bottomOrRight, int reason) {
        final boolean mainStageToTop =
+4 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -90,12 +91,13 @@ public class SplitScreenControllerTests extends ShellTestCase {
    @Test
    public void testIsLaunchingAdjacently_notInSplitScreen() {
        doReturn(false).when(mSplitScreenController).isSplitScreenVisible();
        doReturn(true).when(mSplitScreenController).isValidToEnterSplitScreen(any());

        // Verify launching the same activity returns true.
        Intent startIntent = createStartIntent("startActivity");
        ActivityManager.RunningTaskInfo focusTaskInfo =
                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
        mSplitScreenController.onFocusTaskChanged(focusTaskInfo);
        doReturn(focusTaskInfo).when(mSplitScreenController).getFocusingTaskInfo();
        assertTrue(mSplitScreenController.isLaunchingAdjacently(
                startIntent, SPLIT_POSITION_TOP_OR_LEFT));

@@ -103,7 +105,7 @@ public class SplitScreenControllerTests extends ShellTestCase {
        Intent diffIntent = createStartIntent("diffActivity");
        focusTaskInfo =
                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, diffIntent);
        mSplitScreenController.onFocusTaskChanged(focusTaskInfo);
        doReturn(focusTaskInfo).when(mSplitScreenController).getFocusingTaskInfo();
        assertFalse(mSplitScreenController.isLaunchingAdjacently(
                startIntent, SPLIT_POSITION_TOP_OR_LEFT));
    }