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  - 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 
     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 | 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 
    100 Note that java.util.Map and java.utils.List are not good candidates for cross
    101 language communication because they may contain arbitrary types on the Java
    102 side.  For instance, Map is cast to Map<String,Object> and then the object
    103 values dynamically inspected and serialized as type/value pairs.  Support
    104 exists for sending arbitrary Java serializables, Android Bundles, etc.
    105 
    106 ### C++ Parcelables
    107 
    108 In Java, a parcelable should extend android.os.Parcelable and provide a static
    109 final CREATOR field that acts as a factory for new instances/arrays of
    110 instances of the parcelable.  In addition, in order to be used as an out
    111 parameter, a parcelable class must define a readFromParcel method.
    112 
    113 In C++, parcelables must implement android::Parcelable from binder/Parcelable.h
    114 in libbinder.  Parcelables must define a constructor that takes no arguments.
    115 In order to be used in arrays, a parcelable must implement a copy or move
    116 constructor (called implicitly in vector).
    117 
    118 The C++ generator needs to know what header defines the C++ parcelable.  It
    119 learns this from the `cpp_header` directive shown below.  The generator takes
    120 this string and uses it as the literal include statement in generated code.
    121 The idea here is that you generate your code once, link it into a library along
    122 with parcelable implementations, and export appropriate header paths.  This
    123 header include must make sense in the context of the Android.mk that compiles
    124 this generated code.
    125 
    126 ```
    127 // ExampleParcelable.aidl
    128 package 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
    135 parcelable ExampleParcelable cpp_header "bar/foo.h";
    136 ```
    137 
    138 ### Null Reference Handling
    139 
    140 The aidl generator for both C++ and Java languages has been expanded to
    141 understand nullable annotations.
    142 
    143 Given an interface definition like:
    144 
    145 ```
    146 interface IExample {
    147   void ReadStrings(String neverNull, in @nullable String maybeNull);
    148 };
    149 ```
    150 
    151 the generated C++ header code looks like:
    152 
    153 ```
    154 class IExample {
    155   android::binder::Status ReadStrings(
    156       const android::String16& in_neverNull,
    157       const std::unique_ptr<android::String16>& in_maybeNull);
    158 };
    159 ```
    160 
    161 Note that by default, the generated C++ passes a const reference to the value
    162 of a parameter and rejects null references with a NullPointerException sent
    163 back the caller.  Parameters marked with @nullable are passed by pointer,
    164 allowing native services to explicitly control whether they allow method
    165 overloading via null parameters.  Java stubs and proxies currently do nothing
    166 with the @nullable annotation.
    167 
    168 ### Exception Reporting
    169 
    170 C++ methods generated by the aidl generator return `android::binder::Status`
    171 objects, rather than `android::status_t`.  This Status object allows generated
    172 C++ code to send and receive exceptions (an exception type and a String16 error
    173 message) since we do not use real exceptions in C++.  More background on Status
    174 objects can be found here.
    175 
    176 For legacy support and migration ease, the Status object includes a mechanism
    177 to report a `android::status_t`.  However, that return code is interpreted by a
    178 different code path and does not include a helpful String message.
    179 
    180 For situations where your native service needs to throw an error code specific
    181 to the service, use `Status::fromServiceSpecificError()`.  This kind of
    182 exception comes with a helpful message and an integer error code.  Make your
    183 error codes consistent across services by using interface constants (see
    184 below).
    185 
    186 ### Integer Constants
    187 
    188 AIDL has been enhanced to support defining integer constants as part of an
    189 interface:
    190 
    191 ```
    192 interface IMyInterface {
    193     const int CONST_A = 1;
    194     const int CONST_B = 2;
    195     const int CONST_C = 3;
    196     ...
    197 }
    198 ```
    199 
    200 These map to appropriate 32 bit integer class constants in Java and C++ (e.g.
    201 `IMyInterface.CONST_A` and `IMyInterface::CONST_A` respectively).
    202