• 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 */
16import {Component, Input} from '@angular/core';
17import {Layer} from 'trace/flickerlib/common';
18
19@Component({
20  selector: 'property-groups',
21  template: `
22    <div class="group">
23      <h3 class="group-header mat-subheading-2">Visibility</h3>
24      <div class="left-column">
25        <p class="mat-body-1 flags">
26          <span class="mat-body-2">Flags:</span>
27          &ngsp;
28          {{ item.verboseFlags ? item.verboseFlags : item.flags }}
29        </p>
30        <p *ngFor="let reason of summary()" class="mat-body-1">
31          <span class="mat-body-2">{{ reason.key }}:</span>
32          &ngsp;
33          {{ reason.value }}
34        </p>
35      </div>
36    </div>
37    <mat-divider></mat-divider>
38    <div class="group">
39      <h3 class="group-header mat-subheading-2">Geometry</h3>
40      <div class="left-column">
41        <p class="column-header mat-small">Calculated</p>
42        <p class="property mat-body-2">Transform:</p>
43        <transform-matrix
44          [transform]="item.transform"
45          [formatFloat]="formatFloat"></transform-matrix>
46        <p class="mat-body-1">
47          <span
48            class="mat-body-2"
49            matTooltip="Raw value read from proto.bounds. This is the buffer size or
50              requested crop cropped by parent bounds."
51            >Crop:</span
52          >
53          &ngsp;
54          {{ item.bounds }}
55        </p>
56
57        <p class="mat-body-1">
58          <span
59            class="mat-body-2"
60            matTooltip="Raw value read from proto.screenBounds. This is the calculated crop
61              transformed."
62            >Final Bounds:</span
63          >
64          &ngsp;
65          {{ item.screenBounds }}
66        </p>
67      </div>
68      <div class="right-column">
69        <p class="column-header mat-small">Requested</p>
70        <p class="property mat-body-2">Transform:</p>
71        <transform-matrix
72          [transform]="item.requestedTransform"
73          [formatFloat]="formatFloat"></transform-matrix>
74        <p class="mat-body-1">
75          <span class="mat-body-2">Crop:</span>
76          &ngsp;
77          {{ item.crop ? item.crop : '[empty]' }}
78        </p>
79      </div>
80    </div>
81    <mat-divider></mat-divider>
82    <div class="group">
83      <h3 class="group-header mat-subheading-2">Buffer</h3>
84      <div class="left-column">
85        <p class="mat-body-1">
86          <span class="mat-body-2">Size:</span>
87          &ngsp;
88          {{ item.activeBuffer }}
89        </p>
90        <p class="mat-body-1">
91          <span class="mat-body-2">Frame Number:</span>
92          &ngsp;
93          {{ item.currFrame }}
94        </p>
95        <p class="mat-body-1">
96          <span
97            class="mat-body-2"
98            matTooltip="Rotates or flips the buffer in place. Used with display transform
99              hint to cancel out any buffer transformation when sending to
100              HWC."
101            >Transform:</span
102          >
103          &ngsp;
104          {{ item.bufferTransform }}
105        </p>
106      </div>
107      <div class="right-column">
108        <p class="mat-body-1">
109          <span
110            class="mat-body-2"
111            matTooltip="Scales buffer to the frame by overriding the requested transform
112              for this item."
113            >Destination Frame:</span
114          >
115          &ngsp;
116          {{ getDestinationFrame() }}
117        </p>
118        <p *ngIf="hasIgnoreDestinationFrame()" class="mat-body-1">
119          Destination Frame ignored because item has eIgnoreDestinationFrame flag set.
120        </p>
121      </div>
122    </div>
123    <mat-divider></mat-divider>
124    <div class="group">
125      <h3 class="group-header mat-subheading-2">Hierarchy</h3>
126      <div class="left-column">
127        <p class="mat-body-1">
128          <span class="mat-body-2">z-order:</span>
129          &ngsp;
130          {{ item.z }}
131        </p>
132        <p class="mat-body-1">
133          <span
134            class="mat-body-2"
135            matTooltip="item is z-ordered relative to its relative parents but its bounds
136              and other properties are inherited from its parents."
137            >relative parent:</span
138          >
139          &ngsp;
140          {{ item.zOrderRelativeOfId == -1 ? 'none' : item.zOrderRelativeOfId }}
141        </p>
142      </div>
143    </div>
144    <mat-divider></mat-divider>
145    <div class="group">
146      <h3 class="group-header mat-subheading-2">Effects</h3>
147      <div class="left-column">
148        <p class="column-header mat-small">Calculated</p>
149        <p class="mat-body-1">
150          <span class="mat-body-2">Color:</span>
151          &ngsp;
152          {{ item.color }}
153        </p>
154        <p class="mat-body-1">
155          <span class="mat-body-2">Shadow:</span>
156          &ngsp;
157          {{ item.shadowRadius }} px
158        </p>
159        <p class="mat-body-1">
160          <span class="mat-body-2">Corner Radius:</span>
161          &ngsp;
162          {{ formatFloat(item.cornerRadius) }} px
163        </p>
164        <p class="mat-body-1">
165          <span
166            class="mat-body-2"
167            matTooltip="Crop used to define the bounds of the corner radii. If the bounds
168              are greater than the item bounds then the rounded corner will not
169              be visible."
170            >Corner Radius Crop:</span
171          >
172          &ngsp;
173          {{ item.cornerRadiusCrop }}
174        </p>
175        <p class="mat-body-1">
176          <span class="mat-body-2">Blur:</span>
177          &ngsp;
178          {{ item.proto?.backgroundBlurRadius ? item.proto?.backgroundBlurRadius : 0 }} px
179        </p>
180      </div>
181      <div class="right-column">
182        <p class="column-header mat-small">Requested</p>
183        <p class="mat-body-1">
184          <span class="mat-body-2">Color:</span>
185          &ngsp;
186          {{ item.requestedColor }}
187        </p>
188        <p class="mat-body-1">
189          <span class="mat-body-2">Shadow:</span>
190          &ngsp;
191          {{ item.proto?.requestedShadowRadius ? item.proto?.requestedShadowRadius : 0 }} px
192        </p>
193        <p class="mat-body-1">
194          <span class="mat-body-2">Corner Radius:</span>
195          &ngsp;
196          {{
197            item.proto?.requestedCornerRadius ? formatFloat(item.proto?.requestedCornerRadius) : 0
198          }}
199          px
200        </p>
201      </div>
202    </div>
203    <mat-divider></mat-divider>
204    <div class="group">
205      <h3 class="group-header mat-subheading-2">Input</h3>
206      <ng-container *ngIf="hasInputChannel()">
207        <div class="left-column">
208          <p class="property mat-body-2">To Display Transform:</p>
209          <transform-matrix
210            [transform]="item.inputTransform"
211            [formatFloat]="formatFloat"></transform-matrix>
212          <p class="mat-body-1">
213            <span class="mat-body-2">Touchable Region:</span>
214            &ngsp;
215            {{ item.inputRegion }}
216          </p>
217        </div>
218        <div class="right-column">
219          <p class="column-header mat-small">Config</p>
220          <p class="mat-body-1">
221            <span class="mat-body-2">Focusable:</span>
222            &ngsp;
223            {{ item.proto?.inputWindowInfo.focusable }}
224          </p>
225          <p class="mat-body-1">
226            <span class="mat-body-2">Crop touch region with item:</span>
227            &ngsp;
228            {{
229              item.proto?.inputWindowInfo.cropLayerId &lt;= 0
230                ? "none"
231                : item.proto?.inputWindowInfo.cropLayerId
232            }}
233          </p>
234          <p class="mat-body-1">
235            <span class="mat-body-2">Replace touch region with crop:</span>
236            &ngsp;
237            {{ item.proto?.inputWindowInfo.replaceTouchableRegionWithCrop }}
238          </p>
239        </div>
240      </ng-container>
241      <div *ngIf="!hasInputChannel()" class="left-column">
242        <p class="mat-body-1">
243          <span class="mat-body-2">Input channel:</span>
244          &ngsp; not set
245        </p>
246      </div>
247    </div>
248  `,
249  styles: [
250    `
251      .group {
252        display: flex;
253        flex-direction: row;
254        padding: 8px;
255      }
256
257      .group-header {
258        width: 80px;
259        color: gray;
260      }
261
262      .left-column {
263        flex: 1;
264        padding: 0 5px;
265      }
266
267      .right-column {
268        flex: 1;
269        border: 1px solid var(--border-color);
270        border-left-width: 5px;
271        padding: 0 5px;
272      }
273
274      .column-header {
275        color: gray;
276      }
277    `,
278  ],
279})
280export class PropertyGroupsComponent {
281  @Input() item!: Layer;
282
283  hasInputChannel() {
284    return this.item.proto?.inputWindowInfo;
285  }
286
287  getDestinationFrame() {
288    const frame = this.item.proto?.destinationFrame;
289    if (frame) {
290      return ` left: ${frame.left}, top: ${frame.top}, right: ${frame.right}, bottom: ${frame.bottom}`;
291    } else return '';
292  }
293
294  hasIgnoreDestinationFrame() {
295    return (this.item.flags & 0x400) === 0x400;
296  }
297
298  formatFloat(num: number) {
299    return Math.round(num * 100) / 100;
300  }
301
302  summary(): TreeSummary {
303    const summary = [];
304
305    if (this.item?.visibilityReason?.length > 0) {
306      let reason = '';
307      if (Array.isArray(this.item.visibilityReason)) {
308        reason = this.item.visibilityReason.join(', ');
309      } else {
310        reason = this.item.visibilityReason;
311      }
312
313      summary.push({key: 'Invisible due to', value: reason});
314    }
315
316    if (this.item?.occludedBy?.length > 0) {
317      summary.push({
318        key: 'Occluded by',
319        value: this.item.occludedBy.map((it: any) => it.id).join(', '),
320      });
321    }
322
323    if (this.item?.partiallyOccludedBy?.length > 0) {
324      summary.push({
325        key: 'Partially occluded by',
326        value: this.item.partiallyOccludedBy.map((it: any) => it.id).join(', '),
327      });
328    }
329
330    if (this.item?.coveredBy?.length > 0) {
331      summary.push({
332        key: 'Covered by',
333        value: this.item.coveredBy.map((it: any) => it.id).join(', '),
334      });
335    }
336
337    return summary;
338  }
339}
340
341type TreeSummary = Array<{key: string; value: string}>;
342