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