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