1/*
2 * Copyright 2017, 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 {transform, nanos_to_string, get_visible_chip} from './transform.js'
18
19function transform_window(entry) {
20  var chips = [];
21  var renderIdentifier = (id) => shortenComponentName(id.title) + "@" + id.hashCode;
22  var visible = entry.windowContainer.visible;
23  function transform_rect(rect, label) {
24    var r = rect || {};
25    return {
26        left: r.left || 0,
27        right: r.right || 0,
28        top: r.top || 0,
29        bottom: r.bottom || 0,
30        label,
31    }
32  }
33  var name = renderIdentifier(entry.identifier)
34  var rect = transform_rect((entry.windowFrames || entry).frame, name);
35
36  if (visible) {
37    chips.push(get_visible_chip());
38  } else {
39    rect = undefined;
40  }
41
42  return transform({
43    obj: entry,
44    kind: 'window',
45    name,
46    children: [
47      [entry.childWindows, transform_window],
48      [entry.windowContainer.children.reverse(), transform_window_container_child],
49    ],
50    rect,
51    highlight: rect,
52    chips: chips,
53    visible: visible,
54  });
55}
56
57function transform_activity_record(entry) {
58  return transform({
59    obj: entry,
60    kind: 'activityRecord',
61    name: entry.name,
62    children: [
63      [entry.windowToken.windows, transform_window],
64      [entry.windowToken.windowContainer.children.reverse(), transform_window_container_child],
65    ],
66  });
67}
68
69function transform_task(entry) {
70  return transform({
71    obj: entry,
72    kind: 'task',
73    name: entry.id || 0,
74    children: [
75      [entry.tasks, transform_task],
76      [entry.activities, transform_activity_record],
77      [entry.windowContainer.children.reverse(), transform_window_container_child],
78    ],
79  });
80}
81
82function transform_stack(entry) {
83  return transform({
84    obj: entry,
85    kind: 'stack',
86    name: entry.id || 0,
87    children: [
88      [entry.tasks, transform_task],
89    ],
90  });
91}
92
93function transform_window_token(entry) {
94  return transform({
95    obj: entry,
96    kind: 'winToken',
97    name: '',
98    children: [
99      [entry.windows, transform_window],
100      [entry.windowContainer.children.reverse(), transform_window_container_child],
101    ],
102  });
103}
104
105function transform_below(entry) {
106  return transform({
107    obj: entry,
108    kind: 'belowAppWindow',
109    name: '',
110    children: [
111      [entry.windows, transform_window],
112    ],
113  });
114}
115
116function transform_above(entry) {
117  return transform({
118    obj: entry,
119    kind: 'aboveAppWindow',
120    name: '',
121    children: [
122      [entry.windows, transform_window],
123    ],
124  });
125}
126
127function transform_ime(entry) {
128  return transform({
129    obj: entry,
130    kind: 'imeWindow',
131    name: '',
132    children: [
133      [entry.windows, transform_window],
134    ],
135  });
136}
137
138function transform_window_container_child(entry) {
139  if (entry.displayArea != null) {return transform_display_area(entry.displayArea)}
140  if (entry.displayContent != null) {return transform_display_content(entry.displayContent)}
141  if (entry.task != null) {return transform_task(entry.task)}
142  if (entry.activity != null) {return transform_activity_record(entry.activity)}
143  if (entry.windowToken != null) {return transform_window_token(entry.windowToken)}
144  if (entry.window != null) {return transform_window(entry.window)}
145
146  // The WindowContainerChild may be unknown
147  return transform({
148      obj: entry,
149      kind: 'WindowContainerChild',
150      name: '',
151      children: [[entry.windowContainer.children.reverse(), transform_window_container_child],]
152  });
153}
154
155
156function transform_display_area(entry) {
157  return transform({
158    obj: entry,
159    kind: 'DisplayArea',
160    name: entry.name,
161    children: [
162      [entry.windowContainer.children.reverse(), transform_window_container_child],
163    ],
164  });
165}
166
167function transform_display_content(entry) {
168  var bounds = {
169    width: entry.displayInfo.logicalWidth || 0,
170    height: entry.displayInfo.logicalHeight || 0,
171  };
172
173  return transform({
174    obj: entry,
175    kind: 'display',
176    name: entry.id || 0,
177    children: [
178      [entry.aboveAppWindows, transform_above],
179      [entry.imeWindows, transform_ime],
180      [entry.stacks, transform_stack],
181      [entry.tasks, transform_task],
182      [entry.belowAppWindows, transform_below],
183      [entry.windowContainer.children.reverse(), transform_window_container_child],
184    ],
185    bounds,
186  });
187}
188
189function transform_policy(entry) {
190  return transform({
191    obj: entry,
192    kind: 'policy',
193    name: 'policy',
194    children: [],
195  });
196}
197
198function transform_window_service(entry) {
199  return transform({
200    obj: entry,
201    kind: 'service',
202    name: '',
203    children: [
204      [entry.rootWindowContainer.displays, transform_display_content],
205      [entry.rootWindowContainer.windowContainer.children.reverse(),
206        transform_window_container_child],
207    [[entry.policy], transform_policy],
208    ],
209    timestamp: entry.elapsedRealtimeNanos,
210  });
211}
212
213function transform_entry(entry) {
214  return transform({
215    obj: entry,
216    kind: 'entry',
217    name: nanos_to_string(entry.elapsedRealtimeNanos),
218    children: [
219      [entry.windowManagerService.rootWindowContainer.displays, transform_display_content],
220      [entry.windowManagerService.rootWindowContainer.windowContainer.children.reverse(),
221          transform_window_container_child],
222      [[entry.windowManagerService.policy], transform_policy],
223    ],
224    timestamp: entry.elapsedRealtimeNanos,
225    stableId: 'entry',
226  });
227}
228
229function transform_window_trace(entries) {
230  return transform({
231    obj: entries,
232    kind: 'entries',
233    name: 'entries',
234    children: [
235      [entries.entry, transform_entry],
236    ],
237  });
238}
239
240function shortenComponentName(name) {
241  if (!name.includes('/')) {
242    return name
243  }
244  var split = name.split('/');
245  var pkg = split[0];
246  var clazz = split.slice(1).join('/');
247  if (clazz.startsWith(pkg + '.')) {
248    clazz = clazz.slice(pkg.length + 1);
249    return [pkg, clazz].join('/');
250  }
251  return name;
252}
253
254export {transform_window_service, transform_window_trace};
255