Android14-HAL分析


参考资料:

1、阿豪讲Framework:https://juejin.cn/user/342703355728382/posts

2、术语

1、VINTF : Vendor interface

一、HAL综述

1、HAL:Hardware Abstraction Layer

2、HAL存在的意义

1)HAL是对驱动操作的包装库,操作硬件的具体逻辑可以放到 HAL中(属于算法,如果这部分暴露的话 会让友商反推出硬件IP Core的设计),驱动程序本身只提供基本寄存器操作功能。

3、不同版本的HAL(传统HAL、HIDL HAL、AIDL HAL)开发流程是不同的,HAL(so库)与HIDL/AIDL(进程间通信)要区分开,从推出时间来分类,如下
1)Android 8以前 -> HAL层 以so库和.h文件存在 - 传统HAL
2)Android 8-10 -> HAL层 以进程方式存在 - HIDL HAL
3)Android 10 -> HAL层 以进程方式存在 - AIDL HAL

注意以上Android版本是推出时间,实际上高版本的Android混杂着各个HAL版本(比如Android13 Audio用的是hidl),实在让人混乱!

4、HAL库所在的代码目录

hardware/* 部分厂商开源的硬件适配层HAL代码

hardware/libhardware_legacy //旧的HAL层库

hardware/libhardware //HAL层实库

5、厂家闭源,厂家需要实现什么?

通过OS里面开源例子来了解学习

二、Android各版本HAL的演进

1、参考资料

1)Android8 HAL变迁: https://juejin.cn/post/7359954143916425251

2) Android HIDL HAL 接口定义语言详解:https://blog.youkuaiyun.com/qq_19923217/article/details/88398660

3)AN14 添加HAL层:https://blog.youkuaiyun.com/baidu_41666295/article/details/145503951

每一篇博文 都有参考的意义(不同开发者的知识域都不同,角度不同 即表述的内容也不同,应该各取精华)

2、Android版本对HAL有过几次改革,因此需要了解演进的背景和变化对理解几种HAL层的设计有很大的帮助;

1)尤其是网络上的各类资料,充斥着不同的Android版本,注意区分和分辨;

2)在不同版本上又应该如何选择实现HAL的方式?首先确定硬件厂商,而厂商不同,各自的选择也不同~

3、先理解Android系统各厂家合作模式:
在这里插入图片描述

1)Google : 负责Android系统开发、维护、迭代;

2)芯片厂商:负责适配硬件(vendor),定制Framework,有实力的话会帮忙解bug,加特性;

3)终端厂商:负责进一步定制Framework,有实力的话也会解BUG和加特性;

4、Treble架构(Android 8 / O)

由于系统发布比较频繁,而芯片厂和厂商更新版本代价较高(移植适配,测试耗时耗力),导致下游厂家不愿升级,间接损害Google的利益,Google为了解决升级问题,将芯片厂商从Framework抽离开来,实现互相升级不受影响,这就是Android8引入的Treble架构(代价是大大增加了复杂度),看图:
在这里插入图片描述

1、划分之后,System(放Framework部分)/ Vendor(放厂商部分)分区中的native程序/库(NDK)只能链接各自的库,而这由系统权限设置管理,Framework要访问Vendor的HAL接口,只能通过进程间通信实现;

扩展,Android 9推出product分区(存放终端厂商的针对特定设备的系统配置、应用程序、资源文件)

2、但难免有vendor和Framework互相依赖库,这些“特别的库”被分类出来如下(了解下即可)
1)LL-NDK(low level vendor native development kit),可以framework和vender进程链接,由google来维护,例子:
libEGL.so
libGLESv1_CM.so
libvndksupport.so
2)VNDK : Vendor Native Development Kit(Android 8.0引入,将系统分区和供应商分区分离,保持Android核心系统的纯净性,供应商可以使用VNDK开发自己的HAL,包含在system.img中 - 即VNDK升级与否让供应商决定,可以不升级在新的Android版本上使用)

目录示例:
android\prebuilts\vndk\v30\arm\arch-arm-armv7-a-neon\shared\vndk-core

VNDK深入剖析:https://blog.youkuaiyun.com/learnframework/article/details/134889443
bp中使用proprietary/vendor-only指定

3)SP-HAL:same-Process HAL(framework负责加载的hal库,由google来维护),链接的so库 称为VNDK-SP,需为VNDK或LL-NDK, 例子:
android.hardware.graphics.mapper@2.0-impl.so
android.hardware.renderscrip@1.0-impl.so
4)VNDK-SP:链接LL-NDK/VNDK的SP-HAL

这些特性怎么体现?

1、由SEpolicy强制执行,在te文件或Andorid.bp指定属性;

目录示例:
android\prebuilts\vndk\v30\arm\arch-arm-armv7-a-neon\shared\vndk-sp

3、随着库和进程被隔离开,Framework访问HAL层只能通过进程通信的方式,因此基于binder设计出HIDL HAL;

4、进一步地,Android9之后推出apex,同样也是为了方便第三方对系统组件的更新;

三、传统HAL(<= Android7)

1、HAL应知应会

1、传统的HAL,即厂家提供.so和.h,在需要访问硬件的时候dlopen,调用对应接口
>>既然是厂家实现,Google需要提供demo以保证规范,在哪里?
以audio为例
1)
android\hardware\libhardware\modules\audio //旧架构
android\hardware\libhardware_legacy\audio //新架构
厂家参照这个demo实现自家的audio hal(使用哪个架构,视乎厂家,无论哪个架构,接口都是一样的),并生成so库提供第三方集成
2)qcom开源出来源码实现:
android\hardware\qcom\audio\hal  //对应新架构
android\hardware\qcom\audio\legacy //对应旧架构


2、传统hal必须按照一定规范来写,用库函数 来加载

3、传统的HAL在高版本被弃用?还有必要去了解?
1)没有完全弃用,Android推出新的架构,不会一下子丢弃旧的方式,厂商会逐渐过渡 甚至一直保留都有可能;

2、代码分析

1、在系统服务代码中使用以下方法加载 HAL 模块
const hw_module_t *module;
hw_get_module(AUDIO_HARDWARE_MODULE_ID, &module); //会根据名字去对应目录查找并加载

具体实现如下:
1)
android\hardware\libhardware\hardware.c
typedef struct hw_module_t {
    struct hw_module_methods_t* methods;
}
2)
hw_get_module(const char *id, struct hw_module_t **module)
--hw_get_module_by_class(id, module)
----load(class_id, path, module)
------dlopen(path)
------dlsym(handle, sym) //找到结构体(hw_module_t),存在module指针中

3)例:audio_hw_module实现
struct audio_hw_module{
    struct hw_module_t common;
};
struct audio_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = AUDIO_HARDWARE_MODULE_ID,
        .name = "QCOM Audio HAL",
        .author = "Code Aurora Forum",
        .methods = &hal_module_methods,
    },
};

2、HAL什么时候被加载?最好是对应服务拉起的时候去加载,而事实也是如此
比如AudioFlinger 在启动时通过 hw_get_module方法加载传统hal库,并调用 create() 方法实例化接口

3、例:Vibrator(Vibrator实现相对简单易懂,是学习的好例子)
1)负责加载传统Vibrator HAL库对应的Service进程
frameworks/base/services/core/java/com/android/server/VibratorService.java //注意此传统hal service实现与AIDL hal实现的VibratorService 是有区别的!

2)C语言中的继承
typedef struct vibrator_device {
    struct hw_device_t common;
    int (*vibrator_on)(struct vibrator_device* vibradev, unsigned int timeout_ms);
    int (*vibrator_off)(struct vibrator_device* vibradev);
} vibrator_device_t;
通过指针巧妙实现C语言中的“继承”,vibrator_device(子类) 和 hw_device_t(父类)指针可以相互转换

四、HIDL HAL(Android8-10)

1、参考资料

1)HIDL Hal 开发指南3-HIDL HAL实例程序: https://juejin.cn/post/7360612648043708456

2)Android HAL 与 HIDL 开发笔记:https://evilpan.com/2020/11/01/hidl-basics/

3)HIDL实战(千里马):https://juejin.cn/post/7336743827826065459

2、概述

1、HIDL HAL是什么?

1)HIDL全称HAL interface definition language,而HIDL HAL则为,使用HIDL语言描述HAL层的对外接口,

2)注意HIDL语言只是一个Google提供的辅助工具,必须使用?不是,自己也可以自行实现所有代码

2、与传统HAL的区别?

1)传统HAL:用户<->HAL<->驱动

2)HIDL HAL:用户(client) <-> HIDL(hidl-gen) <-> HAL(service) <-> 驱动

3、Android8后推出的,为了能独立升级Framework和Vendor,按照规定格式和步骤编写代码即可;

2、架构

在这里插入图片描述

1、进程间通讯

对应的设备节点:/dev/hwbinder、/dev/vndbinder

通讯模型:client -> hwbinder/vndbinder-> service -> … -> kernel

2、Client调用的角色通常是什么?

1)framework/vendor java/native进程

3、service的形式,如何分辨?

1)形式:func(client) →binder那套(.hal 文件→hidl-gen工具-> impl.so)→ func(service,一般进测名有@)

1、
console:/ $ ps -A | grep android.hardware
system         219     1    9728   4852 0                   0 S android.hardware.keymaster@3.0-service
audioserver    235     1   21268   8916 0                   0 S android.hardware.audio@2.0-service
bluetooth      236     1    7716   3408 0                   0 S android.hardware.bluetooth@1.0-service
cameraserver   237     1   28412  11948 0                   0 S android.hardware.camera.provider@2.4-service
media          238     1   10232   4312 0                   0 S android.hardware.cas@1.0-service

2、
adb shell service list

2)HIDL HAL的库和进程 命名规范

1、@是分隔符,hidl-gen添加生成的,后面跟着版本号;

2、android.hardware.graphics.composer@1.0-service //Android.硬件.图形.合成器@版本号-服务端;

3)设备中的路径

system/bin/*

4、HIDL HAL的类型

1)根据service访问硬件的形式不同再细分为binderied和Passthrough;

2)为什么搞这么多分类?能简单的谁也不想复杂!

1、系统迭代升级带来的复杂度增加,不可避免;

2、涉及多个厂商,增加机制来实现互相配合;

3)文字总体来说不易理解和吸收,先上图
在这里插入图片描述

1、说明

passthrough:为了复用传统HAL,sevice按照传统HAL的一套去加载HAL so库;

binderied:sevice进程集成HAL层接口,直接访问硬件,优先使用这种,尤其是适配新硬件时;

另外Android还提供一种,直接framework进程,加载HAL层库访问硬件的方式,称为Same-Process HAL这样性能是最佳的,但不解耦;

2、passthrough、binderized、same-Process

binderized与passthrough的区别?>> hal的实现直接在HAL进程中,不再是传统so库
如何选择passthrough、binderized?passthrough是为了厂商过渡使用,而新的硬件应选择binderized方式;

3、实现一个HIDL HAL

通信流程:HIDL Client -> HIDL Service -> driver,重点实现Client->Service,访问driver按照类型后面逐一分析

1)HIDL的开发流程

先上图
在这里插入图片描述

3)说明

1、写一个HIDL HAL涉及的文件
1)可执行程序类:client、hidl.so、service
2)配置类:rc、te、current.txt 、xml
3)工具类(生成源码、bp):hidl_gen、sh

2、hidl-gen + hal 工具只是一个“开发过程中”可选用的工具,自己编写也完全OK;
1)hidl_gen 生成HWBinder通信部分的框架,接口实现需要我们去填充
2)最终还是我们常见的形式:client <-> .so(.h) <-> service  //client完全调用so接口通讯即可,servie 有用户代码(实现接口)和用于进程间通讯的框架代码(这个也是纯调用so接口即可)

3、谁来调用工具hidl_gen 根据hal生成框架代码?
1)可以使用shell调用工具;
2)也可以使用bp,新增字段hidl_interface,记得hal只是中间文件;

3、aidl/hidl tool源码
android\system\tools\

4、hidl lib
android\system\libhidl

5、用到的的shell脚本
1)android\hardware\interfaces\update-makefiles.sh
source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh  //将此sh的接口变量暴露出来,相当于include
do_makefiles_update \   //调用函数
  "android.hardware:hardware/interfaces" \
  "android.hidl:system/libhidl/transport"

2)android\system\tools\hidl\update-makefiles-helper.sh
function do_makefiles_update() { //调用hidl-gen工具}

2)HIDL HAL的语法
1、从hidl-gen工具来理解hal
hidl-gen -o hardware/interfaces/hidl_example/1.0/default -Lc++-impl -randroid.hardware:hardware/interfaces android.hardware.hidl_example@1.0
-o //输出目录
-L //生成类型
-r //指定package_name:root_dir
android.hardware.hidl_example@1.0 //package name

注意,在hal中包名和路径不是一一对应的,其中-r传入的相当于“环境变量”,用于映射包名 对应的实际路径
package android.hardware.hidl_example@1.0;  处理过程:根据包名(android.hardware)匹配根目录,拼接根目录:hardware/interfaces/hidl_example,其中“@”是hidl/aidl特有的语法,跟.其实是一样的,这样的设计有助于简化包名,import会更间接些;

2、hal中的import语句 同 package 同理,需要配合hidl-gen工具使用
import @1.0::IBootControl;

3、HIDL文件组成,与AIDL一样,分两部分:1)interface.hal与type.hal
4、default目录,由hidl_gen创建,用户指定:/hardware/interfaces/boot/1.0/default/

4、hidl 的bp语法
1)
hidl_interface {
    interfaces:[
        "android.hidl.base@1.0",   //依赖的接口,位于 system/libhidl/transport/base/1.0/IBase.hal,同时这也是package_name
    ]
}

3)创建HAL接口&生成impl库
1、编写接口
package android.hardware.hidl_example@1.0;
interface IExample {
    write(string ioctl) generates (int32_t result, string value);
};
2、hidl-gen生成框架代码文件,也可以自己捣鼓实现
3、在代码文件 实现接口具体内容
4、hidl-gen生成Android.bp,也可以自己捣鼓实现
hidl_interface {
    name: "android.hardware.hidl_example@1.0",
    root: "android.hardware",
    srcs: [
        "Example.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    gen_java: true,
}

注:hidl-gen会生成两部分:
1、需要暴露给开发者,生成在default/目录中
2、不需要暴露(getService等等),系统整编时会生成在out/soong/.intermediates/hardware/interfaces/
4)Service实现
1、与binder相似,较为统一和简单,使用hwbinder库接口注册服务
int main(int, char* []) {
    sp<IExample> hidl_example = new Example();
    configureRpcThreadpool(1, true /* callerWillJoin */);
    if (hidl_example->registerAsService() != OK) {
        ALOGE("registerAsService failed");
        return 1;
    }
    joinRpcThreadpool();
    ALOGE("Service exited");
    return 1;
}
5)Client实现
1、与binder相似,较为统一和简单,使用hwbinder库接口获取服务
int main() {
    android::sp<IExample> service = IExample::getService();
    if (service == nullptr) {
        printf("Failed to get service\n");
        return -1;
    }
    service->write("welcome to HIDL", [&]int32_t result, string value){
        printf("result %d %s\n", result, value.c_str());
    }); 
    return 0;
}
6)Configurations
基础文件准备好,剩下就是将其对接系统,让系统帮我们做事!主要有几个部分
1、上电启动怎么做? -> rc 配置文件

