• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.parser.layers
18 
19 import android.graphics.Rect
20 import android.surfaceflinger.nano.Common
21 import android.surfaceflinger.nano.Common.RegionProto
22 import android.surfaceflinger.nano.Display
23 import android.surfaceflinger.nano.Layers
24 import com.android.server.wm.traces.common.ActiveBuffer
25 import com.android.server.wm.traces.common.Color
26 import com.android.server.wm.traces.common.RectF
27 import com.android.server.wm.traces.common.Size
28 import com.android.server.wm.traces.common.layers.BaseLayerTraceEntry
29 import com.android.server.wm.traces.common.layers.Layer
30 import com.android.server.wm.traces.common.layers.LayerTraceEntryBuilder
31 import com.android.server.wm.traces.common.region.Region
32 
33 class LayerTraceEntryLazy(
34     override val timestamp: Long,
35     override val hwcBlob: String = "",
36     override val where: String = "",
37     private val ignoreLayersStackMatchNoDisplay: Boolean = true,
38     private val ignoreLayersInVirtualDisplay: Boolean = true,
39     private var displayProtos: Array<Display.DisplayProto> = emptyArray(),
40     private var layerProtos: Array<Layers.LayerProto> = emptyArray(),
41     private val orphanLayerCallback: ((Layer) -> Boolean)? = null
42 ) : BaseLayerTraceEntry() {
43 
<lambda>null44     private val parsedEntry by lazy {
45         val layers = layerProtos.map { newLayer(it) }.toTypedArray()
46         val displays = displayProtos.map { newDisplay(it) }.toTypedArray()
47         val builder = LayerTraceEntryBuilder(timestamp, layers, displays, hwcBlob, where)
48             .setOrphanLayerCallback(orphanLayerCallback)
49             .ignoreLayersStackMatchNoDisplay(ignoreLayersStackMatchNoDisplay)
50             .ignoreVirtualDisplay(ignoreLayersInVirtualDisplay)
51         displayProtos = emptyArray()
52         layerProtos = emptyArray()
53         builder.build()
54     }
55 
56     override val displays: Array<com.android.server.wm.traces.common.layers.Display>
57         get() = parsedEntry.displays
58 
59     override val flattenedLayers: Array<Layer>
60         get() = parsedEntry.flattenedLayers
61 
62     companion object {
63 
64         @JvmStatic
newLayernull65         fun newLayer(proto: Layers.LayerProto): Layer {
66             // Differentiate between the cases when there's no HWC data on
67             // the trace, and when the visible region is actually empty
68             val activeBuffer = proto.activeBuffer.toBuffer()
69             var visibleRegion = proto.visibleRegion.toRegion()
70             if (visibleRegion == null && activeBuffer.isEmpty) {
71                 visibleRegion = Region.EMPTY
72             }
73             val crop = getCrop(proto.crop)
74             return Layer(
75                 proto.name ?: "",
76                 proto.id,
77                 proto.parent,
78                 proto.z,
79                 visibleRegion,
80                 activeBuffer,
81                 proto.flags,
82                 proto.bounds?.toRectF() ?: RectF.EMPTY,
83                 proto.color.toColor(),
84                 proto.isOpaque,
85                 proto.shadowRadius,
86                 proto.cornerRadius,
87                 proto.type ?: "",
88                 proto.screenBounds?.toRectF(),
89                 Transform(proto.transform, proto.position),
90                 proto.sourceBounds?.toRectF() ?: RectF.EMPTY,
91                 proto.currFrame,
92                 proto.effectiveScalingMode,
93                 Transform(proto.bufferTransform, position = null),
94                 proto.hwcCompositionType,
95                 proto.hwcCrop.toRectF() ?: RectF.EMPTY,
96                 proto.hwcFrame.toRect(),
97                 proto.backgroundBlurRadius,
98                 crop,
99                 proto.isRelativeOf,
100                 proto.zOrderRelativeOf,
101                 proto.layerStack
102             )
103         }
104 
newDisplaynull105         fun newDisplay(
106             proto: Display.DisplayProto
107         ): com.android.server.wm.traces.common.layers.Display {
108             return com.android.server.wm.traces.common.layers.Display(
109                 proto.id.toULong(),
110                 proto.name,
111                 proto.layerStack,
112                 proto.size.toSize(),
113                 proto.layerStackSpaceRect.toRect(),
114                 Transform(proto.transform, position = null),
115                 proto.isVirtual
116             )
117         }
118 
119         @JvmStatic
toRectFnull120         fun Layers.FloatRectProto?.toRectF(): RectF? {
121             return this?.let {
122                 RectF(left = left, top = top, right = right, bottom = bottom)
123             }
124         }
125 
126         @JvmStatic
toSizenull127         fun Common.SizeProto?.toSize(): Size {
128             return this?.let {
129                 Size(this.w, this.h)
130             } ?: Size.EMPTY
131         }
132 
133         @JvmStatic
toColornull134         fun Common.ColorProto?.toColor(): Color {
135             if (this == null) {
136                 return Color.EMPTY
137             }
138             return Color(r, g, b, a)
139         }
140 
141         @JvmStatic
toBuffernull142         fun Layers.ActiveBufferProto?.toBuffer(): ActiveBuffer {
143             if (this == null) {
144                 return ActiveBuffer.EMPTY
145             }
146             return ActiveBuffer(width, height, stride, format)
147         }
148 
149         @JvmStatic
getCropnull150         fun getCrop(crop: Common.RectProto?): com.android.server.wm.traces.common.Rect? {
151             return when {
152                 crop == null -> com.android.server.wm.traces.common.Rect.EMPTY
153                 // crop (0,0) (-1,-1) means no crop
154                 crop.right == -1 && crop.left == 0 && crop.bottom == -1 && crop.top == 0 ->
155                     null
156                 (crop.right - crop.left) <= 0 || (crop.bottom - crop.top) <= 0 ->
157                     com.android.server.wm.traces.common.Rect.EMPTY
158                 else ->
159                     com.android.server.wm.traces.common.Rect(
160                         crop.left, crop.top, crop.right, crop.bottom
161                     )
162             }
163         }
164 
165         /**
166          * Extracts [Rect] from [RegionProto] by returning a rect that encompasses all
167          * the rectangles making up the region.
168          */
169         @JvmStatic
RegionProtonull170         fun RegionProto?.toRegion(): Region? {
171             return if (this == null) {
172                 null
173             } else {
174                 val rects = this.rect.map { it.toRect() }.toTypedArray()
175                 return Region(rects)
176             }
177         }
178 
179         @JvmStatic
toRectnull180         fun Common.RectProto?.toRect(): com.android.server.wm.traces.common.Rect {
181             return if ((this == null) ||
182                 ((this.right - this.left) <= 0 || (this.bottom - this.top) <= 0)
183             ) {
184                 com.android.server.wm.traces.common.Rect.EMPTY
185             } else {
186                 com.android.server.wm.traces.common.Rect(
187                     this.left, this.top, this.right, this.bottom
188                 )
189             }
190         }
191     }
192 }
193