• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Generating C++ Binder Interfaces with `aidl-cpp`
2
3## Background
4
5“aidl” refers to several related but distinct concepts:
6
7 - the AIDL interface [definition language](http://developer.android.com/guide/components/aidl.html)
8 - .aidl files (which contain AIDL)
9 - the aidl generator which transforms AIDL into client/server IPC interfaces
10
11The _aidl generator_ is a command line tool that generates client and server
12stubs for Binder interfaces from a specification in a file with the .aidl
13extension.  For Java interfaces, the executable is called `aidl` while for C++
14the binary is called `aidl-cpp`.  In this document, we’ll use AIDL to describe
15the language of .aidl files and _aidl generator_ to refer to the code generation
16tool that takes an .aidl file, parses the AIDL, and outputs code.
17
18Previously, the _aidl generator_ only generated Java interface/stub/proxy
19objects.  C++ Binder interfaces were handcrafted with various degrees of
20compatibility with the Java equivalents.  The Brillo project added support for
21generating C++ with the _aidl generator_.  This generated C++ is cross-language
22compatible (e.g. Java clients are tested to interoperate with native services).
23
24## Overview
25
26This document describes how C++ generation works with attention to:
27
28 - build interface
29 - cross-language type mapping
30 - C++ parcelables
31 - cross-language error reporting
32 - cross-language null reference handling
33 - cross-language integer constants
34
35## Detailed Design
36
37### Build Interface
38
39Write AIDL in .aidl files and add them to `LOCAL_SRC_FILES` in your Android.mk.
40If your build target is a binary (e.g. you include `$(BUILD_SHARED_LIBRARY)`),
41then the generated code will be C++, not Java.
42
43AIDL definitions should be hosted from the same repository as the
44implementation.  Any system that needs the definition will also need the
45implementation (for both parcelables and interface).  If there are multiple
46implementations (i.e. one in Java and one in C++), keep the definition with the
47native implementation.  Android
48[now has systems](https://developers.google.com/brillo/?hl=en) that run the
49native components of the system without the Java.
50
51If you use an import statement in your AIDL, even from the same package, you
52need to add a path to `LOCAL_AIDL_INCLUDES`.  This path should be relative to
53the root of the Android tree.  For instance, a file IFoo.aidl defining
54com.example.IFoo might sit in a folder hierarchy
55something/something-else/com/example/IFoo.aidl.  Then we would write:
56
57```
58LOCAL_AIDL_INCLUDES := something/something-else
59```
60
61Generated C++ ends up in nested namespaces corresponding to the interface’s
62package.  The generated header also corresponds to the interface package.  So
63com.example.IFoo becomes ::com::example::IFoo in header “com/example/IFoo.h”.
64
65Similar to how Java works, the suffix of the path to a .aidl file must match
66the package.  So if IFoo.aidl declares itself to be in package com.example, the
67folder structure (as given to `LOCAL_SRC_FILES`) must look like:
68`some/prefix/com/example/IFoo.aidl`.
69
70To generate code from .aidl files from another build target (e.g. another
71binary or java), just add a relative path to the .aidl files to
72`LOCAL_SRC_FILES`.  Remember that importing AIDL works the same, even for code
73in other directory hierarchies: add the include root path relative to the
74checkout root to `LOCAL_AIDL_INCLUDES`.
75
76### Type Mapping
77
78The following table summarizes the equivalent C++ types for common Java types
79and whether those types may be used as in/out/inout parameters in AIDL
80interfaces.
81
82| Java Type             | C++ Type            | inout | Notes                                                 |
83|-----------------------|---------------------|-------|-------------------------------------------------------|
84| boolean               | bool                | in    | "These 8 types are all considered primitives.         |
85| byte                  | int8\_t             | in    |                                                       |
86| char                  | char16\_t           | in    |                                                       |
87| int                   | int32\_t            | in    |                                                       |
88| long                  | int64\_t            | in    |                                                       |
89| float                 | float               | in    |                                                       |
90| double                | double              | in    |                                                       |
91| String                | String16            | in    | Supports null references.                             |
92| android.os.Parcelable | android::Parcelable | inout |                                                       |
93| T extends IBinder     | sp<T>               | in    |                                                       |
94| Arrays (T[])          | vector<T>           | inout | May contain only primitives, Strings and parcelables. |
95| List<String>          | vector<String16>    | inout |                                                       |
96| PersistableBundle     | PersistableBundle   | inout | binder/PersistableBundle.h                            |
97| List<IBinder>         | vector<sp<IBinder>> | inout |                                                       |
98| FileDescriptor        | ScopedFd            | inout | nativehelper/ScopedFd.h                               |
99
100Note that java.util.Map and java.utils.List are not good candidates for cross
101language communication because they may contain arbitrary types on the Java
102side.  For instance, Map is cast to Map<String,Object> and then the object
103values dynamically inspected and serialized as type/value pairs.  Support
104exists for sending arbitrary Java serializables, Android Bundles, etc.
105
106### C++ Parcelables
107
108In Java, a parcelable should extend android.os.Parcelable and provide a static
109final CREATOR field that acts as a factory for new instances/arrays of
110instances of the parcelable.  In addition, in order to be used as an out
111parameter, a parcelable class must define a readFromParcel method.
112
113In C++, parcelables must implement android::Parcelable from binder/Parcelable.h
114in libbinder.  Parcelables must define a constructor that takes no arguments.
115In order to be used in arrays, a parcelable must implement a copy or move
116constructor (called implicitly in vector).
117
118The C++ generator needs to know what header defines the C++ parcelable.  It
119learns this from the `cpp_header` directive shown below.  The generator takes
120this string and uses it as the literal include statement in generated code.
121The idea here is that you generate your code once, link it into a library along
122with parcelable implementations, and export appropriate header paths.  This
123header include must make sense in the context of the Android.mk that compiles
124this generated code.
125
126```
127// ExampleParcelable.aidl
128package com.example.android;
129
130// Native types must be aliased at their declaration in the appropriate .aidl
131// file.  This allows multiple interfaces to use a parcelable and its C++
132// equivalent without duplicating the mapping between the C++ and Java types.
133// Generator will assume bar/foo.h declares class
134// com::example::android::ExampleParcelable
135parcelable ExampleParcelable cpp_header "bar/foo.h";
136```
137
138### Null Reference Handling
139
140The aidl generator for both C++ and Java languages has been expanded to
141understand nullable annotations.
142
143Given an interface definition like:
144
145```
146interface IExample {
147  void ReadStrings(String neverNull, in @nullable String maybeNull);
148};
149```
150
151the generated C++ header code looks like:
152
153```
154class IExample {
155  android::binder::Status ReadStrings(
156      const android::String16& in_neverNull,
157      const std::unique_ptr<android::String16>& in_maybeNull);
158};
159```
160
161Note that by default, the generated C++ passes a const reference to the value
162of a parameter and rejects null references with a NullPointerException sent
163back the caller.  Parameters marked with @nullable are passed by pointer,
164allowing native services to explicitly control whether they allow method
165overloading via null parameters.  Java stubs and proxies currently do nothing
166with the @nullable annotation.
167
168### Exception Reporting
169
170C++ methods generated by the aidl generator return `android::binder::Status`
171objects, rather than `android::status_t`.  This Status object allows generated
172C++ code to send and receive exceptions (an exception type and a String16 error
173message) since we do not use real exceptions in C++.  More background on Status
174objects can be found here.
175
176For legacy support and migration ease, the Status object includes a mechanism
177to report a `android::status_t`.  However, that return code is interpreted by a
178different code path and does not include a helpful String message.
179
180For situations where your native service needs to throw an error code specific
181to the service, use `Status::fromServiceSpecificError()`.  This kind of
182exception comes with a helpful message and an integer error code.  Make your
183error codes consistent across services by using interface constants (see
184below).
185
186### Integer Constants
187
188AIDL has been enhanced to support defining integer constants as part of an
189interface:
190
191```
192interface IMyInterface {
193    const int CONST_A = 1;
194    const int CONST_B = 2;
195    const int CONST_C = 3;
196    ...
197}
198```
199
200These map to appropriate 32 bit integer class constants in Java and C++ (e.g.
201`IMyInterface.CONST_A` and `IMyInterface::CONST_A` respectively).
202