Android Treble架构解析

本文主要介绍Treble架构下的HAL&HIDL&Binder相关技术原理。Treble的详细资料文档,请参考Treble 官方文档

1. Treble 简介

Android 8.0 版本的一项新元素是 Project Treble。这是 Android 操作系统框架在架构方面的一项重大改变,旨在让制造商以更低的成本更轻松、更快速地将设备更新到新版 Android 系统。Project Treble 适用于搭载 Android 8.0 及后续版本的所有新设备(这种新的架构已经在 Pixel 手机的开发者预览版中投入使用)。

1.1 系统更新

这里写图片描述

图 1. Treble 推出前的 Android 更新环境

Android 7.x 及更早版本中没有正式的供应商接口,因此设备制造商必须更新大量 Android 代码才能将设备更新到新版 Android 系统:

这里写图片描述
图 2. Treble 推出后的 Android 更新环境

Treble 提供了一个稳定的新供应商接口,供设备制造商访问 Android 代码中特定于硬件的部分,这样一来,设备制造商只需更新 Android 操作系统框架,即可跳过芯片制造商直接提供新的 Android 版本:

1.2 Android 经典架构

为了更好的了解Treble 架构里面的HAL,首先了解一下Android的经典架构。

这里写图片描述

在Android O之前,HAL是一个个的.so库,通过dlopen来进行打开,库和framework位于同一个进程。如图所示:

这里写图片描述

1.3 Trebe 架构

为了能够让Android O之前的版本升级到Android O,Android设计了Passthrough模式,经过转换,可以方便的使用已经存在代码,不需要重新编写相关的HAL。HIDL分为两种模式:Passthrough和Binderized。

  • Binderized: Google官方翻译成绑定试HAL。
  • Passthrough:Google官方翻译成直通式HAL。

大致框架图如下,对于Android O之前的设备,对应图1,对于从之前的设备升级到O的版本,对应图2、图3. 对于直接基于Android O开发的设备,对应图4。

这里写图片描述

新的架构之下,framework和hal运行于不同的进程,所有的HAL采用新的HIDL技术来完成。

这里写图片描述

2. HIDL 深入理解

HIDL是一种接口定义语言,描述了HAL和它的用户之间的接口。接下来深入分析一下HIDL相关实现。

2.1 hidl-gen工具

在Treble架构中,经常会提到HIDL,首先介绍和HIDL相关的一个工具hidl-gen,系统定义的所有的.hal接口,都是通过hidl-gen工具转换成对应的代码。比如hardware/interfaces/power/1.0/IPower.hal,会通过hidl-gen转换成out/soong/.intermediates/hardware/interfaces/power/1.0/android.hardware.power@1.0_genc++/gen/android/hardware/power/1.0/PowerAll.cpp文件,为了深入了解,介绍相关原理,首先分析hidl-gen

hidl-gen源码路径:system/tools/hidl,是在ubuntu上可执行的二进制文件。

使用方法:hidl-gen -o output-path -L language (-r interface-root) fqname

例子:

hidl-gen  -Lmakefile  -r  android.hardware:hardware/interfaces  -r  android.hidl:system/libhidl/transport  android.hardware.power@1.0

参数含义:

  • -L: 语言类型,包括c++, c++-headers, c++-sources, export-header, c++-impl, java, java-constants, vts, makefile, androidbp, androidbp-impl, hash等。hidl-gen可根据传入的语言类型产生不同的文件。
  • fqname: 完全限定名称的输入文件。比如本例中android.hardware.power@1.0,要求在源码目录下必须有hardware/interfaces/power/1.0/目录。
    • 对于单个文件来说,格式如下:package@version::fileName,比如android.hardware.power@1.0::types.Feature。
    • 对于目录来说。格式如下package@version,比如android.hardware.power@1.0。
  • -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/android.hardware.power@1.0_genc++/gen,如果是c++-headers,那么就是out/soong/.intermediates/hardware/interfaces/power/1.0/android.hardware.power@1.0_genc++_headers/gen