2、selinux限制权限怎么办? ->te 配置文件
1)接口hash值(通过函数所有的字符来计算hash值):/hardware/interfaces/current.txt
2)selinux - 规则先不管,只知道要加即可(main.te object.te object.txt)

3、注册信息? -> manifest.xml 配置文件,
1)称为VINTF(vendor interface),注册hwservicemanager的服务需要添加一个VINTF对象,作用是用来收集设备信息并生成可查询的API,用xml格式表示,包含hal接口版本\binder类型等。
2)设备路径:vendor/etc/vintf/manifest.xml
3)为什么不放在代码里面填充?配置分离,调试的时候不需要重新编译,在线改就好!
4)一般格式
<hal format="hidl">
    <name>android.hardware.hidl_example</name>
    <transport>hwbinder</transport>
    <version>1.0</version>
    <interface>
        <name>IExample</name>
        <instance>default</instance>
    </interface>

4、Passthroug HALS实例分析

参考:https://juejin.cn/post/7361204571827535924

1)重点分析HIDL Service -> driver部分,

例子:hardware/interfaces/vibrator/1.0
为了复用传统HAL  >> 大部分都是这种?位于hardware/interfaces/都是这种,判断标准是?

1、VINTF
<transport>hwbinder</transport>

1、
AN9:
android\frameworks\base\services\core\jni\com_android_server_VibratorService.cpp

