Overview
Welcome to rsbinder!
rsbinder is a Rust library and toolset that enables you to utilize Binder IPC on Linux and Android OS. It provides pure Rust implementations that make Binder IPC available across both platforms.
Binder IPC is an object-oriented IPC (Inter-Process Communication) mechanism that Google added to the Linux kernel for Android. Android uses Binder IPC for all process communication, and since 2015, it has been integrated into the Linux kernel, making it available on all Linux systems.
However, since it is rarely used outside of Android, it is disabled by default in most Linux distributions.
Core Components
rsbinder offers the following features:
- crate rsbinder: A library crate for implementing binder service/client functionality.
- crate rsbinder-aidl: A tool for generating Rust code for rsbinder from AIDL files.
- crate rsbinder-tools: Provides CLI tools, including a Binder Service Manager for Linux.
- crate tests: Port of Android's binder test cases to provide various client/server testing features.
- crate example-hello: An example of service/client written using rsbinder.
Key Features of Binder IPC:
- Object-oriented: Binder IPC provides a clean and intuitive object-oriented API for inter-process communication.
- Efficient: Binder IPC is designed for high performance and low overhead with efficient data serialization.
- Secure: Binder IPC provides strong security features to prevent unauthorized access and tampering.
- Versatile: Binder IPC can be used for a variety of purposes, including remote procedure calls, data sharing, and event notification.
- Cross-platform: Works on both Android and Linux environments.
Core Components:
- Parcel: Data serialization and deserialization for IPC transactions
- Binder Objects: Strong and weak references for cross-process communication
- AIDL Compiler: Generates Rust code from Android Interface Definition Language files
- Service Manager: Centralized service discovery and registration (rsb_hub for Linux)
- Thread Pool: Efficient handling of concurrent IPC transactions
- Death Notification: Service lifecycle management and cleanup
Before using Binder IPC, you must enable the feature in the kernel. Please refer to Enable binder for Linux for detailed instructions on setting it up.
Architecture
--- title: Binder IPC Architecture --- flowchart BT AIDL G[[Generated Rust Code for Service and Client]] S(Your Binder Service) C(Binder Client) H(HUB Service Manager) AIDL-->|rsbinder-aidl compiler|G; G-.->|Include|S; G-.->|Include|C; S-.->|Register Service|H; C-.->|Query Service|H; C<-->|Communication|S;
Description of each component of the diagram
-
AIDL (Android Interface Definition Language)
- The Android Interface Definition Language (AIDL) is a tool that lets users abstract away IPC. Given an interface (specified in a .aidl file), the rsbinder-aidl compiler constructs Rust bindings so that this interface can be used across processes, regardless of the runtime or bitness.
- The compiler generates both synchronous and asynchronous Rust code with full type safety.
- https://source.android.com/docs/core/architecture/aidl
-
Generated Rust Code
- rsbinder-aidl generates trait definitions, proxy implementations (Bp*), and native service stubs (Bn*).
- Includes Parcelable implementations for data serialization/deserialization.
- Supports both sync and async programming models with async-trait integration.
- Features automatic memory management and error handling.
-
Your Binder Service
- Implement the generated trait interface to create your service logic.
- Use BnServiceName::new_binder() to create a binder service instance.
- Register your service with the HUB using hub::add_service().
- Join the thread pool to handle incoming client requests.
- Supports both native services and async services with runtime integration.
-
Binder Client
- Use hub::get_interface() to obtain a strongly-typed proxy to the service.
- The generated proxy code handles all IPC marshalling/unmarshalling automatically.
- Supports death notifications for service lifecycle management.
- Can register service callbacks for service availability notifications.
- Full type safety with compile-time interface validation.
-
HUB (Service Manager)
- rsbinder provides rsb_hub, a service manager for Linux environments.
- Handles service registration, discovery, and lifecycle management.
- Provides APIs for listing services, checking service status, and notifications.
- On Android, integrates with the existing Android service manager seamlessly.
- Supports priority-based service access and security policies.
Getting Started
Welcome to rsbinder! This guide will help you get started with Binder IPC development using Rust.
Learning Path
If you are new to Binder IPC, we recommend following this learning path:
-
Architecture - Start here to understand Binder IPC fundamentals
- Learn about the core concepts and components
- Understand the relationship between services and clients
- See how AIDL generates Rust code
-
Installation - Set up your development environment
- Install required dependencies
- Set up binder devices and service manager
- Configure your Rust project
-
Hello World - Build your first Binder service
- Create a simple echo service
- Learn AIDL basics
- Understand service registration and client communication
-
Platform-specific Setup - Choose your target platform:
- Linux Setup - For Linux development
- Android Development - For Android integration
Quick Start Checklist
Before diving into development, ensure you have:
- Rust 1.77+ installed
- Linux kernel with binder support enabled
-
Created binder device using
rsb_device
-
Service manager (
rsb_hub
) running - Basic understanding of AIDL syntax
Key Concepts to Understand
- Services: Server-side implementations that provide functionality
- Clients: Applications that consume services through proxies
- AIDL: Interface definition language for describing service contracts
- Service Manager: Central registry for service discovery
- Parcels: Serialization format for data exchange
- Binder Objects: References that enable cross-process communication
Common Development Workflow
- Define your service interface in an
.aidl
file - Use
rsbinder-aidl
to generate Rust code - Implement your service logic
- Register the service with the service manager
- Create clients that discover and use your service
Ready to start? Head to the Architecture section to learn the fundamentals!
Installation
Prerequisites
Rust Version Requirements
rsbinder requires Rust 1.77 or later. Ensure you have the latest stable Rust toolchain:
$ rustup update stable
$ rustc --version # Should be 1.77+
Enable binder for Linux
Please refer to Enable binder for Linux for detailed instructions on setting it up.
Create binder device file for Linux
After the binder configuration of the Linux kernel is complete, a binder device file must be created.
Method 1: Install from crates.io
Install rsbinder-tools and run to create a binder device:
$ cargo install rsbinder-tools
$ sudo rsb_device binder
Method 2: Build from source
If you prefer to build from source:
$ git clone https://github.com/hiking90/rsbinder.git
$ cd rsbinder
$ cargo build --release
$ sudo target/release/rsb_device binder
The rsb_device
tool will:
- Create
/dev/binderfs
directory if it doesn't exist - Mount binderfs filesystem
- Create the specified binder device
- Set appropriate permissions (0666) for user access
Run a service manager for Linux
If rsbinder-tools is already installed, the rsb_hub executable is also installed. Run it as follows:
$ rsb_hub
Alternatively, if building from source:
$ cargo run --bin rsb_hub
The service manager (rsb_hub) provides:
- Service registration and discovery
- Service lifecycle management
- Priority-based service access
- Service health monitoring
Dependencies for rsbinder projects
Add the following configuration to your Cargo.toml file:
[dependencies]
rsbinder = "0.4.0"
lazy_static = "1"
async-trait = "0.1"
env_logger = "0.11" # Optional: for logging
[build-dependencies]
rsbinder-aidl = "0.4.0"
Feature Flags
rsbinder supports various feature flags for different use cases:
[dependencies]
rsbinder = { version = "0.4.0", features = ["tokio"] } # Default: includes tokio
# or
rsbinder = { version = "0.4.0", features = ["sync"] } # Sync-only version
# or
rsbinder = { version = "0.4.0", features = ["async"] } # Async without tokio
Available features:
tokio
(default): Full tokio async runtime supportsync
: Synchronous-only operationsasync
: Async support without tokio runtimeandroid_*
: Android version compatibility flags
Crate Purposes:
- rsbinder: Core library providing Binder IPC functionality, including kernel communication, data serialization/deserialization, thread pool management, and service lifecycle.
- lazy_static: Required by generated AIDL code for static initialization of interface descriptors and transaction codes.
- async-trait: Required for async interface implementations generated by rsbinder-aidl.
- rsbinder-aidl: AIDL-to-Rust code generator, used in build.rs for compile-time code generation.
- env_logger: Optional but recommended for debugging and development logging.
Hello World!
This tutorial will guide you through creating a simple Binder service that echoes a string back to the client, and a client program that uses the service.
Create a new Rust project
Create a new Rust project using Cargo:
$ cargo new --lib hello
Create a library project for the common library used by both the client and service:
Modify Cargo.toml
In the hello project's Cargo.toml, add the following dependencies:
[package]
name = "hello"
version = "0.1.0"
publish = false
edition = "2021"
[dependencies]
rsbinder = "0.4.0"
lazy_static = "1"
async-trait = "0.1"
env_logger = "0.11"
[build-dependencies]
rsbinder-aidl = "0.4.0"
Add rsbinder, lazy_static, and async-trait to [dependencies], and add rsbinder-aidl to [build-dependencies].
Create an AIDL File
Create an aidl folder in the project's top directory to manage AIDL files:
$ mkdir -p aidl/hello
$ touch aidl/hello/IHello.aidl
The reason for creating an additional hello folder is to create a namespace for the hello package.
Create the aidl/hello/IHello.aidl
file with the following contents:
package hello;
// Defining the IHello Interface
interface IHello {
// Defining the echo() Function.
// The function takes a single parameter of type String and returns a value of type String.
String echo(in String hello);
}
For more information on AIDL syntax, refer to the Android AIDL documentation.
Create the build.rs
Create a build.rs
file in the project root to compile the AIDL file and generate Rust code:
use std::path::PathBuf; fn main() { rsbinder_aidl::Builder::new() .source(PathBuf::from("aidl/hello/IHello.aidl")) .output(PathBuf::from("hello.rs")) .generate() .unwrap(); }
This uses rsbinder-aidl to specify the AIDL source file (IHello.aidl
) and the generated Rust file name (hello.rs
), and then generates the code during the build process.
Create a common library for Client and Service
For the Client and Service, create a library that includes the Rust code generated from AIDL.
Create src/lib.rs and add the following content.
// Include the code hello.rs generated from AIDL.
include!(concat!(env!("OUT_DIR"), "/hello.rs"));
// Set up to use the APIs provided in the code generated for Client and Service.
pub use crate::hello::IHello::*;
// Define the name of the service to be registered in the HUB(service manager).
pub const SERVICE_NAME: &str = "my.hello";
Create a service
Let's configure the src/bin/hello_service.rs file as follows.
use env_logger::Env;
use rsbinder::*;
use hello::*;
// Define the name of the service to be registered in the HUB(service manager).
struct IHelloService;
// Implement the IHello interface for the IHelloService.
impl Interface for IHelloService {
// Reimplement the dump method. This is optional.
fn dump(&self, writer: &mut dyn std::io::Write, _args: &[String]) -> Result<()> {
writeln!(writer, "Dump IHelloService")?;
Ok(())
}
}
// Implement the IHello interface for the IHelloService.
impl IHello for IHelloService {
// Implement the echo method.
fn echo(&self, echo: &str) -> rsbinder::status::Result<String> {
Ok(echo.to_owned())
}
}
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
// Initialize ProcessState with the default binder path and the default max threads.
println!("Initializing ProcessState...");
ProcessState::init_default();
// Start the thread pool.
// This is optional. If you don't call this, only one thread will be created to handle the binder transactions.
println!("Starting thread pool...");
ProcessState::start_thread_pool();
// Create a binder service.
println!("Creating service...");
let service = BnHello::new_binder(IHelloService{});
// Add the service to binder service manager.
println!("Adding service to hub...");
hub::add_service(SERVICE_NAME, service.as_binder())?;
// Join the thread pool.
// This is a blocking call. It will return when the thread pool is terminated.
Ok(ProcessState::join_thread_pool()?)
}
Create a client
Create the src/bin/hello_client.rs file and configure it as follows.
use env_logger::Env;
use rsbinder::*;
use hello::*;
use hub::{BnServiceCallback, IServiceCallback};
use std::sync::Arc;
struct MyServiceCallback {}
impl Interface for MyServiceCallback {}
impl IServiceCallback for MyServiceCallback {
fn onRegistration(&self, name: &str, _service: &SIBinder) -> rsbinder::status::Result<()> {
println!("MyServiceCallback: {name}");
Ok(())
}
}
struct MyDeathRecipient {}
impl DeathRecipient for MyDeathRecipient {
fn binder_died(&self, _who: &WIBinder) {
println!("MyDeathRecipient");
}
}
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
// Initialize ProcessState with the default binder path and the default max threads.
ProcessState::init_default();
println!("list services:");
// This is an example of how to use service manager.
for name in hub::list_services(hub::DUMP_FLAG_PRIORITY_DEFAULT) {
println!("{}", name);
}
let service_callback = BnServiceCallback::new_binder(MyServiceCallback {});
hub::register_for_notifications(SERVICE_NAME, &service_callback)?;
// Create a Hello proxy from binder service manager.
let hello: rsbinder::Strong<dyn IHello> = hub::get_interface(SERVICE_NAME)
.unwrap_or_else(|_| panic!("Can't find {SERVICE_NAME}"));
let recipient = Arc::new(MyDeathRecipient {});
hello
.as_binder()
.link_to_death(Arc::downgrade(&(recipient as Arc<dyn DeathRecipient>)))?;
// Call echo method of Hello proxy.
let echo = hello.echo("Hello World!")?;
println!("Result: {echo}");
Ok(ProcessState::join_thread_pool()?)
}
Project folder and file structure
.
├── Cargo.toml
├── aidl
│ └── hello
│ └── IHello.aidl
├── build.rs
└── src
├── bin
│ ├── hello_client.rs
│ └── hello_service.rs
└── lib.rs
Run Hello Service and Client
Before running the service and client, make sure you have the service manager running:
# In terminal 1: Start the service manager
$ rsb_hub
Now you can run the service and client:
# In terminal 2: Run the service
$ cargo run --bin hello_service
# In terminal 3: Run the client
$ cargo run --bin hello_client
Expected Output
hello_service output:
Initializing ProcessState...
Starting thread pool...
Creating service...
Adding service to hub...
hello_client output:
list services:
my.hello
manager
MyServiceCallback: my.hello
Result: Hello World!
The client demonstrates several advanced features:
- Service Discovery: Lists all available services
- Service Callbacks: Registers for service availability notifications
- Death Recipients: Monitors service lifecycle for cleanup
- Type-safe Proxies: Uses strongly-typed interface for service calls
Troubleshooting
If you encounter issues:
- "Can't find my.hello" - Ensure the service is running and registered
- Permission errors - Check that binder device has correct permissions (0666)
- Service manager not found - Verify
rsb_hub
is running - Build errors - Ensure all dependencies are correctly specified in Cargo.toml
Next Steps
Congratulations! You've successfully created your first Binder service and client. Here are some next steps to explore:
Explore Advanced Features
- Async Services: Use async/await with tokio runtime
- Complex Data Types: Define custom Parcelable structs
- Service Callbacks: Implement bidirectional communication
- Error Handling: Learn about Status codes and error propagation
Run the Test Suite
The rsbinder project includes a comprehensive test suite with 96 test cases (90 currently passing) ported from Android:
# Terminal 1: Start service manager
$ cargo run --bin rsb_hub
# Terminal 2: Start test service
$ cargo run --bin test_service
# Terminal 3: Run tests
$ cargo test test_client::
Study Real Examples
Check out the rsbinder repository for more complex examples:
- example-hello: The complete example from this tutorial
- tests: Comprehensive test cases showing various IPC scenarios
- rsbinder-tools: Real-world service manager implementation
Enable binder for Linux
Most Linux distributions do not have Binder IPC enabled by default, so additional steps are required to use it.
If you are able to build the Linux kernel yourself, you can enable Binder IPC by adding the following kernel configuration options:
CONFIG_ASHMEM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
Other documents related to Binder IPC
Let's examine methods to activate Binder IPC in some representative Linux distributions.
Enable Binder IPC on Arch Linux
Arch Linux provides an easy way to enable Binder IPC support through the linux-zen kernel, which already includes all necessary Binder components.
Install linux-zen Kernel
The linux-zen kernel is the recommended and simplest method to get Binder IPC support on Arch Linux:
# Update system packages
$ sudo pacman -Syu
# Install linux-zen kernel and headers
$ sudo pacman -S linux-zen linux-zen-headers
# Update bootloader configuration
$ sudo grub-mkconfig -o /boot/grub/grub.cfg
# Reboot to use the new kernel
$ sudo reboot
After reboot, select the zen kernel from the GRUB menu or set it as default.
Verification
After installing and booting into the zen kernel, verify Binder support is available:
# Check current kernel
$ uname -r
# Should show something like "6.x.x-zen1-1-zen"
Install rsbinder-tools
Install the rsbinder development tools:
# Install Rust (if not already installed)
$ sudo pacman -S rustup
$ rustup default stable
# Install rsbinder-tools from crates.io
$ cargo install rsbinder-tools
Create and Test Binder Device
Create a binder device and test the setup:
# Create binder device
$ sudo rsb_device binder
# Verify device creation
$ ls -la /dev/binderfs/binder
# Test with a simple example
$ git clone https://github.com/hiking90/rsbinder.git
$ cd rsbinder/example-hello
# Start service manager in one terminal
$ rsb_hub
# In another terminal, run the example
$ cargo run --bin hello_service &
$ cargo run --bin hello_client
Persistent Configuration
To automatically load binder modules on boot:
# Create module loading configuration
$ echo "binder_linux" | sudo tee /etc/modules-load.d/binder.conf
# Set module parameters
$ echo "options binder_linux devices=binder,hwbinder,vndbinder" | sudo tee /etc/modprobe.d/binder.conf
Troubleshooting
If you encounter issues:
# Check kernel messages for binder-related errors
$ dmesg | grep -i binder
# Verify zen kernel is running
$ uname -r | grep zen
# Check if modules loaded successfully
$ sudo modprobe -v binder_linux
References
Enable Binder IPC on Ubuntu Linux
⚠️ Important Notice This document is generated by GitHub Copilot and has not been fully tested or validated in real Ubuntu environments. The instructions provided are based on general knowledge and may require adjustments for your specific system configuration. Please proceed with caution and test thoroughly in a safe environment before applying to production systems.
Ubuntu Linux does not enable Binder IPC by default. Here are several methods to enable it:
Method 1: Use Anbox Kernel Modules (Recommended)
The easiest way is to install the anbox-modules package which provides the necessary kernel modules:
# Install required packages
$ sudo apt update
$ sudo apt install software-properties-common
# Add the anbox PPA
$ sudo add-apt-repository ppa:morphis/anbox-support
$ sudo apt update
# Install anbox modules
$ sudo apt install anbox-modules-dkms
After installation, load the modules:
# Load binder modules
$ sudo modprobe ashmem_linux
$ sudo modprobe binder_linux
# Verify modules are loaded
$ lsmod | grep -E "(ashmem|binder)"
Method 2: Install Custom Kernel
Option A: Using mainline kernel with binder support
Some Ubuntu kernels include binder support. Check if your kernel already has it:
# Check if binder is available
$ grep -E "(ANDROID|BINDER)" /boot/config-$(uname -r)
If not available, you may need to compile a custom kernel or use a kernel that includes binder support.
Option B: Using Ubuntu mainline kernels
You can try installing a mainline kernel that includes binder support:
# Install mainline kernel (example for 6.1)
$ wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v6.1/amd64/linux-headers-6.1.0-060100_6.1.0-060100.202212111530_all.deb
$ wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v6.1/amd64/linux-headers-6.1.0-060100-generic_6.1.0-060100.202212111530_amd64.deb
$ wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v6.1/amd64/linux-image-unsigned-6.1.0-060100-generic_6.1.0-060100.202212111530_amd64.deb
$ wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v6.1/amd64/linux-modules-6.1.0-060100-generic_6.1.0-060100.202212111530_amd64.deb
$ sudo dpkg -i *.deb
$ sudo reboot
Method 3: Build Custom Kernel (Advanced)
If you need to build your own kernel with binder support:
# Install build dependencies
$ sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev
# Download kernel source
$ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
$ tar -xf linux-6.1.tar.xz
$ cd linux-6.1
# Configure kernel with binder support
$ make menuconfig
# Navigate to: General setup -> Enable Android support
# Enable:
# CONFIG_ANDROID=y
# CONFIG_ANDROID_BINDER_IPC=y
# CONFIG_ANDROID_BINDERFS=y
# CONFIG_ASHMEM=y
# Build and install
$ make -j$(nproc)
$ sudo make modules_install
$ sudo make install
$ sudo update-grub
$ sudo reboot
Verification
After enabling binder support, verify it's working:
# Check if binder modules are available
$ find /lib/modules/$(uname -r) -name "*binder*"
# Check if binderfs is supported
$ grep binderfs /proc/filesystems
# Test creating a binder device (requires rsbinder-tools)
$ sudo rsb_device test_binder
Troubleshooting
Common Issues:
- Module not found: Ensure the anbox-modules-dkms package is properly installed
- Permission denied: Make sure you're using sudo for device creation
- Kernel too old: Binder support requires Linux kernel 3.19+ with backported patches or 4.17+ natively
Getting Help:
- Check dmesg for kernel messages:
dmesg | grep -i binder
- Verify module loading:
sudo modprobe -v binder_linux
- Check system logs:
journalctl -f
while loading modules
References
Enable Binder IPC on RedHat Linux (RHEL/CentOS/Fedora)
⚠️ Important Notice This document is generated by GitHub Copilot and has not been fully tested or validated in real RedHat-based environments. The instructions provided are based on general knowledge and may require adjustments for your specific system configuration. Please proceed with caution and test thoroughly in a safe environment before applying to production systems.
RedHat-based distributions (RHEL, CentOS, Fedora) do not include Binder IPC support by default. Here are methods to enable it:
Fedora
Method 1: Custom Kernel Build (Recommended for Fedora)
Fedora provides kernel source packages that can be modified to include binder support:
# Install development tools
$ sudo dnf groupinstall "Development Tools"
$ sudo dnf install fedora-packager fedpkg
$ sudo dnf install kernel-devel kernel-headers
# Install kernel build dependencies
$ sudo dnf builddep kernel
# Get kernel source
$ fedpkg clone -a kernel
$ cd kernel
$ fedpkg switch-branch f$(rpm -E %fedora)
$ fedpkg prep
# Modify kernel config to enable binder
$ cd ~/rpmbuild/BUILD/kernel-*/linux-*
$ make menuconfig
# Enable the following options:
# General setup -> Android support (CONFIG_ANDROID=y)
# CONFIG_ANDROID_BINDER_IPC=y
# CONFIG_ANDROID_BINDERFS=y
# CONFIG_ASHMEM=y
# Build the kernel
$ make -j$(nproc)
$ sudo make modules_install
$ sudo make install
# Update bootloader
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
$ sudo reboot
Method 2: Third-party Kernel Modules
Some third-party repositories may provide binder modules:
# Enable RPM Fusion repositories
$ sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
# Look for available binder-related packages
$ dnf search binder android-tools
RHEL/CentOS
Method 1: Build Custom Kernel
For enterprise distributions, building a custom kernel is often the most reliable approach:
# Install EPEL repository (CentOS/RHEL 8+)
$ sudo dnf install epel-release
# Install development tools
$ sudo dnf groupinstall "Development Tools"
$ sudo dnf install rpm-build rpm-devel libtool
# Install kernel build dependencies
$ sudo dnf install kernel-devel kernel-headers
$ sudo dnf install elfutils-libelf-devel openssl-devel
# Download kernel source matching your running kernel
$ KERNEL_VERSION=$(uname -r | sed 's/\.el.*$//')
$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${KERNEL_VERSION}.tar.xz
$ tar -xf linux-${KERNEL_VERSION}.tar.xz
$ cd linux-${KERNEL_VERSION}
# Use current kernel config as base
$ zcat /proc/config.gz > .config
# or
$ cp /boot/config-$(uname -r) .config
# Modify config to enable binder
$ make menuconfig
# Enable CONFIG_ANDROID=y, CONFIG_ANDROID_BINDER_IPC=y, CONFIG_ANDROID_BINDERFS=y
# Build and install
$ make -j$(nproc)
$ sudo make modules_install
$ sudo make install
# Update GRUB
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
$ sudo reboot
Method 2: Using ELRepo (CentOS/RHEL)
ELRepo sometimes provides additional kernel modules:
# Install ELRepo
$ sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
$ sudo dnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
# Search for kernel modules
$ dnf --enablerepo=elrepo search kernel-ml
CentOS Stream
CentOS Stream may have more recent kernels that could include binder support:
# Check current kernel version
$ uname -r
# Update to latest kernel
$ sudo dnf update kernel
# Check if binder is already available
$ grep -E "(ANDROID|BINDER)" /boot/config-$(uname -r)
Alternative: Container-based Approach
If kernel modification is not feasible, consider using containers:
# Install Podman (RedHat's container runtime)
$ sudo dnf install podman
# Run rsbinder applications in a container with custom kernel
# This requires a base image with binder support
Module Loading (After Kernel Build)
Once you have a kernel with binder support:
# Load binder modules
$ sudo modprobe binder_linux devices="binder,hwbinder,vndbinder"
# Verify modules are loaded
$ lsmod | grep binder
# Create persistent module loading
$ echo "binder_linux" | sudo tee /etc/modules-load.d/binder.conf
# Set module parameters
$ echo "options binder_linux devices=binder,hwbinder,vndbinder" | sudo tee /etc/modprobe.d/binder.conf
SELinux Considerations
RedHat systems use SELinux which may interfere with binder operations:
# Check SELinux status
$ sestatus
# Temporarily disable SELinux for testing
$ sudo setenforce 0
# Create SELinux policy for binder (advanced)
# This requires creating custom SELinux policies for binder devices
Verification
Test that binder is working:
# Check if binderfs is available
$ grep binderfs /proc/filesystems
# Create test binder device
$ sudo mkdir -p /dev/binderfs
$ sudo mount -t binder binder /dev/binderfs
$ sudo rsb_device test_device
# Check device creation
$ ls -la /dev/binderfs/
Troubleshooting
Common Issues:
- Module compilation fails: Ensure all kernel-devel packages match your running kernel
- SELinux denials: Check
audit.log
for SELinux denials and create appropriate policies - Kernel version mismatch: Ensure kernel source matches your running kernel version
Debugging:
# Check kernel messages
$ dmesg | grep -i binder
# Check system journal
$ journalctl -f | grep -i binder
# Verify kernel config
$ grep -E "(ANDROID|BINDER)" /boot/config-$(uname -r)
References
Android Development
rsbinder provides comprehensive support for Android development alongside Linux. Since Android already has a complete Binder IPC environment, you can use rsbinder, rsbinder-aidl, and the existing Android service manager directly. There's no need to create binder devices or run a separate service manager like on Linux.
For building in the Android environment, you need to install the Android NDK and set up a Rust build environment that utilizes the NDK.
See: Android Build Environment Setup
Android Version Compatibility
rsbinder supports multiple Android versions with explicit feature flags for compatibility management. The Binder IPC interface has evolved across Android versions, and rsbinder handles these differences transparently.
Supported Android Versions
- Android 11 (API 30):
android_11
feature - Android 12 (API 31):
android_12
feature - Android 13 (API 33):
android_13
feature - Android 14 (API 34):
android_14
feature - Android 16 (API 36):
android_16
feature
Feature Flag Configuration
In your Cargo.toml
, specify the Android versions you want to support:
[dependencies]
rsbinder = { version = "0.4.0", features = ["android_14_plus"] }
Available feature combinations:
android_11_plus
: Supports Android 11 through 16android_12_plus
: Supports Android 12 through 16android_13_plus
: Supports Android 13 through 16android_14_plus
: Supports Android 14 through 16android_16_plus
: Supports Android 16 only
Protocol Compatibility
rsbinder maintains binary compatibility with Android's Binder protocol:
- Transaction Format: Uses identical
binder_transaction_data
structures - Object Types: Supports all Android Binder object types (BINDER, HANDLE, FD)
- Command Protocols: Implements the same ioctl commands (BC_/BR_ protocol)
- Memory Management: Compatible parcel serialization and shared memory handling
- AIDL Compatibility: Generates code compatible with Android's AIDL interfaces
Version Detection (Optional)
For applications that need to support multiple Android versions dynamically:
#![allow(unused)] fn main() { use android_system_properties::AndroidSystemProperties; let properties = AndroidSystemProperties::new(); if let Some(version) = properties.get("ro.build.version.release") { // Handle version-specific logic if needed println!("Running on Android {}", version); } }
Android-Specific Considerations
- Service Manager: Uses Android's existing service manager automatically
- Permissions: Respects Android's security model and SELinux policies
- Threading: Integrates with Android's Binder thread pool management
- Memory: Uses Android's shared memory mechanisms (ashmem/memfd)
- Stability: Supports Android's interface stability annotations (@VintfStability)
Android Build Environment Setup
This guide will help you set up a complete Android development environment for building and testing rsbinder applications.
Prerequisites
Android SDK Installation
You need to install the Android SDK which includes essential tools like adb
(Android Debug Bridge) and other platform tools required for Android development.
Method 1: Android Studio (Recommended)
Download and install Android Studio, which includes the Android SDK:
Method 2: Command Line Tools Only
If you prefer a minimal installation:
- Download Command Line Tools from Android Developer Downloads
- Extract and set up the SDK manager
Required SDK Components
Install the following SDK components using the SDK Manager:
# Install platform-tools (includes adb)
$ sdkmanager "platform-tools"
# Install emulator (for testing)
$ sdkmanager "emulator"
# Install system images for testing (choose your target API levels)
$ sdkmanager "system-images;android-30;google_apis;x86_64"
$ sdkmanager "system-images;android-34;google_apis;x86_64"
Android NDK Installation
The Android NDK (Native Development Kit) is required for building native Rust code for Android.
Method 1: Through Android Studio
- Open Android Studio
- Go to Tools → SDK Manager → SDK Tools
- Check "NDK (Side by side)" and install
Method 2: Command Line Installation
# Install specific NDK version
$ sdkmanager "ndk;26.1.10909125" # Latest stable version
# or
$ sdkmanager "ndk;25.2.9519653" # Alternative stable version
Method 3: Direct Download
Download from the NDK Downloads page and extract manually.
Environment Setup
Set up environment variables in your shell profile (.bashrc
, .zshrc
, etc.):
# Android SDK
export ANDROID_HOME=$HOME/Android/Sdk # Linux
# export ANDROID_HOME=$HOME/Library/Android/sdk # macOS
# Android NDK
export ANDROID_NDK_ROOT=$ANDROID_HOME/ndk/26.1.10909125
export NDK_HOME=$ANDROID_NDK_ROOT
# Add tools to PATH
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/emulator
Rust Toolchain Setup
Install cargo-ndk
$ cargo install cargo-ndk --version "^3.0"
Add Android targets
$ rustup target add aarch64-linux-android
$ rustup target add x86_64-linux-android
$ rustup target add armv7-linux-androideabi
$ rustup target add i686-linux-android
Building rsbinder for Android
Basic Build Commands
# Build for ARM64 (most common for modern Android devices)
$ cargo ndk -t aarch64-linux-android build --release
# Build for x86_64 (emulator)
$ cargo ndk -t x86_64-linux-android build --release
# Build all targets
$ cargo ndk -t aarch64-linux-android -t x86_64-linux-android build --release
Using envsetup.sh Helper Scripts
The rsbinder project provides a comprehensive envsetup.sh
script with helpful functions for Android development:
# Source the environment setup
$ source ./envsetup.sh
Available Functions
ndk_prepare
: Sets up the Android device for testing
- Roots the device using
adb root
- Creates the remote directory on the device (
/data/rsbinder
by default) - Prepares the environment for file synchronization
$ ndk_prepare
ndk_build
: Builds the project for Android
- Reads configuration from
REMOTE_ANDROID
file - Builds both release binaries and test executables
- Uses
cargo ndk
with the specified target architecture
$ ndk_build
ndk_sync
: Synchronizes built binaries to Android device
- Pushes all executable files to the device
- Uses
adb push
to transfer files to the remote directory - Automatically detects executable files in the target directory
$ ndk_sync
Configuration File: REMOTE_ANDROID
Create a REMOTE_ANDROID
file in the project root to configure your Android target:
# Example REMOTE_ANDROID file
arm64-v8a # cargo-ndk target
aarch64 # rust target architecture
/data/rsbinder # remote directory on device
Common target configurations:
# For ARM64 devices (most modern Android phones)
arm64-v8a
aarch64
/data/rsbinder
# For x86_64 emulator
x86_64
x86_64
/data/rsbinder
Testing on Android
Device Setup
- Enable Developer Options on your Android device
- Enable USB Debugging
- Connect device via USB and authorize debugging
Running Tests
# Complete build and test workflow
$ source ./envsetup.sh
$ ndk_prepare # Set up device
$ ndk_build # Build binaries and tests
$ ndk_sync # Push to device
# Test executables will be available in /data/rsbinder/
Emulator Testing
# Create and start an emulator
$ avdmanager create avd -n test_device -k "system-images;android-34;google_apis;x86_64"
$ emulator -avd test_device
# Build for emulator target
$ cargo ndk -t x86_64-linux-android build --release
Troubleshooting
Common Issues
"adb not found": Ensure platform-tools is installed and in PATH
"cargo-ndk not found": Install with cargo install cargo-ndk
"No targets specified": Add Android targets with rustup target add
"Permission denied on device": Run adb root
or check device permissions
Verification Commands
# Check SDK installation
$ sdkmanager --list_installed
# Check connected devices
$ adb devices
# Check available targets
$ rustup target list | grep android
# Test cargo-ndk installation
$ cargo ndk --version