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 - implementing a generated interface 31 - C++ parcelables 32 - cross-language error reporting 33 - cross-language null reference handling 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| @utf8InCpp String | std::string | in | @utf8InCpp causes UTF16 to UTF8 conversion in C++. | 93| android.os.Parcelable | android::Parcelable | inout | | 94| java.util.Map | android::binder::Map| inout | `std::map<std::string,android::binder::Value>` | 95| T extends IBinder | sp<T> | in | | 96| Arrays (T[]) | vector<T> | inout | May contain only primitives, Strings and parcelables. | 97| List<String> | vector<String16> | inout | | 98| PersistableBundle | PersistableBundle | inout | binder/PersistableBundle.h | 99| List<IBinder> | vector<sp<IBinder>> | inout | | 100| FileDescriptor | unique_fd | inout | android-base/unique_fd.h from libbase | 101 102Note that annotations may be placed at the interface level, as well as on a 103type by type basis. Interface level annotations will be applied 104opportunistically and be overridden by per type annotations. For instance, an 105interface marked @nullable will still not allow null int parameters. 106 107### Implementing a generated interface 108 109Given an interface declaration like: 110 111``` 112package foo; 113 114import bar.IAnotherInterface; 115 116interface IFoo { 117 IAnotherInterface DoSomething(int count, out List<String> output); 118} 119``` 120 121`aidl-cpp` will generate a C++ interface: 122 123``` 124namespace foo { 125 126// Some headers have been omitted for clarity. 127#include <android/String16.h> 128#include <cstdint> 129#include <vector> 130#include <bar/IAnotherInterface.h> 131 132// Some class members have been omitted for clarity. 133class IFoo : public android::IInterface { 134 public: 135 virtual android::binder::Status DoSomething( 136 int32_t count, 137 std::vector<android::String16>* output, 138 android::sp<bar::IAnotherInterface>* returned_value) = 0; 139}; 140``` 141 142Note that `aidl-cpp` will import headers for types used in the interface. For 143imported types (e.g. parcelables and interfaces), it will import a header 144corresponding to the package/class name of the import. For instance, 145`import bar.IAnotherInterface` causes aidl-cpp to generate 146`#include <bar/IAnotherInterface.h>`. 147 148When writing a service that implements this interface, write: 149 150``` 151#include "foo/BnFoo.h" 152 153namespace unrelated_namespace { 154 155class MyFoo : public foo::BnFoo { 156 public: 157 android::binder::Status DoSomething( 158 int32_t count, 159 std::vector<android::String16>* output, 160 android::sp<bar::IAnotherInterface>* returned_value) override { 161 for (int32_t i = 0; i < count; ++i) { 162 output->push_back(String16("...")); 163 } 164 *returned_value = new InstanceOfAnotherInterface; 165 return Status::ok(); 166 } 167}; // class MyFoo 168 169} // namespace unrelated_namespace 170``` 171 172Note that the output values, `output` and `returned_value` are passed by 173pointer, and that this pointer is always valid. 174 175#### Dependencies 176 177The generated C++ code will use symbols from libbinder as well as libutils. 178AIDL files using the FileDescriptor type will also explicitly require 179libnativehelper, although this is likely a transitive dependency of the other 180two, and should be included automatically within the Android build tree 181regardless. 182 183### C++ Parcelables 184 185In Java, a parcelable should extend android.os.Parcelable and provide a static 186final CREATOR field that acts as a factory for new instances/arrays of 187instances of the parcelable. In addition, in order to be used as an out 188parameter, a parcelable class must define a readFromParcel method. 189 190In C++, parcelables must implement android::Parcelable from binder/Parcelable.h 191in libbinder. Parcelables must define a constructor that takes no arguments. 192In order to be used in arrays, a parcelable must implement a copy or move 193constructor (called implicitly in vector). 194 195The C++ generator needs to know what header defines the C++ parcelable. It 196learns this from the `cpp_header` directive shown below. The generator takes 197this string and uses it as the literal include statement in generated code. 198The idea here is that you generate your code once, link it into a library along 199with parcelable implementations, and export appropriate header paths. This 200header include must make sense in the context of the Android.mk that compiles 201this generated code. 202 203``` 204// ExampleParcelable.aidl 205package com.example.android; 206 207// Native types must be aliased at their declaration in the appropriate .aidl 208// file. This allows multiple interfaces to use a parcelable and its C++ 209// equivalent without duplicating the mapping between the C++ and Java types. 210// Generator will assume bar/foo.h declares class 211// com::example::android::ExampleParcelable 212parcelable ExampleParcelable cpp_header "bar/foo.h"; 213``` 214 215### Null Reference Handling 216 217The aidl generator for both C++ and Java languages has been expanded to 218understand nullable annotations. 219 220Given an interface definition like: 221 222``` 223interface IExample { 224 void ReadStrings(String neverNull, in @nullable String maybeNull); 225}; 226``` 227 228the generated C++ header code looks like: 229 230``` 231class IExample { 232 android::binder::Status ReadStrings( 233 const android::String16& in_neverNull, 234 const std::unique_ptr<android::String16>& in_maybeNull); 235}; 236``` 237 238Note that by default, the generated C++ passes a const reference to the value 239of a parameter and rejects null references with a NullPointerException sent 240back the caller. Parameters marked with @nullable are passed by pointer, 241allowing native services to explicitly control whether they allow method 242overloading via null parameters. Java stubs and proxies currently do nothing 243with the @nullable annotation. 244 245Consider an AIDL type `in @nullable List<String> bar`. This type 246indicates that the remote caller may pass in a list of strings, and that both 247the list and any string in the list may be null. This type will map to a C++ 248type `unique_ptr<vector<unique_ptr<String16>>>* bar`. In this case: 249 250 - `bar` is never null 251 - `*bar` might be null 252 - `(*bar)->empty()` could be true 253 - `(**bar)[0]` could be null (and so on) 254 255### Exception Reporting 256 257C++ methods generated by the aidl generator return `android::binder::Status` 258objects, rather than `android::status_t`. This Status object allows generated 259C++ code to send and receive exceptions (an exception type and a String16 error 260message) since we do not use real exceptions in C++. More background on Status 261objects can be found here. 262 263For legacy support and migration ease, the Status object includes a mechanism 264to report a `android::status_t`. However, that return code is interpreted by a 265different code path and does not include a helpful String message. 266 267For situations where your native service needs to throw an error code specific 268to the service, use `Status::fromServiceSpecificError()`. This kind of 269exception comes with a helpful message and an integer error code. Make your 270error codes consistent across services by using interface constants (see 271below). 272