1/* 2 * Copyright (C) 2022 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 {Timestamp} from 'common/time'; 19import {AbstractParser} from 'parsers/legacy/abstract_parser'; 20import {TamperedMessageType} from 'parsers/tampered_message_type'; 21import {RectsComputation} from 'parsers/window_manager/computations/rects_computation'; 22import {WmCustomQueryUtils} from 'parsers/window_manager/custom_query_utils'; 23import {HierarchyTreeBuilderWm} from 'parsers/window_manager/hierarchy_tree_builder_wm'; 24import {PropertiesProviderFactory} from 'parsers/window_manager/properties_provider_factory'; 25import root from 'protos/windowmanager/udc/json'; 26import {com} from 'protos/windowmanager/udc/static'; 27import { 28 CustomQueryParserResultTypeMap, 29 CustomQueryType, 30 VisitableParserCustomQuery, 31} from 'trace/custom_query'; 32import {EntriesRange} from 'trace/trace'; 33import {TraceType} from 'trace/trace_type'; 34import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node'; 35import {PropertiesProvider} from 'trace/tree_node/properties_provider'; 36import {TAMPERED_PROTOS_UDC} from './tampered_protos_udc'; 37 38export class ParserWindowManager extends AbstractParser<HierarchyTreeNode> { 39 private static readonly MAGIC_NUMBER = [ 40 0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45, 41 ]; // .WINTRACE 42 private static readonly WindowManagerTraceFileProto = 43 TamperedMessageType.tamper( 44 root.lookupType('com.android.server.wm.WindowManagerTraceFileProto'), 45 ); 46 47 private readonly factory = new PropertiesProviderFactory(TAMPERED_PROTOS_UDC); 48 private realToBootTimeOffsetNs: bigint | undefined; 49 50 override getTraceType(): TraceType { 51 return TraceType.WINDOW_MANAGER; 52 } 53 54 override getMagicNumber(): number[] { 55 return ParserWindowManager.MAGIC_NUMBER; 56 } 57 58 override getRealToBootTimeOffsetNs(): bigint | undefined { 59 return this.realToBootTimeOffsetNs; 60 } 61 62 override getRealToMonotonicTimeOffsetNs(): bigint | undefined { 63 return undefined; 64 } 65 66 override decodeTrace( 67 buffer: Uint8Array, 68 ): com.android.server.wm.IWindowManagerTraceProto[] { 69 const decoded = ParserWindowManager.WindowManagerTraceFileProto.decode( 70 buffer, 71 ) as com.android.server.wm.IWindowManagerTraceFileProto; 72 const timeOffset = BigInt( 73 decoded.realToElapsedTimeOffsetNanos?.toString() ?? '0', 74 ); 75 this.realToBootTimeOffsetNs = timeOffset !== 0n ? timeOffset : undefined; 76 return decoded.entry ?? []; 77 } 78 79 protected override getTimestamp( 80 entry: com.android.server.wm.IWindowManagerTraceProto, 81 ): Timestamp { 82 return this.timestampConverter.makeTimestampFromBootTimeNs( 83 BigInt(assertDefined(entry.elapsedRealtimeNanos).toString()), 84 ); 85 } 86 87 override processDecodedEntry( 88 index: number, 89 entry: com.android.server.wm.IWindowManagerTraceProto, 90 ): HierarchyTreeNode { 91 return this.makeHierarchyTree(entry); 92 } 93 94 override customQuery<Q extends CustomQueryType>( 95 type: Q, 96 entriesRange: EntriesRange, 97 ): Promise<CustomQueryParserResultTypeMap[Q]> { 98 return new VisitableParserCustomQuery(type) 99 .visit(CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE, () => { 100 const result: CustomQueryParserResultTypeMap[CustomQueryType.WM_WINDOWS_TOKEN_AND_TITLE] = 101 []; 102 this.decodedEntries 103 .slice(entriesRange.start, entriesRange.end) 104 .forEach((windowManagerTraceProto) => { 105 WmCustomQueryUtils.parseWindowsTokenAndTitle( 106 windowManagerTraceProto?.windowManagerService 107 ?.rootWindowContainer, 108 result, 109 ); 110 }); 111 return Promise.resolve(result); 112 }) 113 .getResult(); 114 } 115 116 private makeHierarchyTree( 117 entryProto: com.android.server.wm.IWindowManagerTraceProto, 118 ): HierarchyTreeNode { 119 const containers: PropertiesProvider[] = 120 this.factory.makeContainerProperties( 121 assertDefined(entryProto.windowManagerService), 122 ); 123 124 const entry = this.factory.makeEntryProperties( 125 assertDefined(entryProto.windowManagerService), 126 ); 127 128 return new HierarchyTreeBuilderWm() 129 .setRoot(entry) 130 .setChildren(containers) 131 .setComputations([new RectsComputation()]) 132 .build(); 133 } 134} 135