1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
// Copyright 2022 Jeff Kim <hiking90@gmail.com>
// SPDX-License-Identifier: Apache-2.0
//! A pure Rust implementation of Android Binder IPC mechanism.
//!
//! This library provides a complete implementation of the Android Binder protocol
//! for inter-process communication (IPC) on Linux and Android systems. It enables
//! services to communicate across process boundaries with type safety and efficiency.
//!
//! # Core Components
//!
//! - **Binder**: Core binder object and transaction handling
//! - **Parcel**: Serialization/deserialization for IPC data
//! - **Proxy**: Client-side interface for remote services
//! - **Native**: Server-side service implementation utilities
//! - **ProcessState**: Process-level binder state management
//! - **ServiceManager**: Service discovery and registration (the [`hub`] module)
//! - **RPC transport**: binder-over-socket (`rpc` module, behind the `rpc`
//! feature) — a separate stack from the kernel binder path
//! - **Entry API**: [`serve`] / [`connect`] — publish and look up services
//! with one URI-selected transport (kernel binder or RPC)
//! - **Shared memory**: [`shared_memory`] — payloads too big to copy through
//! a transaction (AOSP `IMemory` wire)
//! - **Interface macros**: `#[rsbinder::interface]` (behind the `macros`
//! feature) — an interface as a Rust trait instead of an `.aidl` file
//!
//! # Wire byte order
//!
//! **The data-parcel wire is little-endian on every host.** A parcel
//! written on one machine can be read on another, whatever either CPU's
//! byte order is, and the bytes are identical to what a peer running
//! Android's libbinder would send for the same value.
//!
//! On a little-endian host — every Android target and almost every Linux
//! one — this costs nothing: the encoding is the memory layout, as it
//! always was. A big-endian host pays a byte swap and gets a parcel its
//! peers can actually read.
//!
//! Not every byte in a parcel is wire, and the distinction matters if you
//! are reading the source:
//!
//! | Layer | What | Byte order |
//! |---|---|---|
//! | Data parcel | scalars, arrays, `String`, the object-free payload | **little-endian** |
//! | Kernel command stream | the `BC_*`/`BR_*` ioctl buffer | host-native |
//! | UAPI structs | `flat_binder_object`, `binder_transaction_data` | host-native |
//!
//! The lower two go to the kernel driver, which parses them with native
//! loads; byte-swapping those would break the driver interface. So on a
//! big-endian host a *kernel* parcel carrying a binder is a mixture —
//! little-endian scalars around a native object header. That is correct:
//! the scalars cross to a peer, the object header does not.
//!
//! ## Support tiers
//!
//! | Path | Little-endian | Big-endian |
//! |---|---|---|
//! | RPC (binder-over-socket) | supported, CI-verified | supported, verified under qemu-user s390x |
//! | Kernel binder | supported, CI-verified | structurally correct but **unverified** — no big-endian binderfs exists to test on |
//!
//! # Data serialization
//!
//! An AIDL interface is already a schema, and the code generated from it
//! is already a complete serializer. `to_bytes` and `from_bytes` (with
//! the `rpc` feature) let you use it for storage rather than only for a
//! transaction:
//!
//! ```no_run
//! # fn main() {}
//! # #[cfg(all(feature = "rpc", feature = "macros"))]
//! # mod example {
//! # #[derive(rsbinder::Parcelable, Default, Debug, Clone)]
//! # struct Settings { volume: i32, name: String }
//! # fn run() -> rsbinder::Result<()> {
//! let settings = Settings { volume: 7, name: "quiet".into() };
//! std::fs::write("settings.bin", rsbinder::to_bytes(&settings)?)?;
//!
//! let restored: Settings = rsbinder::from_bytes(&std::fs::read("settings.bin")?)?;
//! # Ok(())
//! # }
//! # }
//! ```
//!
//! Binders and file descriptors are refused rather than encoded — neither
//! means anything outside the process that made it. `to_bytes`'s own docs
//! cover what makes a stored type survive its schema changing.
//!
//! # Feature flags
//!
//! - `tokio` *(default)* — full async/await support on the Tokio runtime
//! (implies `async`).
//! - `async` — generic async-trait support, without committing to a
//! specific runtime.
//! - `rpc` — master switch for the RPC transport (binder-over-socket), a
//! separate stack from the kernel binder path. Off by default; default
//! and `--no-default-features` builds carry zero RPC/networking cost.
//! - `rpc-tcp-debug` — plaintext TCP backend (implies `rpc`). Debug and
//! interop bring-up **only**, never production — use `rpc-tls` for real
//! networks.
//! - `rpc-vsock` — vsock backend for host↔VM channels (implies `rpc`;
//! Linux and Android targets only).
//! - `rpc-tls` — TLS backend over rustls (implies `rpc`). rsbinder never
//! invents crypto; the caller supplies the `rustls` configuration.
//! - `macros` — `#[rsbinder::interface]`, `#[derive(Parcelable)]` and
//! `#[derive(BinderEnum)]`: declare an interface as a Rust trait, with no
//! `.aidl` file and no `build.rs`. The emitted code is byte-for-byte what
//! `.aidl` produces. Off by default: it pulls the AIDL compiler in as a
//! proc-macro dependency.
//! - `android_10` … `android_16`, plus the `android_*_plus` ranges (e.g.
//! `android_11_plus`) — select which Android service-manager protocol
//! versions to support. Android 10 uses the legacy C service-manager
//! protocol. Android 17 needs no dedicated flag: its service-manager wire
//! format is identical to Android 16's, so `android_16` serves it.
//! Android 15 has **two** protocols and one SDK version —
//! `android-15.0.0_r6` renumbered the interface — so `android_14` serves
//! its initial release and `android_15` serves `r6` and later; enable both
//! to cover every Android 15 device. The choice is measured at runtime,
//! not derived from the SDK version.
//! - `fuzzing`, `test-util` — expose entry points that exist for a fuzz
//! target or a test to reach past the API. Not part of the supported
//! surface, and absent from a normal build; a consumer has no reason to
//! enable either.
//!
//! # Basic Usage
//!
//! This library works with AIDL (Android Interface Definition Language) files to generate
//! type-safe Rust bindings for IPC services.
//!
//! **[`serve`] and [`connect`] are the way in.** One URI picks the
//! transport — `binder:///dev/binderfs/binder` for kernel binder,
//! `unix:///run/svc.sock` or `tcp://…` for RPC — and the service and
//! client code either side of it is identical. The lower-level route
//! ([`ProcessState`] plus the [`hub`] service-manager calls) stays
//! available and is what the entry API is built on; reach for it when you
//! need control the URI does not express, not as the default way to start.
//!
//! ## Setting up an AIDL-based Service
//!
//! First, create an AIDL interface file (`aidl/hello/IHello.aidl`):
//!
//! ```aidl
//! package hello;
//!
//! interface IHello {
//! String echo(in String message);
//! }
//! ```
//!
//! Add a `build.rs` file to generate Rust bindings:
//!
//! ```rust,ignore
//! # use std::path::PathBuf;
//! rsbinder_aidl::Builder::new()
//! .source(PathBuf::from("aidl/hello/IHello.aidl"))
//! .output(PathBuf::from("hello.rs"))
//! .generate()
//! .unwrap();
//! ```
//!
//! In your `Cargo.toml`, add the build dependency:
//!
//! ```toml
//! [build-dependencies]
//! rsbinder-aidl = "*" # Check crates.io for the latest version
//! ```
//!
//! ## Implementing the Service
//!
//! ```rust,ignore
//! use rsbinder::*;
//!
//! // Include the generated code
//! rsbinder::include_aidl!("hello", crate::hello::IHello::*);
//!
//! // Implement the service
//! struct HelloService;
//!
//! impl Interface for HelloService {}
//!
//! impl IHello for HelloService {
//! fn echo(&self, message: &str) -> rsbinder::BinderResult<String> {
//! Ok(format!("Echo: {}", message))
//! }
//! }
//!
//! # fn main() -> Result<()> {
//! // Kernel binder: init the process state, register with the service
//! // manager, start the thread pool and join it. The same three calls
//! // with `serve("unix:///tmp/hello.sock")` serve over RPC instead.
//! rsbinder::serve("binder://")?
//! .add("hello_service", BnHello::new_binder(HelloService))?
//! .run()?;
//! # Ok(())
//! # }
//! ```
//!
//! (`ProcessState::init_default()` + `start_thread_pool()` +
//! `hub::add_service()` + `join_thread_pool()` remain available as the
//! low-level form.)
//!
//! ## Creating a Client
//!
//! ```rust,ignore
//! use rsbinder::*;
//!
//! // Include the same generated code
//! rsbinder::include_aidl!("hello", crate::hello::IHello::*);
//!
//! # fn main() -> Result<()> {
//! // Init the process state, wait for the service to be registered, and
//! // cast it to the interface. Over RPC: "unix:///tmp/hello.sock#hello_service".
//! let hello_service: rsbinder::Strong<dyn IHello> =
//! rsbinder::connect("binder://hello_service")?;
//!
//! // Call remote method
//! let result = hello_service.echo("Hello, World!")?;
//! println!("Service response: {}", result);
//! # Ok(())
//! # }
//! ```
//!
//! ## Opting into kernel-level features
//!
//! Native binders can opt into per-binder kernel features (for example,
//! receiving the caller's SELinux security context) via [`BinderFeatures`]
//! and the `*_with_features` constructor variants. See [`BinderFeatures`]
//! for the available opt-ins.
//!
//! # License
//!
//! Licensed under Apache License, Version 2.0.
//!
//! # References
//!
//! * [AIDL](https://source.android.com/docs/core/architecture/aidl)
//! * [Binder](https://source.android.com/docs/core/architecture/hidl/binder-ipc)
//!
// android-only: clippy false-positives here on thread_locals that already use,
// or cannot use, a `const { .. }` initializer.
// Core binder functionality
// Async binder runtime support. Private: `BoxFuture`, `BinderAsyncPool`
// and `BinderAsyncRuntime` are re-exported at the crate root, which is
// the only path — see the re-export policy below.
/// BinderFS filesystem utilities
/// Helpers for a process bridging two transports (the gateway pattern)
// `CommandStream`, the L2 ioctl buffer. Private, and its field is private
// to the module: `thread_state` cannot reach the L1 codec through it.
// Error types. Private: `Result` and `StatusCode` are re-exported at the
// crate root.
// `ParcelFileDescriptor`, re-exported at the crate root.
// `LazyServiceRegistrar`; documented inside (an outer doc would re-resolve its links at the crate root, as at `entry`).
// Server-side binder construction: `Binder`, `BinderFeatures` and
// `is_handling_transaction`, re-exported at the crate root.
// `Parcel`, re-exported at the crate root.
// The (de)serialization trait stack, re-exported at the crate root.
// `ParcelableHolder`, re-exported at the crate root.
// `Proxy` and `ProxyHandle`, re-exported at the crate root.
/// Process-global proxy count + watermark callbacks
/// with opt-in per-uid tracking. AOSP `BpBinder` proxy-count surface
/// (`getBinderProxyCount` / `setBinderProxyCountWatermarks` /
/// `setBinderProxyCountEventCallback` / `enableCountByUid`).
/// Shared-memory IPC: AOSP `IMemoryHeap` / `IMemory` traits, a
/// `memfd_create` (Linux/Android) / `shm_open` (macOS) backed
/// `MemoryHeapBase`, and wire-faithful `android.utils.IMemory*`
/// stubs so a heap fd can travel over the kernel binder or
/// Unix-socket RPC. See the module docs.
// Status and exception handling: `BinderResult`, `ExceptionCode` and
// `Status`, re-exported at the crate root.
/// Thread-local binder state
/// RPC transport (binder-over-socket) — a separate stack from the
/// kernel binder path. Present only with the `rpc` feature.
/// Service hub and manager implementations
/// Client stub for Android's `PermissionManagerService`
/// (`android.os.IPermissionController`). See module doc for the
/// AOSP-faithful surface and fail-closed `check_permission` helper.
/// Async runtime implementations
// Unified entry API (Plan 2-17): `serve` / `connect` + URI over every
// transport. Kept as a plain (non-doc) comment: an outer doc here would
// merge with the module's inner `//!` docs and re-resolve their intra-doc
// links at the crate root, breaking them.
pub use connect_async;
pub use ;
// Generated `IFooAsyncService` impls carry this attribute. Re-exported so a
// consumer of generated code needs no `async-trait` line of its own.
pub use async_trait as __async_trait;
// The `.aidl`-free path (plan 2-19), behind the `macros` feature: declare an
// interface as a Rust trait and its data types as ordinary structs and enums.
// See the `rsbinder_macros` crate docs for the signature rules and for what
// still needs `.aidl`. `Parcelable` is re-exported as both a trait and a
// derive; they live in different namespaces, so the one name serves both.
pub use ;
// Explicit re-exports: glob re-exports would silently leak every
// newly-added `pub` item in these modules, defeating semver review.
//
// Nine of the modules below are private, and this block is the only way
// in. They exported exactly what is re-exported here, so the module path
// was a second name for each item and nothing else — including one that
// was actively harmful: `status::Result` is `BinderResult`, but shares a
// name with the root `Result`, which is a different type. A domain module
// that carries items of its own (`hub`, `rpc`, `thread_state`, …) stays
// public; those must still be reached via `rsbinder::<module>::<item>`.
// From `binder` — core binder identity, transaction codes, traits.
pub use ;
// `declare_binder_interface!` expands to `$crate::__rpc_stamp_descriptor(...)`
// in consumer crates, so this helper must stay reachable at the crate root.
pub use __rpc_stamp_descriptor;
pub use ;
pub use ;
pub use ParcelFileDescriptor;
// Fuzz entry points for the `fuzz/` crate, which is outside the
// workspace and so can only reach them through the crate root now that
// `file_descriptor` is private.
pub use ;
// From `native` — server-side binder construction.
pub use ;
// From `thread_state` — calling identity (AOSP
// `IPCThreadState::getCalling*`). Kernel-path only; the RPC stack has
// its own `PeerIdentity` model under `rpc::PeerIdentity`.
pub use ;
pub use Parcel;
// Value ↔ bytes, for storing what an interface already knows how to
// describe. Behind `rpc` because the encoder runs in the session-less
// RPC parcel mode — that mode is what refuses binders and fds — and not
// because anything here talks to a socket.
pub use ;
// From `parcelable` — (de)serialization trait stack.
pub use ;
pub use ParcelableHolder;
pub use ;
// From `proxy` — client-side handle types.
pub use ;
// Explicit (not glob) so a newly-added `pub` item in `rt` can't silently leak
// to the crate root without semver review — the policy stated above.
pub use ;
pub use ;
/// Default path to the binder control device
pub const DEFAULT_BINDER_CONTROL_PATH: &str = "/dev/binderfs/binder-control";
/// Default path to the binder device (binderfs, used on Android 11+).
pub const DEFAULT_BINDER_PATH: &str = "/dev/binderfs/binder";
/// Default path to the binderfs mount point
pub const DEFAULT_BINDERFS_PATH: &str = "/dev/binderfs";
/// Legacy binder device path used on Android 10 and earlier.
pub const LEGACY_BINDER_PATH: &str = "/dev/binder";
/// Returns `true` when the runtime Android SDK version is at least `version`.
/// On non-Android platforms this always returns `true`.
/// Returns `true` when the runtime Android SDK version is at least `version`.
/// On non-Android platforms this always returns `true`.
static ANDROID_SDK_VERSION: OnceLock = new;
/// Get the Android SDK version from system properties.
///
/// Returns the Android SDK version number, or 0 if not available.