xref: /aosp_15_r20/development/tools/winscope/src/parsers/transactions/legacy/parser_transactions.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
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 {AddDefaults} from 'parsers/operations/add_defaults';
21import {SetFormatters} from 'parsers/operations/set_formatters';
22import {TamperedMessageType} from 'parsers/tampered_message_type';
23import {TranslateChanges} from 'parsers/transactions/operations/translate_changes';
24import root from 'protos/transactions/udc/json';
25import {android} from 'protos/transactions/udc/static';
26import {
27  CustomQueryParserResultTypeMap,
28  CustomQueryType,
29  VisitableParserCustomQuery,
30} from 'trace/custom_query';
31import {EntriesRange} from 'trace/trace';
32import {TraceType} from 'trace/trace_type';
33import {PropertyTreeBuilderFromProto} from 'trace/tree_node/property_tree_builder_from_proto';
34import {PropertyTreeNode} from 'trace/tree_node/property_tree_node';
35
36class ParserTransactions extends AbstractParser<PropertyTreeNode> {
37  private static readonly MAGIC_NUMBER = [
38    0x09, 0x54, 0x4e, 0x58, 0x54, 0x52, 0x41, 0x43, 0x45,
39  ]; // .TNXTRACE
40
41  private static readonly TransactionsTraceFileProto =
42    TamperedMessageType.tamper(
43      root.lookupType('android.surfaceflinger.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 realToMonotonicTimeOffsetNs: bigint | undefined;
55
56  override getTraceType(): TraceType {
57    return TraceType.TRANSACTIONS;
58  }
59
60  override getMagicNumber(): number[] {
61    return ParserTransactions.MAGIC_NUMBER;
62  }
63
64  override getRealToBootTimeOffsetNs(): bigint | undefined {
65    return undefined;
66  }
67
68  override getRealToMonotonicTimeOffsetNs(): bigint | undefined {
69    return this.realToMonotonicTimeOffsetNs;
70  }
71
72  override decodeTrace(
73    buffer: Uint8Array,
74  ): android.surfaceflinger.proto.ITransactionTraceEntry[] {
75    const decodedProto = ParserTransactions.TransactionsTraceFileProto.decode(
76      buffer,
77    ) as android.surfaceflinger.proto.ITransactionTraceFile;
78
79    const timeOffset = BigInt(
80      decodedProto.realToElapsedTimeOffsetNanos?.toString() ?? '0',
81    );
82    this.realToMonotonicTimeOffsetNs =
83      timeOffset !== 0n ? timeOffset : undefined;
84
85    return decodedProto.entry ?? [];
86  }
87
88  protected override getTimestamp(
89    entryProto: android.surfaceflinger.proto.ITransactionTraceEntry,
90  ): Timestamp {
91    return this.timestampConverter.makeTimestampFromMonotonicNs(
92      BigInt(assertDefined(entryProto.elapsedRealtimeNanos).toString()),
93    );
94  }
95
96  override processDecodedEntry(
97    index: number,
98    entryProto: android.surfaceflinger.proto.ITransactionTraceEntry,
99  ): PropertyTreeNode {
100    return this.makePropertiesTree(entryProto);
101  }
102
103  override customQuery<Q extends CustomQueryType>(
104    type: Q,
105    entriesRange: EntriesRange,
106  ): Promise<CustomQueryParserResultTypeMap[Q]> {
107    return new VisitableParserCustomQuery(type)
108      .visit(CustomQueryType.VSYNCID, async () => {
109        return this.decodedEntries
110          .slice(entriesRange.start, entriesRange.end)
111          .map((entry) => {
112            return BigInt(entry.vsyncId.toString()); // convert Long to bigint
113          });
114      })
115      .getResult();
116  }
117
118  private makePropertiesTree(
119    entryProto: android.surfaceflinger.proto.ITransactionTraceEntry,
120  ): PropertyTreeNode {
121    const tree = new PropertyTreeBuilderFromProto()
122      .setData(entryProto)
123      .setRootId('TransactionsTraceEntry')
124      .setRootName('entry')
125      .build();
126
127    ParserTransactions.OPERATIONS.forEach((operation) => {
128      operation.apply(tree);
129    });
130    return tree;
131  }
132}
133
134export {ParserTransactions};
135