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

Commit 0a42cd3e authored by Shuming Hao's avatar Shuming Hao Committed by Android (Google) Code Review
Browse files

Merge "[1/N] Add one root task per display to support multi split" into main

parents 5757704a bbbf9e3d
Loading
Loading
Loading
Loading
+53 −2
Original line number Diff line number Diff line
@@ -15,10 +15,15 @@
 */

package com.android.wm.shell.splitscreen

import android.app.ActivityManager
import android.hardware.display.DisplayManager
import android.view.Display
import android.view.Display.DEFAULT_DISPLAY
import android.view.SurfaceControl
import android.window.TransitionInfo
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags
import com.android.wm.shell.common.split.SplitLayout
import com.android.wm.shell.protolog.ShellProtoLogGroup

@@ -94,7 +99,8 @@ class SplitMultiDisplayHelper(private val displayManager: DisplayManager) {
     * @return The root task info, or null if not found.
     */
    fun getDisplayRootTaskInfo(displayId: Int): ActivityManager.RunningTaskInfo? {
        return displayTaskMap[displayId]?.rootTaskInfo
        val targetDisplayId = if (Flags.enableMultiDisplaySplit()) displayId else DEFAULT_DISPLAY
        return displayTaskMap[targetDisplayId]?.rootTaskInfo
    }

    /**
@@ -107,7 +113,52 @@ class SplitMultiDisplayHelper(private val displayManager: DisplayManager) {
        displayId: Int,
        rootTaskInfo: ActivityManager.RunningTaskInfo?
    ) {
        val hierarchy = displayTaskMap.computeIfAbsent(displayId) { SplitTaskHierarchy() }
        val targetDisplayId = if (Flags.enableMultiDisplaySplit()) displayId else DEFAULT_DISPLAY
        val hierarchy = displayTaskMap.computeIfAbsent(targetDisplayId) { SplitTaskHierarchy() }
        hierarchy.rootTaskInfo = rootTaskInfo
    }

    fun getDisplayRootTaskLeash(displayId: Int): SurfaceControl? {
        val targetDisplayId = if (Flags.enableMultiDisplaySplit()) displayId else DEFAULT_DISPLAY
        return displayTaskMap[targetDisplayId]?.rootTaskLeash
    }

    fun setDisplayRootTaskLeash(
        displayId: Int,
        leash: SurfaceControl?
    ) {
        val targetDisplayId = if (Flags.enableMultiDisplaySplit()) displayId else DEFAULT_DISPLAY
        val hierarchy = displayTaskMap.computeIfAbsent(targetDisplayId) { SplitTaskHierarchy() }
        hierarchy.rootTaskLeash = leash
    }

    companion object {
        /**
         * Returns the display ID associated with the first change in the given [TransitionInfo].
         * It prioritize the end display ID of the change. If the end display ID is invalid, fall back
         * to the start display ID. If TransitionInfo has no changes, or if the first change has both
         * invalid end display ID and invalid start display ID, this method returns DEFAULT_DISPLAY.
         *
         * @param info the [TransitionInfo] containing transition changes
         * @return a valid display ID, or DEFAULT_DISPLAY as a fallback
         */
        @JvmStatic
        fun getTransitionDisplayId(info: TransitionInfo): Int {
            if (!Flags.enableMultiDisplaySplit()) (
                return DEFAULT_DISPLAY
            )

            if (info.changes.isEmpty()) {
                return DEFAULT_DISPLAY
            }
            // TODO: b/393217881 - take in a specific change instead of the first change for
            //  multi display split related tasks.
            val change: TransitionInfo.Change = info.changes.first()
            var displayId = change.endDisplayId
            if (displayId == Display.INVALID_DISPLAY) {
                displayId = change.startDisplayId
            }
            return if (displayId != Display.INVALID_DISPLAY) displayId else DEFAULT_DISPLAY
        }
    }
}
 No newline at end of file
+132 −55

File changed.

Preview size limit exceeded, changes collapsed.

+7 −4
Original line number Diff line number Diff line
@@ -80,14 +80,17 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
    @StageType private final int mId;
    /** Callback interface for listening to changes in a split-screen stage. */
    public interface StageListenerCallbacks {
        void onRootTaskAppeared();
        /** Called when the root task on current display appears. */
        void onRootTaskAppeared(ActivityManager.RunningTaskInfo taskInfo);

        void onStageVisibilityChanged(StageTaskListener stageTaskListener);

        void onChildTaskStatusChanged(StageTaskListener stage, int taskId, boolean present,
                boolean visible);

        void onRootTaskVanished();

        /** Called when the root task on current display vanishes. */
        void onRootTaskVanished(ActivityManager.RunningTaskInfo taskInfo);

        void onNoLongerSupportMultiWindow(StageTaskListener stageTaskListener,
                ActivityManager.RunningTaskInfo taskInfo);
@@ -220,7 +223,7 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
                    mRootTaskInfo.configuration,
                    mIconProvider);
            mHasRootTask = true;
            mCallbacks.onRootTaskAppeared();
            mCallbacks.onRootTaskAppeared(taskInfo);
            if (mVisible != mRootTaskInfo.isVisible) {
                mVisible = mRootTaskInfo.isVisible;
                mCallbacks.onStageVisibilityChanged(this);
@@ -281,7 +284,7 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
            mHasRootTask = false;
            mVisible = false;
            mHasChildren = false;
            mCallbacks.onRootTaskVanished();
            mCallbacks.onRootTaskVanished(taskInfo);
            mRootTaskInfo = null;
            mRootLeash = null;
            mSyncQueue.runInSync(t -> {
+3 −0
Original line number Diff line number Diff line
@@ -21,9 +21,11 @@ import android.hardware.display.DisplayManager
import android.view.Display
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.window.flags.Flags.enableMultiDisplaySplit
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.split.SplitLayout
import com.google.common.truth.Truth.assertThat
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -52,6 +54,7 @@ class SplitMultiDisplayHelperTests : ShellTestCase() {

    @Before
    fun setUp() {
        assumeTrue(enableMultiDisplaySplit())
        MockitoAnnotations.initMocks(this)
        mockDisplay1 = mockDisplayManager.getDisplay(Display.DEFAULT_DISPLAY) ?: mock(Display::class.java)
        mockDisplay2 = mockDisplayManager.getDisplay(Display.DEFAULT_DISPLAY + 1) ?: mock(Display::class.java)
+1 −2
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import android.app.ActivityManager;
import android.os.SystemProperties;
import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;

@@ -116,7 +115,7 @@ public final class StageTaskListenerTests extends ShellTestCase {
    @Test
    public void testRootTaskAppeared() {
        assertThat(mStageTaskListener.mRootTaskInfo.taskId).isEqualTo(mRootTask.taskId);
        verify(mCallbacks).onRootTaskAppeared();
        verify(mCallbacks).onRootTaskAppeared(mRootTask);
        verify(mCallbacks, never()).onStageVisibilityChanged(mStageTaskListener);
    }