| // Copyright (C) 2024 The Android Open Source Project | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | import m from 'mithril'; | 
 | import {duration, time} from '../base/time'; | 
 | import {Size2D, VerticalBounds} from '../base/geom'; | 
 | import {TimeScale} from '../base/time_scale'; | 
 | import {HighPrecisionTimeSpan} from '../base/high_precision_time_span'; | 
 | import {ColorScheme} from './color_scheme'; | 
 | import {TrackEventDetailsPanel} from './details_panel'; | 
 | import {TrackEventDetails, TrackEventSelection} from './selection'; | 
 | import {Dataset} from '../trace_processor/dataset'; | 
 |  | 
 | export interface TrackManager { | 
 |   /** | 
 |    * Register a new track against a unique key known as a URI. The track is not | 
 |    * shown by default and callers need to either manually add it to a | 
 |    * Workspace or use registerTrackAndShowOnTraceLoad() below. | 
 |    */ | 
 |   registerTrack(trackDesc: TrackDescriptor): void; | 
 |  | 
 |   findTrack( | 
 |     predicate: (desc: TrackDescriptor) => boolean | undefined, | 
 |   ): TrackDescriptor | undefined; | 
 |  | 
 |   getAllTracks(): TrackDescriptor[]; | 
 |  | 
 |   getTrack(uri: string): TrackDescriptor | undefined; | 
 | } | 
 |  | 
 | export interface TrackContext { | 
 |   // This track's URI, used for making selections et al. | 
 |   readonly trackUri: string; | 
 | } | 
 |  | 
 | /** | 
 |  * Contextual information about the track passed to track lifecycle hooks & | 
 |  * render hooks with additional information about the timeline/canvas. | 
 |  */ | 
 | export interface TrackRenderContext extends TrackContext { | 
 |   /** | 
 |    * The time span of the visible window. | 
 |    */ | 
 |   readonly visibleWindow: HighPrecisionTimeSpan; | 
 |  | 
 |   /** | 
 |    * The dimensions of the track on the canvas in pixels. | 
 |    */ | 
 |   readonly size: Size2D; | 
 |  | 
 |   /** | 
 |    * Suggested data resolution. | 
 |    * | 
 |    * This number is the number of time units that corresponds to 1 pixel on the | 
 |    * screen, rounded down to the nearest power of 2. The minimum value is 1. | 
 |    * | 
 |    * It's up to the track whether it would like to use this resolution or | 
 |    * calculate their own based on the timespan and the track dimensions. | 
 |    */ | 
 |   readonly resolution: duration; | 
 |  | 
 |   /** | 
 |    * Canvas context used for rendering. | 
 |    */ | 
 |   readonly ctx: CanvasRenderingContext2D; | 
 |  | 
 |   /** | 
 |    * A time scale used for translating between pixels and time. | 
 |    */ | 
 |   readonly timescale: TimeScale; | 
 | } | 
 |  | 
 | // A definition of a track, including a renderer implementation and metadata. | 
 | export interface TrackDescriptor { | 
 |   // A unique identifier for this track. | 
 |   readonly uri: string; | 
 |  | 
 |   // A factory function returning a new track instance. | 
 |   readonly track: Track; | 
 |  | 
 |   // Human readable title. Always displayed. | 
 |   readonly title: string; | 
 |  | 
 |   // Human readable subtitle. Sometimes displayed if there is room. | 
 |   readonly subtitle?: string; | 
 |  | 
 |   // Optional: A list of tags used for sorting, grouping and "chips". | 
 |   readonly tags?: TrackTags; | 
 |  | 
 |   readonly chips?: ReadonlyArray<string>; | 
 |  | 
 |   readonly pluginId?: string; | 
 | } | 
 |  | 
 | /** | 
 |  * Contextual information passed to mouse events. | 
 |  */ | 
 | export interface TrackMouseEvent { | 
 |   /** | 
 |    * X coordinate of the mouse event w.r.t. the top-left of the track. | 
 |    */ | 
 |   readonly x: number; | 
 |  | 
 |   /** | 
 |    * Y coordinate of the mouse event w.r.t the top-left of the track. | 
 |    */ | 
 |   readonly y: number; | 
 |  | 
 |   /** | 
 |    * A time scale used for translating between pixels and time. | 
 |    */ | 
 |   readonly timescale: TimeScale; | 
 | } | 
 |  | 
 | export interface Track { | 
 |   /** | 
 |    * Optional lifecycle hook called on the first render cycle. Should be used to | 
 |    * create any required resources. | 
 |    * | 
 |    * These lifecycle hooks are asynchronous, but they are run synchronously, | 
 |    * meaning that perfetto will wait for each one to complete before calling the | 
 |    * next one, so the user doesn't have to serialize these calls manually. | 
 |    * | 
 |    * Exactly when this hook is called is left purposely undefined. The only | 
 |    * guarantee is that it will be called exactly once before the first call to | 
 |    * onUpdate(). | 
 |    * | 
 |    * Note: On the first render cycle, both onCreate and onUpdate are called one | 
 |    * after another. | 
 |    */ | 
 |   onCreate?(ctx: TrackContext): Promise<void>; | 
 |  | 
 |   /** | 
 |    * Optional lifecycle hook called on every render cycle. | 
 |    * | 
 |    * The track should inspect things like the visible window, track size, and | 
 |    * resolution to work out whether any data needs to be reloaded based on these | 
 |    * properties and perform a reload. | 
 |    */ | 
 |   onUpdate?(ctx: TrackRenderContext): Promise<void>; | 
 |  | 
 |   /** | 
 |    * Optional lifecycle hook called when the track is no longer visible. Should | 
 |    * be used to clear up any resources. | 
 |    */ | 
 |   onDestroy?(): Promise<void>; | 
 |  | 
 |   /** | 
 |    * Required method used to render the track's content to the canvas, called | 
 |    * synchronously on every render cycle. | 
 |    */ | 
 |   render(ctx: TrackRenderContext): void; | 
 |   onFullRedraw?(): void; | 
 |  | 
 |   /** | 
 |    * Return the vertical bounds (top & bottom) of a slice were it to be rendered | 
 |    * at a specific depth, given the slice height and padding/spacing that this | 
 |    * track uses. | 
 |    */ | 
 |   getSliceVerticalBounds?(depth: number): VerticalBounds | undefined; | 
 |   getHeight(): number; | 
 |   getTrackShellButtons?(): m.Children; | 
 |   onMouseMove?(event: TrackMouseEvent): void; | 
 |   onMouseClick?(event: TrackMouseEvent): boolean; | 
 |   onMouseOut?(): void; | 
 |  | 
 |   /** | 
 |    * Optional: Returns a dataset that represents the events displayed on this | 
 |    * track. | 
 |    */ | 
 |   getDataset?(): Dataset | undefined; | 
 |  | 
 |   /** | 
 |    * Optional: Get details of a track event given by eventId on this track. | 
 |    */ | 
 |   getSelectionDetails?(eventId: number): Promise<TrackEventDetails | undefined>; | 
 |  | 
 |   // Optional: A factory that returns a details panel object for a given track | 
 |   // event selection. This is called each time the selection is changed (and the | 
 |   // selection is relevant to this track). | 
 |   detailsPanel?(sel: TrackEventSelection): TrackEventDetailsPanel; | 
 | } | 
 |  | 
 | // An set of key/value pairs describing a given track. These are used for | 
 | // selecting tracks to pin/unpin, diplsaying "chips" in the track shell, and | 
 | // (in future) the sorting and grouping of tracks. | 
 | // We define a handful of well known fields, and the rest are arbitrary key- | 
 | // value pairs. | 
 | export type TrackTags = Partial<WellKnownTrackTags> & { | 
 |   // There may be arbitrary other key/value pairs. | 
 |   [key: string]: | 
 |     | undefined | 
 |     | string | 
 |     | number | 
 |     | boolean | 
 |     | ReadonlyArray<string> | 
 |     | ReadonlyArray<number>; | 
 | }; | 
 |  | 
 | interface WellKnownTrackTags { | 
 |   // The track "kind", used by various subsystems e.g. aggregation controllers. | 
 |   // This is where "XXX_TRACK_KIND" values should be placed. | 
 |   // TODO(stevegolton): This will be deprecated once we handle group selections | 
 |   // in a more generic way - i.e. EventSet. | 
 |   kind: string; | 
 |  | 
 |   // Optional: list of track IDs represented by this trace. | 
 |   // This list is used for participation in track indexing by track ID. | 
 |   // This index is used by various subsystems to find links between tracks based | 
 |   // on the track IDs used by trace processor. | 
 |   trackIds: ReadonlyArray<number>; | 
 |  | 
 |   // Optional: The CPU number associated with this track. | 
 |   cpu: number; | 
 |  | 
 |   // Optional: The UTID associated with this track. | 
 |   utid: number; | 
 |  | 
 |   // Optional: The UPID associated with this track. | 
 |   upid: number; | 
 |  | 
 |   // Used for sorting and grouping | 
 |   scope: string; | 
 |  | 
 |   // Group name, used as a hint to ask track decider to put this in a group | 
 |   groupName: string; | 
 | } | 
 |  | 
 | export interface Slice { | 
 |   // These properties are updated only once per query result when the Slice | 
 |   // object is created and don't change afterwards. | 
 |   readonly id: number; | 
 |   readonly startNs: time; | 
 |   readonly endNs: time; | 
 |   readonly durNs: duration; | 
 |   readonly ts: time; | 
 |   readonly dur: duration; | 
 |   readonly depth: number; | 
 |   readonly flags: number; | 
 |  | 
 |   // Each slice can represent some extra numerical information by rendering a | 
 |   // portion of the slice with a lighter tint. | 
 |   // |fillRatio\ describes the ratio of the normal area to the tinted area | 
 |   // width of the slice, normalized between 0.0 -> 1.0. | 
 |   // 0.0 means the whole slice is tinted. | 
 |   // 1.0 means none of the slice is tinted. | 
 |   // E.g. If |fillRatio| = 0.65 the slice will be rendered like this: | 
 |   // [############|*******] | 
 |   // ^------------^-------^ | 
 |   //     Normal     Light | 
 |   readonly fillRatio: number; | 
 |  | 
 |   // These can be changed by the Impl. | 
 |   title: string; | 
 |   subTitle: string; | 
 |   colorScheme: ColorScheme; | 
 |   isHighlighted: boolean; | 
 | } |