1/* 2 * Copyright 2017, 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 17/* eslint-disable camelcase */ 18/* eslint-disable max-len */ 19 20import jsonProtoDefsAccessibility from 'frameworks/base/core/proto/android/server/accessibilitytrace.proto'; 21import jsonProtoDefsWm from 'frameworks/base/core/proto/android/server/windowmanagertrace.proto'; 22import jsonProtoDefsProtoLog from 'frameworks/base/core/proto/android/internal/protolog.proto'; 23import jsonProtoDefsSf from 'frameworks/native/services/surfaceflinger/layerproto/layerstrace.proto'; 24import jsonProtoDefsTransaction from 'frameworks/native/services/surfaceflinger/layerproto/transactions.proto'; 25import jsonProtoDefsTransactionLegacy from 'frameworks/native/cmds/surfacereplayer/proto/src/trace.proto'; 26import jsonProtoDefsWl from 'WaylandSafePath/waylandtrace.proto'; 27import jsonProtoDefsSysUi from 'frameworks/base/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto'; 28import jsonProtoDefsLauncher from 'packages/apps/Launcher3/protos/launcher_trace_file.proto'; 29import jsonProtoDefsIme from 'frameworks/base/core/proto/android/view/inputmethod/inputmethodeditortrace.proto'; 30import jsonProtoDefsTags from 'platform_testing/libraries/flicker/src/com/android/server/wm/proto/tags.proto'; 31import jsonProtoDefsErrors from 'platform_testing/libraries/flicker/src/com/android/server/wm/proto/errors.proto'; 32import protobuf from 'protobufjs'; 33import {transform_accessibility_trace} from './transform_accessibility.js'; 34import {transform_transaction_trace} from './transform_transaction.js'; 35import {transform_transaction_trace_legacy} from './transform_transaction_legacy.js'; 36import {transform_wl_outputstate, transform_wayland_trace} from './transform_wl.js'; 37import {transformProtolog} from './transform_protolog.js'; 38import {transform_sysui_trace} from './transform_sys_ui.js'; 39import {transform_launcher_trace} from './transform_launcher.js'; 40import {transform_ime_trace_clients, transform_ime_trace_service, transform_ime_trace_managerservice} from './transform_ime.js'; 41import {mp4Decoder} from './decodeVideo.js'; 42 43import AccessibilityTrace from '@/traces/Accessibility.ts'; 44import SurfaceFlingerTrace from '@/traces/SurfaceFlinger.ts'; 45import WindowManagerTrace from '@/traces/WindowManager.ts'; 46import TransactionsTrace from '@/traces/Transactions.ts'; 47import TransactionsTraceLegacy from '@/traces/TransactionsLegacy.ts'; 48import ScreenRecordingTrace from '@/traces/ScreenRecording.ts'; 49import WaylandTrace from '@/traces/Wayland.ts'; 50import ProtoLogTrace from '@/traces/ProtoLog.ts'; 51import SystemUITrace from '@/traces/SystemUI.ts'; 52import LauncherTrace from '@/traces/Launcher.ts'; 53import ImeTraceClients from '@/traces/InputMethodClients.ts'; 54import ImeTraceService from '@/traces/InputMethodService.ts'; 55import ImeTraceManagerService from '@/traces/InputMethodManagerService.ts'; 56 57import SurfaceFlingerDump from '@/dumps/SurfaceFlinger.ts'; 58import WindowManagerDump from '@/dumps/WindowManager.ts'; 59import WaylandDump from '@/dumps/Wayland.ts'; 60 61import TagTrace from '@/traces/TraceTag.ts'; 62import ErrorTrace from '@/traces/TraceError.ts'; 63 64const AccessibilityTraceMessage = lookup_type(jsonProtoDefsAccessibility, 'com.android.server.accessibility.AccessibilityTraceFileProto'); 65const WmTraceMessage = lookup_type(jsonProtoDefsWm, 'com.android.server.wm.WindowManagerTraceFileProto'); 66const WmDumpMessage = lookup_type(jsonProtoDefsWm, 'com.android.server.wm.WindowManagerServiceDumpProto'); 67const SfTraceMessage = lookup_type(jsonProtoDefsSf, 'android.surfaceflinger.LayersTraceFileProto'); 68const SfDumpMessage = lookup_type(jsonProtoDefsSf, 'android.surfaceflinger.LayersProto'); 69const SfTransactionTraceMessage = lookup_type(jsonProtoDefsTransaction, 'TransactionTraceFile'); 70const SfTransactionTraceMessageLegacy = lookup_type(jsonProtoDefsTransactionLegacy, 'Trace'); 71const WaylandTraceMessage = lookup_type(jsonProtoDefsWl, 'org.chromium.arc.wayland_composer.TraceFileProto'); 72const WaylandDumpMessage = lookup_type(jsonProtoDefsWl, 'org.chromium.arc.wayland_composer.OutputStateProto'); 73const ProtoLogMessage = lookup_type(jsonProtoDefsProtoLog, 'com.android.internal.protolog.ProtoLogFileProto'); 74const SystemUiTraceMessage = lookup_type(jsonProtoDefsSysUi, 'com.android.systemui.tracing.SystemUiTraceFileProto'); 75const LauncherTraceMessage = lookup_type(jsonProtoDefsLauncher, 'com.android.launcher3.tracing.LauncherTraceFileProto'); 76const InputMethodClientsTraceMessage = lookup_type(jsonProtoDefsIme, 'android.view.inputmethod.InputMethodClientsTraceFileProto'); 77const InputMethodServiceTraceMessage = lookup_type(jsonProtoDefsIme, 'android.view.inputmethod.InputMethodServiceTraceFileProto'); 78const InputMethodManagerServiceTraceMessage = lookup_type(jsonProtoDefsIme, 'android.view.inputmethod.InputMethodManagerServiceTraceFileProto'); 79const TagTraceMessage = lookup_type(jsonProtoDefsTags, 'com.android.server.wm.flicker.FlickerTagTraceProto'); 80const ErrorTraceMessage = lookup_type(jsonProtoDefsErrors, 'com.android.server.wm.flicker.FlickerErrorTraceProto'); 81 82const ACCESSIBILITY_MAGIC_NUMBER = [0x09, 0x41, 0x31, 0x31, 0x59, 0x54, 0x52, 0x41, 0x43]; // .A11YTRAC 83const LAYER_TRACE_MAGIC_NUMBER = [0x09, 0x4c, 0x59, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45]; // .LYRTRACE 84const TRANSACTIONS_TRACE_MAGIC_NUMBER = [0x09, 0x54, 0x4e, 0x58, 0x54, 0x52, 0x41, 0x43, 0x45]; // .TNXTRACE 85const WINDOW_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x49, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x45]; // .WINTRACE 86const MPEG4_MAGIC_NMBER = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32]; // ....ftypmp42 87const WAYLAND_TRACE_MAGIC_NUMBER = [0x09, 0x57, 0x59, 0x4c, 0x54, 0x52, 0x41, 0x43, 0x45]; // .WYLTRACE 88const PROTO_LOG_MAGIC_NUMBER = [0x09, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x4c, 0x4f, 0x47]; // .PROTOLOG 89const SYSTEM_UI_MAGIC_NUMBER = [0x09, 0x53, 0x59, 0x53, 0x55, 0x49, 0x54, 0x52, 0x43]; // .SYSUITRC 90const LAUNCHER_MAGIC_NUMBER = [0x09, 0x4C, 0x4E, 0x43, 0x48, 0x52, 0x54, 0x52, 0x43]; // .LNCHRTRC 91const IMC_TRACE_MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x43, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMCTRACE 92const IMS_TRACE_MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x53, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMSTRACE 93const IMM_TRACE_MAGIC_NUMBER = [0x09, 0x49, 0x4d, 0x4d, 0x54, 0x52, 0x41, 0x43, 0x45]; // .IMMTRACE 94const TAG_TRACE_MAGIC_NUMBER = [0x09, 0x54, 0x41, 0x47, 0x54, 0x52, 0x41, 0x43, 0x45]; //.TAGTRACE 95const ERROR_TRACE_MAGIC_NUMBER = [0x09, 0x45, 0x52, 0x52, 0x54, 0x52, 0x41, 0x43, 0x45]; //.ERRORTRACE 96 97const FILE_TYPES = Object.freeze({ 98 ACCESSIBILITY_TRACE: 'AccessibilityTrace', 99 WINDOW_MANAGER_TRACE: 'WindowManagerTrace', 100 SURFACE_FLINGER_TRACE: 'SurfaceFlingerTrace', 101 WINDOW_MANAGER_DUMP: 'WindowManagerDump', 102 SURFACE_FLINGER_DUMP: 'SurfaceFlingerDump', 103 SCREEN_RECORDING: 'ScreenRecording', 104 TRANSACTIONS_TRACE: 'TransactionsTrace', 105 TRANSACTIONS_TRACE_LEGACY: 'TransactionsTraceLegacy', 106 WAYLAND_TRACE: 'WaylandTrace', 107 WAYLAND_DUMP: 'WaylandDump', 108 PROTO_LOG: 'ProtoLog', 109 SYSTEM_UI: 'SystemUI', 110 LAUNCHER: 'Launcher', 111 IME_TRACE_CLIENTS: 'ImeTraceClients', 112 IME_TRACE_SERVICE: 'ImeTrace InputMethodService', 113 IME_TRACE_MANAGERSERVICE: 'ImeTrace InputMethodManagerService', 114 TAG_TRACE: 'TagTrace', 115 ERROR_TRACE: 'ErrorTrace', 116}); 117 118const WINDOW_MANAGER_ICON = 'view_compact'; 119const SURFACE_FLINGER_ICON = 'filter_none'; 120const SCREEN_RECORDING_ICON = 'videocam'; 121const TRANSACTION_ICON = 'timeline'; 122const WAYLAND_ICON = 'filter_none'; 123const PROTO_LOG_ICON = 'notes'; 124const SYSTEM_UI_ICON = 'filter_none'; 125const LAUNCHER_ICON = 'filter_none'; 126const IME_ICON = 'keyboard'; 127const ACCESSIBILITY_ICON = 'filter_none'; 128const TAG_ICON = 'details'; 129const TRACE_ERROR_ICON = 'warning'; 130 131const FILE_ICONS = { 132 [FILE_TYPES.ACCESSIBILITY_TRACE]: ACCESSIBILITY_ICON, 133 [FILE_TYPES.WINDOW_MANAGER_TRACE]: WINDOW_MANAGER_ICON, 134 [FILE_TYPES.SURFACE_FLINGER_TRACE]: SURFACE_FLINGER_ICON, 135 [FILE_TYPES.WINDOW_MANAGER_DUMP]: WINDOW_MANAGER_ICON, 136 [FILE_TYPES.SURFACE_FLINGER_DUMP]: SURFACE_FLINGER_ICON, 137 [FILE_TYPES.SCREEN_RECORDING]: SCREEN_RECORDING_ICON, 138 [FILE_TYPES.TRANSACTIONS_TRACE]: TRANSACTION_ICON, 139 [FILE_TYPES.TRANSACTIONS_TRACE_LEGACY]: TRANSACTION_ICON, 140 [FILE_TYPES.WAYLAND_TRACE]: WAYLAND_ICON, 141 [FILE_TYPES.WAYLAND_DUMP]: WAYLAND_ICON, 142 [FILE_TYPES.PROTO_LOG]: PROTO_LOG_ICON, 143 [FILE_TYPES.SYSTEM_UI]: SYSTEM_UI_ICON, 144 [FILE_TYPES.LAUNCHER]: LAUNCHER_ICON, 145 [FILE_TYPES.IME_TRACE_CLIENTS]: IME_ICON, 146 [FILE_TYPES.IME_TRACE_SERVICE]: IME_ICON, 147 [FILE_TYPES.IME_TRACE_MANAGERSERVICE]: IME_ICON, 148 [FILE_TYPES.TAG_TRACE]: TAG_ICON, 149 [FILE_TYPES.ERROR_TRACE]: TRACE_ERROR_ICON, 150}; 151 152function oneOf(dataType) { 153 return {oneOf: true, type: dataType}; 154} 155 156const TRACE_TYPES = Object.freeze({ 157 ACCESSIBILITY: 'AccessibilityTrace', 158 WINDOW_MANAGER: 'WindowManagerTrace', 159 SURFACE_FLINGER: 'SurfaceFlingerTrace', 160 SCREEN_RECORDING: 'ScreenRecording', 161 TRANSACTION: 'Transaction', 162 TRANSACTION_LEGACY: 'Transaction (Legacy)', 163 WAYLAND: 'Wayland', 164 PROTO_LOG: 'ProtoLog', 165 SYSTEM_UI: 'SystemUI', 166 LAUNCHER: 'Launcher', 167 IME_CLIENTS: 'ImeTrace Clients', 168 IME_SERVICE: 'ImeTrace InputMethodService', 169 IME_MANAGERSERVICE: 'ImeTrace InputMethodManagerService', 170 TAG: 'TagTrace', 171 ERROR: 'ErrorTrace', 172}); 173 174const TRACE_INFO = { 175 [TRACE_TYPES.ACCESSIBILITY]: { 176 name: 'Accessibility', 177 icon: ACCESSIBILITY_ICON, 178 files: [oneOf(FILE_TYPES.ACCESSIBILITY_TRACE)], 179 constructor: AccessibilityTrace, 180 }, 181 [TRACE_TYPES.WINDOW_MANAGER]: { 182 name: 'WindowManager', 183 icon: WINDOW_MANAGER_ICON, 184 files: [oneOf(FILE_TYPES.WINDOW_MANAGER_TRACE)], 185 constructor: WindowManagerTrace, 186 }, 187 [TRACE_TYPES.SURFACE_FLINGER]: { 188 name: 'SurfaceFlinger', 189 icon: SURFACE_FLINGER_ICON, 190 files: [oneOf(FILE_TYPES.SURFACE_FLINGER_TRACE)], 191 constructor: SurfaceFlingerTrace, 192 }, 193 [TRACE_TYPES.SCREEN_RECORDING]: { 194 name: 'Screen recording', 195 icon: SCREEN_RECORDING_ICON, 196 files: [oneOf(FILE_TYPES.SCREEN_RECORDING)], 197 constructor: ScreenRecordingTrace, 198 }, 199 [TRACE_TYPES.TRANSACTION]: { 200 name: 'Transaction', 201 icon: TRANSACTION_ICON, 202 files: [ 203 oneOf(FILE_TYPES.TRANSACTIONS_TRACE), 204 ], 205 constructor: TransactionsTrace, 206 }, 207 [TRACE_TYPES.TRANSACTION_LEGACY]: { 208 name: 'Transactions (Legacy)', 209 icon: TRANSACTION_ICON, 210 files: [ 211 oneOf(FILE_TYPES.TRANSACTIONS_TRACE_LEGACY), 212 ], 213 constructor: TransactionsTraceLegacy, 214 }, 215 [TRACE_TYPES.WAYLAND]: { 216 name: 'Wayland', 217 icon: WAYLAND_ICON, 218 files: [oneOf(FILE_TYPES.WAYLAND_TRACE)], 219 constructor: WaylandTrace, 220 }, 221 [TRACE_TYPES.PROTO_LOG]: { 222 name: 'ProtoLog', 223 icon: PROTO_LOG_ICON, 224 files: [oneOf(FILE_TYPES.PROTO_LOG)], 225 constructor: ProtoLogTrace, 226 }, 227 [TRACE_TYPES.SYSTEM_UI]: { 228 name: 'SystemUI', 229 icon: SYSTEM_UI_ICON, 230 files: [oneOf(FILE_TYPES.SYSTEM_UI)], 231 constructor: SystemUITrace, 232 }, 233 [TRACE_TYPES.LAUNCHER]: { 234 name: 'Launcher', 235 icon: LAUNCHER_ICON, 236 files: [oneOf(FILE_TYPES.LAUNCHER)], 237 constructor: LauncherTrace, 238 }, 239 [TRACE_TYPES.IME_CLIENTS]: { 240 name: 'InputMethodClients', 241 icon: IME_ICON, 242 files: [oneOf(FILE_TYPES.IME_TRACE_CLIENTS)], 243 constructor: ImeTraceClients, 244 }, 245 [TRACE_TYPES.IME_SERVICE]: { 246 name: 'InputMethodService', 247 icon: IME_ICON, 248 files: [oneOf(FILE_TYPES.IME_TRACE_SERVICE)], 249 constructor: ImeTraceService, 250 }, 251 [TRACE_TYPES.IME_MANAGERSERVICE]: { 252 name: 'InputMethodManagerService', 253 icon: IME_ICON, 254 files: [oneOf(FILE_TYPES.IME_TRACE_MANAGERSERVICE)], 255 constructor: ImeTraceManagerService, 256 }, 257 [TRACE_TYPES.TAG]: { 258 name: 'Tag', 259 icon: TAG_ICON, 260 files: [oneOf(FILE_TYPES.TAG_TRACE)], 261 constructor: TagTrace, 262 }, 263 [TRACE_TYPES.ERROR]: { 264 name: 'Error', 265 icon: TRACE_ERROR_ICON, 266 files: [oneOf(FILE_TYPES.ERROR_TRACE)], 267 constructor: ErrorTrace, 268 }, 269}; 270 271const DUMP_TYPES = Object.freeze({ 272 WINDOW_MANAGER: 'WindowManagerDump', 273 SURFACE_FLINGER: 'SurfaceFlingerDump', 274 WAYLAND: 'WaylandDump', 275}); 276 277const DUMP_INFO = { 278 [DUMP_TYPES.WINDOW_MANAGER]: { 279 name: 'WindowManager', 280 icon: WINDOW_MANAGER_ICON, 281 files: [oneOf(FILE_TYPES.WINDOW_MANAGER_DUMP)], 282 constructor: WindowManagerDump, 283 }, 284 [DUMP_TYPES.SURFACE_FLINGER]: { 285 name: 'SurfaceFlinger', 286 icon: SURFACE_FLINGER_ICON, 287 files: [oneOf(FILE_TYPES.SURFACE_FLINGER_DUMP)], 288 constructor: SurfaceFlingerDump, 289 }, 290 [DUMP_TYPES.WAYLAND]: { 291 name: 'Wayland', 292 icon: WAYLAND_ICON, 293 files: [oneOf(FILE_TYPES.WAYLAND_DUMP)], 294 constructor: WaylandDump, 295 }, 296}; 297 298export const TRACE_ICONS = { 299 [TRACE_TYPES.WINDOW_MANAGER]: WINDOW_MANAGER_ICON, 300 [TRACE_TYPES.SURFACE_FLINGER]: SURFACE_FLINGER_ICON, 301 [TRACE_TYPES.SCREEN_RECORDING]: SCREEN_RECORDING_ICON, 302 [TRACE_TYPES.TRANSACTION]: TRANSACTION_ICON, 303 [TRACE_TYPES.TRANSACTION_LEGACY]: TRANSACTION_ICON, 304 [TRACE_TYPES.WAYLAND]: WAYLAND_ICON, 305 [TRACE_TYPES.PROTO_LOG]: PROTO_LOG_ICON, 306 [TRACE_TYPES.SYSTEM_UI]: SYSTEM_UI_ICON, 307 [TRACE_TYPES.LAUNCHER]: LAUNCHER_ICON, 308 [TRACE_TYPES.IME_CLIENTS]: IME_ICON, 309 [TRACE_TYPES.IME_SERVICE]: IME_ICON, 310 [TRACE_TYPES.IME_MANAGERSERVICE]: IME_ICON, 311 [TRACE_TYPES.TAG_TRACE]: TAG_ICON, 312 [TRACE_TYPES.ERROR_TRACE]: TRACE_ERROR_ICON, 313 314 [DUMP_TYPES.WINDOW_MANAGER]: WINDOW_MANAGER_ICON, 315 [DUMP_TYPES.SURFACE_FLINGER]: SURFACE_FLINGER_ICON, 316 [DUMP_TYPES.WAYLAND]: WAYLAND_ICON, 317}; 318 319// TODO: Rename name to defaultName 320const FILE_DECODERS = { 321 [FILE_TYPES.ACCESSIBILITY_TRACE]: { 322 name: 'Accessibility trace', 323 decoder: protoDecoder, 324 decoderParams: { 325 type: FILE_TYPES.ACCESSIBILITY_TRACE, 326 objTypeProto: AccessibilityTraceMessage, 327 transform: transform_accessibility_trace, 328 timeline: true, 329 }, 330 }, 331 [FILE_TYPES.WINDOW_MANAGER_TRACE]: { 332 name: 'WindowManager trace', 333 decoder: protoDecoder, 334 decoderParams: { 335 type: FILE_TYPES.WINDOW_MANAGER_TRACE, 336 objTypeProto: WmTraceMessage, 337 transform: WindowManagerTrace.fromProto, 338 timeline: true, 339 }, 340 }, 341 [FILE_TYPES.SURFACE_FLINGER_TRACE]: { 342 name: 'SurfaceFlinger trace', 343 decoder: protoDecoder, 344 decoderParams: { 345 type: FILE_TYPES.SURFACE_FLINGER_TRACE, 346 mime: 'application/octet-stream', 347 objTypeProto: SfTraceMessage, 348 transform: SurfaceFlingerTrace.fromProto, 349 timeline: true, 350 }, 351 }, 352 [FILE_TYPES.WAYLAND_TRACE]: { 353 name: 'Wayland trace', 354 decoder: protoDecoder, 355 decoderParams: { 356 type: FILE_TYPES.WAYLAND_TRACE, 357 mime: 'application/octet-stream', 358 objTypeProto: WaylandTraceMessage, 359 transform: transform_wayland_trace, 360 timeline: true, 361 }, 362 }, 363 [FILE_TYPES.SURFACE_FLINGER_DUMP]: { 364 name: 'SurfaceFlinger dump', 365 decoder: protoDecoder, 366 decoderParams: { 367 type: FILE_TYPES.SURFACE_FLINGER_DUMP, 368 mime: 'application/octet-stream', 369 objTypeProto: [SfDumpMessage, SfTraceMessage], 370 transform: [SurfaceFlingerDump.fromProto, SurfaceFlingerTrace.fromProto], 371 timeline: true, 372 }, 373 }, 374 [FILE_TYPES.WINDOW_MANAGER_DUMP]: { 375 name: 'WindowManager dump', 376 decoder: protoDecoder, 377 decoderParams: { 378 type: FILE_TYPES.WINDOW_MANAGER_DUMP, 379 mime: 'application/octet-stream', 380 objTypeProto: WmDumpMessage, 381 transform: WindowManagerDump.fromProto, 382 timeline: true, 383 }, 384 }, 385 [FILE_TYPES.WAYLAND_DUMP]: { 386 name: 'Wayland dump', 387 decoder: protoDecoder, 388 decoderParams: { 389 type: FILE_TYPES.WAYLAND_DUMP, 390 mime: 'application/octet-stream', 391 objTypeProto: WaylandDumpMessage, 392 transform: transform_wl_outputstate, 393 timeline: true, 394 }, 395 }, 396 [FILE_TYPES.SCREEN_RECORDING]: { 397 name: 'Screen recording', 398 decoder: videoDecoder, 399 decoderParams: { 400 type: FILE_TYPES.SCREEN_RECORDING, 401 mime: 'video/mp4', 402 videoDecoder: mp4Decoder, 403 }, 404 }, 405 [FILE_TYPES.TRANSACTIONS_TRACE]: { 406 name: 'Transaction', 407 decoder: protoDecoder, 408 decoderParams: { 409 type: FILE_TYPES.TRANSACTIONS_TRACE, 410 mime: 'application/octet-stream', 411 objTypeProto: SfTransactionTraceMessage, 412 transform: transform_transaction_trace, 413 timeline: true, 414 }, 415 }, 416 [FILE_TYPES.TRANSACTIONS_TRACE_LEGACY]: { 417 name: 'Transactions (Legacy)', 418 decoder: protoDecoder, 419 decoderParams: { 420 type: FILE_TYPES.TRANSACTIONS_TRACE_LEGACY, 421 mime: 'application/octet-stream', 422 objTypeProto: SfTransactionTraceMessageLegacy, 423 transform: transform_transaction_trace_legacy, 424 timeline: true, 425 }, 426 }, 427 [FILE_TYPES.PROTO_LOG]: { 428 name: 'ProtoLog', 429 decoder: protoDecoder, 430 decoderParams: { 431 type: FILE_TYPES.PROTO_LOG, 432 mime: 'application/octet-stream', 433 objTypeProto: ProtoLogMessage, 434 transform: transformProtolog, 435 timeline: true, 436 }, 437 }, 438 [FILE_TYPES.SYSTEM_UI]: { 439 name: 'SystemUI trace', 440 decoder: protoDecoder, 441 decoderParams: { 442 type: FILE_TYPES.SYSTEM_UI, 443 mime: 'application/octet-stream', 444 objTypeProto: SystemUiTraceMessage, 445 transform: transform_sysui_trace, 446 timeline: true, 447 }, 448 }, 449 [FILE_TYPES.LAUNCHER]: { 450 name: 'Launcher trace', 451 decoder: protoDecoder, 452 decoderParams: { 453 type: FILE_TYPES.LAUNCHER, 454 mime: 'application/octet-stream', 455 objTypeProto: LauncherTraceMessage, 456 transform: transform_launcher_trace, 457 timeline: true, 458 }, 459 }, 460 [FILE_TYPES.IME_TRACE_CLIENTS]: { 461 name: 'InputMethodClients trace', 462 decoder: protoDecoder, 463 decoderParams: { 464 type: FILE_TYPES.IME_TRACE_CLIENTS, 465 mime: 'application/octet-stream', 466 objTypeProto: InputMethodClientsTraceMessage, 467 transform: transform_ime_trace_clients, 468 timeline: true, 469 }, 470 }, 471 [FILE_TYPES.IME_TRACE_SERVICE]: { 472 name: 'InputMethodService trace', 473 decoder: protoDecoder, 474 decoderParams: { 475 type: FILE_TYPES.IME_TRACE_SERVICE, 476 mime: 'application/octet-stream', 477 objTypeProto: InputMethodServiceTraceMessage, 478 transform: transform_ime_trace_service, 479 timeline: true, 480 }, 481 }, 482 [FILE_TYPES.IME_TRACE_MANAGERSERVICE]: { 483 name: 'InputMethodManagerService trace', 484 decoder: protoDecoder, 485 decoderParams: { 486 type: FILE_TYPES.IME_TRACE_MANAGERSERVICE, 487 mime: 'application/octet-stream', 488 objTypeProto: InputMethodManagerServiceTraceMessage, 489 transform: transform_ime_trace_managerservice, 490 timeline: true, 491 }, 492 }, 493 [FILE_TYPES.TAG_TRACE]: { 494 name: 'Tag trace', 495 decoder: protoDecoder, 496 decoderParams: { 497 type: FILE_TYPES.TAG_TRACE, 498 objTypeProto: TagTraceMessage, 499 transform: TagTrace.fromProto, 500 timeline: true, 501 }, 502 }, 503 [FILE_TYPES.ERROR_TRACE]: { 504 name: 'Error trace', 505 decoder: protoDecoder, 506 decoderParams: { 507 type: FILE_TYPES.ERROR_TRACE, 508 objTypeProto: ErrorTraceMessage, 509 transform: ErrorTrace.fromProto, 510 timeline: true, 511 }, 512 }, 513}; 514 515function lookup_type(protoPath, type) { 516 return protobuf.Root.fromJSON(protoPath).lookupType(type); 517} 518 519// Replace enum values with string representation and 520// add default values to the proto objects. This function also handles 521// a special case with TransformProtos where the matrix may be derived 522// from the transform type. 523function modifyProtoFields(protoObj, displayDefaults) { 524 if (!protoObj || protoObj !== Object(protoObj) || !protoObj.$type) { 525 return; 526 } 527 528 for (const fieldName in protoObj.$type.fields) { 529 if (protoObj.$type.fields.hasOwnProperty(fieldName)) { 530 const fieldProperties = protoObj.$type.fields[fieldName]; 531 const field = protoObj[fieldName]; 532 533 if (Array.isArray(field)) { 534 field.forEach((item, _) => { 535 modifyProtoFields(item, displayDefaults); 536 }); 537 continue; 538 } 539 540 if (displayDefaults && !(field)) { 541 protoObj[fieldName] = fieldProperties.defaultValue; 542 } 543 544 if (fieldProperties.resolvedType && fieldProperties.resolvedType.valuesById) { 545 protoObj[fieldName] = fieldProperties.resolvedType.valuesById[protoObj[fieldProperties.name]]; 546 continue; 547 } 548 modifyProtoFields(protoObj[fieldName], displayDefaults); 549 } 550 } 551} 552 553function decodeAndTransformProto(buffer, params, displayDefaults) { 554 var objTypesProto = []; 555 var transforms = []; 556 if (!Array.isArray(params.objTypeProto)) { 557 objTypesProto = [params.objTypeProto]; 558 transforms = [params.transform]; 559 } else { 560 objTypesProto = params.objTypeProto; 561 transforms = params.transform; 562 } 563 // each trace or dump may have different processors, for example, until S, SF dumps 564 // returne a list of layers and winscope built a [LayerTraceEntry] from them. 565 // From S onwards, returns a LayerTrace object, iterating over multiple items allows 566 // winscope to handle both the new and legacy formats 567 // TODO Refactor the decode.js code into a set of decoders to clean up the code 568 let lastError = null; 569 for (var x = 0; x < objTypesProto.length; x++) { 570 const objType = objTypesProto[x]; 571 const transform = transforms[x]; 572 try { 573 const decoded = objType.decode(buffer); 574 modifyProtoFields(decoded, displayDefaults); 575 const transformed = transform(decoded); 576 return transformed; 577 } catch (e) { 578 lastError = e; 579 // check next parser 580 } 581 } 582 583 if (lastError) { 584 throw lastError; 585 } 586 throw new UndetectableFileType('Unable to parse file'); 587} 588 589function protoDecoder(buffer, params, fileName, store) { 590 const transformed = decodeAndTransformProto(buffer, params, store.displayDefaults); 591 592 // add tagGenerationTrace to dataFile for WM/SF traces so tags can be generated 593 var tagGenerationTrace = null; 594 if (params.type === FILE_TYPES.WINDOW_MANAGER_TRACE || 595 params.type === FILE_TYPES.SURFACE_FLINGER_TRACE) { 596 tagGenerationTrace = transformed; 597 } 598 599 let data; 600 if (params.timeline) { 601 data = transformed.entries ?? transformed.children; 602 } else { 603 data = [transformed]; 604 } 605 const blobUrl = URL.createObjectURL(new Blob([buffer], {type: params.mime})); 606 607 return dataFile( 608 fileName, 609 data.map((x) => x.timestamp), 610 data, 611 blobUrl, 612 params.type, 613 tagGenerationTrace 614 ); 615} 616 617function videoDecoder(buffer, params, fileName, store) { 618 const [data, timeline] = params.videoDecoder(buffer); 619 const blobUrl = URL.createObjectURL(new Blob([data], {type: params.mime})); 620 return dataFile(fileName, timeline, blobUrl, blobUrl, params.type); 621} 622 623function dataFile(filename, timeline, data, blobUrl, type, tagGenerationTrace = null) { 624 return { 625 filename: filename, 626 // Object is frozen for performance reasons 627 // It will prevent Vue from making it a reactive object which will be very slow as the timeline gets larger. 628 timeline: Object.freeze(timeline), 629 data: data, 630 blobUrl: blobUrl, 631 tagGenerationTrace: tagGenerationTrace, 632 type: type, 633 selectedIndex: 0, 634 destroy() { 635 URL.revokeObjectURL(this.blobUrl); 636 }, 637 }; 638} 639 640function arrayEquals(a, b) { 641 if (a.length !== b.length) { 642 return false; 643 } 644 for (let i = 0; i < a.length; i++) { 645 if (a[i] != b[i]) { 646 return false; 647 } 648 } 649 return true; 650} 651 652function arrayStartsWith(array, prefix) { 653 return arrayEquals(array.slice(0, prefix.length), prefix); 654} 655 656function decodedFile(fileType, buffer, fileName, store) { 657 const fileDecoder = FILE_DECODERS[fileType]; 658 return [fileType, fileDecoder.decoder(buffer, fileDecoder.decoderParams, fileName, store)]; 659} 660 661function detectAndDecode(buffer, fileName, store) { 662 if (arrayStartsWith(buffer, LAYER_TRACE_MAGIC_NUMBER)) { 663 return decodedFile(FILE_TYPES.SURFACE_FLINGER_TRACE, buffer, fileName, store); 664 } 665 if (arrayStartsWith(buffer, ACCESSIBILITY_MAGIC_NUMBER)) { 666 return decodedFile(FILE_TYPES.ACCESSIBILITY_TRACE, buffer, fileName, store); 667 } 668 if (arrayStartsWith(buffer, WINDOW_TRACE_MAGIC_NUMBER)) { 669 return decodedFile(FILE_TYPES.WINDOW_MANAGER_TRACE, buffer, fileName, store); 670 } 671 if (arrayStartsWith(buffer, MPEG4_MAGIC_NMBER)) { 672 return decodedFile(FILE_TYPES.SCREEN_RECORDING, buffer, fileName, store); 673 } 674 if (arrayStartsWith(buffer, TRANSACTIONS_TRACE_MAGIC_NUMBER)) { 675 return decodedFile(FILE_TYPES.TRANSACTIONS_TRACE, buffer, fileName, store); 676 } 677 if (arrayStartsWith(buffer, WAYLAND_TRACE_MAGIC_NUMBER)) { 678 return decodedFile(FILE_TYPES.WAYLAND_TRACE, buffer, fileName, store); 679 } 680 if (arrayStartsWith(buffer, PROTO_LOG_MAGIC_NUMBER)) { 681 return decodedFile(FILE_TYPES.PROTO_LOG, buffer, fileName, store); 682 } 683 if (arrayStartsWith(buffer, SYSTEM_UI_MAGIC_NUMBER)) { 684 return decodedFile(FILE_TYPES.SYSTEM_UI, buffer, fileName, store); 685 } 686 if (arrayStartsWith(buffer, LAUNCHER_MAGIC_NUMBER)) { 687 return decodedFile(FILE_TYPES.LAUNCHER, buffer, fileName, store); 688 } 689 if (arrayStartsWith(buffer, IMC_TRACE_MAGIC_NUMBER)) { 690 return decodedFile(FILE_TYPES.IME_TRACE_CLIENTS, buffer, fileName, store); 691 } 692 if (arrayStartsWith(buffer, IMS_TRACE_MAGIC_NUMBER)) { 693 return decodedFile(FILE_TYPES.IME_TRACE_SERVICE, buffer, fileName, store); 694 } 695 if (arrayStartsWith(buffer, IMM_TRACE_MAGIC_NUMBER)) { 696 return decodedFile(FILE_TYPES.IME_TRACE_MANAGERSERVICE, buffer, fileName, store); 697 } 698 if (arrayStartsWith(buffer, TAG_TRACE_MAGIC_NUMBER)) { 699 return decodedFile(FILE_TYPES.TAG_TRACE, buffer, fileName, store); 700 } 701 if (arrayStartsWith(buffer, ERROR_TRACE_MAGIC_NUMBER)) { 702 return decodedFile(FILE_TYPES.ERROR_TRACE, buffer, fileName, store); 703 } 704 705 // TODO(b/169305853): Add magic number at beginning of file for better auto detection 706 for (const [filetype, condition] of [ 707 [FILE_TYPES.TRANSACTIONS_TRACE_LEGACY, (file) => file.data.length > 0], 708 [FILE_TYPES.WAYLAND_DUMP, (file) => (file.data.length > 0 && file.data.children[0] > 0) || file.data.length > 1], 709 [FILE_TYPES.WINDOW_MANAGER_DUMP], 710 [FILE_TYPES.SURFACE_FLINGER_DUMP] 711 ]) { 712 try { 713 const [, fileData] = decodedFile(filetype, buffer, fileName, store); 714 715 // A generic file will often wrongly be decoded as an empty wayland dump file 716 if (condition && !condition(fileData)) { 717 // Fall through to next filetype 718 continue; 719 } 720 721 return [filetype, fileData]; 722 } catch (ex) { 723 // ignore exception and fall through to next filetype 724 } 725 } 726 throw new UndetectableFileType('Unable to detect file'); 727} 728 729/** 730 * Error is raised when detectAndDecode is called but the file can't be 731 * automatically detected as being of a compatible file type. 732 */ 733class UndetectableFileType extends Error { } 734 735export { 736 dataFile, 737 detectAndDecode, 738 decodeAndTransformProto, 739 TagTraceMessage, 740 FILE_TYPES, 741 TRACE_INFO, 742 TRACE_TYPES, 743 DUMP_TYPES, 744 DUMP_INFO, 745 FILE_DECODERS, 746 FILE_ICONS, 747 UndetectableFileType 748}; 749