一、HAL层服务端
1、android/hardware/interfaces/vibrator/1.0/default/service.cpp
defaultPassthroughServiceImplementation<IVibrator>();

2、android/system/libhidl/transport/include/hidl/LegacySupport.h
defaultPassthroughServiceImplementation<IVibrator>();
--registerPassthroughServiceImplementation
----sp<Interface> service = Interface::getService(name, true /* getStub*/); //此接口由系统编译时生成,注意getStub参数传入true
----return service->registerAsService(name); //注册hal服务

3、系统编译生成(根据hal的Android.bp文件生成)
out/soong/.intermediates/hardware/interfaces/vibrator/1.0/android.hardware.vibrator@1.0_genc++/gen/android/hardware/vibrator/1.0/VibratorAll.cpp
::android::sp<IVibrator> IVibrator::getService(const std::string &serviceName, const bool getStub) {
    return ::android::hardware::details::getServiceInternal<BpHwVibrator>(serviceName, true, getStub);
}

3、android/system/libhidl/transport/include/hidl/HidlTransportSupport.h
getServiceInternal
--getRawServiceInternal

4、system/libhidl/transport/ServiceManagement.cpp
1) getRawServiceInternal
--sm = defaultServiceManager1_1();// 获取 HwServiceManager 代理端对象。
--Return<Transport> transportRet = sm->getTransport(descriptor, instance); //获取vintf中的transport参数passthrough HAL 是 hwbinder
--
if (getStub || vintfPassthru || vintfLegacy) {
        const sp<IServiceManager> pm = getPassthroughServiceManager();
        if (pm != nullptr) {
            sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr); //调用PassthroughServiceManager 的 get 函数
            if (!getStub || trebleTestingOverride) {
                base = wrapPassthrough(base);
            }
            return base;
        }
    }
    

