• 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 {perfetto} from 'protos/windowmanager/latest/static';
19import {com} from 'protos/windowmanager/udc/static';
20import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder';
21import {TreeNodeUtils} from 'test/unit/tree_node_utils';
22import {TraceRect} from 'trace/trace_rect';
23import {TraceRectBuilder} from 'trace/trace_rect_builder';
24import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node';
25import {RectsComputation} from './rects_computation';
26
27type DisplayContentProto =
28  | com.android.server.wm.IDisplayContentProto
29  | perfetto.protos.IDisplayContentProto;
30type WindowStateProto =
31  | com.android.server.wm.IWindowStateProto
32  | perfetto.protos.IWindowStateProto;
33
34describe('WindowManager RectsComputation', () => {
35  let hierarchyRoot: HierarchyTreeNode;
36  let computation: RectsComputation;
37  let displayContent: HierarchyTreeNode;
38
39  beforeEach(() => {
40    hierarchyRoot = new HierarchyTreeBuilder()
41      .setId('WindowManagerState')
42      .setName('root')
43      .setProperties({focusedApp: 'testApp'})
44      .setChildren([
45        {
46          id: 1,
47          name: 'Test Display',
48          properties: {
49            id: 1,
50            name: 'Test Display',
51            displayInfo: {
52              logicalWidth: 5,
53              logicalHeight: 5,
54            },
55          } as DisplayContentProto,
56        },
57        {
58          id: 2,
59          name: 'Focused Display',
60          properties: {
61            id: 2,
62            name: 'Focused Display',
63            displayInfo: {
64              logicalWidth: 5,
65              logicalHeight: 5,
66            },
67            focusedApp: 'testApp',
68          } as DisplayContentProto,
69        },
70      ])
71      .build();
72    displayContent = assertDefined(
73      hierarchyRoot.getChildByName('Test Display'),
74    );
75    computation = new RectsComputation();
76  });
77
78  it('makes display rects', () => {
79    const expectedDisplayRects = [
80      new TraceRectBuilder()
81        .setX(0)
82        .setY(0)
83        .setWidth(5)
84        .setHeight(5)
85        .setId('1 Test Display')
86        .setName('Display - Test Display')
87        .setCornerRadius(0)
88        .setDepth(0)
89        .setGroupId(1)
90        .setIsVisible(false)
91        .setIsDisplay(true)
92        .setIsActiveDisplay(false)
93        .setIsSpy(false)
94        .build(),
95
96      new TraceRectBuilder()
97        .setX(0)
98        .setY(0)
99        .setWidth(5)
100        .setHeight(5)
101        .setId('2 Focused Display')
102        .setName('Display - Focused Display')
103        .setCornerRadius(0)
104        .setDepth(0)
105        .setGroupId(2)
106        .setIsVisible(false)
107        .setIsDisplay(true)
108        .setIsActiveDisplay(true)
109        .setIsSpy(false)
110        .build(),
111    ];
112
113    computation.setRoot(hierarchyRoot).executeInPlace();
114
115    const displayRects = displayContent
116      .getRects()
117      ?.concat(
118        assertDefined(
119          hierarchyRoot.getChildByName('Focused Display')?.getRects(),
120        ),
121      );
122
123    expect(displayRects).toEqual(expectedDisplayRects);
124  });
125
126  it('makes window state rects', () => {
127    const state1Node = TreeNodeUtils.makeHierarchyNode({
128      id: 'WindowState',
129      name: 'state1',
130      displayId: 1,
131      isComputedVisible: true,
132      windowFrames: {
133        frame: {left: 0, top: 0, right: 1, bottom: 1},
134      },
135      attributes: {
136        alpha: 0.5,
137      },
138    } as WindowStateProto);
139
140    state1Node.addOrReplaceChild(
141      TreeNodeUtils.makeHierarchyNode({
142        id: 'WindowState',
143        name: 'state2',
144        displayId: 1,
145        isComputedVisible: false,
146        windowFrames: {
147          frame: {left: 0, top: 0, right: 2, bottom: 2},
148        },
149        attributes: {
150          alpha: 0.5,
151        },
152      } as WindowStateProto),
153    );
154    displayContent.addOrReplaceChild(state1Node);
155
156    const expectedRects: TraceRect[] = [
157      new TraceRectBuilder()
158        .setX(0)
159        .setY(0)
160        .setWidth(1)
161        .setHeight(1)
162        .setId('WindowState state1')
163        .setName('state1')
164        .setCornerRadius(0)
165        .setDepth(1)
166        .setGroupId(1)
167        .setIsVisible(true)
168        .setIsDisplay(false)
169        .setOpacity(0.5)
170        .setIsSpy(false)
171        .build(),
172
173      new TraceRectBuilder()
174        .setX(0)
175        .setY(0)
176        .setWidth(2)
177        .setHeight(2)
178        .setId('WindowState state2')
179        .setName('state2')
180        .setCornerRadius(0)
181        .setDepth(2)
182        .setGroupId(1)
183        .setIsVisible(false)
184        .setIsDisplay(false)
185        .setOpacity(0.5)
186        .setIsSpy(false)
187        .build(),
188    ];
189
190    computation.setRoot(hierarchyRoot).executeInPlace();
191
192    const rects: TraceRect[] = [];
193    hierarchyRoot.forEachNodeDfs((node) => {
194      const nodeRects = node.getRects();
195      if (nodeRects && nodeRects.every((rect) => !rect.isDisplay)) {
196        rects.push(...nodeRects);
197      }
198    });
199
200    expect(rects).toEqual(expectedRects);
201  });
202});
203