AIDL interface between Java and C++

旧城冷巷雨未停 提交于 2021-01-20 08:01:22

问题


I am a new to AIDL interface. I would like to implement AIDL interface between Java(Application layer) which is build using gradle and C++(Native layer) which is build using cmake. I need to pass a chunk of data between these two processes using AIDL interface. I am able to implement a .aidl file in application layer and able to create a service. I need to implement a aidl client in native layer and need to pass data. Can anyone suggest me how to implement AIDL which is to be build cmake.


回答1:


To obtain the aidl-cpp binary, you would have to set up the AOSP source code using the instructions here and the first few instructions here. Once you have set up the build environment, you can build the binary with make aidl-cpp. The binary can then be found e.g. in out/host/linux-x86/bin/aidl-cpp. You only have to do this once, after you have obtained the binary you no longer need the AOSP code (though it is nice to have the code around to quickly search for examples).

Regarding the CMake part, as discussed in the comment, once you have build the aidl-cpp binary, you can use the CMake command add_custom_target for code generation.

The aidl-cpp command provides the following instructions:

usage: aidl-cpp INPUT_FILE HEADER_DIR OUTPUT_FILE

OPTIONS:
   -I<DIR>   search path for import statements
   -d<FILE>  generate dependency file
   -ninja    generate dependency file in a format ninja understands

INPUT_FILE:
   an aidl interface file
HEADER_DIR:
   empty directory to put generated headers
OUTPUT_FILE:
   path to write generated .cpp code

So when you call the command from cmake, you would have to provide your AIDL, then a directory in which the generated header files should be stored, and the name under which the generated cpp file should be stored. E.g. aidl-cpp ISomeInterface.aidl ./generated-headers ./generated-cpp/ISomeInterface.cpp. If you want to use a custom data type (see the last section of this answer), you would also have to pass the -I flag to point to the declaration of your custom data types.

Creating a binder client in C++

Once you have generated the header files and the cpp file with aidl-cpp, you can then connect to your service from C++. Here is an example from the AOSP source code:

  • There is an AIDL file called IDropboxManagerService.

  • The interface defined by the AIDL is implemented as DropboxManagerService in Java.

  • The service is called from C++ here:

    • Note the include of <com/android/internal/os/IDropBoxManagerService.h at the beginning of the file (link). This is the header file that has been generated by aidl-cpp from the AIDL file.

    • The default service manager is used to look-up the service called "dropbox":

      defaultServiceManager()->getService(android::String16("dropbox"))
      
    • The result from getService is cast to the interface defined in the generated header file:

      sp<IDropBoxManagerService> service = interface_cast<IDropBoxManagerService>(...)
      
    • The service object now holds a proxy object on which you can call the methods defined in the AIDL. The proxy object will then forward these calls via Binder to the Java service (this is implemented in the cpp file generated by aidl-cpp).

      For example, the AIDL defines a method void add(in DropBoxManager.Entry entry);. The C++ code calls this method with Status status = service->add(entry);. You can check the result of the transaction with status.isOk().

Sending custom data types

Regarding data types, you can find a table with the mapping of C++ types to Java types here.

If you want to send custom objects, you would have to define a C++ class and a Java class, which both implement the Parcelable interface. This interface requires to implement two methods writeToParcel / readFromParcel in C++ and writeToParcel / createFromParcel in Java. You would have to provide matching implementations on each side, so that calling e.g. writeToParcel on the C++ object produces a flat binary encoding that can be read by readFromParcel on the Java side.

You would also have to provide an AIDL file that points to the header for your custom object using the cpp_header directive. See the following example:

  • In the DropBoxManagerService example from the previous section, we saw an object of type Entry.

    • On the C++ side, the class is declared here and implemented here.

    • On the Java side, the class is defined here.

  • In AIDL, a parcelable is declared here. Note this does not define any implementation details, it just declares there is a class of this name. It also points to the C++ header, which will be included by aidl-cpp.

  • The AIDL for the DropBoxManagerService that we looked at in the previous example imports the AIDL for the parcelable here. This allows to use this data type in the AIDL method declarations.

Based on these steps, the Entry class defined in C++ can then be send from C++ to Java. When passing the Entry object to the proxy object in C++, the cpp that was generated by aidl-cpp will use the writeToParcel function implemented for the Entry class to serialize the class into a flat binary encoding. On the Java side, the encoding is received and an Entry Java object is constructed from the encoding.



来源:https://stackoverflow.com/questions/65284392/aidl-interface-between-java-and-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!