• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.splitscreen
18 import android.app.ActivityManager
19 import android.hardware.display.DisplayManager
20 import android.view.SurfaceControl
21 import com.android.internal.protolog.ProtoLog
22 import com.android.wm.shell.common.split.SplitLayout
23 import com.android.wm.shell.protolog.ShellProtoLogGroup
24 
25 /**
26  * Helper class for managing split-screen functionality across multiple displays.
27  */
28 class SplitMultiDisplayHelper(private val displayManager: DisplayManager) {
29 
30     /**
31      * A map that stores the [SplitTaskHierarchy] associated with each display ID.
32      * The keys are display IDs (integers), and the values are [SplitTaskHierarchy] objects,
33      * which encapsulate the information needed to manage split-screen tasks on that display.
34      */
35     private val displayTaskMap: MutableMap<Int, SplitTaskHierarchy> = mutableMapOf()
36 
37     /**
38      * SplitTaskHierarchy is a class that encapsulates the components required
39      * for managing split-screen functionality on a specific display.
40      */
41     data class SplitTaskHierarchy(
42         var rootTaskInfo: ActivityManager.RunningTaskInfo? = null,
43         var mainStage: StageTaskListener? = null,
44         var sideStage: StageTaskListener? = null,
45         var rootTaskLeash: SurfaceControl? = null,
46         var splitLayout: SplitLayout? = null
47     )
48 
49     /**
50      * Returns a list of all currently connected display IDs.
51      *
52      * @return An ArrayList of display IDs.
53      */
54     fun getDisplayIds(): ArrayList<Int> {
55         val displayIds = ArrayList<Int>()
56         displayManager.displays?.forEach { display ->
57             displayIds.add(display.displayId)
58         }
59         return displayIds
60     }
61 
62     /**
63      * Swaps the [SplitTaskHierarchy] objects associated with two different display IDs.
64      *
65      * @param firstDisplayId  The ID of the first display.
66      * @param secondDisplayId The ID of the second display.
67      */
68     fun swapDisplayTaskHierarchy(firstDisplayId: Int, secondDisplayId: Int) {
69         if (!displayTaskMap.containsKey(firstDisplayId) || !displayTaskMap.containsKey(secondDisplayId)) {
70             ProtoLog.w(
71                 ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
72                 "Attempted to swap task hierarchies for invalid display IDs: %d, %d",
73                 firstDisplayId,
74                 secondDisplayId
75             )
76             return
77         }
78 
79         if (firstDisplayId == secondDisplayId) {
80             return
81         }
82 
83         val firstHierarchy = displayTaskMap[firstDisplayId]
84         val secondHierarchy = displayTaskMap[secondDisplayId]
85 
86         displayTaskMap[firstDisplayId] = checkNotNull(secondHierarchy)
87         displayTaskMap[secondDisplayId] = checkNotNull(firstHierarchy)
88     }
89 
90     /**
91      * Gets the root task info for the given display ID.
92      *
93      * @param displayId The ID of the display.
94      * @return The root task info, or null if not found.
95      */
96     fun getDisplayRootTaskInfo(displayId: Int): ActivityManager.RunningTaskInfo? {
97         return displayTaskMap[displayId]?.rootTaskInfo
98     }
99 
100     /**
101      * Sets the root task info for the given display ID.
102      *
103      * @param displayId    The ID of the display.
104      * @param rootTaskInfo The root task info to set.
105      */
106     fun setDisplayRootTaskInfo(
107         displayId: Int,
108         rootTaskInfo: ActivityManager.RunningTaskInfo?
109     ) {
110         val hierarchy = displayTaskMap.computeIfAbsent(displayId) { SplitTaskHierarchy() }
111         hierarchy.rootTaskInfo = rootTaskInfo
112     }
113 }