1 /* <lambda>null2 * Copyright (C) 2021 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.server.wm.traces.common 18 19 import com.android.server.wm.traces.common.layers.Layer 20 import com.android.server.wm.traces.common.layers.BaseLayerTraceEntry 21 import com.android.server.wm.traces.common.layers.Transform 22 import com.android.server.wm.traces.common.layers.Transform.Companion.isFlagSet 23 import com.android.server.wm.traces.common.service.PlatformConsts 24 import com.android.server.wm.traces.common.windowmanager.WindowManagerState 25 import com.android.server.wm.traces.common.windowmanager.windows.WindowState 26 27 typealias DUMP = DeviceStateDump<WindowManagerState, BaseLayerTraceEntry> 28 29 object WindowManagerConditionsFactory { 30 private val navBarWindowName = FlickerComponentName.NAV_BAR.toWindowName() 31 private val navBarLayerName = FlickerComponentName.NAV_BAR.toLayerName() 32 private val statusBarWindowName = FlickerComponentName.STATUS_BAR.toWindowName() 33 private val statusBarLayerName = FlickerComponentName.STATUS_BAR.toLayerName() 34 35 /** 36 * Condition to check if the nav bar window is visible 37 */ 38 fun isNavBarVisible(): Condition<DUMP> = 39 ConditionList(listOf( 40 isNavBarWindowVisible(), isNavBarLayerVisible(), isNavBarLayerOpaque())) 41 42 /** 43 * Condition to check if the nav bar window is visible 44 */ 45 fun isNavBarWindowVisible(): Condition<DUMP> = 46 Condition("isNavBarWindowVisible") { 47 it.wmState.isWindowVisible(navBarWindowName) 48 } 49 50 /** 51 * Condition to check if the nav bar layer is visible 52 */ 53 fun isNavBarLayerVisible(): Condition<DUMP> = 54 isLayerVisible(navBarLayerName) 55 56 /** 57 * Condition to check if the nav bar layer is opaque 58 */ 59 fun isNavBarLayerOpaque(): Condition<DUMP> = 60 Condition("isNavBarLayerOpaque") { 61 (it.layerState.getLayerWithBuffer(navBarLayerName) 62 ?.color?.a ?: 0f) == 1f 63 } 64 65 /** 66 * Condition to check if the status bar window is visible 67 */ 68 fun isStatusBarVisible(): Condition<DUMP> = 69 ConditionList(listOf( 70 isStatusBarWindowVisible(), isStatusBarLayerVisible(), isStatusBarLayerOpaque())) 71 72 /** 73 * Condition to check if the nav bar window is visible 74 */ 75 fun isStatusBarWindowVisible(): 76 Condition<DUMP> = 77 Condition("isStatusBarWindowVisible") { 78 it.wmState.isWindowVisible(statusBarWindowName) 79 } 80 81 /** 82 * Condition to check if the nav bar layer is visible 83 */ 84 fun isStatusBarLayerVisible(): Condition<DUMP> = 85 isLayerVisible(statusBarLayerName) 86 87 /** 88 * Condition to check if the nav bar layer is opaque 89 */ 90 fun isStatusBarLayerOpaque(): Condition<DUMP> = 91 Condition("isStatusBarLayerOpaque") { 92 (it.layerState.getLayerWithBuffer(statusBarLayerName) 93 ?.color?.a ?: 0f) == 1f 94 } 95 96 fun isHomeActivityVisible(): Condition<DUMP> = 97 Condition("isHomeActivityVisible") { 98 it.wmState.homeActivity?.isVisible == true 99 } 100 101 fun isAppTransitionIdle( 102 displayId: Int 103 ): Condition<DUMP> = 104 Condition("isAppTransitionIdle[$displayId]") { 105 it.wmState.getDisplay(displayId) 106 ?.appTransitionState == WindowManagerState.APP_STATE_IDLE 107 } 108 109 fun containsActivity( 110 component: FlickerComponentName 111 ): Condition<DUMP> = 112 Condition("containsActivity[${component.toActivityName()}]") { 113 it.wmState.containsActivity(component.toActivityName()) 114 } 115 116 fun containsWindow( 117 component: FlickerComponentName 118 ): Condition<DUMP> = 119 Condition("containsWindow[${component.toWindowName()}]") { 120 it.wmState.containsWindow(component.toWindowName()) 121 } 122 123 fun isWindowSurfaceShown( 124 windowName: String 125 ): Condition<DUMP> = 126 Condition("isWindowSurfaceShown[$windowName]") { 127 it.wmState.isWindowSurfaceShown(windowName) 128 } 129 130 fun isWindowSurfaceShown( 131 component: FlickerComponentName 132 ): Condition<DUMP> = 133 isWindowSurfaceShown(component.toWindowName()) 134 135 fun isActivityVisible( 136 component: FlickerComponentName 137 ): Condition<DUMP> = 138 Condition("isActivityVisible[${component.toActivityName()}]") { 139 it.wmState.isActivityVisible(component.toActivityName()) 140 } 141 142 fun isWMStateComplete(): Condition<DUMP> = 143 Condition("isWMStateComplete") { 144 it.wmState.isComplete() 145 } 146 147 fun hasRotation( 148 expectedRotation: Int, 149 displayId: Int 150 ): Condition<DUMP> { 151 val hasRotationCondition = Condition<DUMP>( 152 "hasRotation[$expectedRotation, display=$displayId]") { 153 val currRotation = it.wmState.getRotation(displayId) 154 currRotation == expectedRotation 155 } 156 return ConditionList(listOf( 157 hasRotationCondition, 158 isLayerVisible(FlickerComponentName.ROTATION).negate(), 159 isLayerVisible(FlickerComponentName.BACK_SURFACE).negate(), 160 hasLayersAnimating().negate() 161 )) 162 } 163 164 fun isWindowVisible( 165 component: FlickerComponentName, 166 displayId: Int = 0 167 ): Condition<DUMP> = 168 ConditionList( 169 containsActivity(component), 170 containsWindow(component), 171 isActivityVisible(component), 172 isWindowSurfaceShown(component), 173 isAppTransitionIdle(displayId)) 174 175 fun isLayerVisible( 176 layerName: String 177 ): Condition<DUMP> = 178 Condition("isLayerVisible[$layerName]") { 179 it.layerState.isVisible(layerName) 180 } 181 182 fun isLayerVisible( 183 layerId: Int 184 ): Condition<DUMP> = 185 Condition("isLayerVisible[layerId=$layerId]") { 186 it.layerState.getLayerById(layerId)?.isVisible ?: false 187 } 188 189 fun isLayerColorAlphaOne( 190 component: FlickerComponentName 191 ): Condition<DUMP> = 192 Condition("isLayerColorAlphaOne[${component.toLayerName()}]") { 193 val layers = it.layerState.getVisibleLayersByName(component) 194 layers.any { layer -> layer.color.a == 1.0f } 195 } 196 197 fun isLayerColorAlphaOne( 198 layerId: Int 199 ): Condition<DUMP> = 200 Condition("isLayerColorAlphaOne[$layerId]") { 201 val layer = it.layerState.getLayerById(layerId) 202 layer?.color?.a == 1.0f 203 } 204 205 fun isLayerTransformFlagSet( 206 component: FlickerComponentName, 207 transform: Int 208 ): Condition<DUMP> = 209 Condition("isLayerTransformFlagSet[" + 210 "${component.toLayerName()},transform=$transform]") { 211 val layers = it.layerState.getVisibleLayersByName(component) 212 layers.any { layer -> isTransformFlagSet(layer, transform) } 213 } 214 215 fun isLayerTransformFlagSet( 216 layerId: Int, 217 transform: Int 218 ): Condition<DUMP> = 219 Condition("isLayerTransformFlagSet[$layerId, $transform]") { 220 val layer = it.layerState.getLayerById(layerId) 221 layer?.transform?.type?.isFlagSet(transform) ?: false 222 } 223 224 fun isLayerTransformIdentity( 225 layerId: Int 226 ): Condition<DUMP> = 227 ConditionList(listOf( 228 isLayerTransformFlagSet(layerId, Transform.SCALE_VAL).negate(), 229 isLayerTransformFlagSet(layerId, Transform.TRANSLATE_VAL).negate(), 230 isLayerTransformFlagSet(layerId, Transform.ROTATE_VAL).negate() 231 )) 232 233 private fun isTransformFlagSet(layer: Layer, transform: Int): Boolean = 234 layer.transform.type?.isFlagSet(transform) ?: false 235 236 fun BaseLayerTraceEntry.getVisibleLayersByName( 237 component: FlickerComponentName 238 ): List<Layer> = visibleLayers.filter { it.name.contains(component.toLayerName()) } 239 240 fun isLayerVisible( 241 component: FlickerComponentName 242 ): Condition<DUMP> = 243 isLayerVisible(component.toLayerName()) 244 245 fun hasLayersAnimating(): Condition<DUMP> = 246 Condition("hasLayersAnimating") { 247 it.layerState.isAnimating() 248 } 249 250 fun isPipWindowLayerSizeMatch( 251 layerId: Int 252 ): Condition<DUMP> = 253 Condition("isPipWindowLayerSizeMatch[layerId=$layerId]") { 254 val pipWindow = it.wmState.pinnedWindows 255 .firstOrNull { pinnedWindow -> pinnedWindow.layerId == layerId } 256 ?: error("Unable to find window with layerId $layerId") 257 val windowHeight = pipWindow.frame.height.toFloat() 258 val windowWidth = pipWindow.frame.width.toFloat() 259 260 val pipLayer = it.layerState.getLayerById(layerId) 261 val layerHeight = pipLayer?.sourceBounds?.height 262 ?: error("Unable to find layer with id $layerId") 263 val layerWidth = pipLayer.sourceBounds.width 264 265 windowHeight == layerHeight && windowWidth == layerWidth 266 } 267 268 fun hasPipWindow(): Condition<DUMP> = 269 Condition("hasPipWindow") { 270 it.wmState.hasPipWindow() 271 } 272 273 fun isImeShown( 274 displayId: Int 275 ): Condition<DUMP> = 276 ConditionList(listOf( 277 isImeOnDisplay(displayId), 278 isLayerVisible(FlickerComponentName.IME), 279 isImeSurfaceShown(), 280 isWindowSurfaceShown(FlickerComponentName.IME.toWindowName()) 281 )) 282 283 private fun isImeOnDisplay( 284 displayId: Int 285 ): Condition<DUMP> = 286 Condition("isImeOnDisplay[$displayId]") { 287 it.wmState.inputMethodWindowState?.displayId == displayId 288 } 289 290 private fun isImeSurfaceShown(): 291 Condition<DUMP> = 292 Condition("isImeSurfaceShown") { 293 it.wmState.inputMethodWindowState?.isSurfaceShown == true 294 } 295 296 fun isAppLaunchEnded(taskId: Int): 297 Condition<DUMP> = 298 Condition("containsVisibleAppLaunchWindow[taskId=$taskId]") { dump -> 299 val windowStates = dump.wmState.getRootTask(taskId)?.activities?.flatMap { 300 it.children.filterIsInstance<WindowState>() 301 } 302 windowStates != null && windowStates.none { window -> 303 window.attributes.type == PlatformConsts.TYPE_APPLICATION_STARTING && 304 window.isVisible 305 } 306 } 307 }