Android HAL in-depth exploration (7) Detailed explanation of the use of hidl-gen and hidl2aidl

Preface

The hardware abstraction layer (HAL) in Android system development is a set of interface and data type definitions that are used to describe the functions and attributes of hardware devices, thereby achieving decoupling of hardware and software. In order to facilitate the use of HAL, Android provides a special language called HIDL, which is a language based on IDL (interface definition), which can be used to define HAL interfaces and data types, and generate code files in different languages ​​and types. Such as C++, Java, Android.bp, etc.

This article will introduce two HIDL-related tools: hidl-gen and hidl2aidl. hidl-gen is a tool for generating HIDL code files. It can generate corresponding proxy classes, stub classes, callback classes, etc. based on the interfaces and data types defined in the .hal file, and provides a framework and examples for interface implementation and testing. code. hidl2aidl is a tool for converting HIDL code files into .aidl files. It can generate corresponding .aidl files based on the interfaces and data types defined in the .hal file, and maintain the original structure and semantics as much as possible.

This article will learn the basic usage of hidl-gen and hidl2aidl, the generated code files, implementation principles, differences and connections, etc., so that we can better understand and use these two tools.

Instructions for using hidl-gen

Basic usage of hidl-gen

hidl-gen is a tool for generating HIDL code files. It can generate corresponding proxy classes, stub classes, callback classes, etc. based on the interfaces and data types defined in the .hal file, and provides a framework and examples for interface implementation and testing. code. hidl-gen accepts the following parameters:

- -h: 打印这个菜单。
- -L <language>: 可以选择以下选项:
    - check           : 解析接口,检查是否有效,但不写入任何文件。
    - c++             : (内部) (已弃用) 生成C++接口文件,用于与HIDL接口通信。
    - c++-headers     : (内部) 生成C++头文件,用于与HIDL接口通信。
    - c++-sources     : (内部) 生成C++源文件,用于与HIDL接口通信。
    - export-header   : 根据@export枚举生成一个头文件,用于维护旧代码。
    - c++-impl        : 生成HIDL接口的C++实现的模板和示例代码(为了方便)。
    - c++-impl-headers: c++-impl,但只有头文件。
    - c++-impl-sources: c++-impl,但只有源文件。
    - c++-adapter     : 将一个x.(y+n)接口转换为一个x.y接口的适配器。
    - c++-adapter-headers: c++-adapter,但只有辅助头文件。
    - c++-adapter-sources: c++-adapter,但只有辅助源文件。
    - c++-adapter-main: c++-adapter,但只有适配器二进制源文件。
    - java            : (内部) 生成Java库,用于在Java中与HIDL接口通信。
    - java-impl       : 生成HIDL接口的Java实现的模板和示例代码(为了方便)。
    - java-constants  : (内部) 类似于export-header,但是针对Java(如果存在@export,则-Lmakefile总是创建)。
    - vts             : (内部) 生成vts proto文件,用于在vtsd中使用。
    - makefile        : (已移除) 用于为-Ljava和-Ljava-constants生成makefile。
    - androidbp       : (内部) 生成Soong bp文件,用于-Lc++-headers、-Lc++-sources、-Ljava、-Ljava-constants和-Lc++-adapter。
    - androidbp-impl  : 生成-Lc++-impl创建的实现的模板bp文件。
    - hash            : 将接口的哈希值以`current.txt`格式打印到标准输出。
    - function-count  : 打印包或接口添加的函数总数。
    - dependencies    : 打印所有依赖类型。
    - inheritance-hierarchy: 将继承类型的层次结构作为一个JSON对象打印出来。
    - format          : 格式化.hal文件
- -O <owner>: 模块的所有者,用于-Landroidbp(-impl)?.
- -o <output path>: 文件输出位置。
- -p <root path>: Android构建根目录,默认为$ANDROID_BUILD_TOP或pwd。
- -R: 如果在-r中没有指定,则不添加默认包根目录。
- -r <package:path root>: 例如,android.hardware:hardware/interfaces.
- -v: 输出详细信息。
- -d <depfile>: depfile写入位置。

