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