# Android Platform Binder Codelab

go/android-binder-codelab

This Android Platform Developer codelab explores the use of Binder in the
Android Platform. go/android-codelab is a prerequisite for this work. In this
codelab, you create an AIDL interface along with client and server processes
that communicate with each other over Binder.

## Goals

There are four goals for this codelab:

1.  Introduce you to Binder, Android's core IPC mechanism
2.  Use AIDL to define a Binder interface for a simple client/server interaction
3.  Use Binder's Service Management infrastructure to make the service available
    to clients
4.  Get and use the service with basic error handling

## What to expect

### Estimated time

*   Hands-off time ~4 hours
*   Hands-on time ~1 hours

### Prerequisites

**Before** taking this codelab, complete go/android-codelab first. If external,
follow https://source.android.com/docs/setup/start.

You will need an Android repo with the ability to make changes, build, deploy,
test, and upload the changes. All of this is covered in go/android-codelab.

See the slides at go/onboarding-binder for a summary of key concepts that will
help you understand the steps in this codelab.

## Codelab

Most of this code can be found in `system/tools/aidl/codelab`, but the example
service isn't installed on real devices. The build code to install the service
on the device and the sepolicy changes are described in this `README.md` but not
submitted.

### Create the new AIDL interface

Choose a location for the AIDL interface definition.

*   `hardware/interfaces` - for
    [HAL](https://source.android.com/docs/core/architecture/hal) interfaces that
    device-specific processes implement and the Android Platform depends on as a
    client
*   `frameworks/hardware/interfaces` - for interfaces that the Android Framework
    implements for device-specific clients
*   `system/hardware/interfaces` - for interfaces that Android system process
    implement for device-specific clients
*   Any other directory for interfaces that are used between processes that are
    installed on the same
    [partitions](https://source.android.com/docs/core/architecture/partitions)

Create a new `aidl_interface` module in a new or existing `Android.bp` file.

Note: go/android.bp has all of the available Soong modules and their supported
fields.

```soong
// File: `system/tools/aidl/codelab/aidl/Android.bp`
aidl_interface {
  // Package name for the interface. This is used when generating the libraries
  // that the services and clients will depend on.
  name: "hello.world",
  // The source `.aidl` files that define this interface. It is recommended to
  // create them in a directory next to this Android.bp file with a
  // directory structure that follows the package name. If you want to change
  // this, use `local_include_dir` to point to the new directory.
  srcs: [
    "hello/world/*.aidl",
  ],
  // For simplicity we start with an unstable interface. See
  // https://source.android.com/docs/core/architecture/aidl/stable-aidl
  // for details on stable interfaces.
  unstable: true,
  // This field controls which libraries are generated at build time and their
  // backend-specific configurations. AIDL supports different languages.
  backend: {
    ndk: {
      enabled: true,
    }
    rust: {
      enabled: true,
    }
  }
}
```

Create your first AIDL file.

```java
// File: `system/tools/aidl/codelab/aidl/hello/world/IHello.aidl`
// The package name is recommended to match the `name` in the `aidl_interface`
package hello.world;

interface IHello {
  // Have the service log a message for us
  void LogMessage(String message);
  // Get a "hello world" message from the service
  String getMessage();
}
```

Build the generated AIDL libraries.

```shell
m hello.world-ndk hello.world-rust
```

Note: `m hello.world` without the backend suffix will not build anything.

### Create the service

Android encourages Rust for native services so let's build a Rust service!

Binder has easy-to-use libraries to facilitate fuzzing of binder services that
require the service being defined in its own library. With that in mind, we
create the library that implements the interface first.

#### Interface implementation

Create a separate library for the interface implementation so it can be used
for the service and for the fuzzer.

* See [service/Android.bp](service/Android.bp)

* See [service/hello_service.rs](service/hello_service.rs)

#### Service binary

Create the service that registers itself with servicemanager and joins the
binder threadpool.

* See [service/Android.bp](service/Android.bp)

* See [service/service_main.rs](service/service_main.rs)

An init.rc file is required for the process to be started on a device.

* See
  [service/hello-world-service-test.rc](service/hello-world-service-test.rc)

#### Sepolicy for the service

Associate the service binary with a selinux context so init can start it.
```
// File: system/sepolicy/private/file_contexts
/system/bin/hello-world-service-test u:object_r:hello_exec:s0
```

Add a file for the service to define its types, associate the binary to the
types, and give permissions to the service..
```
// File: system/sepolicy/private/hello.te

// Permissions required for the process to start
type hello, domain;
typeattribute hello coredomain;
type hello_exec, system_file_type, exec_type, file_type;
init_daemon_domain(hello)

// Permissions to be a binder service and talk to service_manager
binder_service(hello)
binder_use(hello)
binder_call(hello, binderservicedomain)

// Give permissions to this service to register itself with service_manager
allow hello hello_service:service_manager { add find };
```

Declare this service as a service_manager_type
```
// File: system/sepolicy/public/service.te
type hello_service,             service_manager_type;
```

Associate the AIDL interface/instance with this service
```
// File: system/sepolicy/private/service_contexts
hello.world.IHello/default u:object_r:hello_service:s0
```

#### Fuzzer

Create the fuzzer and use `fuzz_service` to do all of the hard work!

* See [service/Android.bp](service/Android.bp)

* See [service/service_fuzzer.rs](service/service_fuzzer.rs)

Associate the fuzzer with the interface by adding the following to
`system/sepolicy/build/soong/service_fuzzer_bindings.go`:
```
"hello.world.IHello/default":             []string{"hello-world-fuzzer"},
```
This step is required by the build system once we add the sepolicy for the
service in the previous step.

### Create the client

#### Sepolicy for the client

We skip these details by creating the client in a `cc_test`.

The clients need permission to `find` the service through servicemanager:

`allow <client> hello_service:servicemanager find;`

The clients need permission to `call` the service, pass the binders to other
processes, and use any file descriptors returned through the interface. The
`binder_call` macro handles all this for us.

`binder_call(<client>, hello_service);`

### Test the changes

Add the service to the device. Since this is a system service it needs to be
added to the system partition. We add the following to
`build/make/target/product/base_system.mk`.

```
PRODUCT_PACKAGES += hello-world-service-test
```

Build the device.

Launch the device.

Verify the service is in the `dumpsys -l` output.

`atest hello-world-client-test` and verify it passes!

## Wrap up

Congratulations! You are now familiar with some core concepts of Binder and AIDL
in Android.
When you think of IPC in Android, think of Binder.
When you think of Binder, think of AIDL.

See https://source.android.com/docs/core/architecture/aidl for related AIDL and
Binder documentation.
Check out https://source.android.com/docs/core/architecture/aidl/aidl-hals for
details that are more specific to Hardware Abstraction Layer (HAL) services.

### Supporting documentation

*   go/onboarding-binder
*   go/binder-ipc
*   go/stable-aidl
*   go/aidl-backends
*   go/aidl (for app developers with Java/Kotlin)

See all of the other AIDL related pages in our external documentation:
https://source.android.com/docs/core/architecture/aidl.

### Feedback

If you are external please see
https://source.android.com/docs/setup/contribute/report-bugs to find out how to
create a Bug for questions, suggestions, or reporting bugs.

Please write to android-idl-discuss@google.com.

Anyone is free to create and upload CLs in `system/tools/aidl/codelab/` with any
suggestions or corrections.

### Wish list

Add your suggested additions and updates to this codelab here!

1.  I wish this codelab would dive deeper into `DeathRecipients` and remote
    reference counting