2) Return<sp<IBase>> get(const hidl_string& fqName, const hidl_string& name) override {
    openLibs()
    ret = (*generator)(name.c_str()); //调用HIDL_FETCH_IVibrator加载传统HAL库
}

5、android/hardware/interfaces/vibrator/1.0/default/Vibrator.cpp
IVibrator* HIDL_FETCH_IVibrator(const char * /*hal*/) {
    vibrator_device_t *vib_device;
    const hw_module_t *hw_module = nullptr;

    int ret = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, &hw_module);
    if (ret == 0) {
        ret = vibrator_open(hw_module, &vib_device);
        if (ret != 0) {
            ALOGE("vibrator_open failed: %d", ret);
        }
    } else {
        ALOGE("hw_get_module %s failed: %d", VIBRATOR_HARDWARE_MODULE_ID, ret);
    }

    if (ret == 0) {
        return new Vibrator(vib_device);
    } else {
        ALOGE("Passthrough failed to open legacy HAL.");
        return nullptr;
    }
}

5、binderied实例分析

1)重点分析HIDL Service -> driver

例子:android\hardware\interfaces\vibrator\1.3
基于Passthrough进行简单分析

1、VINTF
<transport>hwbinder</transport>

2、服务端
1)android\hardware\interfaces\vibrator\1.3\example\service.cpp
int main() {
    configureRpcThreadpool(1, true);
    status_t status = registerVibratorService();
}

