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