android HAL浅探
又挖一个坑,好久没写了,看得代码多而繁乱,又没有专精一块,到头来还是困惑丛生,不管了,做个笔记,写写自己对android hal层的一点理解。
涉及的代码来自android-4.0版本。
1.概念和原因
android hal的概念和存在的原因,不必多说,其实就两点。1.隔离具体驱动接口的变化,2.保护硬件厂商的关键信息。
通过这一层的封装
1.各类硬件(fb,gps,sensor)只需要实现规定的接口即可,驱动接口的不兼容(比如各种硬件设备的ioctl,很可能是厂商自己规定的命令),可以隔离变化。
2.硬件厂商在封装的接口,只需提供一个so即可,使用时,用dlopen hook到相关的接口,不用开放源代码,可以保护一些敏感信息。
总体来说,这层位于kernel/driver之上,framework层之下。
(都是废话,没有干货,呵呵)
2.硬件相关代码位置
在hardware/libhardware/include/hardware目录里面,可以看到目前使用这种方式抽象的硬件种类大致有如下几种。(btw,android貌似还有另外的方式操作硬件,具体的我没看明白,貌似wifi的方式就不太一样,好像是通过协议栈来操作的,对这块不熟悉,只是随便看了看)
audio(声卡,我姑且这么叫,这块驱动层次都有若干标准,让人头晕眼花,比如oss/alsa/jack/等等等。。。这还不是最可恶的,他们还可以互为后端,比oss接口封装成alsa,或者反过来,我去。。。)
camera(摄像头,不多说, 主要我也不太懂,这块linux到是有标准接口,v4l2--->video for linux 2,移植所需要做的工作就是把v4l2接口封装成android规定的,呵呵)
gps(定位,这个真是一点没研究过了)
sensor(传感器,指南针,重力加速度,压力,位置,。。。)
lights(背光,调节背光强弱的)
display(显示相关的几个设备,fb-->framebuffer,应该对应的是屏幕,仅仅是屏幕,不包括显存,gralloc这个设备,才对应的是真正的显存及其操作,hwcomposer,其实就是overlay了,播放视频时需要,ps:这里的display仅仅指lcd,不包括hdmi,vga等等,呵呵)
3.display设备被调用的方式
我主要看了display所需要的硬件设备,其他设备,精力和兴趣的原因,没有多看。
android display最终的显示的数据都会交给surfaceflinger(直译,屏幕投递者,呵呵),所以操作display硬件的代码这里一定会有。
在framework/base/services/surfaceflinger/displayhardware目录下面,封装了这部分接口,我们可以通过研究这块接口封装,来看到具体硬件是如何被抽象的。
首先,我对surfaceflinger也没非常通彻的理解,只了解一个大概,所以,我只说流程,不说细节。
1.先看surfaceflinger构造函数能不能发现什么,貌似没有发现new displayhardware之类的语句,那这些操作在哪里?我们知道surfaceflinger从Thread和sp继承,那还有两个地方可以去瞧瞧。
1).onfirstref,sp模板构造出来的类,这个函数是首先会被调用的,不过貌似这里也没有,只有一个run(启动线程)
2).readyToRun,这个函数,在run之前一定会被调用一把的,进去一看,发现我们想要的DisplayHardware* const hw = new DisplayHardware(this, dpy)语句,哈哈,这里构造了display硬件的对应的类。
2.DisplayHardware构造函数
这个类上面所说的三类硬件,又归结了两类,
1).FramebufferNativeWindow(这个对应了fb与gralloc,抽象的具体代码在framework/base/libs/ui,这个库里面包括了ui相关所有东西,显示,输入消息,按键映射等等),
2).HWComposer(这个对应了hwcomposer)
(感觉都是一堆废话,都明白的东西,居然还没讲到如何调用)
好吧,我们再简单一点,直接进去看hwcomposer是如何调用的
hardware.h里面给了两个函数,
hw_get_module
hw_get_module_by_class
具体就是,你传一个硬件id(每种硬件,对应一个id,id是字符串,各不相同)下来,我把这个module对应的接口给你。
来看hwcomposer的构造函数。里面调用了hw_get_module,他对应的id是HWC_HARDWARE_MODULE_ID,
在hardware/libhardware/include/hwcomposer.h看到 #define HWC_HARDWARE_MODULE_ID "hwcomposer"
同时其他对应的文件里面,fb的id是 #define GRALLOC_HARDWARE_FB0 "fb0"
gralloc的id是 #define GRALLOC_HARDWARE_MODULE_ID "gralloc"
我们看看最关键的地方hw_get_module是如何实现的。这个关键点在于load函数。
load函数dlopen相关的vendor库,然后通过dlsym找一个HAL_MODULE_INFO_SYM_AS_STR的全局变量(#define HAL_MODULE_INFO_SYM_AS_STR "HMI",其实就是对应了HAL_MODULE_INFO_SYM这个)
这个我认为是最关键的点,就找这个全局变量,所有设备编译出来的so库,都要包括这个hmi的变量,可以通过查看代码来验证这个猜测。
这个地方找到之后,就完全了软硬件合体了。
这里不仅可以找到common的open接口,也可以找到各种私有接口,
比如fb就规定了六个接口
int (*setSwapInterval)(struct framebuffer_device_t* window,int interval);
int (*setUpdateRect)(struct framebuffer_device_t* window,int left, int top, int width, int height);
int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
int (*compositionComplete)(struct framebuffer_device_t* dev);
void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);
int (*enableScreen)(struct framebuffer_device_t* dev, int enable);
底层实现这几个接口即可。
看完overlay硬件的抽象方式,再按这个思路去看fb,gralloc,gps,会发现他们的过程完全一致。也许大家一直这么做的,但是我是从android里面知道这样的隔离变化方案的,很好很强大。谢谢谷歌。
over。
有点乱,过程就是这样了,自己的笔记,不喜勿喷。