status_t registerVibratorService() {
    sp<IVibrator> vibrator = new Vibrator();
    return vibrator->registerAsService();
}

2)android\hardware\interfaces\vibrator\1.3\example\Vibrator.cpp
HAL访问driver实现

3、客户端(java service -> jni -> getservice)
frameworks/base/services/core/java/com/android/server/VibratorService.java
本身是一个 Binder 服务端向 App 提供服务,同时也是一个 HwBinder 客户端通过 JNI 访问到 HAL 服务端

4、JNI
android\frameworks\base\services\core\jni\com_android_server_VibratorService.cpp (AN9)

Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) {
    // Assume that if getService returns a nullptr, HAL is not available on the
    // device.
    static sp<I> sHal = I::getService();  //获取hal服务
    static bool sAvailable = sHal != nullptr;

    if (!sAvailable) {
        return NullptrStatus<R>();
    }
}

6、same-process HAL

例子:hardware/interfaces/graphics/mapper
参考:https://blog.youkuaiyun.com/learnframework/article/details/134724489
基于Passthrough进行简单分析

1、直接链接so库,可以提高性能,但不解耦
>> 与Passthrougth 加载传统hal的区别?没有跨进程通信
2、same-Process : 客户端依然通过getservice接口去获取hal层接口;
3、same-process的方式较少,主要是显示相关,并且由google维护

1、VINTF
<transport arch="32+64">passthrough</transport>

