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