• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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 android.tools.common.flicker.config.splitscreen
18 
19 import android.tools.common.flicker.ScenarioInstance
20 import android.tools.common.flicker.assertors.ComponentTemplate
21 import android.tools.common.flicker.config.ScenarioId
22 import android.tools.common.traces.component.ComponentNameMatcher
23 import android.tools.common.traces.component.FullComponentIdMatcher
24 import android.tools.common.traces.component.IComponentMatcher
25 import android.tools.common.traces.surfaceflinger.LayersTrace
26 import android.tools.common.traces.wm.Transition
27 
28 object Components {
29     val SPLIT_SCREEN_DIVIDER =
30         ComponentTemplate("SplitScreenDivider") {
31             ComponentNameMatcher("", "StageCoordinatorSplitDivider#")
32         }
33     val SPLIT_SCREEN_PRIMARY_APP =
34         ComponentTemplate("SPLIT_SCREEN_PRIMARY_APP") { scenarioInstance: ScenarioInstance ->
35             val associatedTransition =
36                 scenarioInstance.associatedTransition
37                     ?: error(
38                         "Can only extract SPLIT_SCREEN_PRIMARY_APP from scenario with transition"
39                     )
40             val layersTrace =
41                 scenarioInstance.reader.readLayersTrace() ?: error("Missing layers trace")
42 
43             when (scenarioInstance.type) {
44                 ScenarioId("SPLIT_SCREEN_ENTER") -> {
45                     Components.getSplitscreenOpeningComponentMatchers(
46                             associatedTransition,
47                             layersTrace
48                         )[0]
49                 }
50                 ScenarioId("SPLIT_SCREEN_EXIT") -> {
51                     TODO(
52                         "Not implemented :: ${scenarioInstance.type} :: " +
53                             "${scenarioInstance.associatedTransition}"
54                     )
55                 }
56                 ScenarioId("SPLIT_SCREEN_RESIZE") -> {
57                     val change = associatedTransition.changes.first()
58                     FullComponentIdMatcher(change.windowId, change.layerId)
59                 }
60                 else -> error("Unsupported transition type")
61             }
62         }
63     val SPLIT_SCREEN_SECONDARY_APP =
64         ComponentTemplate("SPLIT_SCREEN_SECONDARY_APP") { scenarioInstance: ScenarioInstance ->
65             val associatedTransition =
66                 scenarioInstance.associatedTransition
67                     ?: error(
68                         "Can only extract SPLIT_SCREEN_SECONDARY_APP from scenario with transition"
69                     )
70             val layersTrace =
71                 scenarioInstance.reader.readLayersTrace() ?: error("Missing layers trace")
72 
73             when (scenarioInstance.type) {
74                 ScenarioId("SPLIT_SCREEN_ENTER") -> {
75                     Components.getSplitscreenOpeningComponentMatchers(
76                             associatedTransition,
77                             layersTrace
78                         )[1]
79                 }
80                 ScenarioId("SPLIT_SCREEN_EXIT") -> {
81                     TODO(
82                         "Not implemented :: ${scenarioInstance.type} :: " +
83                             "${scenarioInstance.associatedTransition}"
84                     )
85                 }
86                 ScenarioId("SPLIT_SCREEN_RESIZE") -> {
87                     val change = associatedTransition.changes.last()
88                     FullComponentIdMatcher(change.windowId, change.layerId)
89                 }
90                 else -> error("Unsupported transition type")
91             }
92         }
93 
94     private fun getSplitscreenOpeningComponentMatchers(
95         associatedTransition: Transition,
96         layersTrace: LayersTrace
97     ): List<IComponentMatcher> {
98         // Task (part of changes)
99         // - Task (part of changes)
100         //   - SplitDecorManager
101         //   - Task for app (part of changes)
102         // - Task (part of changes)
103         //   - SplitDecorManager
104         //   - Task for app (part of changes)
105         // - SplitWindowManager
106         //   - StageCoordinatorSplitDividerLeash#1378
107 
108         val layerIds = associatedTransition.changes.map { it.layerId }
109         val layers =
110             associatedTransition.changes.map { change ->
111                 layersTrace.entries.last().flattenedLayers.first { it.id == change.layerId }
112             }
113 
114         val appIds = layers.filter { layerIds.contains(it.parent?.parent?.id) }.map { it.id }
115 
116         val componentMatchers =
117             associatedTransition.changes
118                 .filter { appIds.contains(it.layerId) }
119                 .map { FullComponentIdMatcher(it.windowId, it.layerId) }
120 
121         require(componentMatchers.size == 2) {
122             "Expected to get 2 splitscreen apps but got ${componentMatchers.size}"
123         }
124 
125         return componentMatchers
126     }
127 }
128