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 {HierarchyTreeManagerServiceFactory} from 'parsers/input_method/hierarchy_tree_manager_service_factory'; 20import {AbstractParser} from 'parsers/legacy/abstract_parser'; 21import {TamperedMessageType} from 'parsers/tampered_message_type'; 22import root from 'protos/ime/udc/json'; 23import {android} from 'protos/ime/udc/static'; 24import {TraceType} from 'trace/trace_type'; 25import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node'; 26 27type ImeProto = android.view.inputmethod.IInputMethodManagerServiceTraceProto; 28 29class ParserInputMethodManagerService extends AbstractParser< 30 HierarchyTreeNode, 31 ImeProto 32> { 33 private static readonly MAGIC_NUMBER = [ 34 0x09, 0x49, 0x4d, 0x4d, 0x54, 0x52, 0x41, 0x43, 0x45, 35 ]; // .IMMTRACE 36 37 private static readonly InputMethodManagerServiceTraceFileProto = 38 TamperedMessageType.tamper( 39 root.lookupType( 40 'android.view.inputmethod.InputMethodManagerServiceTraceFileProto', 41 ), 42 ); 43 private static readonly ENTRY_FIELD = 44 ParserInputMethodManagerService.InputMethodManagerServiceTraceFileProto 45 .fields['entry']; 46 private static readonly MANAGER_SERVICE_FIELD = assertDefined( 47 ParserInputMethodManagerService.ENTRY_FIELD.tamperedMessageType, 48 ).fields['inputMethodManagerService']; 49 private static readonly HIERARCHY_TREE_FACTORY = 50 new HierarchyTreeManagerServiceFactory( 51 ParserInputMethodManagerService.ENTRY_FIELD, 52 ParserInputMethodManagerService.MANAGER_SERVICE_FIELD, 53 ); 54 55 private realToBootTimeOffsetNs: bigint | undefined; 56 57 override getTraceType(): TraceType { 58 return TraceType.INPUT_METHOD_MANAGER_SERVICE; 59 } 60 61 override getMagicNumber(): number[] { 62 return ParserInputMethodManagerService.MAGIC_NUMBER; 63 } 64 65 override getRealToBootTimeOffsetNs(): bigint | undefined { 66 return this.realToBootTimeOffsetNs; 67 } 68 69 override getRealToMonotonicTimeOffsetNs(): bigint | undefined { 70 return undefined; 71 } 72 73 override decodeTrace(buffer: Uint8Array): ImeProto[] { 74 const decoded = 75 ParserInputMethodManagerService.InputMethodManagerServiceTraceFileProto.decode( 76 buffer, 77 ) as android.view.inputmethod.IInputMethodManagerServiceTraceFileProto; 78 const timeOffset = BigInt( 79 decoded.realToElapsedTimeOffsetNanos?.toString() ?? '0', 80 ); 81 this.realToBootTimeOffsetNs = timeOffset !== 0n ? timeOffset : undefined; 82 return decoded.entry ?? []; 83 } 84 85 protected override getTimestamp(entry: ImeProto): Timestamp { 86 return this.timestampConverter.makeTimestampFromBootTimeNs( 87 BigInt(assertDefined(entry.elapsedRealtimeNanos).toString()), 88 ); 89 } 90 91 protected override processDecodedEntry( 92 index: number, 93 entry: ImeProto, 94 ): HierarchyTreeNode { 95 if ( 96 entry.elapsedRealtimeNanos === undefined || 97 entry.elapsedRealtimeNanos === null 98 ) { 99 throw new Error( 100 'Missing elapsedRealtimeNanos on IME Manager Service entry', 101 ); 102 } 103 return ParserInputMethodManagerService.HIERARCHY_TREE_FACTORY.makeHierarchyTree( 104 entry, 105 ); 106 } 107} 108 109export {ParserInputMethodManagerService}; 110