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 11 The _aidl generator_ is a command line tool that generates client and server 12 stubs for Binder interfaces from a specification in a file with the .aidl 13 extension. For Java interfaces, the executable is called `aidl` while for C++ 14 the binary is called `aidl-cpp`. In this document, well use AIDL to describe 15 the language of .aidl files and _aidl generator_ to refer to the code generation 16 tool that takes an .aidl file, parses the AIDL, and outputs code. 17 18 Previously, the _aidl generator_ only generated Java interface/stub/proxy 19 objects. C++ Binder interfaces were handcrafted with various degrees of 20 compatibility with the Java equivalents. The Brillo project added support for 21 generating C++ with the _aidl generator_. This generated C++ is cross-language 22 compatible (e.g. Java clients are tested to interoperate with native services). 23 24 ## Overview 25 26 This 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 39 Write AIDL in .aidl files and add them to `LOCAL_SRC_FILES` in your Android.mk. 40 If your build target is a binary (e.g. you include `$(BUILD_SHARED_LIBRARY)`), 41 then the generated code will be C++, not Java. 42 43 AIDL definitions should be hosted from the same repository as the 44 implementation. Any system that needs the definition will also need the 45 implementation (for both parcelables and interface). If there are multiple 46 implementations (i.e. one in Java and one in C++), keep the definition with the 47 native implementation. Android 48 [now has systems](https://developers.google.com/brillo/?hl=en) that run the 49 native components of the system without the Java. 50 51 If you use an import statement in your AIDL, even from the same package, you 52 need to add a path to `LOCAL_AIDL_INCLUDES`. This path should be relative to 53 the root of the Android tree. For instance, a file IFoo.aidl defining 54 com.example.IFoo might sit in a folder hierarchy 55 something/something-else/com/example/IFoo.aidl. Then we would write: 56 57 ``` 58 LOCAL_AIDL_INCLUDES := something/something-else 59 ``` 60 61 Generated C++ ends up in nested namespaces corresponding to the interfaces 62 package. The generated header also corresponds to the interface package. So 63 com.example.IFoo becomes ::com::example::IFoo in header com/example/IFoo.h. 64 65 Similar to how Java works, the suffix of the path to a .aidl file must match 66 the package. So if IFoo.aidl declares itself to be in package com.example, the 67 folder structure (as given to `LOCAL_SRC_FILES`) must look like: 68 `some/prefix/com/example/IFoo.aidl`. 69 70 To generate code from .aidl files from another build target (e.g. another 71 binary 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 73 in other directory hierarchies: add the include root path relative to the 74 checkout root to `LOCAL_AIDL_INCLUDES`. 75 76 ### Type Mapping 77 78 The following table summarizes the equivalent C++ types for common Java types 79 and whether those types may be used as in/out/inout parameters in AIDL 80 interfaces. 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 102 Note that annotations may be placed at the interface level, as well as on a 103 type by type basis. Interface level annotations will be applied 104 opportunistically and be overridden by per type annotations. For instance, an 105 interface marked @nullable will still not allow null int parameters. 106 107 ### Implementing a generated interface 108 109 Given an interface declaration like: 110 111 ``` 112 package foo; 113 114 import bar.IAnotherInterface; 115 116 interface IFoo { 117 IAnotherInterface DoSomething(int count, out List<String> output); 118 } 119 ``` 120 121 `aidl-cpp` will generate a C++ interface: 122 123 ``` 124 namespace 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. 133 class 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 142 Note that `aidl-cpp` will import headers for types used in the interface. For 143 imported types (e.g. parcelables and interfaces), it will import a header 144 corresponding 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 148 When writing a service that implements this interface, write: 149 150 ``` 151 #include "foo/BnFoo.h" 152 153 namespace unrelated_namespace { 154 155 class 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 172 Note that the output values, `output` and `returned_value` are passed by 173 pointer, and that this pointer is always valid. 174 175 #### Dependencies 176 177 The generated C++ code will use symbols from libbinder as well as libutils. 178 AIDL files using the FileDescriptor type will also explicitly require 179 libnativehelper, although this is likely a transitive dependency of the other 180 two, and should be included automatically within the Android build tree 181 regardless. 182 183 ### C++ Parcelables 184 185 In Java, a parcelable should extend android.os.Parcelable and provide a static 186 final CREATOR field that acts as a factory for new instances/arrays of 187 instances of the parcelable. In addition, in order to be used as an out 188 parameter, a parcelable class must define a readFromParcel method. 189 190 In C++, parcelables must implement android::Parcelable from binder/Parcelable.h 191 in libbinder. Parcelables must define a constructor that takes no arguments. 192 In order to be used in arrays, a parcelable must implement a copy or move 193 constructor (called implicitly in vector). 194 195 The C++ generator needs to know what header defines the C++ parcelable. It 196 learns this from the `cpp_header` directive shown below. The generator takes 197 this string and uses it as the literal include statement in generated code. 198 The idea here is that you generate your code once, link it into a library along 199 with parcelable implementations, and export appropriate header paths. This 200 header include must make sense in the context of the Android.mk that compiles 201 this generated code. 202 203 ``` 204 // ExampleParcelable.aidl 205 package 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 212 parcelable ExampleParcelable cpp_header "bar/foo.h"; 213 ``` 214 215 ### Null Reference Handling 216 217 The aidl generator for both C++ and Java languages has been expanded to 218 understand nullable annotations. 219 220 Given an interface definition like: 221 222 ``` 223 interface IExample { 224 void ReadStrings(String neverNull, in @nullable String maybeNull); 225 }; 226 ``` 227 228 the generated C++ header code looks like: 229 230 ``` 231 class IExample { 232 android::binder::Status ReadStrings( 233 const android::String16& in_neverNull, 234 const std::unique_ptr<android::String16>& in_maybeNull); 235 }; 236 ``` 237 238 Note that by default, the generated C++ passes a const reference to the value 239 of a parameter and rejects null references with a NullPointerException sent 240 back the caller. Parameters marked with @nullable are passed by pointer, 241 allowing native services to explicitly control whether they allow method 242 overloading via null parameters. Java stubs and proxies currently do nothing 243 with the @nullable annotation. 244 245 Consider an AIDL type `in @nullable List<String> bar`. This type 246 indicates that the remote caller may pass in a list of strings, and that both 247 the list and any string in the list may be null. This type will map to a C++ 248 type `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 257 C++ methods generated by the aidl generator return `android::binder::Status` 258 objects, rather than `android::status_t`. This Status object allows generated 259 C++ code to send and receive exceptions (an exception type and a String16 error 260 message) since we do not use real exceptions in C++. More background on Status 261 objects can be found here. 262 263 For legacy support and migration ease, the Status object includes a mechanism 264 to report a `android::status_t`. However, that return code is interpreted by a 265 different code path and does not include a helpful String message. 266 267 For situations where your native service needs to throw an error code specific 268 to the service, use `Status::fromServiceSpecificError()`. This kind of 269 exception comes with a helpful message and an integer error code. Make your 270 error codes consistent across services by using interface constants (see 271 below). 272