HIDL是一种接口定义语言,描述了HAL和它的用户之间的接口。同aidi类似,我们只需要为hal定义相关接口,然后通过hidl-gen工具即可自动编译生成对应的C++或者java源文件,定义hal接口的文件命名为xxx.hal,为了编译这些.hal文件,需要编写相应的Android.bp或者Android.mk文件:
1. Android.bp文件用于编译C++;
2. Android.mk文件用于编译Java;
所有的HIDL Interface 都是通过一个.hal文件来描述,为了方便编译生成每一个子hal。Google在系统默认提供了一个脚本update-makefiles.sh,位于hardware/interfaces/、frameworks/hardware/interfaces/、system/hardware/interfaces/、system/libhidl/。以hardware/interfaces/里面的代码为实例做介绍:
#!/bin/bash
source system/tools/hidl/update-makefiles-helper.sh
do_makefiles_update \
"android.hardware:hardware/interfaces" \
"android.hidl:system/libhidl/transport"
这个脚本的主要作用:根据hal文件生成Android.mk(makefile)和Android.bp(blueprint)文件。在hardware/interfaces的子目录里面,存在.hal文件的目录,都会产生Android.bp和Android.mk文件。详细分析如下:
Updating makefiles for android.hardware in hardware/interfaces.
Updating ….
3.获取所有的包名。通过function get_packages()函数,获取hardware/interfaces路径下面的所有hal文件所在的目录路径,比如子目录power里面的hal文件的路径是power/1.0,加上当前的参数包名hardware/interfaces,通过点的方式连接,将nfc/1.0+hardware/interfaces里面的斜线转换成点,最终获取的包名就是 [email protected],依次类推获取所有的包名。
Android.mk: hidl-gen -Lmakefile -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport [email protected]
编译最终在./out/target/common/gen/JAVA_LIBRARIES目录下生成Java源文件。
Android.bp: hidl-gen -Landroidbp -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport [email protected]
编译最终在./out/soong/.intermediates/hardware/interfaces目录下生成Java源文件。
5.在hardware/interfaces的每个子目录下面产生Android.bp文件,文件内容主要是subdirs的初始化,存放当前目录需要包含的子目录。比如hardware/interfaces/power/下面的Android.bp文件。// This is an autogenerated file, do not edit.
subdirs = [
"1.0",
"1.0/default",
"1.0/vts/functional",
]
经过以上步骤,就会在对应的子目录产生Android.mk和Android.bp文件。这样以后我们就可以执行正常的编译命令进行编译了。比如mmm hardware/interfaces/power/,默认情况下,在源码中,Android.mk和Android.bp文件已经存在。
在Treble架构中,系统定义的所有的.hal接口,都是通过hidl-gen工具转换成对应的代码。比如hardware/interfaces/power/1.0/IPower.hal,会通过hidl-gen转换成out/soong/.intermediates/hardware/interfaces/power/1.0/[email protected]_genc++/gen/android/hardware/power/1.0/PowerAll.cpp文件。
hidl-gen源码路径:system/tools/hidl,是在ubuntu上可执行的二进制文件。
使用方法:hidl-gen -o output-path -L language (-r interface-root) fqname
参数含义:
-L: 语言类型,包括c++, c++-headers, c++-sources, export-header, c++-impl, java, java-constants, vts, makefile, androidbp, androidbp-impl, hash等。hidl-gen可根据传入的语言类型产生不同的文件。fqname:完全限定名称的输入文件。比如本例中[email protected],要求在源码目录下必须有hardware/interfaces/power/1.0/目录。
对于单个文件来说,格式如下:package@version::fileName,比如[email protected]::types.Feature。
对于目录来说。格式如下package@version,比如[email protected]。
-r: 格式package:path,可选,对fqname对应的文件来说,用来指定包名和文件所在的目录到Android系统源码根目录的路径。如果没有制定,前缀默认是:android.hardware,目录是Android源码的根目录。
-o : 存放hidl-gen产生的中间文件的路径。我们查看hardware/interfaces/power/1.0/Android.bp,可以看到,-o参数都是写的$(genDir),一般都是在out/soong/.intermediates/hardware/interfaces/power/1.0/下面,根据-L的不同,后面产生的路径可能不太一样,比如c++,那么就会就是out/soong/.intermediates/hardware/interfaces/power/1.0/[email protected]_genc++/gen,如果是c++-headers,那么就是out/soong/.intermediates/hardware/interfaces/power/1.0/[email protected]_genc++_headers/gen。
对于实例来说,fqname是:[email protected],包名是android.hardware,文件所在的目录是hardware/interfaces。例子中的命令会在out/soong/.intermediates/hardware/interfaces/power/1.0/下面产生对应的c++文件。
在hardware/interfaces/graphics/composer目录下mm编译将生成:
[email protected] .so
[email protected]
[email protected]
[email protected]
他们之间的关系如下图所示:
[email protected]为hal进程的可执行文件,在[email protected]是hal进程启动的配置脚本文件:
也就是说AndroidO的Treble架构下,所有hal都运行在独立的进程空间:
AndroidO之前版本的Hal都是编译为so库,然后动态链接到各个Framework Server进程,经过hidl化后,所有的Hal都运行在自己的Hal Process中,与Framework Server进程分离,这样既方便系统升级,也有利于系统稳定性,hal crash了也不至于导致Framework Server Process crash。那AndroidO下的hal库变化了吗?没有,google提供了passthou模式用于兼容之前的hal实现方式。