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