Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated document for rsbinder 0.2.0 #1

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# Summary
# **Rsbinder** Development Guide

- [Chapter 1](./chapter_1.md)
**rsbinder** provides crates implemented in pure Rust that make Binder IPC available on both Android and Linux.

- [Overview](./overview.md)
- [Architecture](./architecture.md)
- [Getting Started](./getting-started.md)
- [Installation](./installation.md)
- [Hello, World!](./hello-world.md)
- [Enable binder for Linux](./enable-binder-for-linux.md)
- [Arch Linux](./arch-linux.md)
- [TODO: Ubuntu Linux]()
- [TODO: Redhat Linux]()
10 changes: 10 additions & 0 deletions src/arch-linux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Enable Binder IPC on Arch Linux

Let's install the linux-zen kernel provided by Arch Linux. Zen kernel already includes Binder IPC.
```
$ pacman -S linux-zen
```

For detailed instructions on installing a new kernel in Arch Linux, refer to the following URL.

[https://wiki.archlinux.org/title/kernel](https://wiki.archlinux.org/title/kernel)
38 changes: 38 additions & 0 deletions src/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Architecture

```mermaid
---
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
- The Android Interface Definition Language (AIDL) is a tool that lets users abstract away IPC. Given an interface (specified in a .aidl file), various build systems use the **rsbinder-aidl** crate to construct Rust bindings so that this interface can be used across processes, regardless of the runtime or bitness there.
- [https://source.android.com/docs/core/architecture/aidl](https://source.android.com/docs/core/architecture/aidl)
- Your Binder Service
- Include the Rust code generated from AIDL to create your service.
- Use rsbinder::hub to register your service with the HUB and wait for client requests.
- Binder Client
- Use the Rust code generated from AIDL to communicate with the service.
- Query the HUB to check if the required service is available and receive a Binder Object (rsbinder::SIBinder) for the service.
- Use the Binder Object to communicate with the Binder Service.
- HUB(Service Manager)
- rsbinder provides **rsb_hub**, a service manager for Linux.
- On Android, no additional work is required since the Android service manager is already running.

1 change: 0 additions & 1 deletion src/chapter_1.md

This file was deleted.

12 changes: 12 additions & 0 deletions src/enable-binder-for-linux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 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.
5 changes: 5 additions & 0 deletions src/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Getting Started
If you are new to Binder IPC,
read the [Architecture](./architecture.md) document first.

The Architecture document provides a comprehensive overview of Binder IPC, including its design, implementation, and usage. It will help you understand the basics of Binder IPC before you start using **rsbinder**.
170 changes: 170 additions & 0 deletions src/hello-world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# 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.2.0"
lazy_static = "1"
async-trait = "0.1"
env_logger = "0.11"

[build-dependencies]
rsbinder-aidl = "0.2.0"

```
Add rsbinder, lazy_static, and async-trait to [dependencies], and add rsbinder-aidl to [build-dependencies].

## Create a AIDL File
Create an aidl folder in the project's top directory to manage AIDL files:
```
$ mkdir -p aidl/hello
$ touch IHello.aidl
```
The reason for creating an additional **hello** folder is to create a space for the **hello** package.

Create an 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](https://source.android.com/docs/core/architecture/aidl).

## Create the build.rs
Create a build.rs file 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.

## 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.
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.
ProcessState::start_thread_pool();

// Create a binder service.
let service = BnHello::new_binder(IHelloService{});

// Add the service to binder service manager.
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::*;

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();

// Create a Hello proxy from binder service manager.
let hello: rsbinder::Strong<dyn IHello> = hub::get_interface(SERVICE_NAME)
.expect(&format!("Can't find {SERVICE_NAME}"));

// Call echo method of Hello proxy.
println!("Result: {}", hello.echo("Hello World!")?);

Ok(())
}
```

## Project folder and file structure
```
.
├── Cargo.toml
├── aidl
│   └── hello
│   └── IHello.aidl
├── build.rs
└── src
├── bin
│   ├── hello_client.rs
│   └── hello_service.rs
└── lib.rs
```
18 changes: 18 additions & 0 deletions src/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Installation
Add the following configuration to your Cargo.toml file:

```
[dependencies]
rsbinder = "0.2.0"
lazy_static = "1"
async-trait = "0.1"

[build-dependencies]
rsbinder-aidl = "0.2.0"
```

The crates purposes:
- **rsbinder**: This library provides various functionalities for Binder IPC, including communication with the Linux kernel and data serialization/deserialization.
- **lazy_static**: The code generated by the **rsbinder-aidl** compiler depends on the lazy_static crate.
- **async-trait**: The code generated by **rsbinder-aidl** creates both sync and async code. The async code depends on the async-trait crate.
- **rsbinder-aidl**: This is used for AIDL compilation and is invoked in build.rs.
17 changes: 17 additions & 0 deletions src/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Overview
Welcome to **rsbinder**!

**rsbinder** is a Rust library and toolset that enables you to utilize Binder IPC on Linux and Android OS.

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.

### 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.
- 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.

Before using Binder IPC, you must enable the feature in the kernel. Please refer to [Enable binder for Linux](./ch02-00-enable-binder-for-linux.md) for detailed instructions on setting it up.
Empty file added src/redhat-linux.md
Empty file.
Empty file added src/ubuntu-linux.md
Empty file.
Loading