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