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