• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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