2、与Passthrough相近,差异在于
1)只有so(该库会在client调用getservice时加载),没有service产生
android\hardware\interfaces\graphics\mapper\2.0\default\Android.bp
cc_library_shared {
    name: "android.hardware.graphics.mapper@2.0-impl",
...
}

2)
android\hardware\interfaces\graphics\mapper\2.0\default\passthrough.cpp
extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
    return GrallocLoader::load(); //load 传统hal库(比如gralloc_msm8909.so)
}

3)加载传统hal库
android\hardware\interfaces\graphics\mapper\2.0\utils\passthrough\include\mapper-passthrough\2.0\GrallocLoader.h
static IMapper* load() {
        const hw_module_t* module = loadModule();
        auto hal = createHal(module);
        return createMapper(std::move(hal));
}

static const hw_module_t* loadModule() {
        const hw_module_t* module;
        int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
        return module;
}

五、AIDL HAL(>=Android11)

1、概述

AIDL:Android interface definition language

1)使用:https://www.jianshu.com/p/d1fac6ccee98

2)知乎详解:https://zhuanlan.zhihu.com/p/338093696

3)Developers:https://developer.android.google.cn/guide/components/aidl?hl=zh-cn

小结:

1、Android的IPC通信机制,按照它定义的规则来即可;

2、应用层的原理,AIDL是Android独有的一门进程间通信语言,我们编写*.aidl文件,AS自动翻译为复杂一些的*.java文件;

3、HIDL HAL -> AIDL HAL的变化使得 JAVA应用层可直接访问HAL,是有进步的。

2、架构

来源:https://juejin.cn/post/7366848656615374883
在这里插入图片描述

1、访问HAL依然采用进程间通讯(binder);

2、模型:client -> binder -> service ->hw_get_module(),回到传统的AIDL binder通讯,使用AIDL工具生成进程间通讯代码;

3、相较于HIDL(HIDL本质上是AIDL的复制版本),不再细分进程间通信类型,CPP/JAVA层统一使用AIDL,这样更加灵活高效;

4、针对一些显示相关的hal,要求性能高,系统进程直接通过dlopen访问hal (空间换效率)- 称为stable-c hal,那么APP访问HAL只需要一个跨进程通信;

5、AIDL的使用详解(APP):https://blog.youkuaiyun.com/u014294681/article/details/88126988

3、AIDL开发流程

1、aidl工具,与hidl类似
android\system\tools\aidl
1)
// aidl executable
cc_binary_host {
    name: "aidl",
    defaults: ["aidl_defaults"],
    srcs: ["main.cpp"],
    static_libs: [
        "libaidl-common",
        "libbase",
        "liblog",
    ],
}
2)生成四种服务端代码(CPP/JAVA/NDK/RUST),转换实现的源码
转换为CPP:aidl_to_cpp.cpp (依赖libbinder)
转换为JAVA: aidl_to_java.cpp
转换为ndk :aidl_to_ndk.cpp (也是cpp代码,依赖libbinder_ndk,Google更推荐)
转换为rust:aidl_to_rust.cpp

4、AIDL-HAL实例分析

例子:android\hardware\interfaces\vibrator\aidl
这里给出的是HAL层实现的整体框架和实例,没有实现访问硬件的HAL接口,厂商可以参照这个来 开发自己的aidl-hal

1、文件树
│ Android.bp
├─aidl_api //历史aidl版本
│  └─android.hardware.vibrator
│      ├─1
│      ├─2
│      └─current
├─android //aidl文件
│  └─hardware
│      └─vibrator
│              ActivePwle.aidl
│              Braking.aidl
│              BrakingPwle.aidl
│              CompositeEffect.aidl
│              CompositePrimitive.aidl
│              Effect.aidl
│              EffectStrength.aidl
│              IVibrator.aidl
│              IVibratorCallback.aidl
│              IVibratorManager.aidl
│              PrimitivePwle.aidl
├─default //service及hal层接口实现
│  │  Android.bp //可借助aidl生成,开发人员需要调整
│  │  android.hardware.vibrator.xml
│  │  fuzzer.cpp
│  │  main.cpp  //aidl-service
│  │  vibrator-default.rc
│  │  Vibrator.cpp  //兼容旧的api,可借助aidl生成,接口需要开发人员实现
│  │  VibratorManager.cpp //新API,可借助aidl生成,接口需要开发人员实现
│  ├─apex //apex组件配置文件
│  │      Android.bp
│  │      apex_manifest.json
│  │      com.android.hardware.vibrator.avbpubkey
│  │      com.android.hardware.vibrator.pem
│  │      com.android.hardware.vibrator.pk8
│  │      com.android.hardware.vibrator.rc
│  │      com.android.hardware.vibrator.x509.pem
│  │      file_contexts
│  ├─example_java_client //APP访问HAL示例程序(APP -> AIDL HAL服务,不需经过Framework)
│  │  │  Android.bp
│  │  │  AndroidManifest.xml
│  │  │  getter.cpp
│  │  │  jarjar.txt
│  │  └─example
│  │      └─vib
│  │              MyActivity.java
│  └─include
│      └─vibrator-impl
│              Vibrator.h
│              VibratorManager.h
└─vts //测试套件