FQNAME是.hal文件或包名(以@开头)的完全限定名,格式为PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?,用于创建输出。

Code files generated by hidl-gen

hidl-gen can generate different types of code files based on the hardware/interfaces/can_bus/1.0/ICanBus.hal file. The following are some commonly used commands:

  • Generate a C++ header file and store it in the hardware/interfaces/can_bus/2.0/default directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Lc++-headers \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]

hardware/interfaces/can_bus/2.0$ tree
.
├── default
│   └── android
│       └── hardware
│           └── can_bus
│               └── 2.0
│                   ├── BnHwCanBus.h
│                   ├── BpHwCanBus.h
│                   ├── BsCanBus.h
│                   ├── ICanBus.h
│                   └── IHwCanBus.h
└── ICanBus.hal

5 directories, 6 files
  • Generate C++ source files and store them in the hardware/interfaces/can_bus/2.0/default directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Lc++-sources \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]

.
├── default
│   └── android
│       └── hardware
│           └── can_bus
│               └── 2.0
│                   ├── CanBusAll.cpp
└── ICanBus.hal
  • Generate a C++ implementation file and store it in the hardware/interfaces/can_bus/2.0/default directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Lc++-impl \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]

hardware/interfaces/can_bus/2.0$ tree
.
├── default
│   ├── android
│   │   └── hardware
│   │       └── can_bus
│   │           └── 2.0
│   │               └── CanBusAll.cpp
│   ├── CanBus.cpp
│   └── CanBus.h
└── ICanBus.hal
  • Generate the Android.bp file and store it in the hardware/interfaces/can_bus/2.0/ directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Landroidbp \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]

hardware/interfaces/can_bus/2.0$ tree
.
├── Android.bp
└── ICanBus.hal
  • Generate the Android.bp implementation file and store it in the hardware/interfaces/can_bus/2.0/default directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Landroidbp-impl \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]
  
hardware/interfaces/can_bus/2.0$ tree
├── default
│   ├── Android.bp
└── ICanBus.hal
  • Generate Java files and store them in the hardware/interfaces/can_bus/2.0/default directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]
  
hardware/interfaces/can_bus/2.0$ tree
├── default
│   ├── ICanBus.java
└── ICanBus.hal
  • Generate Java implementation files and store them in the hardware/interfaces/can_bus/2.0/default directory:
hidl-gen -o hardware/interfaces/can_bus/2.0/default -Ljava-impl \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport \
  [email protected]
  
hardware/interfaces/can_bus/2.0$ tree
├── default
│   ├── CanBus.java
└── ICanBus.hal

Implementation principle of hidl-gen generated code

hidl-genUse the LLVM-based Clang library to parse .halthe file and generate AST. It then traverses this AST and uses the appropriate code generator to generate target code. (I don’t really understand the non-technical words involved, so it’s just diao)

hidl-gen simplifies the process:

  1. Parse the command line parameters and obtain the output directory, language type, dependencies and .hal file information.
  2. Create clang::CompilerInstance object to manage compiler components.
  3. Set the compiler front-end action and use the custom HidlFrontendAction class to process the AST.
  4. Compile each .hal file to generate AST.
  5. According to the parameters, create the corresponding CodeGenerator object, such as a C++ header file generator.
  6. Traverse the AST nodes, generate code files and save them to the output directory.
  7. Release resources and exit.

Instructions for using hidl2aidl

Basic usage of hidl2aidl

If you don't have this tool, just execute m hidl2aidl under the source code to compile it.

hidl2aidl is a tool for converting .hal files into .aidl files. It can generate corresponding .aidl files based on the interfaces and data types defined in the .hal file, and maintain the original structure and semantics as much as possible. hidl2aidl accepts the following parameters:


