diff --git a/tools/winscope/adb_proxy/winscope_proxy.py b/tools/winscope/adb_proxy/winscope_proxy.py index ef2cc18b1..f8555f82f 100755 --- a/tools/winscope/adb_proxy/winscope_proxy.py +++ b/tools/winscope/adb_proxy/winscope_proxy.py @@ -47,7 +47,7 @@ LOG_LEVEL = logging.WARNING PORT = 5544 # Keep in sync with WINSCOPE_PROXY_VERSION in Winscope DataAdb.vue -VERSION = '0.6' +VERSION = '0.7' WINSCOPE_VERSION_HEADER = "Winscope-Proxy-Version" WINSCOPE_TOKEN_HEADER = "Winscope-Token" @@ -139,6 +139,11 @@ TRACE_TARGETS = { 'su root cmd window logging start\necho "WM logging started."', 'su root cmd window logging stop >/dev/null 2>&1' ), + "ime_trace": TraceTarget( + File("/data/misc/wmtrace/ime_trace.pb", "ime_trace"), + 'su root ime tracing start\necho "IME trace started."', + 'su root ime tracing stop >/dev/null 2>&1' + ), } diff --git a/tools/winscope/src/DataAdb.vue b/tools/winscope/src/DataAdb.vue index 42c952090..3b08b98bf 100644 --- a/tools/winscope/src/DataAdb.vue +++ b/tools/winscope/src/DataAdb.vue @@ -142,7 +142,7 @@ const STATES = { LOAD_DATA: 8, }; -const WINSCOPE_PROXY_VERSION = '0.6'; +const WINSCOPE_PROXY_VERSION = '0.7'; const WINSCOPE_PROXY_URL = 'http://localhost:5544'; const PROXY_ENDPOINTS = { DEVICES: '/devices/', @@ -170,6 +170,9 @@ const TRACES = { 'screen_recording': { name: 'Screen Recording', }, + 'ime_trace': { + name: 'Input Method', + }, }; const TRACE_CONFIG = { @@ -201,6 +204,7 @@ const proxyFileTypeAdapter = { 'proto_log': FILE_TYPES.PROTO_LOG, 'system_ui_trace': FILE_TYPES.SYSTEM_UI, 'launcher_trace': FILE_TYPES.LAUNCHER, + 'ime_trace': FILE_TYPES.IME_TRACE, }; const CONFIGS = Object.keys(TRACE_CONFIG).flatMap((file) => TRACE_CONFIG[file]); diff --git a/tools/winscope/src/decode.js b/tools/winscope/src/decode.js index 42c383068..41958a6b8 100644 --- a/tools/winscope/src/decode.js +++ b/tools/winscope/src/decode.js @@ -24,6 +24,7 @@ import jsonProtoDefsTransaction from 'frameworks/native/cmds/surfacereplayer/pro import jsonProtoDefsWl from 'WaylandSafePath/waylandtrace.proto'; import jsonProtoDefsSysUi from 'frameworks/base/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto'; import jsonProtoDefsLauncher from 'packages/apps/Launcher3/protos/launcher_trace_file.proto'; +import jsonProtoDefsIme from 'frameworks/base/core/proto/android/view/inputmethod/inputmethodeditortrace.proto'; import protobuf from 'protobufjs'; import {transformLayers, transformLayersTrace} from './transform_sf.js'; import {transform_transaction_trace} from './transform_transaction.js'; @@ -31,6 +32,7 @@ import {transform_wl_outputstate, transform_wayland_trace} from './transform_wl. import {transformProtolog} from './transform_protolog.js'; import {transform_sysui_trace} from './transform_sys_ui.js'; import {transform_launcher_trace} from './transform_launcher.js'; +import {transform_ime_trace} from './transform_ime.js'; import {fill_transform_data} from './matrix_utils.js'; import {mp4Decoder} from './decodeVideo.js'; @@ -42,6 +44,7 @@ import WaylandTrace from '@/traces/Wayland.ts'; import ProtoLogTrace from '@/traces/ProtoLog.ts'; import SystemUITrace from '@/traces/SystemUI.ts'; import LauncherTrace from '@/traces/Launcher.ts'; +import ImeTrace from '@/traces/InputMethodEditor.ts'; import SurfaceFlingerDump from '@/dumps/SurfaceFlinger.ts'; import WindowManagerDump from '@/dumps/WindowManager.ts'; @@ -57,6 +60,7 @@ const WaylandDumpMessage = lookup_type(jsonProtoDefsWl, 'org.chromium.arc.waylan const ProtoLogMessage = lookup_type(jsonProtoDefsProtoLog, 'com.android.internal.protolog.ProtoLogFileProto'); const SystemUiTraceMessage = lookup_type(jsonProtoDefsSysUi, 'com.android.systemui.tracing.SystemUiTraceFileProto'); const LauncherTraceMessage = lookup_type(jsonProtoDefsLauncher, 'com.android.launcher3.tracing.LauncherTraceFileProto'); +const InputMethodEditorTraceMessage = lookup_type(jsonProtoDefsIme, "android.view.inputmethod.InputMethodEditorTraceFileProto"); const LAYER_TRACE_MAGIC_NUMBER = [0x09, 0x4c, 0x59, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45]; // .LYRTRACE const WINDOW_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45]; // .WINTRACE @@ -65,6 +69,7 @@ const WAYLAND_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x59, 0x4c, 0x54, 0x52, 0x41, 0x const PROTO_LOG_MAGIC_NUMBER = [0x09, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47]; // .PROTOLOG const SYSTEM_UI_MAGIC_NUMBER = [0x09, 0x53, 0x59, 0x53, 0x55, 0x49, 0x54, 0x52, 0x43]; // .SYSUITRC const LAUNCHER_MAGIC_NUMBER = [0x09, 0x4C, 0x4E, 0x43, 0x48, 0x52, 0x54, 0x52, 0x43]; // .LNCHRTRC +const IME_TRACE_MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x45, 0x54, 0x52, 0x41, 0x43, 0x45] //.IMETRACE const FILE_TYPES = Object.freeze({ WINDOW_MANAGER_TRACE: 'WindowManagerTrace', @@ -78,6 +83,7 @@ const FILE_TYPES = Object.freeze({ PROTO_LOG: 'ProtoLog', SYSTEM_UI: 'SystemUI', LAUNCHER: 'Launcher', + IME_TRACE: 'ImeTrace', }); const WINDOW_MANAGER_ICON = 'view_compact'; @@ -88,6 +94,7 @@ const WAYLAND_ICON = 'filter_none'; const PROTO_LOG_ICON = 'notes'; const SYSTEM_UI_ICON = 'filter_none'; const LAUNCHER_ICON = 'filter_none'; +const IME_ICON = 'keyboard'; const FILE_ICONS = { [FILE_TYPES.WINDOW_MANAGER_TRACE]: WINDOW_MANAGER_ICON, @@ -101,6 +108,7 @@ const FILE_ICONS = { [FILE_TYPES.PROTO_LOG]: PROTO_LOG_ICON, [FILE_TYPES.SYSTEM_UI]: SYSTEM_UI_ICON, [FILE_TYPES.LAUNCHER]: LAUNCHER_ICON, + [FILE_TYPES.IME_TRACE]: IME_ICON, }; function oneOf(dataType) { @@ -120,6 +128,7 @@ const TRACE_TYPES = Object.freeze({ PROTO_LOG: 'ProtoLog', SYSTEM_UI: 'SystemUI', LAUNCHER: 'Launcher', + IME: 'ImeTrace', }); const TRACE_INFO = { @@ -173,6 +182,12 @@ const TRACE_INFO = { files: [oneOf(FILE_TYPES.LAUNCHER)], constructor: LauncherTrace, }, + [TRACE_TYPES.IME]: { + name: 'InputMethodEditor', + icon: IME_ICON, + files: [oneOf(FILE_TYPES.IME_TRACE)], + constructor: ImeTrace, + }, }; const DUMP_TYPES = Object.freeze({ @@ -322,6 +337,17 @@ const FILE_DECODERS = { timeline: true, }, }, + [FILE_TYPES.IME_TRACE]: { + name: 'InputMethodEditor trace', + decoder: protoDecoder, + decoderParams: { + type: FILE_TYPES.IME_TRACE, + mime: 'application/octet-stream', + protoType: InputMethodEditorTraceMessage, + transform: transform_ime_trace, + timeline: true, + }, + }, }; function lookup_type(protoPath, type) { @@ -452,6 +478,9 @@ function detectAndDecode(buffer, fileName, store) { if (arrayStartsWith(buffer, LAUNCHER_MAGIC_NUMBER)) { return decodedFile(FILE_TYPES.LAUNCHER, buffer, fileName, store); } + if (arrayStartsWith(buffer, IME_TRACE_MAGIC_NUMBER)) { + return decodedFile(FILE_TYPES.IME_TRACE, buffer, fileName, store); + } // TODO(b/169305853): Add magic number at beginning of file for better auto detection for (const [filetype, condition] of [ diff --git a/tools/winscope/src/main.js b/tools/winscope/src/main.js index 506dda526..cc7c834b9 100644 --- a/tools/winscope/src/main.js +++ b/tools/winscope/src/main.js @@ -34,6 +34,7 @@ const fileOrder = { [TRACE_TYPES.SURFACE_FLINGER]: 2, [TRACE_TYPES.TRANSACTION]: 3, [TRACE_TYPES.PROTO_LOG]: 4, + [TRACE_TYPES.IME]: 5, }; function sortFiles(files) { diff --git a/tools/winscope/src/mixins/FileType.js b/tools/winscope/src/mixins/FileType.js index e8624a730..aee04b12c 100644 --- a/tools/winscope/src/mixins/FileType.js +++ b/tools/winscope/src/mixins/FileType.js @@ -23,6 +23,7 @@ const mixin = { file.type == TRACE_TYPES.WAYLAND || file.type == TRACE_TYPES.SYSTEM_UI || file.type == TRACE_TYPES.LAUNCHER || + file.type == TRACE_TYPES.IME || file.type == DUMP_TYPES.WINDOW_MANAGER || file.type == DUMP_TYPES.SURFACE_FLINGER || file.type == DUMP_TYPES.WAYLAND; diff --git a/tools/winscope/src/traces/InputMethodEditor.ts b/tools/winscope/src/traces/InputMethodEditor.ts new file mode 100644 index 000000000..8339d708f --- /dev/null +++ b/tools/winscope/src/traces/InputMethodEditor.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020, 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 { FILE_TYPES, TRACE_TYPES } from '@/decode.js'; +import TraceBase from './TraceBase'; + +export default class InputMethodEditor extends TraceBase { + imeTraceFile: any; + + constructor(files) { + const imeTraceFile = files[FILE_TYPES.IME_TRACE]; + super(imeTraceFile.data, imeTraceFile.timeline, files); + + this.imeTraceFile = imeTraceFile; + } + + get type() { + return TRACE_TYPES.IME; + } +} diff --git a/tools/winscope/src/transform_ime.js b/tools/winscope/src/transform_ime.js new file mode 100644 index 000000000..aca895f03 --- /dev/null +++ b/tools/winscope/src/transform_ime.js @@ -0,0 +1,56 @@ +import {nanos_to_string, transform} from './transform.js' + +function transform_ime_trace(entries) { + return transform({ + obj: entries, + kind: 'entries', + name: 'entries', + children: [ + [entries.entry, transform_entry] + ] + }); +} + +function transform_entry(entry) { + return transform({ + obj: entry, + kind: 'entry', + name: nanos_to_string(entry.elapsedRealtimeNanos), + children: [ + [[entry.inputMethodManagerService], transform_imms_dump], + [[entry.inputMethodService], transform_ims_dump], + [[entry.clients], transform_client_dump] + ], + timestamp: entry.elapsedRealtimeNanos, + stableId: 'entry' + }); +} + +function transform_imms_dump(entry) { + return transform({ + obj: entry, + kind: 'InputMethodManagerService', + name: '', + children: [] + }); +} + +function transform_client_dump(entry) { + return transform({ + obj: entry, + kind: 'Clients', + name: '', + children: [] + }); +} + +function transform_ims_dump(entry) { + return transform({ + obj: entry, + kind: 'InputMethodService', + name: '', + children: [] + }); +} + +export {transform_ime_trace}; \ No newline at end of file