1)创建HAL接口&生成impl接口
1、
aidl_interface {
    name: "android.hardware.vibrator",
    vendor_available: true,
    host_supported: true,
    srcs: [
        "android/hardware/vibrator/*.aidl",
    ],
    stability: "vintf",
}

生成两部分:
1、需要暴露给开发者,生成在default/目录中 >> 构建库 libvibratorexampleimpl
2、不需要暴露,生成在out/soong/.... >> 构建库 android.hardware.vibrator-V2-ndk

2)aidl-Service
1、android\hardware\interfaces\vibrator\aidl\default\Android.bp
cc_library_static {
    name: "libvibratorexampleimpl",
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "android.hardware.vibrator-V2-ndk",
    ],
    srcs: [
        "Vibrator.cpp",
        "VibratorManager.cpp",
    ],
}

2、
android\hardware\interfaces\vibrator\aidl\default\Vibrator.cpp
android\hardware\interfaces\vibrator\aidl\default\VibratorManager.cpp
实现hal接口

aidl-service端是如何连接厂商的库的? 亦或aidl-service由厂商来管控?>> 应该是的,hidl也应如此!

3、
cc_binary {
    name: "android.hardware.vibrator-service.example",
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "android.hardware.vibrator-V2-ndk",
    ],
    static_libs: [
        "libvibratorexampleimpl",
    ],
    srcs: ["main.cpp"],
}
可以看出是用的是aidl生成的ndk服务器代码

2、android\hardware\interfaces\vibrator\aidl\default\main.cpp
int main() {
    ABinderProcess_setThreadPoolMaxThreadCount(0);
    // make a default vibrator service
    auto vib = ndk::SharedRefBase::make<Vibrator>();
    binder_status_t status = AServiceManager_addService(
            vib->asBinder().get(), Vibrator::makeServiceName("default").c_str());
    CHECK_EQ(status, STATUS_OK);

    // make the vibrator manager service with a different vibrator
    auto managedVib = ndk::SharedRefBase::make<Vibrator>();
    auto vibManager = ndk::SharedRefBase::make<VibratorManager>(std::move(managedVib));
    status = AServiceManager_addService(vibManager->asBinder().get(),
                                        VibratorManager::makeServiceName("default").c_str());
    CHECK_EQ(status, STATUS_OK);
    ABinderProcess_joinThreadPool();
    return EXIT_FAILURE;  // should not reach
}
将Vibrator和VibratorManager通过AServiceManager_addService接口注册服务
3)aidl-client-1
1)APP->AIDL-HAL
android\hardware\interfaces\vibrator\aidl\default\example_java_client\example\vib\MyActivity.java
import android.hardware.vibrator.IVibrator;
public class MyActivity extends Activity {
    public void onCreate(Bundle b){
        System.loadLibrary("example_vib_getter");
        IVibrator v = IVibrator.Stub.asInterface(gimme("android.hardware.vibrator.IVibrator/default")); //获取服务端接口,凭证是"android.hardware.vibrator.IVibrator/default"
    }
}

1、两个 App 的构建,一个在 Vendor 分区,一个在 Product 分区,不同分区的权限由SEpolicy来指定
2、如何指定app的运行分区? bp里面有字段可用(Android 10以上才可用),非运行分区,而是安装分区,分区被设置权限