- -o <output path>:指定输出目录,用于存放生成的.aidl文件。
- -h: 打印这个菜单。
- -p <root path>:指定Android构建根目录,默认为$ANDROID_BUILD_TOP或pwd。
- -R: 如果在-r中没有指定,则不添加默认包根目录。
- -r <package:path root>:指定依赖包的位置,用于解析.hal文件中的import语句。可以有多个-r参数,每个参数表示一个包和一个位置,用冒号分隔。位置可以是相对路径或绝对路径。例如,android.hardware:hardware/interfaces。
- -v: 输出详细信息。
- -d <depfile>:指定depfile写入位置。

FQNAME是.hal文件或包名(以@开头)的完全限定名,格式为PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?,用于转换为.aidl文件。

For example, hidl2aidl can generate .aidl files based on all .hal files in the [email protected] package and store them in the hardware/interfaces/smart_home/2.0/aidl directory. :

hidl2aidl -o hardware/interfaces/can_bus/2.0/aidl -r android.hardware:hardware/interfaces [email protected]

hardware/interfaces/can_bus/2.0$ tree
.
├── aidl
│   └── android
│       └── hardware
│           └── can_bus2
│               ├── conversion.log
│               └── ICanBus.aidl

.aidl file generated by hidl2aidl

hidl2aidl will generate the corresponding .aidl file based on the interface and data type defined in the .hal file, and maintain the original structure and semantics as much as possible. For example:

  • If an interface ICanBus is defined in the .hal file and has four methods dev_openCan, dev_closeCan, dev_sendCan and dev_receiveCan, then hidl2aidl will generate an ICanBus.aidl file and define an ICanBus interface and have four methods dev_openCan, dev_closeCan, dev_sendCan and dev_receiveCan. The following is the content of the generated aidl file:
// FIXME: license file if you have one

package android.hardware.can_bus2;

interface ICanBus {
    
    
    // Adding return type to method instead of out param int fd since there is only one return value.
    int dev_openCan(in String canx);

    // Adding return type to method instead of out param int ret since there is only one return value.
    int dev_closeCan(in int fd);

    // Adding return type to method instead of out param int ret since there is only one return value.
    int dev_sendCan(in int fd, in long canid, in long eff, in long rtr, in int len,
        in int[] data);

    // Adding return type to method instead of out param byte[] data since there is only one return value.
    byte[] dev_receiveCan(in int fd);
}

If a more complex hal file is generated, it will be outrageous. I wrote it by hand at first, and found that I couldn't write any complex content at all.
Insert image description here

Implementation principle of hidl2aidl conversion code

hidl2aidl is also an LLVM-based tool that uses the clang library to parse .hal files, generate AST, and generate .aidl files through the AidlCodeGenerator class.

Process overview of hidl2aidl:

  1. Parse command line parameters and obtain output directory, dependencies and .hal file information.
  2. Create clang::CompilerInstance object to manage compiler components.
  3. Set the compiler front-end action and use the HidlFrontendAction class to process the AST.
  4. Compile each .hal file to generate AST.
  5. Create an AidlCodeGenerator object for generating .aidl files.
  6. Traverse AST nodes, generate .aidl files and save them to the output directory.
  7. Release resources and exit.

The difference and connection between hidl-gen and hidl2aidl

Both hidl-gen and hidl2aidl are based on LLVM and use the clang library to parse .hal files to generate code. Their main differences are:

  • hidl-gen supports generating code in multiple languages ​​(such as C++, Java) and provides agents, stubs, callback classes, etc., and can also generate interface implementations and test frameworks;
  • hidl2aidl only generates .aidl files and interface and data type definitions.

What they have in common is:

  • Both serve Android HIDL development and help us use HIDL to define HAL interfaces and data types.
  • According to the .hal file, they can generate identifiers such as namespaces and class names, and resolve dependent packages.

Summarize

The article discusses the basic common methods of two HIDL tools: hidl-gen and hidl2aidl. These two tools are designed to help us use HIDL to define HAL interfaces and data types. They generate identifiers based on .hal files and resolve dependent packages. Automatically generate some code frameworks.

I hope this article can help you use these two tools. If you have any questions or suggestions, please leave a message. Thanks!

Guess you like

Origin blog.csdn.net/SHH_1064994894/article/details/133019895