• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2024 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
17import {assertDefined} from 'common/assert_utils';
18import {Transform} from 'parsers/surface_flinger/transform_utils';
19import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder';
20import {TraceRectBuilder} from 'trace/trace_rect_builder';
21import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node';
22import {UiRect} from 'viewers/components/rects/ui_rect';
23import {UiRectBuilder} from 'viewers/components/rects/ui_rect_builder';
24import {UI_RECT_FACTORY} from './ui_rect_factory';
25
26describe('UI_RECT_FACTORY', () => {
27  let hierarchyRoot: HierarchyTreeNode;
28  let node1: HierarchyTreeNode;
29  let node2: HierarchyTreeNode;
30
31  beforeEach(() => {
32    hierarchyRoot = new HierarchyTreeBuilder()
33      .setId('TreeEntry')
34      .setName('root')
35      .setChildren([
36        {id: 1, name: 'node1'},
37        {id: 2, name: 'node2'},
38      ])
39      .build();
40    node1 = assertDefined(hierarchyRoot.getChildByName('node1'));
41    node2 = assertDefined(hierarchyRoot.getChildByName('node2'));
42  });
43
44  it('extracts rects from hierarchy tree', () => {
45    buildRectAndSetToNode(node1, 0);
46    buildRectAndSetToNode(node2, 1);
47
48    const expectedUiRect1 = new UiRectBuilder()
49      .setX(0)
50      .setY(0)
51      .setWidth(1)
52      .setHeight(1)
53      .setId('1 node1')
54      .setLabel('node1')
55      .setCornerRadius(0)
56      .setGroupId(0)
57      .setTransform(Transform.EMPTY.matrix)
58      .setIsVisible(true)
59      .setIsDisplay(false)
60      .setIsActiveDisplay(false)
61      .setIsClickable(true)
62      .setHasContent(false)
63      .setDepth(0)
64      .setOpacity(0.5)
65      .build();
66
67    const expectedUiRect2 = new UiRectBuilder()
68      .setX(0)
69      .setY(0)
70      .setWidth(1)
71      .setHeight(1)
72      .setId('2 node2')
73      .setLabel('node2')
74      .setCornerRadius(0)
75      .setGroupId(0)
76      .setTransform(Transform.EMPTY.matrix)
77      .setIsVisible(true)
78      .setIsDisplay(false)
79      .setIsActiveDisplay(false)
80      .setIsClickable(true)
81      .setHasContent(false)
82      .setDepth(1)
83      .setOpacity(0.5)
84      .build();
85
86    const expectedRects: UiRect[] = [expectedUiRect1, expectedUiRect2];
87
88    expect(UI_RECT_FACTORY.makeUiRects(hierarchyRoot)).toEqual(expectedRects);
89  });
90
91  it('makes rects with data from trace rect', () => {
92    buildRectAndSetToNode(node2, 1, 5, 10, true, true, false, true);
93
94    const expectedUiRect2 = new UiRectBuilder()
95      .setX(0)
96      .setY(0)
97      .setWidth(5)
98      .setHeight(10)
99      .setId('2 node2')
100      .setLabel('node2')
101      .setCornerRadius(0)
102      .setGroupId(0)
103      .setTransform(Transform.EMPTY.matrix)
104      .setIsVisible(true)
105      .setIsDisplay(true)
106      .setIsActiveDisplay(true)
107      .setIsClickable(false)
108      .setHasContent(false)
109      .setDepth(1)
110      .setOpacity(0.5)
111      .build();
112
113    const expectedRects: UiRect[] = [expectedUiRect2];
114
115    expect(UI_RECT_FACTORY.makeUiRects(hierarchyRoot)).toEqual(expectedRects);
116  });
117
118  it('handles depth order different to dfs order', () => {
119    buildRectAndSetToNode(node1, 1);
120    buildRectAndSetToNode(node2, 0);
121
122    const expectedUiRect1 = new UiRectBuilder()
123      .setX(0)
124      .setY(0)
125      .setWidth(1)
126      .setHeight(1)
127      .setId('1 node1')
128      .setLabel('node1')
129      .setCornerRadius(0)
130      .setGroupId(0)
131      .setTransform(Transform.EMPTY.matrix)
132      .setIsVisible(true)
133      .setIsDisplay(false)
134      .setIsActiveDisplay(false)
135      .setIsClickable(true)
136      .setHasContent(false)
137      .setDepth(1)
138      .setOpacity(0.5)
139      .build();
140
141    const expectedUiRect2 = new UiRectBuilder()
142      .setX(0)
143      .setY(0)
144      .setWidth(1)
145      .setHeight(1)
146      .setId('2 node2')
147      .setLabel('node2')
148      .setCornerRadius(0)
149      .setGroupId(0)
150      .setTransform(Transform.EMPTY.matrix)
151      .setIsVisible(true)
152      .setIsDisplay(false)
153      .setIsActiveDisplay(false)
154      .setIsClickable(true)
155      .setHasContent(false)
156      .setDepth(0)
157      .setOpacity(0.5)
158      .build();
159
160    const expectedRects: UiRect[] = [expectedUiRect1, expectedUiRect2];
161    expect(UI_RECT_FACTORY.makeUiRects(hierarchyRoot)).toEqual(expectedRects);
162  });
163
164  it('makes vc rects with groupId, content and empty label', () => {
165    const GROUP_ID = 11;
166
167    buildRectAndSetToNode(node1, 1);
168    buildRectAndSetToNode(node2, 0);
169
170    const expectedVcUiRect1 = new UiRectBuilder()
171      .setX(0)
172      .setY(0)
173      .setWidth(1)
174      .setHeight(1)
175      .setId('1 node1')
176      .setLabel('')
177      .setCornerRadius(0)
178      .setGroupId(GROUP_ID)
179      .setTransform(Transform.EMPTY.matrix)
180      .setIsVisible(true)
181      .setIsDisplay(false)
182      .setIsActiveDisplay(false)
183      .setIsClickable(true)
184      .setHasContent(true)
185      .setDepth(1)
186      .setOpacity(0.5)
187      .build();
188
189    const expectedVcUiRect2 = new UiRectBuilder()
190      .setX(0)
191      .setY(0)
192      .setWidth(1)
193      .setHeight(1)
194      .setId('2 node2')
195      .setLabel('')
196      .setCornerRadius(0)
197      .setGroupId(GROUP_ID)
198      .setTransform(Transform.EMPTY.matrix)
199      .setIsVisible(true)
200      .setIsDisplay(false)
201      .setIsActiveDisplay(false)
202      .setIsClickable(true)
203      .setHasContent(true)
204      .setDepth(0)
205      .setOpacity(0.5)
206      .build();
207
208    const expectedRects: UiRect[] = [expectedVcUiRect1, expectedVcUiRect2];
209    expect(UI_RECT_FACTORY.makeVcUiRects(hierarchyRoot, GROUP_ID)).toEqual(
210      expectedRects,
211    );
212  });
213
214  it('discards vc trace rects with zero height or width', () => {
215    const GROUP_ID = 11;
216
217    buildRectAndSetToNode(node1, 1, 0, 1);
218    buildRectAndSetToNode(node2, 0, 1, 0);
219
220    expect(UI_RECT_FACTORY.makeVcUiRects(hierarchyRoot, GROUP_ID)).toEqual([]);
221  });
222
223  it('makes input rects', () => {
224    // The root of the hierarchy should contain the display info in the primary rects.
225    buildRectAndSetToNode(hierarchyRoot, 0, 1, 1, true, true);
226    // The rest of the nodes should contain input windows in the secondary rects.
227    // The opacity is determined by whether the window is a spy and display.
228    buildRectAndSetToNode(node1, 1, 1, 1, false, false, true);
229    buildRectAndSetToNode(node2, 2, 1, 1, false, false, false);
230
231    function hasContent(id: string) {
232      return id === node1.id;
233    }
234
235    const expectedRootRect = new UiRectBuilder()
236      .setX(0)
237      .setY(0)
238      .setWidth(1)
239      .setHeight(1)
240      .setId('TreeEntry root')
241      .setLabel('root')
242      .setCornerRadius(0)
243      .setGroupId(0)
244      .setTransform(Transform.EMPTY.matrix)
245      .setIsVisible(true)
246      .setIsDisplay(true)
247      .setIsActiveDisplay(false)
248      .setIsClickable(true)
249      .setHasContent(false)
250      .setDepth(0)
251      .setOpacity(1)
252      .build();
253
254    const expectedInputRect1 = new UiRectBuilder()
255      .setX(0)
256      .setY(0)
257      .setWidth(1)
258      .setHeight(1)
259      .setId('1 node1')
260      .setLabel('node1')
261      .setCornerRadius(0)
262      .setGroupId(0)
263      .setTransform(Transform.EMPTY.matrix)
264      .setIsVisible(true)
265      .setIsDisplay(false)
266      .setIsActiveDisplay(false)
267      .setIsClickable(true)
268      .setHasContent(true)
269      .setDepth(1)
270      .setOpacity(0.25)
271      .build();
272
273    const expectedInputRect2 = new UiRectBuilder()
274      .setX(0)
275      .setY(0)
276      .setWidth(1)
277      .setHeight(1)
278      .setId('2 node2')
279      .setLabel('node2')
280      .setCornerRadius(0)
281      .setGroupId(0)
282      .setTransform(Transform.EMPTY.matrix)
283      .setIsVisible(true)
284      .setIsDisplay(false)
285      .setIsActiveDisplay(false)
286      .setIsClickable(true)
287      .setHasContent(false)
288      .setDepth(2)
289      .setOpacity(0.9)
290      .build();
291
292    const expectedRects: UiRect[] = [
293      expectedRootRect,
294      expectedInputRect1,
295      expectedInputRect2,
296    ];
297    expect(UI_RECT_FACTORY.makeInputRects(hierarchyRoot, hasContent)).toEqual(
298      expectedRects,
299    );
300  });
301
302  function buildRectAndSetToNode(
303    node: HierarchyTreeNode,
304    depth: number,
305    width = 1,
306    height = 1,
307    isPrimary = true,
308    isDisplay = false,
309    isSpy = false,
310    isActiveDisplay = false,
311  ) {
312    const rect = new TraceRectBuilder()
313      .setX(0)
314      .setY(0)
315      .setWidth(width)
316      .setHeight(height)
317      .setId(node.id)
318      .setName(node.name)
319      .setCornerRadius(0)
320      .setTransform(Transform.EMPTY.matrix)
321      .setDepth(depth)
322      .setGroupId(0)
323      .setIsVisible(true)
324      .setIsDisplay(isDisplay)
325      .setIsActiveDisplay(isActiveDisplay)
326      .setOpacity(0.5)
327      .setIsSpy(isSpy)
328      .build();
329
330    isPrimary ? node.setRects([rect]) : node.setSecondaryRects([rect]);
331  }
332});
333