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