Skip to content

Android fd backed shm#79

Open
dallison wants to merge 19 commits into
mainfrom
android-fd-backed-shm
Open

Android fd backed shm#79
dallison wants to merge 19 commits into
mainfrom
android-fd-backed-shm

Conversation

@dallison
Copy link
Copy Markdown
Owner

@dallison dallison commented May 29, 2026

Removes the use of /dev/subspace for shared memory on android and uses memfd_create instead. This is sent to the server for safe keeping and for retrieval by other publishers and subscribers. This removes any mods needed for SELInux on Android.

Also adds Soong/Blueprint builds for Android and a Java client. Adds tests for Java client.

Adds .cursor/skills/subspace-builds/SKILL.md, an agent-readable build guide. Agents should use it when asked to build, test, cross-compile, or debug Subspace builds across Bazel, CMake, Android, Soong/Blueprint, AOSP, QNX, Linux, or macOS.

Cross-computer discovery and bridging across NAT

Adds an optional TCP unicast discovery mode so two servers can bridge channels even when they cannot exchange UDP datagrams directly (e.g. one runs inside a NAT'd VM or Android emulator). UDP broadcast/unicast discovery remains the default for the LAN case.

  • --tcp_discovery runs the Query/Advertise/Subscribe handshake over a single TCP connection. The server with --peer_address dials the peer's --disc_port; the other listens. Because only the NAT'd side initiates, this avoids both the inbound-reachability and UDP source-port-rewrite problems. It also lets two servers run on one host without contending for the UDP discovery port.
  • --bridge_advertise_address=IP makes a NAT'd server advertise a forwarded loopback endpoint (e.g. 127.0.0.1 reached via adb forward/adb reverse) for its bridge/retirement listeners, and binds those listeners to the any-address.

Supporting changes:

  • Keep absl flag names on Android (ABSL_FLAGS_STRIP_NAMES=0 in the bazel Android configs); without this the server/tools rejected every command-line flag (even --socket) on Android.
  • manual_tests/pub gains --local and --channel; sub gains --channel; both line-buffer stdout so scripted output isn't lost.
  • Adds manual_tests/cross_host_bridge.sh, a manual cross-computer test that bridges a channel in both directions and verifies delivery, in two modes:
    • native — two servers on one host over loopback.
    • emulator — this host bridged to a running Android emulator (sets up the adb tunnels automatically).

Verified both directions natively and on an arm64 Android emulator (publish on Android/subscribe on host and vice versa). Documentation added to README.md, docs/server-architecture.md, and docs/android.md.

dallison added 19 commits May 28, 2026 10:36
Use anonymous FDs for Android shared memory so clients can keep allocating and resizing buffers without relying on a device-visible shm directory.
Use typed allocator metadata for registered client buffers, remove unused fields, and stop checking in generated protobuf outputs while keeping Android fd-backed buffers shareable across publishers and subscribers.
Keep the Rust client aligned with the fd-backed buffer registration protocol so the full test suite builds again.
Anonymous memfds have no name, so the process-global registry only emulated
shm_open-by-name for the unit test; the real Android client owns its
descriptors in the BufferSet and shares them with subscribers via the server.
Create now returns a caller-owned memfd, open-by-name is unsupported on
Android, and destroy is a no-op there (no named object, no shadow file).
UDP discovery assumes peers can exchange datagrams directly and be reached on
their advertised port, which fails across a NAT such as an Android emulator or
VM. --tcp_discovery runs the Query/Advertise/Subscribe handshake over a single
TCP connection that the peer with --peer_address dials (the other side
listens), so only the NAT'd side needs to initiate and there is no source-port
rewriting. --bridge_advertise_address lets a NAT'd server advertise a forwarded
loopback endpoint for its bridge/retirement listeners and binds them to the
any-address.

Also: keep absl flag names on Android builds (ABSL_FLAGS_STRIP_NAMES=0) so
server/tool command-line flags parse; add --local/--channel to the manual pub
and --channel to sub; line-buffer their stdout; and add
manual_tests/cross_host_bridge.sh which bridges a channel in both directions
between two host servers or between the host and a running Android emulator.
Verified both directions natively and on an arm64 emulator.
Add a README section covering UDP broadcast/unicast and the new TCP unicast
discovery, the relevant server flags, --bridge_advertise_address, and the
manual_tests/cross_host_bridge.sh cross-computer test. Link the Android guide.
The discovery connection list is an unordered collection keyed by connection
identity with add/remove/iterate semantics, so a flat_hash_set of shared_ptr
fits better than a vector (O(1) removal, no linear scan).
Key the registry by (session_id, buffer_index) and (slot_id, is_prefix)
so register, find, and unregister are O(1) average instead of linear
scans. Replace the ClientBuffers() vector accessor with
ForEachClientBuffer() and NumClientBuffers().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant