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