1 /* 2 * 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.traces.surfaceflinger 18 19 import android.tools.common.datatypes.ActiveBuffer 20 import android.tools.common.datatypes.Color 21 import android.tools.common.datatypes.Rect 22 import android.tools.common.datatypes.RectF 23 import android.tools.common.datatypes.Region 24 import kotlin.js.JsExport 25 import kotlin.js.JsName 26 27 /** 28 * Common properties of a layer that are not related to their position in the hierarchy 29 * 30 * These properties are frequently stable throughout the trace and can be more efficiently cached 31 * than the full layers 32 */ 33 @JsExport 34 interface ILayerProperties { 35 val visibleRegion: Region? 36 @JsName("activeBuffer") val activeBuffer: ActiveBuffer 37 @JsName("flags") val flags: Int 38 @JsName("bounds") val bounds: RectF 39 @JsName("color") val color: Color 40 @JsName("isOpaque") val isOpaque: Boolean 41 @JsName("shadowRadius") val shadowRadius: Float 42 @JsName("cornerRadius") val cornerRadius: Float 43 @JsName("type") val type: String 44 @JsName("screenBounds") val screenBounds: RectF 45 @JsName("transform") val transform: Transform 46 @JsName("sourceBounds") val sourceBounds: RectF 47 @JsName("effectiveScalingMode") val effectiveScalingMode: Int 48 @JsName("bufferTransform") val bufferTransform: Transform 49 @JsName("hwcCompositionType") val hwcCompositionType: HwcCompositionType 50 @JsName("hwcCrop") val hwcCrop: RectF 51 @JsName("hwcFrame") val hwcFrame: Rect 52 @JsName("backgroundBlurRadius") val backgroundBlurRadius: Int 53 @JsName("crop") val crop: Rect 54 @JsName("isRelativeOf") val isRelativeOf: Boolean 55 @JsName("zOrderRelativeOfId") val zOrderRelativeOfId: Int 56 @JsName("stackId") val stackId: Int 57 @JsName("requestedTransform") val requestedTransform: Transform 58 @JsName("requestedColor") val requestedColor: Color 59 @JsName("cornerRadiusCrop") val cornerRadiusCrop: RectF 60 @JsName("inputTransform") val inputTransform: Transform 61 @JsName("inputRegion") val inputRegion: Region? 62 @JsName("excludesCompositionState") val excludesCompositionState: Boolean 63 64 @JsName("isScaling") 65 val isScaling: Boolean 66 get() = transform.isScaling 67 @JsName("isTranslating") 68 val isTranslating: Boolean 69 get() = transform.isTranslating 70 @JsName("isRotating") 71 val isRotating: Boolean 72 get() = transform.isRotating 73 74 /** 75 * Checks if the layer's active buffer is empty 76 * 77 * An active buffer is empty if it is not in the proto or if its height or width are 0 78 * 79 * @return 80 */ 81 @JsName("isActiveBufferEmpty") 82 val isActiveBufferEmpty: Boolean 83 get() = activeBuffer.isEmpty 84 85 /** 86 * Converts flags to human readable tokens. 87 * 88 * @return 89 */ 90 @JsName("verboseFlags") 91 val verboseFlags: String 92 get() { <lambda>null93 val tokens = Flag.values().filter { (it.value and flags) != 0 }.map { it.name } 94 95 return if (tokens.isEmpty()) { 96 "" 97 } else { 98 "${tokens.joinToString("|")} (0x${flags.toString(16)})" 99 } 100 } 101 102 /** 103 * Checks if the [Layer] has a color 104 * 105 * @return 106 */ 107 @JsName("fillsColor") 108 val fillsColor: Boolean 109 get() = color.isNotEmpty 110 111 /** 112 * Checks if the [Layer] draws a shadow 113 * 114 * @return 115 */ 116 @JsName("drawsShadows") 117 val drawsShadows: Boolean 118 get() = shadowRadius > 0 119 120 /** 121 * Checks if the [Layer] has blur 122 * 123 * @return 124 */ 125 @JsName("hasBlur") 126 val hasBlur: Boolean 127 get() = backgroundBlurRadius > 0 128 129 /** 130 * Checks if the [Layer] has rounded corners 131 * 132 * @return 133 */ 134 @JsName("hasRoundedCorners") 135 val hasRoundedCorners: Boolean 136 get() = cornerRadius > 0 137 138 /** 139 * Checks if the [Layer] draws has effects, which include: 140 * - is a color layer 141 * - is an effects layers which [fillsColor] or [drawsShadows] 142 * 143 * @return 144 */ 145 @JsName("hasEffects") 146 val hasEffects: Boolean 147 get() { 148 return fillsColor || drawsShadows 149 } 150 isAnimatingnull151 fun isAnimating(prevLayerState: ILayerProperties?): Boolean = 152 when (prevLayerState) { 153 // when there's no previous state, use a heuristic based on the transform 154 null -> !transform.isSimpleRotation 155 else -> 156 visibleRegion != prevLayerState.visibleRegion || 157 transform != prevLayerState.transform || 158 color != prevLayerState.color 159 } 160 } 161