blob: 0d5b52e7e34999538f8cac0944ff243aef6d32dd [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {TimestampType} from 'common/time';
import {TamperedMessageType} from 'parsers/tampered_message_type';
import root from 'protos/transactions/latest/json';
import {perfetto} from 'protos/transactions/latest/static';
import {
CustomQueryParserResultTypeMap,
CustomQueryType,
VisitableParserCustomQuery,
} from 'trace/custom_query';
import {EntriesRange} from 'trace/index_types';
import {TraceFile} from 'trace/trace_file';
import {TraceType} from 'trace/trace_type';
import {WasmEngineProxy} from 'trace_processor/wasm_engine_proxy';
import {AbstractParser} from './abstract_parser';
import {FakeProtoTransformer} from './fake_proto_transformer';
import {Utils} from './utils';
export class ParserTransactions extends AbstractParser<object> {
private static readonly TransactionsTraceEntryProto = TamperedMessageType.tamper(
root.lookupType('perfetto.protos.TransactionTraceEntry')
);
private static readonly LayerState = root.lookupType('perfetto.protos.LayerState');
private static readonly DisplayState = root.lookupType('perfetto.protos.DisplayState');
private protoTransformer: FakeProtoTransformer;
constructor(traceFile: TraceFile, traceProcessor: WasmEngineProxy) {
super(traceFile, traceProcessor);
this.protoTransformer = new FakeProtoTransformer(
ParserTransactions.TransactionsTraceEntryProto
);
}
override getTraceType(): TraceType {
return TraceType.TRANSACTIONS;
}
override async getEntry(
index: number,
timestampType: TimestampType
): Promise<perfetto.protos.ITransactionTraceEntry> {
let entryProto = await Utils.queryEntry(this.traceProcessor, this.getTableName(), index);
entryProto = this.protoTransformer.transform(entryProto);
entryProto = this.decodeWhatBitsetFields(entryProto);
return entryProto;
}
protected override getTableName(): string {
return 'surfaceflinger_transactions';
}
override async customQuery<Q extends CustomQueryType>(
type: Q,
entriesRange: EntriesRange
): Promise<CustomQueryParserResultTypeMap[Q]> {
return new VisitableParserCustomQuery(type)
.visit(CustomQueryType.VSYNCID, async () => {
return Utils.queryVsyncId(this.traceProcessor, this.getTableName(), entriesRange);
})
.getResult();
}
private decodeWhatBitsetFields(
transactionTraceEntry: perfetto.protos.ITransactionTraceEntry
): perfetto.protos.ITransactionTraceEntry {
const decodeBitset32 = (bitset: number, EnumProto: any) => {
return Object.keys(EnumProto).filter((key) => {
const value = EnumProto[key];
return (bitset & value) !== 0;
});
};
const concatBitsetTokens = (tokens: string[]) => {
if (tokens.length === 0) {
return '0';
}
return tokens.join(' | ');
};
const LayerStateChangesLsbEnum = (ParserTransactions.LayerState as any).ChangesLsb;
const LayerStateChangesMsbEnum = (ParserTransactions.LayerState as any).ChangesMsb;
const DisplayStateChangesEnum = (ParserTransactions.DisplayState as any).Changes;
transactionTraceEntry.transactions?.forEach((transactionState) => {
transactionState?.layerChanges?.forEach((layerState) => {
const originalValue = BigInt(layerState.what?.toString() ?? 0n);
(layerState.what as unknown as string) = concatBitsetTokens(
decodeBitset32(Number(originalValue), LayerStateChangesLsbEnum).concat(
decodeBitset32(Number(originalValue >> 32n), LayerStateChangesMsbEnum)
)
);
});
transactionState.displayChanges?.forEach((displayState) => {
(displayState.what as unknown as string) = concatBitsetTokens(
decodeBitset32(Number(displayState.what), DisplayStateChangesEnum)
);
});
});
transactionTraceEntry?.addedDisplays?.forEach((displayState) => {
(displayState.what as unknown as string) = concatBitsetTokens(
decodeBitset32(Number(displayState.what), DisplayStateChangesEnum)
);
});
return transactionTraceEntry;
}
}