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