• 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
15/**
16 * A plain js object, holding objects of type |Class| keyed by string id.
17 * We use this instead of using |Map| object since it is simpler and faster to
18 * serialize for use in postMessage.
19 */
20export interface ObjectById<Class extends{id: string}> { [id: string]: Class; }
21
22export type Timestamped<T> = {
23  [P in keyof T]: T[P];
24}&{lastUpdate: number};
25
26export type OmniboxState =
27    Timestamped<{omnibox: string; mode: 'SEARCH' | 'COMMAND'}>;
28
29export type VisibleState =
30    Timestamped<{startSec: number; endSec: number; resolution: number;}>;
31
32export type TimestampedAreaSelection = Timestamped<AreaSelection>;
33export interface AreaSelection {
34  area?: Area;
35}
36export interface Area {
37  startSec: number;
38  endSec: number;
39  tracks: string[];
40}
41
42export const MAX_TIME = 180;
43
44export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
45
46
47export type EngineMode = 'WASM'|'HTTP_RPC';
48
49export type NewEngineMode = 'USE_HTTP_RPC_IF_AVAILABLE'|'FORCE_BUILTIN_WASM';
50
51export type HeapProfileFlamegraphViewingOption =
52    'SPACE'|'ALLOC_SPACE'|'OBJECTS'|'ALLOC_OBJECTS';
53
54export interface CallsiteInfo {
55  id: number;
56  parentId: number;
57  depth: number;
58  name?: string;
59  totalSize: number;
60  selfSize: number;
61  mapping: string;
62  merged: boolean;
63}
64
65export interface TraceFileSource {
66  type: 'FILE';
67  file: File;
68}
69
70export interface TraceArrayBufferSource {
71  type: 'ARRAY_BUFFER';
72  title: string;
73  url?: string;
74  buffer: ArrayBuffer;
75}
76
77export interface TraceUrlSource {
78  type: 'URL';
79  url: string;
80}
81
82export interface TraceHttpRpcSource {
83  type: 'HTTP_RPC';
84}
85
86export type TraceSource =
87    TraceFileSource|TraceArrayBufferSource|TraceUrlSource|TraceHttpRpcSource;
88
89export interface TrackState {
90  id: string;
91  engineId: string;
92  kind: string;
93  name: string;
94  trackGroup?: string;
95  config: {};
96}
97
98export interface TrackGroupState {
99  id: string;
100  engineId: string;
101  name: string;
102  collapsed: boolean;
103  tracks: string[];  // Child track ids.
104  summaryTrackId: string;
105}
106
107export interface EngineConfig {
108  id: string;
109  mode?: EngineMode;  // Is undefined until |ready| is true.
110  ready: boolean;
111  failed?: string;  // If defined the engine has crashed with the given message.
112  source: TraceSource;
113}
114
115export interface QueryConfig {
116  id: string;
117  engineId: string;
118  query: string;
119}
120
121export interface PermalinkConfig {
122  requestId?: string;  // Set by the frontend to request a new permalink.
123  hash?: string;       // Set by the controller when the link has been created.
124}
125
126export interface TraceTime {
127  startSec: number;
128  endSec: number;
129}
130
131export interface FrontendLocalState {
132  omniboxState: OmniboxState;
133  visibleState: VisibleState;
134  selectedArea: TimestampedAreaSelection;
135}
136
137export interface Status {
138  msg: string;
139  timestamp: number;  // Epoch in seconds (Date.now() / 1000).
140}
141
142export interface Note {
143  noteType: 'DEFAULT'|'MOVIE';
144  id: string;
145  timestamp: number;
146  color: string;
147  text: string;
148}
149
150export interface AreaNote {
151  noteType: 'AREA';
152  id: string;
153  timestamp: number;
154  area: Area;
155  color: string;
156  text: string;
157}
158
159export interface NoteSelection {
160  kind: 'NOTE';
161  id: string;
162}
163
164export interface SliceSelection {
165  kind: 'SLICE';
166  id: number;
167}
168
169export interface CounterSelection {
170  kind: 'COUNTER';
171  leftTs: number;
172  rightTs: number;
173  id: number;
174}
175
176export interface HeapProfileSelection {
177  kind: 'HEAP_PROFILE';
178  id: number;
179  upid: number;
180  ts: number;
181  type: string;
182}
183
184export interface HeapProfileFlamegraph {
185  kind: 'HEAP_PROFILE_FLAMEGRAPH';
186  id: number;
187  upid: number;
188  ts: number;
189  type: string;
190  viewingOption: HeapProfileFlamegraphViewingOption;
191  focusRegex: string;
192  expandedCallsite?: CallsiteInfo;
193}
194
195export interface CpuProfileSampleSelection {
196  kind: 'CPU_PROFILE_SAMPLE';
197  id: number;
198  utid: number;
199  ts: number;
200}
201
202export interface ChromeSliceSelection {
203  kind: 'CHROME_SLICE';
204  id: number;
205  table: string;
206}
207
208export interface ThreadStateSelection {
209  kind: 'THREAD_STATE';
210  utid: number;
211  ts: number;
212  dur: number;
213  state: string;
214  cpu: number;
215}
216
217type Selection = (NoteSelection|SliceSelection|CounterSelection|
218                  HeapProfileSelection|CpuProfileSampleSelection|
219                  ChromeSliceSelection|ThreadStateSelection)&{trackId?: string};
220
221export interface LogsPagination {
222  offset: number;
223  count: number;
224}
225
226export interface RecordingTarget {
227  name: string;
228  os: TargetOs;
229}
230
231export interface AdbRecordingTarget extends RecordingTarget {
232  serial: string;
233}
234
235export interface Sorting {
236  column: string;
237  direction: 'DESC'|'ASC';
238}
239
240export interface AggregationState {
241  id: string;
242  sorting?: Sorting;
243}
244
245export interface State {
246  // tslint:disable-next-line:no-any
247  [key: string]: any;
248  route: string|null;
249  nextId: number;
250
251  /**
252   * State of the ConfigEditor.
253   */
254  recordConfig: RecordConfig;
255  displayConfigAsPbtxt: boolean;
256
257  /**
258   * Open traces.
259   */
260  newEngineMode: NewEngineMode;
261  engines: ObjectById<EngineConfig>;
262  traceTime: TraceTime;
263  trackGroups: ObjectById<TrackGroupState>;
264  tracks: ObjectById<TrackState>;
265  aggregatePreferences: ObjectById<AggregationState>;
266  visibleTracks: string[];
267  scrollingTracks: string[];
268  pinnedTracks: string[];
269  queries: ObjectById<QueryConfig>;
270  permalink: PermalinkConfig;
271  notes: ObjectById<Note|AreaNote>;
272  status: Status;
273  currentSelection: Selection|null;
274  currentHeapProfileFlamegraph: HeapProfileFlamegraph|null;
275  logsPagination: LogsPagination;
276
277  /**
278   * This state is updated on the frontend at 60Hz and eventually syncronised to
279   * the controller at 10Hz. When the controller sends state updates to the
280   * frontend the frontend has special logic to pick whichever version of this
281   * key is most up to date.
282   */
283  frontendLocalState: FrontendLocalState;
284
285  video: string | null;
286  videoEnabled: boolean;
287  videoOffset: number;
288  videoNoteIds: string[];
289  scrubbingEnabled: boolean;
290  flagPauseEnabled: boolean;
291
292  /**
293   * Trace recording
294   */
295  recordingInProgress: boolean;
296  recordingCancelled: boolean;
297  extensionInstalled: boolean;
298  recordingTarget: RecordingTarget;
299  availableAdbDevices: AdbRecordingTarget[];
300  lastRecordingError?: string;
301  recordingStatus?: string;
302
303  chromeCategories: string[]|undefined;
304  analyzePageQuery?: string;
305}
306
307export const defaultTraceTime = {
308  startSec: 0,
309  endSec: 10,
310};
311
312export declare type RecordMode =
313    'STOP_WHEN_FULL' | 'RING_BUFFER' | 'LONG_TRACE';
314
315// 'Q','P','O' for Android, 'L' for Linux, 'C' for Chrome.
316export declare type TargetOs = 'Q' | 'P' | 'O' | 'C' | 'L';
317
318export function isAndroidP(target: RecordingTarget) {
319  return target.os === 'P';
320}
321
322export function isAndroidTarget(target: RecordingTarget) {
323  return ['Q', 'P', 'O'].includes(target.os);
324}
325
326export function isChromeTarget(target: RecordingTarget) {
327  return target.os === 'C';
328}
329
330export function isLinuxTarget(target: RecordingTarget) {
331  return target.os === 'L';
332}
333
334export function isAdbTarget(target: RecordingTarget):
335    target is AdbRecordingTarget {
336  if ((target as AdbRecordingTarget).serial) return true;
337  return false;
338}
339
340export interface RecordConfig {
341  [key: string]: null|number|boolean|string|string[];
342
343  // Global settings
344  mode: RecordMode;
345  durationMs: number;
346  bufferSizeMb: number;
347  maxFileSizeMb: number;      // Only for mode == 'LONG_TRACE'.
348  fileWritePeriodMs: number;  // Only for mode == 'LONG_TRACE'.
349
350  cpuSched: boolean;
351  cpuLatency: boolean;
352  cpuFreq: boolean;
353  cpuCoarse: boolean;
354  cpuCoarsePollMs: number;
355  cpuSyscall: boolean;
356
357  screenRecord: boolean;
358
359  gpuFreq: boolean;
360
361  ftrace: boolean;
362  atrace: boolean;
363  ftraceEvents: string[];
364  ftraceExtraEvents: string;
365  atraceCats: string[];
366  atraceApps: string;
367  ftraceBufferSizeKb: number;
368  ftraceDrainPeriodMs: number;
369  androidLogs: boolean;
370  androidLogBuffers: string[];
371
372  batteryDrain: boolean;
373  batteryDrainPollMs: number;
374
375  boardSensors: boolean;
376
377  memHiFreq: boolean;
378  memLmk: boolean;
379  meminfo: boolean;
380  meminfoPeriodMs: number;
381  meminfoCounters: string[];
382  vmstat: boolean;
383  vmstatPeriodMs: number;
384  vmstatCounters: string[];
385
386  heapProfiling: boolean;
387  hpSamplingIntervalBytes: number;
388  hpProcesses: string;
389  hpContinuousDumpsPhase: number;
390  hpContinuousDumpsInterval: number;
391  hpSharedMemoryBuffer: number;
392
393  javaHeapDump: boolean;
394  jpProcesses: string;
395  jpContinuousDumpsPhase: number;
396  jpContinuousDumpsInterval: number;
397
398  procStats: boolean;
399  procStatsPeriodMs: number;
400
401  chromeCategoriesSelected: string[];
402}
403
404export function createEmptyRecordConfig(): RecordConfig {
405  return {
406    mode: 'STOP_WHEN_FULL',
407    durationMs: 10000.0,
408    maxFileSizeMb: 100,
409    fileWritePeriodMs: 2500,
410    bufferSizeMb: 10.0,
411
412    cpuSched: false,
413    cpuLatency: false,
414    cpuFreq: false,
415    cpuSyscall: false,
416
417    screenRecord: false,
418
419    gpuFreq: false,
420
421    ftrace: false,
422    atrace: false,
423    ftraceEvents: [],
424    ftraceExtraEvents: '',
425    atraceCats: [],
426    atraceApps: '',
427    ftraceBufferSizeKb: 2 * 1024,
428    ftraceDrainPeriodMs: 250,
429    androidLogs: false,
430    androidLogBuffers: [],
431
432    cpuCoarse: false,
433    cpuCoarsePollMs: 1000,
434
435    batteryDrain: false,
436    batteryDrainPollMs: 1000,
437
438    boardSensors: false,
439
440    memHiFreq: false,
441    meminfo: false,
442    meminfoPeriodMs: 1000,
443    meminfoCounters: [],
444
445    vmstat: false,
446    vmstatPeriodMs: 1000,
447    vmstatCounters: [],
448
449    heapProfiling: false,
450    hpSamplingIntervalBytes: 4096,
451    hpProcesses: '',
452    hpContinuousDumpsPhase: 0,
453    hpContinuousDumpsInterval: 0,
454    hpSharedMemoryBuffer: 8 * 1048576,
455
456    javaHeapDump: false,
457    jpProcesses: '',
458    jpContinuousDumpsPhase: 0,
459    jpContinuousDumpsInterval: 0,
460
461    memLmk: false,
462    procStats: false,
463    procStatsPeriodMs: 1000,
464
465    chromeCategoriesSelected: [],
466  };
467}
468
469export function getDefaultRecordingTargets(): RecordingTarget[] {
470  return [
471    {os: 'Q', name: 'Android Q+'},
472    {os: 'P', name: 'Android P'},
473    {os: 'O', name: 'Android O-'},
474    {os: 'C', name: 'Chrome'},
475    {os: 'L', name: 'Linux desktop'}
476  ];
477}
478
479export function getBuiltinChromeCategoryList(): string[] {
480  // List of static Chrome categories, last updated at Chromium 81.0.4021.0 from
481  // Chromium's //base/trace_event/builtin_categories.h.
482  return [
483    'accessibility',
484    'AccountFetcherService',
485    'android_webview',
486    'audio',
487    'base',
488    'benchmark',
489    'blink',
490    'blink.animations',
491    'blink.console',
492    'blink_gc',
493    'blink.net',
494    'blink_style',
495    'blink.user_timing',
496    'blink.worker',
497    'Blob',
498    'browser',
499    'browsing_data',
500    'CacheStorage',
501    'camera',
502    'cast_perf_test',
503    'cast.stream',
504    'cc',
505    'cc.debug',
506    'cdp.perf',
507    'chromeos',
508    'cma',
509    'compositor',
510    'content',
511    'content_capture',
512    'devtools',
513    'devtools.timeline',
514    'devtools.timeline.async',
515    'download',
516    'download_service',
517    'drm',
518    'drmcursor',
519    'dwrite',
520    'DXVA Decoding',
521    'EarlyJava',
522    'evdev',
523    'event',
524    'exo',
525    'explore_sites',
526    'FileSystem',
527    'file_system_provider',
528    'fonts',
529    'GAMEPAD',
530    'gpu',
531    'gpu.capture',
532    'headless',
533    'hwoverlays',
534    'identity',
535    'IndexedDB',
536    'input',
537    'io',
538    'ipc',
539    'Java',
540    'jni',
541    'jpeg',
542    'latency',
543    'latencyInfo',
544    'leveldb',
545    'loading',
546    'log',
547    'login',
548    'media',
549    'media_router',
550    'memory',
551    'midi',
552    'mojom',
553    'mus',
554    'native',
555    'navigation',
556    'net',
557    'netlog',
558    'offline_pages',
559    'omnibox',
560    'oobe',
561    'ozone',
562    'passwords',
563    'p2p',
564    'page-serialization',
565    'pepper',
566    'ppapi',
567    'ppapi proxy',
568    'rail',
569    'renderer',
570    'renderer_host',
571    'renderer.scheduler',
572    'RLZ',
573    'safe_browsing',
574    'screenlock_monitor',
575    'sequence_manager',
576    'service_manager',
577    'ServiceWorker',
578    'shell',
579    'shortcut_viewer',
580    'shutdown',
581    'SiteEngagement',
582    'skia',
583    'startup',
584    'sync',
585    'sync_lock_contention',
586    'thread_pool',
587    'test_gpu',
588    'test_tracing',
589    'toplevel',
590    'ui',
591    'v8',
592    'v8.execute',
593    'ValueStoreFrontend::Backend',
594    'views',
595    'views.frame',
596    'viz',
597    'vk',
598    'wayland',
599    'webaudio',
600    'weblayer',
601    'WebCore',
602    'webrtc',
603    'xr',
604    'disabled-by-default-animation-worklet',
605    'disabled-by-default-audio-worklet',
606    'disabled-by-default-blink.debug',
607    'disabled-by-default-blink.debug.display_lock',
608    'disabled-by-default-blink.debug.layout',
609    'disabled-by-default-blink.debug.layout.trees',
610    'disabled-by-default-blink.feature_usage',
611    'disabled-by-default-blink_gc',
612    'disabled-by-default-blink.image_decoding',
613    'disabled-by-default-blink.invalidation',
614    'disabled-by-default-cc',
615    'disabled-by-default-cc.debug',
616    'disabled-by-default-cc.debug.cdp-perf',
617    'disabled-by-default-cc.debug.display_items',
618    'disabled-by-default-cc.debug.picture',
619    'disabled-by-default-cc.debug.scheduler',
620    'disabled-by-default-cc.debug.scheduler.frames',
621    'disabled-by-default-cc.debug.scheduler.now',
622    'disabled-by-default-cpu_profiler',
623    'disabled-by-default-cpu_profiler.debug',
624    'disabled-by-default-devtools.screenshot',
625    'disabled-by-default-devtools.timeline',
626    'disabled-by-default-devtools.timeline.frame',
627    'disabled-by-default-devtools.timeline.inputs',
628    'disabled-by-default-devtools.timeline.invalidationTracking',
629    'disabled-by-default-devtools.timeline.layers',
630    'disabled-by-default-devtools.timeline.picture',
631    'disabled-by-default-file',
632    'disabled-by-default-fonts',
633    'disabled-by-default-gpu_cmd_queue',
634    'disabled-by-default-gpu.dawn',
635    'disabled-by-default-gpu.debug',
636    'disabled-by-default-gpu_decoder',
637    'disabled-by-default-gpu.device',
638    'disabled-by-default-gpu.service',
639    'disabled-by-default-histogram_samples',
640    'disabled-by-default-ipc.flow',
641    'disabled-by-default-java-heap-profiler',
642    'disabled-by-default-layer-element',
643    'disabled-by-default-lifecycles',
644    'disabled-by-default-loading',
645    'disabled-by-default-memory-infra',
646    'disabled-by-default-memory-infra.v8.code_stats',
647    'disabled-by-default-net',
648    'disabled-by-default-network',
649    'disabled-by-default-paint-worklet',
650    'disabled-by-default-power',
651    'disabled-by-default-renderer.scheduler',
652    'disabled-by-default-renderer.scheduler.debug',
653    'disabled-by-default-sequence_manager',
654    'disabled-by-default-sequence_manager.debug',
655    'disabled-by-default-sequence_manager.verbose_snapshots',
656    'disabled-by-default-skia',
657    'disabled-by-default-skia.gpu',
658    'disabled-by-default-skia.gpu.cache',
659    'disabled-by-default-SyncFileSystem',
660    'disabled-by-default-system_stats',
661    'disabled-by-default-thread_pool_diagnostics',
662    'disabled-by-default-toplevel.flow',
663    'disabled-by-default-toplevel.ipc',
664    'disabled-by-default-v8.compile',
665    'disabled-by-default-v8.cpu_profiler',
666    'disabled-by-default-v8.cpu_profiler.hires',
667    'disabled-by-default-v8.gc',
668    'disabled-by-default-v8.gc_stats',
669    'disabled-by-default-v8.ic_stats',
670    'disabled-by-default-v8.runtime',
671    'disabled-by-default-v8.runtime_stats',
672    'disabled-by-default-v8.runtime_stats_sampling',
673    'disabled-by-default-v8.turbofan',
674    'disabled-by-default-v8.wasm',
675    'disabled-by-default-video_and_image_capture',
676    'disabled-by-default-viz.debug.overlay_planes',
677    'disabled-by-default-viz.hit_testing_flow',
678    'disabled-by-default-viz.overdraw',
679    'disabled-by-default-viz.quads',
680    'disabled-by-default-viz.surface_id_flow',
681    'disabled-by-default-viz.surface_lifetime',
682    'disabled-by-default-viz.triangles',
683    'disabled-by-default-worker.scheduler',
684  ];
685}
686
687export function createEmptyState(): State {
688  return {
689    route: null,
690    nextId: 0,
691    newEngineMode: 'USE_HTTP_RPC_IF_AVAILABLE',
692    engines: {},
693    traceTime: {...defaultTraceTime},
694    tracks: {},
695    aggregatePreferences: {},
696    trackGroups: {},
697    visibleTracks: [],
698    pinnedTracks: [],
699    scrollingTracks: [],
700    queries: {},
701    permalink: {},
702    notes: {},
703
704    recordConfig: createEmptyRecordConfig(),
705    displayConfigAsPbtxt: false,
706
707    frontendLocalState: {
708      omniboxState: {
709        lastUpdate: 0,
710        omnibox: '',
711        mode: 'SEARCH',
712      },
713
714      visibleState: {
715        ...defaultTraceTime,
716        lastUpdate: 0,
717        resolution: 0,
718      },
719      selectedArea: {
720        lastUpdate: 0,
721      }
722    },
723
724    logsPagination: {
725      offset: 0,
726      count: 0,
727    },
728
729    status: {msg: '', timestamp: 0},
730    currentSelection: null,
731    currentHeapProfileFlamegraph: null,
732
733    video: null,
734    videoEnabled: false,
735    videoOffset: 0,
736    videoNoteIds: [],
737    scrubbingEnabled: false,
738    flagPauseEnabled: false,
739    recordingInProgress: false,
740    recordingCancelled: false,
741    extensionInstalled: false,
742    recordingTarget: getDefaultRecordingTargets()[0],
743    availableAdbDevices: [],
744
745    chromeCategories: undefined,
746  };
747}
748
749export function getContainingTrackId(state: State, trackId: string): null|
750    string {
751  const track = state.tracks[trackId];
752  if (!track) {
753    return null;
754  }
755  const parentId = track.trackGroup;
756  if (!parentId) {
757    return null;
758  }
759  return parentId;
760}
761