[Android AIDL Series 1] Manually compile aidl files to generate Java, C++[android], C++[ndk], Rust interfaces

AIDL files are widely used in the Android system and are closely related to the underlying Binder mechanism.
In the Android source code or Android Studio, the aidl file is usually automatically compiled to generate an interface file for the corresponding language.
For application layer Java development, the package of aidl and binder is relatively "clean", so you don't need to pay too much attention to the calling details of binder, and you don't need to care too much about the compilation process of aidl.
If you are doing middle and lower layer development, including framework and native layer development, you may need to write native service, and it is necessary to understand the underlying mechanism of binder.

Start by compiling aidl. Here we only explain the process of compiling aidl to generate various types of back-end interface files. The content of the generated interface file will be introduced separately in an article.

The following demos were tested on an Ubuntu system.

1. Preparation

1. aidl compilation tool

That is, the aidl command is available in the Android sdk or the Android source code.

For aidl in the sdk, the path needs to be added to the path.
Location: ~/Android/Sdk/build-tools/33.0.2/aidl

Aidl in the source code is automatically added to the path after the source code compilation environment is set.
Location: out/soong/host/linux-x86/bin/aidl

2. Aidl file for demo

Write 2 simple aidl files, one is the service interface and the other is the callback interface. Can be used to cover most practical scenarios.
The file directory structure and file content are as follows.

$ tree .
.
└── aidl
    └── com
        └── my
            └── pkg
                ├── IMyServiceCallback.aidl
                └── IMyServiceInterface.aidl

Callback interface definition:

// IMyServiceCallback.aidl
package com.my.pkg;

 interface IMyServiceCallback {
    
    
    void onEvent(int code, String message);
}

Service interface definition:

// IMyServiceInterface
package com.my.pkg;

interface IMyServiceInterface {
    
    
    int doSomething(in String str, int num);
    void setCallBack(com.my.pkg.IMyServiceCallback callback);
}

2. Generate Java interface

Run the following command to generate a Java interface file.
illustrate:

  1. aidl instructions
    aidl --lang={java|cpp|ndk} [options] input_aidl_file.
    On the command line, aidl prints instructions without any parameters.
  2. –lang={java|cpp|ndk}
    specifies the generated interface type. If not specified, Java files are generated by default.
  3. -o Specify the output directory
    Java: Omit the -o parameter, and the java file will be generated in the aidl file directory.
    C++/Rust: Required parameter.
    In order to clear the viewing effect, specify to a separate directory: -o ./java
  4. -I DIR, --include=DIR
    import search path, specify the directory where the dependent aidl file is located. Not the C++ header files directory.
    For example: IMyServiceInterface.aidl refers to IMyServiceCallback.aidl, and the -I parameter needs to be specified when generating IMyServiceInterface.aidl to compile normally.
    As long as there is a dependency in the AIDL file, this parameter must be specified to generate any type of interface (Java, C++, Rust).
# 前2条命令效果相同,不指定--lang参数,默认生成Java文件
$ aidl -o ./java --lang=java aidl/com/my/pkg/IMyServiceCallback.aidl 
$ aidl -o ./java aidl/com/my/pkg/IMyServiceCallback.aidl 

$ aidl -I ./aidl/ -o ./java aidl/com/my/pkg/IMyServiceInterface.aidl

$ tree 
.
├── aidl
│   └── com
│       └── my
│           └── pkg
│               ├── IMyServiceCallback.aidl
│               └── IMyServiceInterface.aidl
└── java
    └── com
        └── my
            └── pkg
                ├── IMyServiceCallback.java
                └── IMyServiceInterface.java

3. Generate C++[Android] interface

  1. The difference between cpp and ndk
    cpp: The generated code is to be compiled in the Android source code, and the native interface in the Android source code will be called in the code.
    For example, the referenced header files:
    <binder/IBinder.h>, <binder/IInterface.h>, <binder/Status.h>, <android-base/macros.h>

    ndk: The generated code is to be compiled independently using ndk, calling the interface of ndk,
    for example, the referenced header file:
    <android/binder_interface_utils.h> <android/binder_ibinder.h>

  2. –lang=cpp, the parameter specifies to generate the C++ interface file compiled under the Android source code.

  3. The -o and -h parameters specify the path to the output of the .cpp file and the .h file, respectively. A different directory can be specified.
    1) There are many C++ interface files, and one aidl file generates 4 files. After compiling IMyServiceCallback.aidl in the first step, the generated files include:
    3 header files:
    an Interface header file: IMyServiceCallback.h,
    a Bp header file: BpMyServiceCallback.h,
    a Bn header file: BnMyServiceCallback.h,
    and a source code file: IMyServiceCallback.cpp

