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'; 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 = AndroidTargetInfo|ChromeTargetInfo|HostOsTargetInfo; 88 89// RecordingTargetV2 is subclassed by Android devices and the Chrome browser/OS. 90// It creates tracing sessions which are used by the UI. For Android, it manages 91// the connection with the device. 92export interface RecordingTargetV2 { 93 // Allows targets to surface target specific information such as 94 // well known key/value pairs: OS, targetType('ANDROID', 'CHROME', etc.) 95 getInfo(): TargetInfo; 96 97 // Disconnects the target. 98 disconnect(disconnectMessage?: string): Promise<void>; 99 100 // Returns true if we are able to connect to the target without interfering 101 // with other processes. For example, for adb devices connected over WebUSB, 102 // this will be false when we can not claim the interface (Which most likely 103 // means that 'adb server' is running locally.). After querrying this method, 104 // the caller can decide if they want to connect to the target and as a side 105 // effect take the connection away from other processes. 106 canConnectWithoutContention(): Promise<boolean>; 107 108 // Whether the recording target can be used in a tracing session. For example, 109 // virtual targets do not support a tracing session. 110 canCreateTracingSession(recordingMode?: string): boolean; 111 112 // Some target information can only be obtained after connecting to the 113 // target. This will establish a connection and retrieve data such as 114 // dataSources and apiLevel for Android. 115 fetchTargetInfo(tracingSessionListener: TracingSessionListener): 116 Promise<void>; 117 118 createTracingSession(tracingSessionListener: TracingSessionListener): 119 Promise<TracingSession>; 120} 121 122// TracingSession is used by the UI to record a trace. Depending on user 123// actions, the UI can start/stop/cancel a session. During the recording, it 124// provides updates about buffer usage. It is subclassed by 125// TracedTracingSession, which manages the communication with traced and has 126// logic for encoding/decoding Perfetto client requests/replies. 127export interface TracingSession { 128 // Starts the tracing session. 129 start(config: TraceConfig): void; 130 131 // Will stop the tracing session and NOT return any trace. 132 cancel(): void; 133 134 // Will stop the tracing session. The implementing class may also return 135 // the trace using a callback. 136 stop(): void; 137 138 // Returns the percentage of the trace buffer that is currently being 139 // occupied. 140 getTraceBufferUsage(): Promise<number>; 141} 142 143// Connection with an Adb device. Implementations will have logic specific to 144// the connection protocol used(Ex: WebSocket, WebUsb). 145export interface AdbConnection { 146 // Will push a binary to a given path. 147 push(binary: ArrayBuffer, path: string): Promise<void>; 148 149 // Will issue a shell command to the device. 150 shell(cmd: string): Promise<ByteStream>; 151 152 // Will establish a connection(a ByteStream) with the device. 153 connectSocket(path: string): Promise<ByteStream>; 154 155 // Returns true if we are able to connect without interfering 156 // with other processes. For example, for adb devices connected over WebUSB, 157 // this will be false when we can not claim the interface (Which most likely 158 // means that 'adb server' is running locally.). 159 canConnectWithoutContention(): Promise<boolean>; 160 161 // Ends the connection. 162 disconnect(disconnectMessage?: string): Promise<void>; 163} 164 165// A stream for a connection between a target and a tracing session. 166export interface ByteStream { 167 // The caller can add callbacks, to be executed when the stream receives new 168 // data or when it finished closing itself. 169 addOnStreamDataCallback(onStreamData: OnStreamDataCallback): void; 170 addOnStreamCloseCallback(onStreamClose: OnStreamCloseCallback): void; 171 172 isConnected(): boolean; 173 write(data: string|Uint8Array): void; 174 175 close(): void; 176 closeAndWaitForTeardown(): Promise<void>; 177} 178 179// Handles binary messages received over the ByteStream. 180export interface OnStreamDataCallback { 181 (data: Uint8Array): void; 182} 183 184// Called when the ByteStream is closed. 185export interface OnStreamCloseCallback { 186 (): void; 187} 188 189// OnTraceDataCallback will return the entire trace when it has been fully 190// assembled. This will be changed in the following CL aosp/2057640. 191export interface OnTraceDataCallback { 192 (trace: Uint8Array): void; 193} 194 195// Handles messages that are useful in the UI and that occur at any layer of the 196// recording (trace, connection). The messages includes both status messages and 197// error messages. 198export interface OnMessageCallback { 199 (message: string): void; 200} 201 202// Handles the loss of the connection at the connection layer (used by the 203// AdbConnection). 204export interface OnDisconnectCallback { 205 (errorMessage?: string): void; 206} 207 208// Called when there is a change of targets or within a target. 209// For instance, it's used when an Adb device becomes connected/disconnected. 210// It's also executed by a target when the information it stores gets updated. 211export interface OnTargetChangeCallback { 212 (): void; 213} 214 215// A collection of callbacks that is passed to RecordingTargetV2 and 216// subsequently to TracingSession. The callbacks are decided by the UI, so the 217// recording code is not coupled with the rendering logic. 218export interface TracingSessionListener { 219 onTraceData: OnTraceDataCallback; 220 onStatus: OnMessageCallback; 221 onDisconnect: OnDisconnectCallback; 222 onError: OnMessageCallback; 223} 224