1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {BigintMath} from '../base/bigint_math'; 16import {duration, time} from '../base/time'; 17import {RecordConfig} from '../controller/record_config_types'; 18import { 19 Aggregation, 20 PivotTree, 21 TableColumn, 22} from '../frontend/pivot_table_types'; 23 24import { 25 selectionToLegacySelection, 26 Selection, 27 LegacySelection, 28} from '../core/selection_manager'; 29 30export { 31 Selection, 32 SelectionKind, 33 NoteSelection, 34 SliceSelection, 35 HeapProfileSelection, 36 PerfSamplesSelection, 37 LegacySelection, 38 AreaSelection, 39 ProfileType, 40 ThreadSliceSelection, 41 CpuProfileSampleSelection, 42} from '../core/selection_manager'; 43 44// Tracks within track groups (usually corresponding to processes) are sorted. 45// As we want to group all tracks related to a given thread together, we use 46// two keys: 47// - Primary key corresponds to a priority of a track block (all tracks related 48// to a given thread or a single track if it's not thread-associated). 49// - Secondary key corresponds to a priority of a given thread-associated track 50// within its thread track block. 51// Each track will have a sort key, which either a primary sort key 52// (for non-thread tracks) or a tid and secondary sort key (mapping of tid to 53// primary sort key is done independently). 54export enum PrimaryTrackSortKey { 55 DEBUG_TRACK, 56 NULL_TRACK, 57 PROCESS_SCHEDULING_TRACK, 58 PROCESS_SUMMARY_TRACK, 59 EXPECTED_FRAMES_SLICE_TRACK, 60 ACTUAL_FRAMES_SLICE_TRACK, 61 PERF_SAMPLES_PROFILE_TRACK, 62 HEAP_PROFILE_TRACK, 63 MAIN_THREAD, 64 RENDER_THREAD, 65 GPU_COMPLETION_THREAD, 66 CHROME_IO_THREAD, 67 CHROME_COMPOSITOR_THREAD, 68 ORDINARY_THREAD, 69 COUNTER_TRACK, 70 ASYNC_SLICE_TRACK, 71 ORDINARY_TRACK, 72} 73 74/** 75 * A plain js object, holding objects of type |Class| keyed by string id. 76 * We use this instead of using |Map| object since it is simpler and faster to 77 * serialize for use in postMessage. 78 */ 79export interface ObjectById<Class extends {id: string}> { 80 [id: string]: Class; 81} 82 83// Same as ObjectById but the key parameter is called `key` rather than `id`. 84export interface ObjectByKey<Class extends {key: string}> { 85 [key: string]: Class; 86} 87 88export interface Timestamped { 89 lastUpdate: number; 90} 91 92export type OmniboxMode = 'SEARCH' | 'COMMAND'; 93 94export interface OmniboxState { 95 omnibox: string; 96 mode: OmniboxMode; 97 force?: boolean; 98} 99 100// This is simply an arbitrarily large number to default to. 101export const RESOLUTION_DEFAULT = BigintMath.bitFloor(1_000_000_000_000n); 102 103export interface VisibleState extends Timestamped { 104 start: time; 105 end: time; 106 resolution: duration; 107} 108 109export interface Area { 110 start: time; 111 end: time; 112 tracks: string[]; 113} 114 115export const MAX_TIME = 180; 116 117// 3: TrackKindPriority and related sorting changes. 118// 5: Move a large number of items off frontendLocalState and onto state. 119// 6: Common PivotTableConfig and pivot table specific PivotTableState. 120// 7: Split Chrome categories in two and add 'symbolize ksyms' flag. 121// 8: Rename several variables 122// "[...]HeapProfileFlamegraph[...]" -> "[...]Flamegraph[...]". 123// 9: Add a field to track last loaded recording profile name 124// 10: Change last loaded profile tracking type to accommodate auto-save. 125// 11: Rename updateChromeCategories to fetchChromeCategories. 126// 12: Add a field to cache mapping from UI track ID to trace track ID in order 127// to speed up flow arrows rendering. 128// 13: FlamegraphState changed to support area selection. 129// 14: Changed the type of uiTrackIdByTraceTrackId from `Map` to an object with 130// typed key/value because a `Map` does not preserve type during 131// serialisation+deserialisation. 132// 15: Added state for Pivot Table V2 133// 16: Added boolean tracking if the flamegraph modal was dismissed 134// 17: 135// - add currentEngineId to track the id of the current engine 136// - remove nextNoteId, nextAreaId and use nextId as a unique counter for all 137// indexing except the indexing of the engines 138// 18: areaSelection change see b/235869542 139// 19: Added visualisedArgs state. 140// 20: Refactored thread sorting order. 141// 21: Updated perf sample selection to include a ts range instead of single ts 142// 22: Add log selection kind. 143// 23: Add log filtering criteria for Android log entries. 144// 24: Store only a single Engine. 145// 25: Move omnibox state off VisibleState. 146// 26: Add tags for filtering Android log entries. 147// 27. Add a text entry for filtering Android log entries. 148// 28. Add a boolean indicating if non matching log entries are hidden. 149// 29. Add ftrace state. <-- Borked, state contains a non-serializable object. 150// 30. Convert ftraceFilter.excludedNames from Set<string> to string[]. 151// 31. Convert all timestamps to bigints. 152// 32. Add pendingDeeplink. 153// 33. Add plugins state. 154// 34. Add additional pendingDeeplink fields (query, pid). 155// 35. Add force to OmniboxState 156// 36. Remove metrics 157// 37. Add additional pendingDeeplink fields (visStart, visEnd). 158// 38. Add track tags. 159// 39. Ported cpu_slice, ftrace, and android_log tracks to plugin tracks. Track 160// state entries now require a URI and old track implementations are no 161// longer registered. 162// 40. Ported counter, process summary/sched, & cpu_freq to plugin tracks. 163// 41. Ported all remaining tracks. 164// 42. Rename trackId -> trackKey. 165// 43. Remove visibleTracks. 166// 44. Add TabsV2 state. 167// 45. Remove v1 tracks. 168// 46. Remove trackKeyByTrackId. 169// 47. Selection V2 170// 48. Rename legacySelection -> selection and introduce new Selection type. 171// 49. Remove currentTab, which is only relevant to TabsV1. 172// 50. Remove ftrace filter state. 173// 51. Changed structure of FlamegraphState.expandedCallsiteByViewingOption. 174// 52. Update track group state - don't make the summary track the first track. 175// 53. Remove android log state. 176// 54. Remove traceTime. 177// 55. Rename TrackGroupState.id -> TrackGroupState.key. 178// 56. Renamed chrome slice to thread slice everywhere. 179// 57. Remove flamegraph related code from state. 180// 58. Remove area map. 181// 59. Deprecate old area selection type. 182// 60. Deprecate old note selection type. 183// 61. Remove params/state from TrackState. 184export const STATE_VERSION = 61; 185 186export const SCROLLING_TRACK_GROUP = 'ScrollingTracks'; 187 188export type EngineMode = 'WASM' | 'HTTP_RPC'; 189 190export type NewEngineMode = 'USE_HTTP_RPC_IF_AVAILABLE' | 'FORCE_BUILTIN_WASM'; 191 192// Key that is used to sort tracks within a block of tracks associated with a 193// given thread. 194export enum InThreadTrackSortKey { 195 THREAD_COUNTER_TRACK, 196 THREAD_SCHEDULING_STATE_TRACK, 197 CPU_STACK_SAMPLES_TRACK, 198 VISUALISED_ARGS_TRACK, 199 ORDINARY, 200 DEFAULT_TRACK, 201} 202 203// Sort key used for sorting tracks associated with a thread. 204export type ThreadTrackSortKey = { 205 utid: number; 206 priority: InThreadTrackSortKey; 207}; 208 209// Sort key for all tracks: both thread-associated and non-thread associated. 210export type TrackSortKey = PrimaryTrackSortKey | ThreadTrackSortKey; 211 212// Mapping which defines order for threads within a given process. 213export type UtidToTrackSortKey = { 214 [utid: number]: { 215 tid?: number; 216 sortKey: PrimaryTrackSortKey; 217 }; 218}; 219 220export interface TraceFileSource { 221 type: 'FILE'; 222 file: File; 223} 224 225export interface TraceArrayBufferSource { 226 type: 'ARRAY_BUFFER'; 227 buffer: ArrayBuffer; 228 title: string; 229 url?: string; 230 fileName?: string; 231 232 // |uuid| is set only when loading via ?local_cache_key=1234. When set, 233 // this matches global.state.traceUuid, with the exception of the following 234 // time window: When a trace T1 is loaded and the user loads another trace T2, 235 // this |uuid| will be == T2, but the globals.state.traceUuid will be 236 // temporarily == T1 until T2 has been loaded (consistently to what happens 237 // with all other state fields). 238 uuid?: string; 239 // if |localOnly| is true then the trace should not be shared or downloaded. 240 localOnly?: boolean; 241 242 // The set of extra args, keyed by plugin, that can be passed when opening the 243 // trace via postMessge deep-linking. See post_message_handler.ts for details. 244 pluginArgs?: {[pluginId: string]: {[key: string]: unknown}}; 245} 246 247export interface TraceUrlSource { 248 type: 'URL'; 249 url: string; 250} 251 252export interface TraceHttpRpcSource { 253 type: 'HTTP_RPC'; 254} 255 256export type TraceSource = 257 | TraceFileSource 258 | TraceArrayBufferSource 259 | TraceUrlSource 260 | TraceHttpRpcSource; 261 262export interface TrackState { 263 uri: string; 264 key: string; 265 name: string; 266 labels?: string[]; 267 trackSortKey: TrackSortKey; 268 trackGroup?: string; 269 closeable?: boolean; 270} 271 272export interface TrackGroupState { 273 key: string; 274 name: string; 275 collapsed: boolean; 276 tracks: string[]; // Child track ids. 277 fixedOrdering?: boolean; // Render tracks without sorting. 278 summaryTrack: string | undefined; 279} 280 281export interface EngineConfig { 282 id: string; 283 mode?: EngineMode; // Is undefined until |ready| is true. 284 ready: boolean; 285 failed?: string; // If defined the engine has crashed with the given message. 286 source: TraceSource; 287} 288 289export interface QueryConfig { 290 id: string; 291 engineId?: string; 292 query: string; 293} 294 295export interface FrontendLocalState { 296 visibleState: VisibleState; 297} 298 299export interface Status { 300 msg: string; 301 timestamp: number; // Epoch in seconds (Date.now() / 1000). 302} 303 304export interface Note { 305 noteType: 'DEFAULT'; 306 id: string; 307 timestamp: time; 308 color: string; 309 text: string; 310} 311 312export interface SpanNote { 313 noteType: 'SPAN'; 314 id: string; 315 start: time; 316 end: time; 317 color: string; 318 text: string; 319} 320 321export interface Pagination { 322 offset: number; 323 count: number; 324} 325 326export interface RecordingTarget { 327 name: string; 328 os: TargetOs; 329} 330 331export interface AdbRecordingTarget extends RecordingTarget { 332 serial: string; 333} 334 335export interface Sorting { 336 column: string; 337 direction: 'DESC' | 'ASC'; 338} 339 340export interface AggregationState { 341 id: string; 342 sorting?: Sorting; 343} 344 345// Auxiliary metadata needed to parse the query result, as well as to render it 346// correctly. Generated together with the text of query and passed without the 347// change to the query response. 348export interface PivotTableQueryMetadata { 349 pivotColumns: TableColumn[]; 350 aggregationColumns: Aggregation[]; 351 countIndex: number; 352} 353 354// Everything that's necessary to run the query for pivot table 355export interface PivotTableQuery { 356 text: string; 357 metadata: PivotTableQueryMetadata; 358} 359 360// Pivot table query result 361export interface PivotTableResult { 362 // Hierarchical pivot structure on top of rows 363 tree: PivotTree; 364 // Copy of the query metadata from the request, bundled up with the query 365 // result to ensure the correct rendering. 366 metadata: PivotTableQueryMetadata; 367} 368 369// Input parameters to check whether the pivot table needs to be re-queried. 370export interface PivotTableAreaState { 371 start: time; 372 end: time; 373 tracks: string[]; 374} 375 376export interface PivotTableState { 377 // Currently selected area, if null, pivot table is not going to be visible. 378 selectionArea?: PivotTableAreaState; 379 380 // Query response 381 queryResult: PivotTableResult | null; 382 383 // Selected pivots for tables other than slice. 384 // Because of the query generation, pivoting happens first on non-slice 385 // pivots; therefore, those can't be put after slice pivots. In order to 386 // maintain the separation more clearly, slice and non-slice pivots are 387 // located in separate arrays. 388 selectedPivots: TableColumn[]; 389 390 // Selected aggregation columns. Stored same way as pivots. 391 selectedAggregations: Aggregation[]; 392 393 // Whether the pivot table results should be constrained to the selected area. 394 constrainToArea: boolean; 395 396 // Set to true by frontend to request controller to perform the query to 397 // acquire the necessary data from the engine. 398 queryRequested: boolean; 399} 400 401export interface LoadedConfigNone { 402 type: 'NONE'; 403} 404 405export interface LoadedConfigAutomatic { 406 type: 'AUTOMATIC'; 407} 408 409export interface LoadedConfigNamed { 410 type: 'NAMED'; 411 name: string; 412} 413 414export type LoadedConfig = 415 | LoadedConfigNone 416 | LoadedConfigAutomatic 417 | LoadedConfigNamed; 418 419export interface NonSerializableState { 420 pivotTable: PivotTableState; 421} 422 423export interface PendingDeeplinkState { 424 ts?: string; 425 dur?: string; 426 tid?: string; 427 pid?: string; 428 query?: string; 429 visStart?: string; 430 visEnd?: string; 431} 432 433export interface TabsV2State { 434 openTabs: string[]; 435 currentTab: string; 436} 437 438export interface State { 439 version: number; 440 nextId: string; 441 442 /** 443 * State of the ConfigEditor. 444 */ 445 recordConfig: RecordConfig; 446 displayConfigAsPbtxt: boolean; 447 lastLoadedConfig: LoadedConfig; 448 449 /** 450 * Open traces. 451 */ 452 newEngineMode: NewEngineMode; 453 engine?: EngineConfig; 454 traceUuid?: string; 455 trackGroups: ObjectByKey<TrackGroupState>; 456 tracks: ObjectByKey<TrackState>; 457 utidToThreadSortKey: UtidToTrackSortKey; 458 aggregatePreferences: ObjectById<AggregationState>; 459 scrollingTracks: string[]; 460 pinnedTracks: string[]; 461 debugTrackId?: string; 462 lastTrackReloadRequest?: number; 463 queries: ObjectById<QueryConfig>; 464 notes: ObjectById<Note | SpanNote>; 465 status: Status; 466 selection: Selection; 467 traceConversionInProgress: boolean; 468 flamegraphModalDismissed: boolean; 469 470 /** 471 * This state is updated on the frontend at 60Hz and eventually syncronised to 472 * the controller at 10Hz. When the controller sends state updates to the 473 * frontend the frontend has special logic to pick whichever version of this 474 * key is most up to date. 475 */ 476 frontendLocalState: FrontendLocalState; 477 478 // Show track perf debugging overlay 479 perfDebug: boolean; 480 481 // Show the sidebar extended 482 sidebarVisible: boolean; 483 484 // Hovered and focused events 485 hoveredUtid: number; 486 hoveredPid: number; 487 hoverCursorTimestamp: time; 488 hoveredNoteTimestamp: time; 489 highlightedSliceId: number; 490 focusedFlowIdLeft: number; 491 focusedFlowIdRight: number; 492 pendingScrollId?: number; 493 494 searchIndex: number; 495 496 tabs: TabsV2State; 497 498 /** 499 * Trace recording 500 */ 501 recordingInProgress: boolean; 502 recordingCancelled: boolean; 503 extensionInstalled: boolean; 504 recordingTarget: RecordingTarget; 505 availableAdbDevices: AdbRecordingTarget[]; 506 lastRecordingError?: string; 507 recordingStatus?: string; 508 509 fetchChromeCategories: boolean; 510 chromeCategories: string[] | undefined; 511 512 // Special key: this part of the state is not going to be serialized when 513 // using permalink. Can be used to store those parts of the state that can't 514 // be serialized at the moment, such as ES6 Set and Map. 515 nonSerializableState: NonSerializableState; 516 517 // Omnibox info. 518 omniboxState: OmniboxState; 519 520 // Pending deeplink which will happen when we first finish opening a 521 // trace. 522 pendingDeeplink?: PendingDeeplinkState; 523 524 // Individual plugin states 525 // eslint-disable-next-line @typescript-eslint/no-explicit-any 526 plugins: {[key: string]: any}; 527} 528 529export declare type RecordMode = 530 | 'STOP_WHEN_FULL' 531 | 'RING_BUFFER' 532 | 'LONG_TRACE'; 533 534// 'Q','P','O' for Android, 'L' for Linux, 'C' for Chrome. 535export declare type TargetOs = 536 | 'S' 537 | 'R' 538 | 'Q' 539 | 'P' 540 | 'O' 541 | 'C' 542 | 'L' 543 | 'CrOS' 544 | 'Win'; 545 546export function isAndroidP(target: RecordingTarget) { 547 return target.os === 'P'; 548} 549 550export function isAndroidTarget(target: RecordingTarget) { 551 return ['Q', 'P', 'O'].includes(target.os); 552} 553 554export function isChromeTarget(target: RecordingTarget) { 555 return ['C', 'CrOS'].includes(target.os); 556} 557 558export function isCrOSTarget(target: RecordingTarget) { 559 return target.os === 'CrOS'; 560} 561 562export function isLinuxTarget(target: RecordingTarget) { 563 return target.os === 'L'; 564} 565 566export function isWindowsTarget(target: RecordingTarget) { 567 return target.os === 'Win'; 568} 569 570export function isAdbTarget( 571 target: RecordingTarget, 572): target is AdbRecordingTarget { 573 return !!(target as AdbRecordingTarget).serial; 574} 575 576export function hasActiveProbes(config: RecordConfig) { 577 const fieldsWithEmptyResult = new Set<string>([ 578 'hpBlockClient', 579 'allAtraceApps', 580 'chromePrivacyFiltering', 581 ]); 582 let key: keyof RecordConfig; 583 for (key in config) { 584 if ( 585 typeof config[key] === 'boolean' && 586 config[key] === true && 587 !fieldsWithEmptyResult.has(key) 588 ) { 589 return true; 590 } 591 } 592 if (config.chromeCategoriesSelected.length > 0) { 593 return true; 594 } 595 return config.chromeHighOverheadCategoriesSelected.length > 0; 596} 597 598export function getDefaultRecordingTargets(): RecordingTarget[] { 599 return [ 600 {os: 'Q', name: 'Android Q+ / 10+'}, 601 {os: 'P', name: 'Android P / 9'}, 602 {os: 'O', name: 'Android O- / 8-'}, 603 {os: 'C', name: 'Chrome'}, 604 {os: 'CrOS', name: 'Chrome OS (system trace)'}, 605 {os: 'L', name: 'Linux desktop'}, 606 {os: 'Win', name: 'Windows desktop'}, 607 ]; 608} 609 610export function getBuiltinChromeCategoryList(): string[] { 611 // List of static Chrome categories, last updated at 2024-05-15 from HEAD of 612 // Chromium's //base/trace_event/builtin_categories.h. 613 return [ 614 'accessibility', 615 'AccountFetcherService', 616 'android.adpf', 617 'android.ui.jank', 618 'android_webview', 619 'android_webview.timeline', 620 'aogh', 621 'audio', 622 'base', 623 'benchmark', 624 'blink', 625 'blink.animations', 626 'blink.bindings', 627 'blink.console', 628 'blink.net', 629 'blink.resource', 630 'blink.user_timing', 631 'blink.worker', 632 'blink_style', 633 'Blob', 634 'browser', 635 'browsing_data', 636 'CacheStorage', 637 'Calculators', 638 'CameraStream', 639 'cppgc', 640 'camera', 641 'cast_app', 642 'cast_perf_test', 643 'cast.mdns', 644 'cast.mdns.socket', 645 'cast.stream', 646 'cc', 647 'cc.debug', 648 'cdp.perf', 649 'chromeos', 650 'cma', 651 'compositor', 652 'content', 653 'content_capture', 654 'interactions', 655 'delegated_ink_trails', 656 'device', 657 'devtools', 658 'devtools.contrast', 659 'devtools.timeline', 660 'disk_cache', 661 'download', 662 'download_service', 663 'drm', 664 'drmcursor', 665 'dwrite', 666 'DXVA_Decoding', 667 'evdev', 668 'event', 669 'event_latency', 670 'exo', 671 'extensions', 672 'explore_sites', 673 'FileSystem', 674 'file_system_provider', 675 'fledge', 676 'fonts', 677 'GAMEPAD', 678 'gpu', 679 'gpu.angle', 680 'gpu.angle.texture_metrics', 681 'gpu.capture', 682 'graphics.pipeline', 683 'headless', 684 'history', 685 'hwoverlays', 686 'identity', 687 'ime', 688 'IndexedDB', 689 'input', 690 'input.scrolling', 691 'io', 692 'ipc', 693 'Java', 694 'jni', 695 'jpeg', 696 'latency', 697 'latencyInfo', 698 'leveldb', 699 'loading', 700 'log', 701 'login', 702 'media', 703 'media_router', 704 'memory', 705 'midi', 706 'mojom', 707 'mus', 708 'native', 709 'navigation', 710 'navigation.debug', 711 'net', 712 'network.scheduler', 713 'netlog', 714 'offline_pages', 715 'omnibox', 716 'oobe', 717 'openscreen', 718 'ozone', 719 'partition_alloc', 720 'passwords', 721 'p2p', 722 'page-serialization', 723 'paint_preview', 724 'pepper', 725 'PlatformMalloc', 726 'power', 727 'ppapi', 728 'ppapi_proxy', 729 'print', 730 'raf_investigation', 731 'rail', 732 'renderer', 733 'renderer_host', 734 'renderer.scheduler', 735 'resources', 736 'RLZ', 737 'ServiceWorker', 738 'SiteEngagement', 739 'safe_browsing', 740 'scheduler', 741 'scheduler.long_tasks', 742 'screenlock_monitor', 743 'segmentation_platform', 744 'sequence_manager', 745 'service_manager', 746 'sharing', 747 'shell', 748 'shortcut_viewer', 749 'shutdown', 750 'skia', 751 'sql', 752 'stadia_media', 753 'stadia_rtc', 754 'startup', 755 'sync', 756 'system_apps', 757 'test_gpu', 758 'toplevel', 759 'toplevel.flow', 760 'ui', 761 'v8', 762 'v8.execute', 763 'v8.wasm', 764 'ValueStoreFrontend::Backend', 765 'views', 766 'views.frame', 767 'viz', 768 'vk', 769 'wakeup.flow', 770 'wayland', 771 'webaudio', 772 'webengine.fidl', 773 'weblayer', 774 'WebCore', 775 'webnn', 776 'webrtc', 777 'webrtc_stats', 778 'xr', 779 'disabled-by-default-android_view_hierarchy', 780 'disabled-by-default-animation-worklet', 781 'disabled-by-default-audio', 782 'disabled-by-default-audio.latency', 783 'disabled-by-default-audio-worklet', 784 'disabled-by-default-base', 785 'disabled-by-default-blink.debug', 786 'disabled-by-default-blink.debug.display_lock', 787 'disabled-by-default-blink.debug.layout', 788 'disabled-by-default-blink.debug.layout.trees', 789 'disabled-by-default-blink.feature_usage', 790 'disabled-by-default-blink.image_decoding', 791 'disabled-by-default-blink.invalidation', 792 'disabled-by-default-identifiability', 793 'disabled-by-default-identifiability.high_entropy_api', 794 'disabled-by-default-cc', 795 'disabled-by-default-cc.debug', 796 'disabled-by-default-cc.debug.cdp-perf', 797 'disabled-by-default-cc.debug.display_items', 798 'disabled-by-default-cc.debug.lcd_text', 799 'disabled-by-default-cc.debug.picture', 800 'disabled-by-default-cc.debug.scheduler', 801 'disabled-by-default-cc.debug.scheduler.frames', 802 'disabled-by-default-cc.debug.scheduler.now', 803 'disabled-by-default-content.verbose', 804 'disabled-by-default-cpu_profiler', 805 'disabled-by-default-cppgc', 806 'disabled-by-default-cpu_profiler.debug', 807 'disabled-by-default-devtools.screenshot', 808 'disabled-by-default-devtools.timeline', 809 'disabled-by-default-devtools.timeline.frame', 810 'disabled-by-default-devtools.timeline.inputs', 811 'disabled-by-default-devtools.timeline.invalidationTracking', 812 'disabled-by-default-devtools.timeline.layers', 813 'disabled-by-default-devtools.timeline.picture', 814 'disabled-by-default-devtools.timeline.stack', 815 'disabled-by-default-devtools.target-rundown', 816 'disabled-by-default-devtools.v8-source-rundown', 817 'disabled-by-default-devtools.v8-source-rundown-sources', 818 'disabled-by-default-file', 819 'disabled-by-default-fonts', 820 'disabled-by-default-gpu_cmd_queue', 821 'disabled-by-default-gpu.dawn', 822 'disabled-by-default-gpu.debug', 823 'disabled-by-default-gpu.decoder', 824 'disabled-by-default-gpu.device', 825 'disabled-by-default-gpu.graphite.dawn', 826 'disabled-by-default-gpu.service', 827 'disabled-by-default-gpu.vulkan.vma', 828 'disabled-by-default-histogram_samples', 829 'disabled-by-default-java-heap-profiler', 830 'disabled-by-default-layer-element', 831 'disabled-by-default-layout_shift.debug', 832 'disabled-by-default-lifecycles', 833 'disabled-by-default-loading', 834 'disabled-by-default-mediastream', 835 'disabled-by-default-memory-infra', 836 'disabled-by-default-memory-infra.v8.code_stats', 837 'disabled-by-default-mojom', 838 'disabled-by-default-net', 839 'disabled-by-default-network', 840 'disabled-by-default-paint-worklet', 841 'disabled-by-default-power', 842 'disabled-by-default-renderer.scheduler', 843 'disabled-by-default-renderer.scheduler.debug', 844 'disabled-by-default-sequence_manager', 845 'disabled-by-default-sequence_manager.debug', 846 'disabled-by-default-sequence_manager.verbose_snapshots', 847 'disabled-by-default-skia', 848 'disabled-by-default-skia.gpu', 849 'disabled-by-default-skia.gpu.cache', 850 'disabled-by-default-skia.shaders', 851 'disabled-by-default-skottie', 852 'disabled-by-default-SyncFileSystem', 853 'disabled-by-default-system_power', 854 'disabled-by-default-system_stats', 855 'disabled-by-default-thread_pool_diagnostics', 856 'disabled-by-default-toplevel.ipc', 857 'disabled-by-default-user_action_samples', 858 'disabled-by-default-v8.compile', 859 'disabled-by-default-v8.cpu_profiler', 860 'disabled-by-default-v8.gc', 861 'disabled-by-default-v8.gc_stats', 862 'disabled-by-default-v8.ic_stats', 863 'disabled-by-default-v8.inspector', 864 'disabled-by-default-v8.runtime', 865 'disabled-by-default-v8.runtime_stats', 866 'disabled-by-default-v8.runtime_stats_sampling', 867 'disabled-by-default-v8.stack_trace', 868 'disabled-by-default-v8.turbofan', 869 'disabled-by-default-v8.wasm.detailed', 870 'disabled-by-default-v8.wasm.turbofan', 871 'disabled-by-default-video_and_image_capture', 872 'disabled-by-default-display.framedisplayed', 873 'disabled-by-default-viz.gpu_composite_time', 874 'disabled-by-default-viz.debug.overlay_planes', 875 'disabled-by-default-viz.hit_testing_flow', 876 'disabled-by-default-viz.overdraw', 877 'disabled-by-default-viz.quads', 878 'disabled-by-default-viz.surface_id_flow', 879 'disabled-by-default-viz.surface_lifetime', 880 'disabled-by-default-viz.triangles', 881 'disabled-by-default-viz.visual_debugger', 882 'disabled-by-default-webaudio.audionode', 883 'disabled-by-default-webgpu', 884 'disabled-by-default-webnn', 885 'disabled-by-default-webrtc', 886 'disabled-by-default-worker.scheduler', 887 'disabled-by-default-xr.debug', 888 ]; 889} 890 891export function getContainingGroupKey( 892 state: State, 893 trackKey: string, 894): null | string { 895 const track = state.tracks[trackKey]; 896 if (track === undefined) { 897 return null; 898 } 899 const parentGroupKey = track.trackGroup; 900 if (!parentGroupKey) { 901 return null; 902 } 903 return parentGroupKey; 904} 905 906export function getLegacySelection(state: State): LegacySelection | null { 907 return selectionToLegacySelection(state.selection); 908} 909