xref: /aosp_15_r20/development/tools/winscope/src/parsers/window_manager/custom_query_utils.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1/*
2 * Copyright (C) 2023 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 {perfetto} from 'protos/windowmanager/latest/static';
17import {com} from 'protos/windowmanager/udc/static';
18import {
19  CustomQueryParserResultTypeMap,
20  CustomQueryType,
21} from 'trace/custom_query';
22
23type WindowsTokenAndTitle =
24  CustomQueryParserResultTypeMap[CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE];
25
26type ActivityRecordProto =
27  | com.android.server.wm.IActivityRecordProto
28  | perfetto.protos.IActivityRecordProto;
29type DisplayAreaProto =
30  | com.android.server.wm.IDisplayAreaProto
31  | perfetto.protos.DisplayAreaProto;
32type DisplayContentProto =
33  | com.android.server.wm.IDisplayContentProto
34  | perfetto.protos.DisplayContentProto;
35type RootWindowContainerProto =
36  | com.android.server.wm.IRootWindowContainerProto
37  | perfetto.protos.IRootWindowContainerProto;
38type TaskFragmentProto =
39  | com.android.server.wm.ITaskFragmentProto
40  | perfetto.protos.ITaskFragmentProto;
41type TaskProto = com.android.server.wm.ITaskProto | perfetto.protos.ITaskProto;
42type WindowContainerProto =
43  | com.android.server.wm.IWindowContainerProto
44  | perfetto.protos.IWindowContainerProto;
45type WindowStateProto =
46  | com.android.server.wm.IWindowStateProto
47  | perfetto.protos.IWindowStateProto;
48type WindowTokenProto =
49  | com.android.server.wm.IWindowTokenProto
50  | perfetto.protos.IWindowTokenProto;
51
52export class WmCustomQueryUtils {
53  private static readonly NA = 'n/a';
54
55  static parseWindowsTokenAndTitle(
56    rootWindowContainer: RootWindowContainerProto,
57    result: WindowsTokenAndTitle,
58  ) {
59    const token =
60      rootWindowContainer?.windowContainer?.identifier?.hashCode?.toString(
61        16,
62      ) ?? WmCustomQueryUtils.NA;
63    const title =
64      rootWindowContainer?.windowContainer?.identifier?.title ??
65      WmCustomQueryUtils.NA;
66    result.push({token, title});
67    WmCustomQueryUtils.parseWindowContainerProto(
68      rootWindowContainer?.windowContainer,
69      result,
70    );
71  }
72
73  private static parseWindowContainerProto(
74    proto: WindowContainerProto | null | undefined,
75    result: WindowsTokenAndTitle,
76  ) {
77    if (!proto) {
78      return;
79    }
80
81    for (const windowContainerChildProto of proto?.children ?? []) {
82      WmCustomQueryUtils.parseActivityRecordProto(
83        windowContainerChildProto.activity,
84        result,
85      );
86      WmCustomQueryUtils.parseDisplayAreaProto(
87        windowContainerChildProto.displayArea,
88        result,
89      );
90      WmCustomQueryUtils.parseDisplayContentProto(
91        windowContainerChildProto.displayContent,
92        result,
93      );
94      WmCustomQueryUtils.parseTaskProto(windowContainerChildProto.task, result);
95      WmCustomQueryUtils.parseTaskFragmentProto(
96        windowContainerChildProto.taskFragment,
97        result,
98      );
99      WmCustomQueryUtils.parseWindowStateProto(
100        windowContainerChildProto.window,
101        result,
102      );
103      WmCustomQueryUtils.parseWindowContainerProto(
104        windowContainerChildProto.windowContainer,
105        result,
106      );
107      WmCustomQueryUtils.parseWindowTokenProto(
108        windowContainerChildProto.windowToken,
109        result,
110      );
111    }
112  }
113
114  private static parseActivityRecordProto(
115    proto: ActivityRecordProto | null | undefined,
116    result: WindowsTokenAndTitle,
117  ) {
118    if (!proto) {
119      return;
120    }
121    const token =
122      proto.windowToken?.hashCode?.toString(16) ?? WmCustomQueryUtils.NA;
123    const title = proto.name ?? WmCustomQueryUtils.NA;
124    result.push({token, title});
125    WmCustomQueryUtils.parseWindowContainerProto(
126      proto.windowToken?.windowContainer,
127      result,
128    );
129  }
130
131  private static parseDisplayAreaProto(
132    proto: DisplayAreaProto | null | undefined,
133    result: WindowsTokenAndTitle,
134  ) {
135    if (!proto) {
136      return;
137    }
138    const token =
139      proto.windowContainer?.identifier?.hashCode?.toString(16) ??
140      WmCustomQueryUtils.NA;
141    const title = proto.name ?? WmCustomQueryUtils.NA;
142    result.push({token, title});
143    WmCustomQueryUtils.parseWindowContainerProto(proto.windowContainer, result);
144  }
145
146  private static parseDisplayContentProto(
147    proto: DisplayContentProto | null | undefined,
148    result: WindowsTokenAndTitle,
149  ) {
150    if (!proto) {
151      return;
152    }
153    const token =
154      proto.rootDisplayArea?.windowContainer?.identifier?.hashCode?.toString(
155        16,
156      ) ?? WmCustomQueryUtils.NA;
157    const title = proto.displayInfo?.name ?? WmCustomQueryUtils.NA;
158    result.push({token, title});
159    WmCustomQueryUtils.parseWindowContainerProto(
160      proto.rootDisplayArea?.windowContainer,
161      result,
162    );
163  }
164
165  private static parseTaskProto(
166    proto: TaskProto | null | undefined,
167    result: WindowsTokenAndTitle,
168  ) {
169    if (!proto) {
170      return;
171    }
172    const token =
173      proto.taskFragment?.windowContainer?.identifier?.hashCode?.toString(16) ??
174      WmCustomQueryUtils.NA;
175    const title =
176      proto.taskFragment?.windowContainer?.identifier?.title ??
177      WmCustomQueryUtils.NA;
178    result.push({token, title});
179    for (const activity of proto.activities ?? []) {
180      WmCustomQueryUtils.parseActivityRecordProto(activity, result);
181    }
182    WmCustomQueryUtils.parseTaskFragmentProto(proto.taskFragment, result);
183  }
184
185  private static parseTaskFragmentProto(
186    proto: TaskFragmentProto | null | undefined,
187    result: WindowsTokenAndTitle,
188  ) {
189    if (!proto) {
190      return;
191    }
192    WmCustomQueryUtils.parseWindowContainerProto(
193      proto?.windowContainer,
194      result,
195    );
196  }
197
198  private static parseWindowStateProto(
199    proto: WindowStateProto | null | undefined,
200    result: WindowsTokenAndTitle,
201  ) {
202    if (!proto) {
203      return;
204    }
205    const token =
206      proto.windowContainer?.identifier?.hashCode?.toString(16) ??
207      WmCustomQueryUtils.NA;
208    const title =
209      proto.windowContainer?.identifier?.title ?? WmCustomQueryUtils.NA;
210    result.push({token, title});
211    WmCustomQueryUtils.parseWindowContainerProto(proto.windowContainer, result);
212  }
213
214  private static parseWindowTokenProto(
215    proto: WindowTokenProto | null | undefined,
216    result: WindowsTokenAndTitle,
217  ) {
218    if (!proto) {
219      return;
220    }
221    const hash = proto.hashCode?.toString(16) ?? WmCustomQueryUtils.NA;
222    result.push({token: hash, title: hash});
223    WmCustomQueryUtils.parseWindowContainerProto(proto.windowContainer, result);
224  }
225}
226