$ aidl -h ./cpp_android/ -o ./cpp_android --lang=cpp aidl/com/my/pkg/IMyServiceCallback.aidl
$ tree 
.
├── aidl
│   └── com
│       └── my
│           └── pkg
│               ├── IMyServiceCallback.aidl
│               └── IMyServiceInterface.aidl
└── cpp_android
    └── com
        └── my
            └── pkg
                ├── BnMyServiceCallback.h
                ├── BpMyServiceCallback.h
                ├── IMyServiceCallback.cpp
                └── IMyServiceCallback.h

$ aidl -I ./aidl/ -h ./cpp_android/ -o ./cpp_android --lang=cpp aidl/com/my/pkg/IMyServiceInterface.aidl
$ tree 
.
├── aidl
│   └── com
│       └── my
│           └── pkg
│               ├── IMyServiceCallback.aidl
│               └── IMyServiceInterface.aidl
└── cpp_android
    └── com
        └── my
            └── pkg
                ├── BnMyServiceCallback.h
                ├── BnMyServiceInterface.h
                ├── BpMyServiceCallback.h
                ├── BpMyServiceInterface.h
                ├── IMyServiceCallback.cpp
                ├── IMyServiceCallback.h
                ├── IMyServiceInterface.cpp
                └── IMyServiceInterface.h

4. Generate C++[ndk] interface

Except that --lang=ndk specifies to generate the ndk backend interface, the process and result are similar to cpp.

$ aidl -I ./aidl/ -h ./cpp_ndk -o ./cpp_ndk --lang=ndk aidl/com/my/pkg/IMyServiceInterface.aidl 
$ aidl -h ./cpp_ndk -o ./cpp_ndk --lang=ndk aidl/com/my/pkg/IMyServiceCallback.aidl 

$ tree cpp_*
cpp_android
└── com
    └── my
        └── pkg
            ├── BnMyServiceCallback.h
            ├── BnMyServiceInterface.h
            ├── BpMyServiceCallback.h
            ├── BpMyServiceInterface.h
            ├── IMyServiceCallback.cpp
            ├── IMyServiceCallback.h
            ├── IMyServiceInterface.cpp
            └── IMyServiceInterface.h
cpp_ndk
├── aidl
│   └── com
│       └── my
│           └── pkg
│               ├── BnMyServiceCallback.h
│               ├── BnMyServiceInterface.h
│               ├── BpMyServiceCallback.h
│               ├── BpMyServiceInterface.h
│               ├── IMyServiceCallback.h
│               └── IMyServiceInterface.h
└── com
    └── my
        └── pkg
            ├── IMyServiceCallback.cpp
            └── IMyServiceInterface.cpp

5. Generate Rust interface file

  1. --lang=rust specifies to generate the rust backend interface file.
  2. Just set the output path through the -o parameter, the output result is similar to Java, one aidl file corresponds to one .rs file.
  3. The Rust backend is only supported by a newer version of aidl, probably after Android 12, you can check the aidl command to help confirm.
$ aidl -o ./rust --lang=rust aidl/com/my/pkg/IMyServiceCallback.aidl 
$ aidl -I ./aidl/ -o ./rust --lang=rust aidl/com/my/pkg/IMyServiceInterface.aidl

$ tree 
.
├── aidl
│   └── com
│       └── my
│           └── pkg
│               ├── IMyServiceCallback.aidl
│               └── IMyServiceInterface.aidl
└── rust
    └── com
        └── my
            └── pkg
                ├── IMyServiceCallback.rs
                └── IMyServiceInterface.rs

Guess you like

Origin blog.csdn.net/yinminsumeng/article/details/129324917