1// Copyright (C) 2022 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 {TraceConfig} from '../protos'; 16 17// TargetFactory connects, disconnects and keeps track of targets. 18// There is one factory for AndroidWebusb, AndroidWebsocket, Chrome etc. 19// For instance, the AndroidWebusb factory returns a RecordingTargetV2 for each 20// device. 21export interface TargetFactory { 22 // Store the kind explicitly as a string as opposed to using class.kind in 23 // case we ever minify our code. 24 readonly kind: string; 25 26 // Setter for OnTargetChange, which is executed when a target is 27 // added/removed or when its information is updated. 28 setOnTargetChange(onTargetChange: OnTargetChangeCallback): void; 29 30 getName(): string; 31 32 listTargets(): RecordingTargetV2[]; 33 // Returns recording problems that we encounter when not directly using the 34 // target. For instance we connect webusb devices when Perfetto is loaded. If 35 // there is an issue with connecting a webusb device, we do not want to crash 36 // all of Perfetto, as the user may not want to use the recording 37 // functionality at all. 38 listRecordingProblems(): string[]; 39 40 connectNewTarget(): Promise<RecordingTargetV2>; 41} 42 43export interface DataSource { 44 name: string; 45 46 // Contains information that is opaque to the recording code. The caller can 47 // use the DataSource name to type cast the DataSource descriptor. 48 // For targets calling QueryServiceState, 'descriptor' will hold the 49 // datasource descriptor: 50 // https://source.corp.google.com/android/external/perfetto/protos/perfetto/ 51 // common/data_source_descriptor.proto;l=28-60 52 // For Chrome, 'descriptor' will contain the answer received from 53 // 'GetCategories': 54 // https://source.corp.google.com/android/external/perfetto/ui/src/ 55 // chrome_extension/chrome_tracing_controller.ts;l=220 56 descriptor: unknown; 57} 58 59// Common fields for all types of targetInfo: Chrome, Android, Linux etc. 60interface TargetInfoBase { 61 name: string; 62 63 // The dataSources exposed by a target. They are fetched from the target 64 // (ex: using QSS for Android or GetCategories for Chrome). 65 dataSources: DataSource[]; 66} 67 68export interface AndroidTargetInfo extends TargetInfoBase { 69 targetType: 'ANDROID'; 70 71 // This is the Android API level. For instance, it can be 32, 31, 30 etc. 72 // It is the "API level" column here: 73 // https://source.android.com/setup/start/build-numbers 74 androidApiLevel?: number; 75} 76 77export interface ChromeTargetInfo extends TargetInfoBase { 78 targetType: 'CHROME' | 'CHROME_OS' | 'WINDOWS'; 79} 80 81export interface HostOsTargetInfo extends TargetInfoBase { 82 targetType: 'LINUX' | 'MACOS'; 83} 84 85// Holds information about a target. It's used by the UI and the logic which 86// generates a config. 87export type TargetInfo = 88 | AndroidTargetInfo 89 | ChromeTargetInfo 90 | HostOsTargetInfo; 91 92// RecordingTargetV2 is subclassed by Android devices and the Chrome browser/OS. 93// It creates tracing sessions which are used by the UI. For Android, it manages 94// the connection with the device. 95export interface RecordingTargetV2 { 96 // Allows targets to surface target specific information such as 97 // well known key/value pairs: OS, targetType('ANDROID', 'CHROME', etc.) 98 getInfo(): TargetInfo; 99 100 // Disconnects the target. 101 disconnect(disconnectMessage?: string): Promise<void>; 102 103 // Returns true if we are able to connect to the target without interfering 104 // with other processes. For example, for adb devices connected over WebUSB, 105 // this will be false when we can not claim the interface (Which most likely 106 // means that 'adb server' is running locally.). After querrying this method, 107 // the caller can decide if they want to connect to the target and as a side 108 // effect take the connection away from other processes. 109 canConnectWithoutContention(): Promise<boolean>; 110 111 // Whether the recording target can be used in a tracing session. For example, 112 // virtual targets do not support a tracing session. 113 canCreateTracingSession(recordingMode?: string): boolean; 114 115 // Some target information can only be obtained after connecting to the 116 // target. This will establish a connection and retrieve data such as 117 // dataSources and apiLevel for Android. 118 fetchTargetInfo( 119 tracingSessionListener: TracingSessionListener, 120 ): Promise<void>; 121 122 createTracingSession( 123 tracingSessionListener: TracingSessionListener, 124 ): Promise<TracingSession>; 125} 126 127// TracingSession is used by the UI to record a trace. Depending on user 128// actions, the UI can start/stop/cancel a session. During the recording, it 129// provides updates about buffer usage. It is subclassed by 130// TracedTracingSession, which manages the communication with traced and has 131// logic for encoding/decoding Perfetto client requests/replies. 132export interface TracingSession { 133 // Starts the tracing session. 134 start(config: TraceConfig): void; 135 136 // Will stop the tracing session and NOT return any trace. 137 cancel(): void; 138 139 // Will stop the tracing session. The implementing class may also return 140 // the trace using a callback. 141 stop(): void; 142 143 // Returns the percentage of the trace buffer that is currently being 144 // occupied. 145 getTraceBufferUsage(): Promise<number>; 146} 147 148// Connection with an Adb device. Implementations will have logic specific to 149// the connection protocol used(Ex: WebSocket, WebUsb). 150export interface AdbConnection { 151 // Will push a binary to a given path. 152 push(binary: ArrayBuffer, path: string): Promise<void>; 153 154 // Will issue a shell command to the device. 155 shell(cmd: string): Promise<ByteStream>; 156 157 // Will establish a connection(a ByteStream) with the device. 158 connectSocket(path: string): Promise<ByteStream>; 159 160 // Returns true if we are able to connect without interfering 161 // with other processes. For example, for adb devices connected over WebUSB, 162 // this will be false when we can not claim the interface (Which most likely 163 // means that 'adb server' is running locally.). 164 canConnectWithoutContention(): Promise<boolean>; 165 166 // Ends the connection. 167 disconnect(disconnectMessage?: string): Promise<void>; 168} 169 170// A stream for a connection between a target and a tracing session. 171export interface ByteStream { 172 // The caller can add callbacks, to be executed when the stream receives new 173 // data or when it finished closing itself. 174 addOnStreamDataCallback(onStreamData: OnStreamDataCallback): void; 175 addOnStreamCloseCallback(onStreamClose: OnStreamCloseCallback): void; 176 177 isConnected(): boolean; 178 write(data: string | Uint8Array): void; 179 180 close(): void; 181 closeAndWaitForTeardown(): Promise<void>; 182} 183 184// Handles binary messages received over the ByteStream. 185export interface OnStreamDataCallback { 186 (data: Uint8Array): void; 187} 188 189// Called when the ByteStream is closed. 190export interface OnStreamCloseCallback { 191 (): void; 192} 193 194// OnTraceDataCallback will return the entire trace when it has been fully 195// assembled. This will be changed in the following CL aosp/2057640. 196export interface OnTraceDataCallback { 197 (trace: Uint8Array): void; 198} 199 200// Handles messages that are useful in the UI and that occur at any layer of the 201// recording (trace, connection). The messages includes both status messages and 202// error messages. 203export interface OnMessageCallback { 204 (message: string): void; 205} 206 207// Handles the loss of the connection at the connection layer (used by the 208// AdbConnection). 209export interface OnDisconnectCallback { 210 (errorMessage?: string): void; 211} 212 213// Called when there is a change of targets or within a target. 214// For instance, it's used when an Adb device becomes connected/disconnected. 215// It's also executed by a target when the information it stores gets updated. 216export interface OnTargetChangeCallback { 217 (): void; 218} 219 220// A collection of callbacks that is passed to RecordingTargetV2 and 221// subsequently to TracingSession. The callbacks are decided by the UI, so the 222// recording code is not coupled with the rendering logic. 223export interface TracingSessionListener { 224 onTraceData: OnTraceDataCallback; 225 onStatus: OnMessageCallback; 226 onDisconnect: OnDisconnectCallback; 227 onError: OnMessageCallback; 228} 229