blob: 877fddc1ca0cb80260b55300f0625bd54ef5616f [file] [log] [blame]
// 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 {Optional} from '../base/utils';
import {UntypedEventSet} from '../core/event_set';
import {LegacySelection, Selection} from '../core/selection_manager';
import {Size} from '../base/geom';
import {TimeScale} from '../frontend/time_scale';
import {HighPrecisionTimeSpan} from '../common/high_precision_time_span';
export interface TrackContext {
// This track's key, used for making selections et al.
readonly trackKey: 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: Size;
/**
* 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 trackFactory: (ctx: TrackContext) => 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;
// Optional: A details panel to use when this track is selected.
readonly detailsPanel?: TrackSelectionDetailsPanel;
// Optional: method to look up the start and duration of an event on this track
readonly getEventBounds?: (
id: number,
) => Promise<Optional<{ts: time; dur: duration}>>;
}
export interface LegacyDetailsPanel {
render(selection: LegacySelection): m.Children;
isLoading?(): boolean;
}
export interface DetailsPanel {
render(selection: Selection): m.Children;
isLoading?(): boolean;
}
export interface TrackSelectionDetailsPanel {
render(id: number): m.Children;
isLoading?(): boolean;
}
export interface SliceRect {
left: number;
width: number;
top: number;
height: number;
visible: boolean;
}
/**
* 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;
getSliceRect?(
ctx: TrackRenderContext,
tStart: time,
tEnd: time,
depth: number,
): Optional<SliceRect>;
getHeight(): number;
getTrackShellButtons?(): m.Children;
onMouseMove?(event: TrackMouseEvent): void;
onMouseClick?(event: TrackMouseEvent): boolean;
onMouseOut?(): void;
/**
* Optional: Get the event set that represents this track's data.
*/
getEventSet?(): UntypedEventSet;
}
// 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;
}