对于实例来说,fqname是:android.hardware.power@1.0,包名是android.hardware,文件所在的目录是hardware/interfaces。例子中的命令会在out/soong/.intermediates/hardware/interfaces/power/1.0/下面产生对应的c++文件。

2.2 生成子hal的Android.mkAndroid.bp文件

正如我们所知,所有的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.bpAndroid.mk文件。详细分析如下:

a. source system/tools下面的update-makefiles-helper.sh,然后执行do_makefiles_update

b. 解析传入进去的参数。参数android.hardware:hardware/interfaces:

  • android.hardware: android.hardware表示包名。
  • hardware/interfaces:表示相对于根目录的文件路径。

会输出如下LOG:

Updating makefiles for android.hardware in hardware/interfaces.
Updating ….

c. 获取所有的包名。通过function get_packages()函数,获取hardware/interfaces路径下面的所有hal文件所在的目录路径,比如子目录power里面的hal文件的路径是power/1.0,加上当前的参数包名hardware/interfaces,通过点的方式连接,将nfc/1.0+hardware/interfaces里面的斜线转换成点,最终获取的包名就是 android.hardware.power@1.0,依次类推获取所有的包名。

d. 执行hidl-gen命令.将c步骤里面获取的参数和包名还有类名传入hidl-gen命令,在hardware/interfaces/power/1.0目录下产生Android.mkAndroid.bp文件。

  • Android.mk: hidl-gen -Lmakefile -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.power@1.0
  • Android.bp: hidl-gen -Landroidbp -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.power@1.0

关于hidl-gen,后续章节会介绍。

e. 在hardware/interfaces的每个子目录下面产生Android.bp文件,文件内容主要是subdirs的初始化,存放当前目录需要包含的子目录。比如hardware/interfaces/power/下面的Android.bp文件。

@hardware/interfaces/power/Android.bp

// This is an autogenerated file, do not edit.
subdirs = [ 
    "1.0",
    "1.0/default",
    "1.0/vts/functional",
]

意思就是说,编译的时候,需要编译hardware/interfaces/power目录下面的三个子目录。

经过以上步骤,就会在对应的子目录产生Android.mkAndroid.bp文件。这样以后我们就可以执行正常的编译命令进行编译了。比如mmm hardware/interfaces/power/,默认情况下,在源码中,Android.mkAndroid.bp文件已经存在。

2.3 转换.hal 文件为代码

如前面所示,每个接口都是定义在.hal文件里面,比如hardware/interfaces/power/1.0/IPower.hal,通过hidl-gen生成的android.bp文件里面会定义

filegroup {
    name: "android.hardware.power@1.0_hal",
    srcs: [
        "types.hal",
        "IPower.hal",
    ],
}

genrule {
    name: "android.hardware.power@1.0_genc++",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0",
    srcs: [
        ":android.hardware.power@1.0_hal",
    ],
    out: [
        "android/hardware/power/1.0/types.cpp",
        "android/hardware/power/1.0/PowerAll.cpp",
    ],
}

可以看到在Android.bp里面,通过hidl-gen在out下面产生了types.cppPowerAll.cpp. 实际例子很多,不做详细介绍。

对于生成的PowerAll.cpp来说,我们可以看到,除了IPower.hal里面定义的函数之外,还生成了很多其他的方法,这个是hidl-gen默认产生,为了能够支持binder通信。在IPower.hal里面定义的setInteractive(bool interactive);,在PowerAll.cpp里面对应的是BpHwPower::setInteractive(bool interactive)。通过命名就可以知道,这个和Binder机制里面的命名一致。代码如下:

::android::hardware::Return<void> BpHwPower::setInteractive(bool interactive) {
    atrace_begin(ATRACE_TAG_HAL, "HIDL::IPower::setInteractive::client");
    #ifdef __ANDROID_DEBUGGABLE__
    if (UNLIKELY(mEnableInstrumentation)) {
        std::vector<void *> _hidl_args;
        _hidl_args.push_back((void *)&interactive);
        for (const auto &callba
  • 19
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值