1/* 2 * Copyright (C) 2024 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 {AbstractInputEventParser} from 'parsers/input/perfetto/abstract_input_event_parser'; 20import {SetFormatters} from 'parsers/operations/set_formatters'; 21import {TranslateIntDef} from 'parsers/operations/translate_intdef'; 22import {FakeProtoTransformer} from 'parsers/perfetto/fake_proto_transformer'; 23import {Utils} from 'parsers/perfetto/utils'; 24import {perfetto} from 'protos/input/latest/static'; 25import {TraceFile} from 'trace/trace_file'; 26import {TraceType} from 'trace/trace_type'; 27import {PropertyTreeBuilderFromProto} from 'trace/tree_node/property_tree_builder_from_proto'; 28import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; 29import {WasmEngineProxy} from 'trace_processor/wasm_engine_proxy'; 30 31export class ParserMotionEvent extends AbstractInputEventParser { 32 private static readonly MotionEventField = 33 AbstractInputEventParser.WrapperProto.fields['motionEvent']; 34 35 private static readonly MOTION_EVENT_OPS = [ 36 new SetFormatters(ParserMotionEvent.MotionEventField), 37 new TranslateIntDef(ParserMotionEvent.MotionEventField), 38 ]; 39 40 private motionEventTransformer: FakeProtoTransformer; 41 42 constructor( 43 traceFile: TraceFile, 44 traceProcessor: WasmEngineProxy, 45 timestampConverter: ParserTimestampConverter, 46 ) { 47 super(traceFile, traceProcessor, timestampConverter); 48 49 this.motionEventTransformer = new FakeProtoTransformer( 50 assertDefined(ParserMotionEvent.MotionEventField.tamperedMessageType), 51 ); 52 } 53 54 override getTraceType(): TraceType { 55 return TraceType.INPUT_MOTION_EVENT; 56 } 57 58 override async getEntry(index: number): Promise<PropertyTreeNode> { 59 const motionEvent = await this.getMotionEventProto(index); 60 const events = perfetto.protos.InputEventWrapper.create({ 61 motionEvent, 62 windowDispatchEvents: await this.getDispatchEvents(motionEvent.eventId), 63 }); 64 return this.makeMotionPropertiesTree(events); 65 } 66 67 private async getMotionEventProto( 68 index: number, 69 ): Promise<perfetto.protos.AndroidMotionEvent> { 70 let motionEventProto = await Utils.queryEntry( 71 this.traceProcessor, 72 this.getTableName(), 73 this.entryIndexToRowIdMap, 74 index, 75 ); 76 77 motionEventProto = this.motionEventTransformer.transform(motionEventProto); 78 return motionEventProto; 79 } 80 81 protected override getTableName(): string { 82 return 'android_motion_events'; 83 } 84 85 protected override getStdLibModuleName(): string | undefined { 86 return 'android.input'; 87 } 88 89 private makeMotionPropertiesTree( 90 entryProto: perfetto.protos.InputEventWrapper, 91 ): PropertyTreeNode { 92 const tree = new PropertyTreeBuilderFromProto() 93 .setData(entryProto) 94 .setRootId('AndroidMotionEvent') 95 .setRootName('entry') 96 .build(); 97 98 ParserMotionEvent.MOTION_EVENT_OPS.forEach((operation) => { 99 operation.apply(assertDefined(tree.getChildByName('motionEvent'))); 100 }); 101 102 this.processDispatchEventsTree( 103 assertDefined(tree.getChildByName('windowDispatchEvents')), 104 ); 105 106 return tree; 107 } 108} 109