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:

  1. 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
  2. Installation - Set up your development environment

    • Install required dependencies
    • Set up binder devices and service manager
    • Configure your Rust project
  3. Hello World - Build your first Binder service

    • Create a simple echo service
    • Learn AIDL basics
    • Understand service registration and client communication
  4. Platform-specific Setup - Choose your target platform:

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

  1. Define your service interface in an .aidl file
  2. Use rsbinder-aidl to generate Rust code
  3. Implement your service logic
  4. Register the service with the service manager
  5. 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 support
  • sync: Synchronous-only operations
  • async: Async support without tokio runtime
  • android_*: 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:

  1. "Can't find my.hello" - Ensure the service is running and registered
  2. Permission errors - Check that binder device has correct permissions (0666)
  3. Service manager not found - Verify rsb_hub is running
  4. 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

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:

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:

  1. Module not found: Ensure the anbox-modules-dkms package is properly installed
  2. Permission denied: Make sure you're using sudo for device creation
  3. 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

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:

  1. Module compilation fails: Ensure all kernel-devel packages match your running kernel
  2. SELinux denials: Check audit.log for SELinux denials and create appropriate policies
  3. 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 16
  • android_12_plus: Supports Android 12 through 16
  • android_13_plus: Supports Android 13 through 16
  • android_14_plus: Supports Android 14 through 16
  • android_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.

Download and install Android Studio, which includes the Android SDK:

Method 2: Command Line Tools Only

If you prefer a minimal installation:

  1. Download Command Line Tools from Android Developer Downloads
  2. 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

  1. Enable Developer Options on your Android device
  2. Enable USB Debugging
  3. 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