4)aidl-client-2
1、APP -> Framework
1)frameworks/base/core/java/android/app/Activity.java
public Object getSystemService(@ServiceName @NonNull String name) {
    return super.getSystemService(name);
}
2)frameworks/base/core/java/android/view/ContextThemeWrapper.java
public Object getSystemService(String name) {
    return getBaseContext().getSystemService(name);
}
3)frameworks/base/core/java/android/app/ContextImpl.java
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}
4)frameworks/base/core/java/android/app/SystemServiceRegistry.java
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
    public final T getService(ContextImpl ctx) {
        service = createService(ctx); //创建一个SystemVibratorManager
        ret = service; 
        return ret;
    }
}

public class SystemVibratorManager  extends VibratorManager {
    private final IVibratorManagerService mService;
}


2、framework->JNI->aidl hal
1)frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
addService. 向 ServiceManager 注册一个 VibratorManagerService (binder) 服务。

2)VibratorManagerService调用JNI
frameworks/base/services/core/jni/com_android_server_vibrator_VibratorManagerService.cpp

static vibrator::ManagerHalController* gManager GUARDED_BY(gManagerMutex) = nullptr;
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject callbackListener) {
    std::unique_ptr<NativeVibratorManagerService> service =
            std::make_unique<NativeVibratorManagerService>(env, callbackListener);
    {
        std::lock_guard<std::mutex> lock(gManagerMutex);
        gManager = service->hal();
    }
    return reinterpret_cast<jlong>(service.release());
}

3)android\frameworks\native\services\vibratorservice\VibratorHalController.cpp
libvibratorservice.so >> 此库与传统的 hal VibratorService(java) 是有区别的!
一路调用
ManagerHalController() 构造函数中 connectManagerHal
--connectManagerHal
----waitForVintfService

defaultServiceManager 获取服务,name:"android.hardware.vibrator.IVibrator/default")
/android/frameworks/native/libs/binder/include/binder/IServiceManager.h
template<typename INTERFACE>
sp<INTERFACE> waitForVintfService(
        const String16& instance = String16("default")) {
    return waitForDeclaredService<INTERFACE>(
        INTERFACE::descriptor + String16("/") + instance);
}

template<typename INTERFACE>
sp<INTERFACE> waitForDeclaredService(const String16& name) {
    const sp<IServiceManager> sm = defaultServiceManager();
    if (!sm->isDeclared(name)) return nullptr;
    return interface_cast<INTERFACE>(sm->waitForService(name));
}

5、stable-c实例分析

与HIDL中的same-process有什么差别?
1)本质上没有差别,stable-c对应的就是same-process,但使用的框架不同,一个是HIDL框架(库)、一个是AIDL框架(库)

例子:android\hardware\interfaces\graphics\mapper\stable-c

1、
android\hardware\interfaces\graphics\mapper\stable-c\imapper5_abicheck.cpp
AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) {}
 _Nullable* _Nonnull  标注非空,通常用于代码注释和静态分析工具
 
2、对外接口定义(框架)- libimapper_providerutils.so
android\hardware\interfaces\graphics\mapper\stable-c\implutils\include\android\hardware\graphics\mapper\utils\IMapperProvider.h

3、实现 - mapper.minigbm.so (链接libimapper_providerutils.so,继承方式 实现 具体实现)
android\external\minigbm\cros_gralloc\mapper_stablec\Mapper.cpp

6、实现一个ADIL

1、https://juejin.cn/post/7369117524481966130
2、https://blog.youkuaiyun.com/learnframework/article/details/134945726
>跟着写一个例子,实践!

六、小结

1、AIDL和HIDL的区别?

AIDL用于应用程序与framework之间的IPC通信(java层)- Binder

HIDL用于framework与HAL层通信(C++层)- HwBinder

无论Binder/HwBinder都是使用Binder驱动完成通信;

AIDL还是HIDL,我们只需关注

1、如何新增接口?

2、查看/调试现有架构 - 只需关注client接口 ↔ service接口,中间过程不需太多关注!

2、较新的Android版本,如AN14上有多个版本的hal?

1)传统HAL / HIDL HAL / AIDL HAL是同时存在,源码都会保留,配置根据系统来配置!

2)视乎芯片厂商(主芯片/IOT)的选择,不一定跟着Google新的架构走!

3)不同版本的Android系统源代码 AIDL 与 HIDL的service也不尽相同

3、配置这么多,如何掌握?

实操、记录和总结!

4、Binder RPC 、HWBinder RPC 、AIDL for Hal区别?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值