xref: /aosp_15_r20/external/perfetto/ui/src/public/selection.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2024 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 {time, duration, TimeSpan} from '../base/time';
16import {Engine} from '../trace_processor/engine';
17import {ColumnDef, Sorting, ThreadStateExtra} from './aggregation';
18import {TrackDescriptor} from './track';
19
20export interface SelectionManager {
21  readonly selection: Selection;
22
23  findTimeRangeOfSelection(): TimeSpan | undefined;
24  clear(): void;
25
26  /**
27   * Select a track event.
28   *
29   * @param trackUri - The URI of the track to select.
30   * @param eventId - The value of the events ID column.
31   * @param opts - Additional options.
32   */
33  selectTrackEvent(
34    trackUri: string,
35    eventId: number,
36    opts?: SelectionOpts,
37  ): void;
38
39  /**
40   * Select a track.
41   *
42   * @param trackUri - The URI for the track to select.
43   * @param opts - Additional options.
44   */
45  selectTrack(trackUri: string, opts?: SelectionOpts): void;
46
47  /**
48   * Select a track event via a sql table name + id.
49   *
50   * @param sqlTableName - The name of the SQL table to resolve.
51   * @param id - The ID of the event in that table.
52   * @param opts - Additional options.
53   */
54  selectSqlEvent(sqlTableName: string, id: number, opts?: SelectionOpts): void;
55
56  /**
57   * Create an area selection for the purposes of aggregation.
58   *
59   * @param args - The area to select.
60   * @param opts - Additional options.
61   */
62  selectArea(args: Area, opts?: SelectionOpts): void;
63
64  scrollToCurrentSelection(): void;
65  registerAreaSelectionAggregator(aggr: AreaSelectionAggregator): void;
66
67  /**
68   * Register a new SQL selection resolver.
69   *
70   * A resolver consists of a SQL table name and a callback. When someone
71   * expresses an interest in selecting a slice on a matching table, the
72   * callback is called which can return a selection object or undefined.
73   */
74  registerSqlSelectionResolver(resolver: SqlSelectionResolver): void;
75}
76
77export interface AreaSelectionAggregator {
78  readonly id: string;
79  createAggregateView(engine: Engine, area: AreaSelection): Promise<boolean>;
80  getExtra(
81    engine: Engine,
82    area: AreaSelection,
83  ): Promise<ThreadStateExtra | void>;
84  getTabName(): string;
85  getDefaultSorting(): Sorting;
86  getColumnDefinitions(): ColumnDef[];
87}
88
89export type Selection =
90  | TrackEventSelection
91  | TrackSelection
92  | AreaSelection
93  | NoteSelection
94  | EmptySelection;
95
96/** Defines how changes to selection affect the rest of the UI state */
97export interface SelectionOpts {
98  clearSearch?: boolean; // Default: true.
99  switchToCurrentSelectionTab?: boolean; // Default: true.
100  scrollToSelection?: boolean; // Default: false.
101}
102
103export interface TrackEventSelection extends TrackEventDetails {
104  readonly kind: 'track_event';
105  readonly trackUri: string;
106  readonly eventId: number;
107}
108
109export interface TrackSelection {
110  readonly kind: 'track';
111  readonly trackUri: string;
112}
113
114export interface TrackEventDetails {
115  // ts and dur are required by the core, and must be provided.
116  readonly ts: time;
117  // Note: dur can be -1 for instant events.
118  readonly dur: duration;
119
120  // Optional additional information.
121  // TODO(stevegolton): Find an elegant way of moving this information out of
122  // the core.
123  readonly wakeupTs?: time;
124  readonly wakerCpu?: number;
125  readonly upid?: number;
126  readonly utid?: number;
127  readonly tableName?: string;
128  readonly profileType?: ProfileType;
129  readonly interactionType?: string;
130}
131
132export interface Area {
133  readonly start: time;
134  readonly end: time;
135  // TODO(primiano): this should be ReadonlyArray<> after the pivot table state
136  // doesn't use State/Immer anymore.
137  readonly trackUris: string[];
138}
139
140export interface AreaSelection extends Area {
141  readonly kind: 'area';
142
143  // This array contains the resolved TrackDescriptor from Area.trackUris.
144  // The resolution is done by SelectionManager whenever a kind='area' selection
145  // is performed.
146  readonly tracks: ReadonlyArray<TrackDescriptor>;
147}
148
149export interface NoteSelection {
150  readonly kind: 'note';
151  readonly id: string;
152}
153
154export interface EmptySelection {
155  readonly kind: 'empty';
156}
157
158export enum ProfileType {
159  HEAP_PROFILE = 'heap_profile',
160  MIXED_HEAP_PROFILE = 'heap_profile:com.android.art,libc.malloc',
161  NATIVE_HEAP_PROFILE = 'heap_profile:libc.malloc',
162  JAVA_HEAP_SAMPLES = 'heap_profile:com.android.art',
163  JAVA_HEAP_GRAPH = 'graph',
164  PERF_SAMPLE = 'perf',
165}
166
167export function profileType(s: string): ProfileType {
168  if (s === 'heap_profile:libc.malloc,com.android.art') {
169    s = 'heap_profile:com.android.art,libc.malloc';
170  }
171  if (Object.values(ProfileType).includes(s as ProfileType)) {
172    return s as ProfileType;
173  }
174  if (s.startsWith('heap_profile')) {
175    return ProfileType.HEAP_PROFILE;
176  }
177  throw new Error('Unknown type ${s}');
178}
179
180export interface SqlSelectionResolver {
181  readonly sqlTableName: string;
182  readonly callback: (
183    id: number,
184    sqlTable: string,
185  ) => Promise<{trackUri: string; eventId: number} | undefined>;
186}
187