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 */ 16 17import {assertDefined} from 'common/assert_utils'; 18import {ParserTimestampConverter} from 'common/timestamp_converter'; 19import {AddDefaults} from 'parsers/operations/add_defaults'; 20import {SetFormatters} from 'parsers/operations/set_formatters'; 21import {AbstractParser} from 'parsers/perfetto/abstract_parser'; 22import {FakeProtoTransformer} from 'parsers/perfetto/fake_proto_transformer'; 23import {Utils} from 'parsers/perfetto/utils'; 24import {TamperedMessageType} from 'parsers/tampered_message_type'; 25import {TranslateChanges} from 'parsers/transactions/operations/translate_changes'; 26import root from 'protos/transactions/latest/json'; 27import {perfetto} from 'protos/transactions/latest/static'; 28import { 29 CustomQueryParserResultTypeMap, 30 CustomQueryType, 31 VisitableParserCustomQuery, 32} from 'trace/custom_query'; 33import {EntriesRange} from 'trace/index_types'; 34import {TraceFile} from 'trace/trace_file'; 35import {TraceType} from 'trace/trace_type'; 36import {PropertyTreeBuilderFromProto} from 'trace/tree_node/property_tree_builder_from_proto'; 37import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; 38import {WasmEngineProxy} from 'trace_processor/wasm_engine_proxy'; 39 40export class ParserTransactions extends AbstractParser<PropertyTreeNode> { 41 private static readonly TransactionsTraceFileProto = 42 TamperedMessageType.tamper( 43 root.lookupType('perfetto.protos.TransactionTraceFile'), 44 ); 45 private static readonly TransactionsTraceEntryField = 46 ParserTransactions.TransactionsTraceFileProto.fields['entry']; 47 48 private static readonly OPERATIONS = [ 49 new AddDefaults(ParserTransactions.TransactionsTraceEntryField), 50 new SetFormatters(ParserTransactions.TransactionsTraceEntryField), 51 new TranslateChanges(), 52 ]; 53 54 private protoTransformer: FakeProtoTransformer; 55 56 constructor( 57 traceFile: TraceFile, 58 traceProcessor: WasmEngineProxy, 59 timestampConverter: ParserTimestampConverter, 60 ) { 61 super(traceFile, traceProcessor, timestampConverter); 62 63 this.protoTransformer = new FakeProtoTransformer( 64 assertDefined( 65 ParserTransactions.TransactionsTraceEntryField.tamperedMessageType, 66 ), 67 ); 68 } 69 70 override getTraceType(): TraceType { 71 return TraceType.TRANSACTIONS; 72 } 73 74 override async getEntry(index: number): Promise<PropertyTreeNode> { 75 let entryProto = await Utils.queryEntry( 76 this.traceProcessor, 77 this.getTableName(), 78 this.entryIndexToRowIdMap, 79 index, 80 ); 81 entryProto = this.protoTransformer.transform(entryProto); 82 return this.makePropertiesTree(entryProto); 83 } 84 85 protected override getTableName(): string { 86 return 'surfaceflinger_transactions'; 87 } 88 89 override async customQuery<Q extends CustomQueryType>( 90 type: Q, 91 entriesRange: EntriesRange, 92 ): Promise<CustomQueryParserResultTypeMap[Q]> { 93 return new VisitableParserCustomQuery(type) 94 .visit(CustomQueryType.VSYNCID, async () => { 95 return Utils.queryVsyncId( 96 this.traceProcessor, 97 this.getTableName(), 98 this.entryIndexToRowIdMap, 99 entriesRange, 100 ); 101 }) 102 .getResult(); 103 } 104 105 private makePropertiesTree( 106 entryProto: perfetto.protos.TransactionTraceEntry, 107 ): PropertyTreeNode { 108 const tree = new PropertyTreeBuilderFromProto() 109 .setData(entryProto) 110 .setRootId('TransactionsTraceEntry') 111 .setRootName('entry') 112 .build(); 113 114 ParserTransactions.OPERATIONS.forEach((operation) => { 115 operation.apply(tree); 116 }); 117 return tree; 118 } 119} 120