Primiano Tucci | a662485 | 2020-05-21 19:12:50 +0100 | [diff] [blame] | 1 | # Tracing API and ABI: surfaces and stability |
| 2 | |
| 3 | This document describes the API and ABI surface of the |
| 4 | [Perfetto Client Library][cli_lib], what can be expected to be stable long-term |
| 5 | and what not. |
| 6 | |
| 7 | #### In summary |
| 8 | |
| 9 | * The public C++ API in `include/perfetto/tracing/` is mostly stable but can |
| 10 | occasionally break at compile-time throughout 2020. |
| 11 | * The C++ API within `include/perfetto/ext/` is internal-only and exposed only |
| 12 | for Chromium. |
| 13 | * The tracing protocol ABI is based on protobuf-over-UNIX-socket and shared |
| 14 | memory. It is long-term stable and maintains compatibility in both directions |
| 15 | (old service + newer client and vice-versa). |
| 16 | * The [DataSourceDescriptor][data_source_descriptor.proto], |
| 17 | [DataSourceConfig][data_source_config.proto] and |
| 18 | [TracePacket][trace-packet-ref] protos are updated maintaining backwards |
| 19 | compatibility unless a message is marked as experimental. Trace Processor |
| 20 | deals with importing older trace formats. |
| 21 | * There isn't a version number neither in the trace file nor in the tracing |
| 22 | protocol and there will never be one. Feature flags are used when necessary. |
| 23 | |
| 24 | ## C++ API |
| 25 | |
| 26 | The Client Library C++ API allows an app to contribute to the trace with custom |
| 27 | trace events. Its headers live under [`include/perfetto/`](/include/perfetto). |
| 28 | |
| 29 | There are three different tiers of this API, offering increasingly higher |
| 30 | expressive power, at the cost of increased complexity. The three tiers are built |
| 31 | on top of each other. (Googlers, for more details see also |
| 32 | [go/perfetto-client-api](http://go/perfetto-client-api)). |
| 33 | |
| 34 |  |
| 35 | |
| 36 | ### Track Event (public) |
| 37 | |
| 38 | This mainly consists of the `TRACE_EVENT*` macros defined in |
| 39 | [`track_event.h`](/include/perfetto/tracing/track_event.h). |
| 40 | Those macros provide apps with a quick and easy way to add common types of |
| 41 | instrumentation points (slices, counters, instant events). |
| 42 | For details and instructions see the [Client Library doc][cli_lib]. |
| 43 | |
| 44 | ### Custom Data Sources (public) |
| 45 | |
| 46 | This consists of the `perfetto::DataSource` base class and the |
| 47 | `perfetto::Tracing` controller class defined in |
| 48 | [`tracing.h`](/include/perfetto/tracing.h). |
| 49 | These classes allow an app to create custom data sources which can get |
| 50 | notifications about tracing sessions lifecycle and emit custom protos in the |
| 51 | trace (e.g. memory snapshots, compositor layers, etc). |
| 52 | |
| 53 | For details and instructions see the [Client Library doc][cli_lib]. |
| 54 | |
| 55 | Both the Track Event API and the custom data source are meant to be a public |
| 56 | API. |
| 57 | |
| 58 | WARNING: The team is still iterating on this API surface. While we try to avoid |
| 59 | deliberate breakages, some occasional compile-time breakages might be |
| 60 | encountered when updating the library. The interface is expected to |
| 61 | stabilize by the end of 2020. |
| 62 | |
| 63 | ### Producer / Consumer API (internal) |
| 64 | |
| 65 | This consists of all the interfaces defined in the |
| 66 | [`include/perfetto/ext`](/include/perfetto/ext) directory. These provide access |
| 67 | to the lowest levels of the Perfetto internals (manually registering producers |
| 68 | and data sources, handling all IPCs). |
| 69 | |
| 70 | These interfaces will always be highly unstable. We highly discourage |
| 71 | any project from depending on this API because it is too complex and extremely |
| 72 | hard to get right. |
| 73 | This API surface exists only for the Chromium project, which has unique |
| 74 | challenges (e.g., its own IPC system, complex sandboxing models) and has dozens |
| 75 | of subtle use cases accumulated through over ten years of legacy of |
| 76 | chrome://tracing. The team is continuously reshaping this surface to gradually |
| 77 | migrate all Chrome Tracing use cases over to Perfetto. |
| 78 | |
| 79 | ## Tracing Protocol ABI |
| 80 | |
| 81 | The Tracing Protocol ABI consists of the following binary interfaces that allow |
| 82 | various processes in the operating system to contribute to tracing sessions and |
| 83 | inject tracing data into the tracing service: |
| 84 | |
| 85 | * [Socket protocol](#socket-protocol) |
| 86 | * [Shared memory layout](#shmem-abi) |
| 87 | * [Protobuf messages](#protos) |
| 88 | |
| 89 | The whole tracing protocol ABI is binary stable across platforms and is updated |
| 90 | maintaining both backwards and forward compatibility. No breaking changes |
| 91 | have been introduced since its first revision in Android 9 (Pie, 2018). |
| 92 | See also the [ABI Stability](#abi-stability) section below. |
| 93 | |
| 94 |  |
| 95 | |
| 96 | ### {#socket-protocol} Socket protocol |
| 97 | |
| 98 | At the lowest level, the tracing protocol is initiated with a UNIX socket of |
| 99 | type `SOCK_STREAM` to the tracing service. |
| 100 | The tracing service listens on two distinct sockets: producer and consumer. |
| 101 | |
| 102 |  |
| 103 | |
| 104 | Both sockets use the same wire protocol, the `IPCFrame` message defined in |
| 105 | [wire_protocol.proto](/protos/perfetto/ipc/wire_protocol.proto). The wire |
| 106 | protocol is simply based on a sequence of length-prefixed messages of the form: |
| 107 | ``` |
| 108 | < 4 bytes len little-endian > < proto-encoded IPCFrame > |
| 109 | |
| 110 | 04 00 00 00 A0 A1 A2 A3 05 00 00 00 B0 B1 B2 B3 B4 ... |
| 111 | { len: 4 } [ Frame 1 ] { len: 5 } [ Frame 2 ] |
| 112 | ``` |
| 113 | |
| 114 | The `IPCFrame` proto message defines a request/response protocol that is |
| 115 | compatible with the [protobuf services syntax][proto_rpc]. `IPCFrame` defines |
| 116 | the following frame types: |
| 117 | |
| 118 | 1. `BindService {producer, consumer} -> service`<br> |
| 119 | Binds to one of the two service ports (either `producer_port` or |
| 120 | `consumer_port`). |
| 121 | |
| 122 | 2. `BindServiceReply service -> {producer, consumer}`<br> |
| 123 | Replies to the bind request, listing all the RPC methods available, together |
| 124 | with their method ID. |
| 125 | |
| 126 | 3. `InvokeMethod {producer, consumer} -> service`<br> |
| 127 | Invokes a RPC method, identified by the ID returned by `BindServiceReply`. |
| 128 | The invocation takes as unique argument a proto sub-message. Each method |
| 129 | defines a pair of _request_ and _response_ method types.<br> |
| 130 | For instance the `RegisterDataSource` defined in [producer_port.proto] takes |
| 131 | a `perfetto.protos.RegisterDataSourceRequest` and returns a |
| 132 | `perfetto.protos.RegisterDataSourceResponse`. |
| 133 | |
| 134 | 4. `InvokeMethodReply service -> {producer, consumer}`<br> |
| 135 | Returns the result of the corresponding invocation or an error flag. |
| 136 | If a method return signature is marked as `stream` (e.g. |
| 137 | `returns (stream GetAsyncCommandResponse)`), the method invocation can be |
| 138 | followed by more than one `InvokeMethodReply`, all with the same |
| 139 | `request_id`. All replies in the stream but the last one will have |
| 140 | `has_more: true`, to notify the client more responses for the same invocation |
| 141 | will follow. |
| 142 | |
| 143 | Here is how the traffic over the IPC socket looks like: |
| 144 | |
| 145 | ``` |
| 146 | # [Prd > Svc] Bind request for the remote service named "producer_port" |
| 147 | request_id: 1 |
| 148 | msg_bind_service { service_name: "producer_port" } |
| 149 | |
| 150 | # [Svc > Prd] Service reply. |
| 151 | request_id: 1 |
| 152 | msg_bind_service_reply: { |
| 153 | success: true |
| 154 | service_id: 42 |
| 155 | methods: {id: 2; name: "InitializeConnection" } |
| 156 | methods: {id: 5; name: "RegisterDataSource" } |
| 157 | methods: {id: 3; name: "UnregisterDataSource" } |
| 158 | ... |
| 159 | } |
| 160 | |
| 161 | # [Prd > Svc] Method invocation (RegisterDataSource) |
| 162 | request_id: 2 |
| 163 | msg_invoke_method: { |
| 164 | service_id: 42 # "producer_port" |
| 165 | method_id: 5 # "RegisterDataSource" |
| 166 | |
| 167 | # Proto-encoded bytes for the RegisterDataSourceRequest message. |
| 168 | args_proto: [XX XX XX XX] |
| 169 | } |
| 170 | |
| 171 | # [Svc > Prd] Result of RegisterDataSource method invocation. |
| 172 | request_id: 2 |
| 173 | msg_invoke_method_reply: { |
| 174 | success: true |
| 175 | has_more: false # EOF for this request |
| 176 | |
| 177 | # Proto-encoded bytes for the RegisterDataSourceResponse message. |
| 178 | reply_proto: [XX XX XX XX] |
| 179 | } |
| 180 | ``` |
| 181 | |
| 182 | #### Producer socket |
| 183 | |
| 184 | The producer socket exposes the RPC interface defined in [producer_port.proto]. |
| 185 | It allows processes to advertise data sources and their capabilities, receive |
| 186 | notifications about the tracing session lifecycle (trace being started, stopped) |
| 187 | and signal trace data commits and flush requests. |
| 188 | |
| 189 | This socket is also used by the producer and the service to exchange a |
| 190 | tmpfs file descriptor during initialization for setting up the |
| 191 | [shared memory buffer](/docs/concepts/buffers.md) where tracing data will be |
| 192 | written (asynchronously). |
| 193 | |
| 194 | On Android this socket is linked at `/dev/socket/traced_producer`. On all |
| 195 | platforms it is overridable via the `PERFETTO_PRODUCER_SOCK_NAME` env var. |
| 196 | |
| 197 | On Android all apps and most system processes can connect to it |
| 198 | (see [`perfetto_producer` in SELinux policies][selinux_producer]). |
| 199 | |
| 200 | In the Perfetto codebase, the [`traced_probes`](/src/traced/probes/) and |
| 201 | [`heapprofd`](/src/profiling/memory) processes use the producer socket for |
| 202 | injecting system-wide tracing / profiling data. |
| 203 | |
| 204 | #### Consumer socket |
| 205 | |
| 206 | The consumer socket exposes the RPC interface defined in [consumer_port.proto]. |
| 207 | The consumer socket allows processes to control tracing sessions (start / stop |
| 208 | tracing) and read back trace data. |
| 209 | |
| 210 | On Android this socket is linked at `/dev/socket/traced_consumer`. On all |
| 211 | platforms it is overridable via the `PERFETTO_CONSUMER_SOCK_NAME` env var. |
| 212 | |
| 213 | Trace data contains sensitive information that discloses the activity the |
| 214 | system (e.g., which processes / threads are running) and can allow side-channel |
| 215 | attacks. For this reason the consumer socket is intended to be exposed only to |
| 216 | a few privileged processes. |
| 217 | |
| 218 | On Android, only the `adb shell` domain (used by various UI tools like |
| 219 | [Perfetto UI](https://ui.perfetto.dev/), |
| 220 | [Android Studio](https://developer.android.com/studio) or the |
| 221 | [Android GPU Inspector](https://github.com/google/agi)) |
| 222 | and few other trusted system services are allowed to access the consumer socket |
| 223 | (see [traced_consumer in SELinux][selinux_consumer]). |
| 224 | |
| 225 | In the Perfetto codebase, the [`perfetto`](/docs/reference/perfetto-cli) |
| 226 | binary (`/system/bin/perfetto` on Android) provides a consumer implementation |
| 227 | and exposes it through a command line interface. |
| 228 | |
| 229 | #### Socket protocol FAQs |
| 230 | |
| 231 | _Why SOCK_STREAM and not DGRAM/SEQPACKET?_ |
| 232 | |
| 233 | 1. To allow direct passthrough of the consumer socket on Android through |
| 234 | `adb forward localabstract` and allow host tools to directly talk to the |
| 235 | on-device tracing service. Today both the Perfetto UI and Android GPU |
| 236 | Inspector do this. |
| 237 | 2. To allow in future to directly control a remote service over TCP or SSH |
| 238 | tunneling. |
| 239 | 3. Because the socket buffer for `SOCK_DGRAM` is extremely limited and |
| 240 | and `SOCK_SEQPACKET` is not supported on MacOS. |
| 241 | |
| 242 | _Why not gRPC?_ |
| 243 | |
| 244 | The team evaluated gRPC in late 2017 as an alternative but ruled it out |
| 245 | due to: (i) binary size and memory footprint; (ii) the complexity and overhead |
| 246 | of running a full HTTP/2 stack over a UNIX socket; (iii) the lack of |
| 247 | fine-grained control on back-pressure. |
| 248 | |
| 249 | _Is the UNIX socket protocol used within Chrome processes?_ |
| 250 | |
| 251 | No. Within Chrome processes (the browser app, not CrOS) Perfetto doesn't use |
| 252 | any doesn't use any unix socket. Instead it uses the functionally equivalent |
| 253 | Mojo endpoints [`Producer{Client,Host}` and `Consumer{Client,Host}`][mojom]. |
| 254 | |
| 255 | ### Shared memory |
| 256 | |
| 257 | This section describes the binary interface of the memory buffer shared between |
| 258 | a producer process and the tracing service (SMB). |
| 259 | |
| 260 | The SMB is a staging area to decouple data sources living in the Producer |
| 261 | and allow them to do non-blocking async writes. A SMB is small-ish, typically |
| 262 | hundreds of KB. Its size is configurable by the producer when connecting. |
| 263 | For more architectural details about the SMB see also the |
| 264 | [buffers and dataflow doc](/docs/concepts/buffers.md) and the |
| 265 | [shared_memory_abi.h] sources. |
| 266 | |
| 267 | #### Obtaining the SMB |
| 268 | |
| 269 | The SMB is obtained by passing a tmpfs file descriptor over the producer socket |
| 270 | and memory-mapping it both from the producer and service. |
| 271 | The producer specifies the desired SMB size and memory layout when sending the |
| 272 | [`InitializeConnectionRequest`][producer_port.proto] request to the |
| 273 | service, which is the very first IPC sent after connection. |
| 274 | By default, the service creates the SMB and passes back its file descriptor to |
| 275 | the producer with the the [`InitializeConnectionResponse`][producer_port.proto] |
| 276 | IPC reply. Recent versions of the service (Android R / 11) allow the FD to be |
| 277 | created by the producer and passed down to the service in the request. When the |
| 278 | service supports this, it acks the request setting |
| 279 | `InitializeConnectionResponse.using_shmem_provided_by_producer = true`. At the |
| 280 | time of writing this feature is used only by Chrome for dealing with lazy |
| 281 | Mojo initialization during startup tracing. |
| 282 | |
| 283 | #### SMB memory layout: pages, chunks, fragments and packets |
| 284 | |
| 285 | The SMB is partitioned into fixed-size pages. A SMB page must be an integer |
| 286 | multiple of 4KB. The only valid sizes are: 4KB, 8KB, 16KB, 32KB. |
| 287 | |
| 288 | The size of a SMB page is determined by each Producer at connection time, via |
| 289 | the `shared_memory_page_size_hint_bytes` field of `InitializeConnectionRequest` |
| 290 | and cannot be changed afterwards. All pages in the SMB have the same size, |
| 291 | constant throughout the lifetime of the producer process. |
| 292 | |
| 293 |  |
| 294 | |
| 295 | **A page** is a fixed-sized partition of the shared memory buffer and is just a |
| 296 | container of chunks. |
| 297 | The Producer can partition each Page SMB using a limited number of predetermined |
| 298 | layouts (1 page : 1 chunk; 1 page : 2 chunks and so on). |
| 299 | The page layout is stored in a 32-bit atomic word in the page header. The same |
| 300 | 32-bit word contains also the state of each chunk (2 bits per chunk). |
| 301 | |
| 302 | Having fixed the total SMB size (hence the total memory overhead), the page |
| 303 | size is a triangular trade off between: |
| 304 | |
| 305 | 1. IPC traffic: smaller pages -> more IPCs. |
| 306 | 2. Producer lock freedom: larger pages -> larger chunks -> data sources can |
| 307 | write more data without needing to swap chunks and synchronize. |
| 308 | 3. Risk of write-starving the SMB: larger pages -> higher chance that the |
| 309 | Service won't manage to drain them and the SMB remains full. |
| 310 | |
| 311 | The page size, on the other side, has no implications on memory wasted due to |
| 312 | fragmentation (see Chunk below). |
| 313 | |
| 314 | **A chunk** A chunk is a portion of a Page and contains a linear sequence of |
| 315 | [`TracePacket(s)`][trace-packet-ref] (the root trace proto). |
| 316 | |
| 317 | A Chunk defines the granularity of the interaction between the Producer and |
| 318 | tracing Service. When a producer fills a chunk it sends `CommitData` IPC to the |
| 319 | service, asking it to copy its contents into the central non-shared buffers. |
| 320 | |
| 321 | A a chunk can be in one of the following four states: |
| 322 | |
| 323 | * `Free` : The Chunk is free. The Service shall never touch it, the Producer |
| 324 | can acquire it when writing and transition it into the `BeingWritten` state. |
| 325 | |
| 326 | * `BeingWritten`: The Chunk is being written by the Producer and is not |
| 327 | complete yet (i.e. there is still room to write other trace packets). |
| 328 | The Service never alter the state of chunks in the `BeingWritten` state |
| 329 | (but will still read them when flushing even if incomplete). |
| 330 | |
| 331 | * `Complete`: The Producer is done writing the chunk and won't touch it |
| 332 | again. The Service can move it to its non-shared ring buffer and mark the |
| 333 | chunk as `BeingRead` -> `Free` when done. |
| 334 | |
| 335 | * `BeingRead`: The Service is moving the page into its non-shared ring |
| 336 | buffer. Producers never touch chunks in this state. |
| 337 | _Note: this state ended up being never used as the service directly |
| 338 | transitions chunks from `Complete` back to `Free`_. |
| 339 | |
| 340 | A chunk is owned exclusively by one thread of one data source of the producer. |
| 341 | |
| 342 | Chunks are essentially single-writer single-thread lock-free arenas. Locking |
| 343 | happens only when a Chunk is full and a new one needs to be acquired. |
| 344 | |
| 345 | Locking happens only within the scope of a Producer process. |
| 346 | Inter-process locking is not generally allowed. The Producer cannot lock the |
| 347 | Service and vice versa. In the worst case, any of the two can starve the SMB, by |
| 348 | marking all chunks as either being read or written. But that has the only side |
| 349 | effect of losing the trace data. |
| 350 | The only case when stalling on the writer-side (the Producer) can occur is when |
| 351 | a data source in a producer opts in into using the |
| 352 | [`BufferExhaustedPolicy.kStall`](/docs/concepts/buffers.md) policy and the SMB |
| 353 | is full. |
| 354 | |
| 355 | **[TracePacket][trace-packet-ref]** is the atom of tracing. Putting aside |
| 356 | pages and chunks a trace is conceptually just a concatenation of TracePacket(s). |
| 357 | A TracePacket can be big (up to 64 MB) and can span across several chunks, hence |
| 358 | across several pages. |
| 359 | A TracePacket can therefore be >> chunk size, >> page size and even >> SMB size. |
| 360 | The Chunk header carries metadata to deal with the TracePacket splitting. |
| 361 | |
| 362 | Overview of the Page, Chunk, Fragment and Packet concepts:<br> |
| 363 |  |
| 364 | |
| 365 | Memory layout of a Page:<br> |
| 366 |  |
| 367 | |
| 368 | Because a packet can be larger than a page, the first and the last packets in |
| 369 | a chunk can be fragments. |
| 370 | |
| 371 |  |
| 372 | |
| 373 | #### Post-facto patching through IPC |
| 374 | |
| 375 | If a TracePacket is particularly large, it is very likely that the chunk that |
| 376 | contains its initial fragments is committed into the central buffers and removed |
| 377 | from the SMB by the time the last fragments of the same packets is written. |
| 378 | |
| 379 | Nested messages in protobuf are prefixed by their length. In a zero-copy |
| 380 | direct-serialization scenario like tracing, the length is known only when the |
| 381 | last field of a submessage is written and cannot be known upfront. |
| 382 | |
| 383 | Because of this, it is possible that when the last fragment of a packet is |
| 384 | written, the writer needs to backfill the size prefix in an earlier fragment, |
| 385 | which now might have disappeared from the SMB. |
| 386 | |
| 387 | In order to do this, the tracing protocol allows to patch the contents of a |
| 388 | chunk through the `CommitData` IPC (see |
| 389 | [`CommitDataRequest.ChunkToPatch`][commit_data_request.proto]) after the tracing |
| 390 | service copied it into the central buffer. There is no guarantee that the |
| 391 | fragment will be still there (e.g., it can be over-written in ring-buffer mode). |
| 392 | The service will patch the chunk only if it's still in the buffer and only if |
| 393 | the producer ID that wrote it matches the Producer ID of the patch request over |
| 394 | IPC (the Producer ID is not spoofable and is tied to the IPC socket file |
| 395 | descriptor). |
| 396 | |
| 397 | ### Proto definitions |
| 398 | |
| 399 | The following protobuf messages are part of the overall trace protocol ABI and |
| 400 | are updated maintaining backward-compatibility, unless marked as experimental |
| 401 | in the comments. |
| 402 | |
| 403 | TIP: See also the _Updating A Message Type_ section of the |
| 404 | [Protobuf Language Guide][proto-updating] for valid ABI-compatible changes |
| 405 | when updating the schema of a protobuf message. |
| 406 | |
| 407 | #### DataSourceDescriptor |
| 408 | |
| 409 | Defined in [data_source_descriptor.proto]. This message is sent |
| 410 | Producer -> Service through IPC on the Producer socket during the Producer |
| 411 | initialization, before any tracing session is started. This message is used |
| 412 | to register advertise a data source and its capabilities (e.g., which GPU HW |
| 413 | counters are supported, their possible sampling rates). |
| 414 | |
| 415 | #### DataSourceConfig |
| 416 | |
| 417 | Defined in [data_source_config.proto]. This message is sent: |
| 418 | |
| 419 | * Consumer -> Service through IPC on the Consumer socket, as part of the |
| 420 | [TraceConfig](/docs/concepts/config.md) when a Consumer starts a new tracing |
| 421 | session. |
| 422 | |
| 423 | * Service -> Producer through IPC on the Producer socket, as a reaction to the |
| 424 | above. The service passes through each `DataSourceConfig` section defined in |
| 425 | the `TraceConfig` to the corresponding Producer(s) that advertise that data |
| 426 | source. |
| 427 | |
| 428 | #### TracePacket |
| 429 | |
| 430 | Defined in [trace_packet.proto]. This is the root object written by any data |
| 431 | source into the SMB when producing any form of trace event. |
| 432 | See the [TracePacket reference][trace-packet-ref] for the full details. |
| 433 | |
| 434 | ## {#abi-stability} ABI Stability |
| 435 | |
| 436 | All the layers of the tracing protocol ABI are long-term stable and can only |
| 437 | be changed maintaining backwards compatibility. |
| 438 | |
| 439 | This is due to the fact that on every Android release the `traced` service |
| 440 | gets frozen in the system image while unbundled apps (e.g. Chrome) and host |
| 441 | tools (e.g. Perfetto UI) can be updated at a more frequently cadence. |
| 442 | |
| 443 | Both the following scenarios are possible: |
| 444 | |
| 445 | #### Producer/Consumer client older than tracing service |
| 446 | |
| 447 | This happens typically during Android development. At some point some newer code |
| 448 | is dropped in the Android platform and shipped to users, while client software |
| 449 | and host tools will lag behind (or simply the user has not updated their app / |
| 450 | tools). |
| 451 | |
| 452 | The tracing service needs to support clients talking and older version of the |
| 453 | Producer or Consumer tracing protocol. |
| 454 | |
| 455 | * Don't remove IPC methods from the service. |
| 456 | * Assume that fields added later to existing methods might be absent. |
| 457 | * For newer Producer/Consumer behaviors, advertise those behaviors through |
| 458 | feature flags when connecting to the service. Good examples of this are the |
| 459 | `will_notify_on_stop` or `handles_incremental_state_clear` flags in |
| 460 | [data_source_descriptor.proto] |
| 461 | |
| 462 | #### Producer/Consumer client newer than tracing service |
| 463 | |
| 464 | This is the most likely scenario. At some point in 2022 a large number of phones |
| 465 | will still run Android P or Q, hence running a snapshot of the tracing service |
| 466 | from ~2018-2020, but will run a recent version Google Chrome. |
| 467 | Chrome, when configured in system-tracing mode (i.e. system-wide + in-app |
| 468 | tracing), connects to the Android's `traced` producer socket and talks the |
| 469 | latest version of the tracing protocol. |
| 470 | |
| 471 | The producer/consumer client code needs to be able to talk with an older version of the |
| 472 | service, which might not support some newer features. |
| 473 | |
| 474 | * Newer IPC methods defined in [producer_port.proto] won't exist in the older |
| 475 | service. When connecting on the socket the service lists its RPC methods |
| 476 | and the client is able to detect if a method is available or not. |
| 477 | At the C++ IPC layer, invoking a method that doesn't exist on the service |
| 478 | causes the `Deferred<>` promise to be rejected. |
| 479 | |
| 480 | * Newer fields in existing IPC methods will just be ignored by the older version |
| 481 | of the service. |
| 482 | |
| 483 | * If the producer/consumer client depends on a new behavior of the service, and |
| 484 | that behavior cannot be inferred by the presence of a method, a new feature |
| 485 | flag must be exposed through the `QueryCapabilities` method. |
| 486 | |
| 487 | ## Static linking vs shared library |
| 488 | |
| 489 | The Perfetto Client Library is only available in the form of a static library |
| 490 | and a single-source amalgamated SDK (which is effectively a static library). |
| 491 | The library implements the Tracing Protocol ABI so, once statically linked, |
| 492 | depends only on the socket and shared memory protocol ABI, which are guaranteed |
| 493 | to be stable. |
| 494 | |
| 495 | No shared library distributions are available. We strongly discourage teams from |
| 496 | attempting to build the tracing library as shared library and use it from a |
| 497 | different linker unit. It is fine to link AND use the client library within |
| 498 | the same shared library, as long as none of the perfetto C++ API is exported. |
| 499 | |
| 500 | The `PERFETTO_EXPORT` annotations are only used when building the third tier of |
| 501 | the client library in chromium component builds and cannot be easily repurposed |
| 502 | for delineating shared library boundaries for the other two API tiers. |
| 503 | |
| 504 | This is because the C++ the first two tiers of the Client Library C++ API make |
| 505 | extensive use of inline headers and C++ templates, in order to allow the |
| 506 | compiler to see through most of the layers of abstraction. |
| 507 | |
| 508 | Maintaining the C++ ABI across hundreds of inlined functions and a shared |
| 509 | library is prohibitively expensive and too prone to break in extremely subtle |
| 510 | ways. For this reason the team has ruled out shared library distributions for |
| 511 | the time being. |
| 512 | |
| 513 | [cli_lib]: /docs/instrumentation/tracing-sdk.md |
| 514 | [selinux_producer]: https://cs.android.com/search?q=perfetto_producer%20f:sepolicy.*%5C.te&sq= |
| 515 | [selinux_consumer]:https://cs.android.com/search?q=f:sepolicy%2F.*%5C.te%20traced_consumer&sq= |
| 516 | [mojom]: https://source.chromium.org/chromium/chromium/src/+/master:services/tracing/public/mojom/perfetto_service.mojom?q=producer%20f:%5C.mojom$%20perfetto&ss=chromium&originalUrl=https:%2F%2Fcs.chromium.org%2F |
| 517 | [proto_rpc]: https://developers.google.com/protocol-buffers/docs/proto#services |
| 518 | [producer_port.proto]: /protos/perfetto/ipc/producer_port.proto |
| 519 | [consumer_port.proto]: /protos/perfetto/ipc/consumer_port.proto |
| 520 | [trace_packet.proto]: /protos/perfetto/trace/trace_packet.proto |
| 521 | [data_source_descriptor.proto]: /protos/perfetto/common/data_source_descriptor.proto |
| 522 | [data_source_config.proto]: /protos/perfetto/config/data_source_config.proto |
| 523 | [trace-packet-ref]: /docs/reference/trace-packet-proto.autogen |
| 524 | [shared_memory_abi.h]: /include/perfetto/ext/tracing/core/shared_memory_abi.h |
| 525 | [commit_data_request.proto]: /protos/perfetto/common/commit_data_request.proto |
| 526 | [proto-updating]: https://developers.google.com/protocol-buffers/docs/proto#updating |