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