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 m from 'mithril'; 16import {duration, time} from '../base/time'; 17import {Size2D, VerticalBounds} from '../base/geom'; 18import {TimeScale} from '../base/time_scale'; 19import {HighPrecisionTimeSpan} from '../base/high_precision_time_span'; 20import {ColorScheme} from '../base/color_scheme'; 21import {TrackEventDetailsPanel} from './details_panel'; 22import {TrackEventDetails, TrackEventSelection} from './selection'; 23import {SourceDataset} from '../trace_processor/dataset'; 24import {TrackNode} from './workspace'; 25 26export interface TrackFilterCriteria { 27 readonly name: string; 28 29 // Run on each node to work out whether it satisfies the selected filter 30 // option. 31 readonly predicate: (track: TrackNode, filterOption: string) => boolean; 32 33 // The list of possible filter options. 34 readonly options: ReadonlyArray<{key: string; label: string}>; 35} 36 37export interface TrackManager { 38 /** 39 * Register a new track against a unique key known as a URI. The track is not 40 * shown by default and callers need to either manually add it to a 41 * Workspace or use registerTrackAndShowOnTraceLoad() below. 42 */ 43 registerTrack(track: Track): void; 44 45 findTrack( 46 predicate: (track: Track) => boolean | undefined, 47 ): Track | undefined; 48 49 getAllTracks(): Track[]; 50 51 getTrack(uri: string): Track | undefined; 52 53 /** 54 * Register a track filter criteria, which can be used by end users to control 55 * the list of tracks they see in workspaces. These criteria can provide more 56 * power to the user compared to e.g. purely filtering by name. 57 */ 58 registerTrackFilterCriteria(filter: TrackFilterCriteria): void; 59} 60 61export interface TrackContext { 62 // This track's URI, used for making selections et al. 63 readonly trackUri: string; 64} 65 66/** 67 * Contextual information about the track passed to track lifecycle hooks & 68 * render hooks with additional information about the timeline/canvas. 69 */ 70export interface TrackRenderContext extends TrackContext { 71 /** 72 * The time span of the visible window. 73 */ 74 readonly visibleWindow: HighPrecisionTimeSpan; 75 76 /** 77 * The dimensions of the track on the canvas in pixels. 78 */ 79 readonly size: Size2D; 80 81 /** 82 * Suggested data resolution. 83 * 84 * This number is the number of time units that corresponds to 1 pixel on the 85 * screen, rounded down to the nearest power of 2. The minimum value is 1. 86 * 87 * It's up to the track whether it would like to use this resolution or 88 * calculate their own based on the timespan and the track dimensions. 89 */ 90 readonly resolution: duration; 91 92 /** 93 * Canvas context used for rendering. 94 */ 95 readonly ctx: CanvasRenderingContext2D; 96 97 /** 98 * A time scale used for translating between pixels and time. 99 */ 100 readonly timescale: TimeScale; 101} 102 103// A definition of a track, including a renderer implementation and metadata. 104export interface Track { 105 // A unique identifier for this track. 106 readonly uri: string; 107 108 // A factory function returning a new track instance. 109 readonly track: TrackRenderer; 110 111 // Human readable title. Always displayed. 112 readonly title: string; 113 114 // Human readable subtitle. Sometimes displayed if there is room. 115 readonly subtitle?: string; 116 117 // Optional: A list of tags used for sorting, grouping and "chips". 118 readonly tags?: TrackTags; 119 120 readonly chips?: ReadonlyArray<string>; 121 122 readonly pluginId?: string; 123} 124 125/** 126 * Contextual information passed to mouse events. 127 */ 128export interface TrackMouseEvent { 129 /** 130 * X coordinate of the mouse event w.r.t. the top-left of the track. 131 */ 132 readonly x: number; 133 134 /** 135 * Y coordinate of the mouse event w.r.t the top-left of the track. 136 */ 137 readonly y: number; 138 139 /** 140 * A time scale used for translating between pixels and time. 141 */ 142 readonly timescale: TimeScale; 143} 144 145export interface TrackRenderer { 146 /** 147 * Describes which root table the events on this track come from. This is 148 * mainly for use by flows (before they get refactored to be more generic) and 149 * will be used by the SQL table resolver mechanism along with dataset. 150 * TODO(stevegolton): Maybe move this onto dataset directly? 151 */ 152 readonly rootTableName?: string; 153 154 /** 155 * Optional lifecycle hook called on the first render cycle. Should be used to 156 * create any required resources. 157 * 158 * These lifecycle hooks are asynchronous, but they are run synchronously, 159 * meaning that perfetto will wait for each one to complete before calling the 160 * next one, so the user doesn't have to serialize these calls manually. 161 * 162 * Exactly when this hook is called is left purposely undefined. The only 163 * guarantee is that it will be called exactly once before the first call to 164 * onUpdate(). 165 * 166 * Note: On the first render cycle, both onCreate and onUpdate are called one 167 * after another. 168 */ 169 onCreate?(ctx: TrackContext): Promise<void>; 170 171 /** 172 * Optional lifecycle hook called on every render cycle. 173 * 174 * The track should inspect things like the visible window, track size, and 175 * resolution to work out whether any data needs to be reloaded based on these 176 * properties and perform a reload. 177 */ 178 onUpdate?(ctx: TrackRenderContext): Promise<void>; 179 180 /** 181 * Optional lifecycle hook called when the track is no longer visible. Should 182 * be used to clear up any resources. 183 */ 184 onDestroy?(): Promise<void>; 185 186 /** 187 * Required method used to render the track's content to the canvas, called 188 * synchronously on every render cycle. 189 */ 190 render(ctx: TrackRenderContext): void; 191 onFullRedraw?(): void; 192 193 /** 194 * Return the vertical bounds (top & bottom) of a slice were it to be rendered 195 * at a specific depth, given the slice height and padding/spacing that this 196 * track uses. 197 */ 198 getSliceVerticalBounds?(depth: number): VerticalBounds | undefined; 199 getHeight(): number; 200 getTrackShellButtons?(): m.Children; 201 onMouseMove?(event: TrackMouseEvent): void; 202 onMouseClick?(event: TrackMouseEvent): boolean; 203 onMouseOut?(): void; 204 205 /** 206 * Optional: Returns a dataset that represents the events displayed on this 207 * track. 208 */ 209 getDataset?(): SourceDataset | undefined; 210 211 /** 212 * Optional: Get details of a track event given by eventId on this track. 213 */ 214 getSelectionDetails?(eventId: number): Promise<TrackEventDetails | undefined>; 215 216 // Optional: A factory that returns a details panel object for a given track 217 // event selection. This is called each time the selection is changed (and the 218 // selection is relevant to this track). 219 detailsPanel?(sel: TrackEventSelection): TrackEventDetailsPanel | undefined; 220} 221 222// An set of key/value pairs describing a given track. These are used for 223// selecting tracks to pin/unpin, diplsaying "chips" in the track shell, and 224// (in future) the sorting and grouping of tracks. 225// We define a handful of well known fields, and the rest are arbitrary key- 226// value pairs. 227export type TrackTags = Partial<WellKnownTrackTags> & { 228 // There may be arbitrary other key/value pairs. 229 [key: string]: 230 | undefined 231 | string 232 | number 233 | boolean 234 | ReadonlyArray<string> 235 | ReadonlyArray<number>; 236}; 237 238interface WellKnownTrackTags { 239 // The track "kind", used by various subsystems e.g. aggregation controllers. 240 // This is where "XXX_TRACK_KIND" values should be placed. 241 // TODO(stevegolton): This will be deprecated once we handle group selections 242 // in a more generic way - i.e. EventSet. 243 kind: string; 244 245 // Optional: list of track IDs represented by this trace. 246 // This list is used for participation in track indexing by track ID. 247 // This index is used by various subsystems to find links between tracks based 248 // on the track IDs used by trace processor. 249 trackIds: ReadonlyArray<number>; 250 251 // Optional: The CPU number associated with this track. 252 cpu: number; 253 254 // Optional: The UTID associated with this track. 255 utid: number; 256 257 // Optional: The UPID associated with this track. 258 upid: number; 259 260 // Used for sorting and grouping 261 scope: string; 262 263 // Group name, used as a hint to ask track decider to put this in a group 264 groupName: string; 265} 266 267export interface Slice { 268 // These properties are updated only once per query result when the Slice 269 // object is created and don't change afterwards. 270 readonly id: number; 271 readonly startNs: time; 272 readonly endNs: time; 273 readonly durNs: duration; 274 readonly ts: time; 275 readonly dur: duration; 276 readonly depth: number; 277 readonly flags: number; 278 279 // Each slice can represent some extra numerical information by rendering a 280 // portion of the slice with a lighter tint. 281 // |fillRatio\ describes the ratio of the normal area to the tinted area 282 // width of the slice, normalized between 0.0 -> 1.0. 283 // 0.0 means the whole slice is tinted. 284 // 1.0 means none of the slice is tinted. 285 // E.g. If |fillRatio| = 0.65 the slice will be rendered like this: 286 // [############|*******] 287 // ^------------^-------^ 288 // Normal Light 289 readonly fillRatio: number; 290 291 // These can be changed by the Impl. 292 title?: string; 293 subTitle: string; 294 colorScheme: ColorScheme; 295 isHighlighted: boolean; 296} 297