Home | History | Annotate | Download | only in docs
      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