当前位置:首页 > > 充电吧
[导读]作者:华清远见讲师上一篇我们分析了android HAL层的主要的两个结构体hw_module_t(硬件模块)和hw_device_t(硬件设备)的成员,下面我们来具体看看上层app到底是怎么实现操作

作者:华清远见讲师


上一篇我们分析了android HAL层的主要的两个结构体hw_module_t(硬件模块)和hw_device_t(硬件设备)的成员,下面我们来具体看看上层app到底是怎么实现操作硬件的?

我们知道,一些硬件厂商不愿意将自己的一些核心代码开放出去,所以将这些代码放到HAL层,但是怎么保证它不开放呢?HAL层代码不是也让大家知道下载吗?其实硬件厂商的HAL核心代码是以共享库的形式出现的,每次在需要的时候,hal会自动加载调用相关共享库。那么是怎么加载找到某一硬件设备对应的共享库的呢?这也是我们这篇都要说的。

上层app通过jni调用hal层的hw_get_module函数获取硬件模块,这个函数是上层与hal打交道的入口。所以如果我们以程序调用执行的流程去看源码的话,这个函数就是hal层第一个被调用的函数,下面我们就

从这个函数开始,沿着程序执行的流程走下去。

hw_get_module函数定义在/hardware/libhardware/hardware.c中,打开这个文件可以看到定义如下:

1 int hw_get_module(const char *id, const struct hw_module_t **module)

2 {

3 int status;

4 int i;

5 const struct hw_module_t *hmi = NULL;

6 char prop[PATH_MAX];

7 char path[PATH_MAX];

8

9 /*

10 * Here we rely on the fact that calling dlopen multiple times on

11 * the same .so will simply increment a refcount (and not load

12 * a new copy of the library).

13 * We also assume that dlopen() is thread-safe.

14 */

15

16 /* Loop through the configuration variants looking for a module */

17 for (i=0 ; i

18 if (i < HAL_VARIANT_KEYS_COUNT) {

19 if (property_get(variant_keys[i], prop, NULL) == 0) {//获取属性

20 continue;

21 }

22 snprintf(path, sizeof(path), "%s/%s.%s.so",

23 HAL_LIBRARY_PATH1, id, prop);

24 if (access(path, R_OK) == 0) break;//检查system路径是否有库文件

25

26 snprintf(path, sizeof(path), "%s/%s.%s.so",

27 HAL_LIBRARY_PATH2, id, prop);

28 if (access(path, R_OK) == 0) break;//检查vender路径是否有库文件

29 } else {

30 snprintf(path, sizeof(path), "%s/%s.default.so",//如果都没有,则使用缺省的

31 HAL_LIBRARY_PATH1, id);

32 if (access(path, R_OK) == 0) break;

33 }

34 }

35

36 status = -ENOENT;

37 if (i < HAL_VARIANT_KEYS_COUNT+1) {

38 /* load the module, if this fails, we're doomed, and we should not try

39 * to load a different variant. */

40 status = load(id, path, module);//装载库,得到module

41 }

42

43 return status;

44 }

看第一行我们知道有两个参数,第一参数id就是要获取的硬件模块的id,第二个参数module就是我们想得到的硬件模块结构体的指针。

所以可以看出,上层首先给hal需要获取的硬件模块的id,hw_get_module函数根据这个id去查找匹配和这个id对应的硬件模块结构体的。

下面看看怎么找的。

17行有个for循环,上限是HAL_VARIANT_KEYS_COUNT+1,那么这个HAL_VARIANT_KEYS_COUNT是什么呢?查看同文件下找到有:

static const int HAL_VARIANT_KEYS_COUNT =

(sizeof(variant_keys)/sizeof(variant_keys[0]));

原来它是ariant_keys这个数组的元素个数。那么这个数组又是什么呢?在本文件找,有:

/**

* There are a set of variant filename for modules. The form of the filename

* is ".variant.so" so for the led module the Dream variants

* of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:

*

* led.trout.so

* led.msm7k.so

* led.ARMV6.so

* led.default.so

*/

static const char *variant_keys[] = {

"ro.hardware", /* This goes first so that it can pick up a different

file on the emulator. */

"ro.product.board",

"ro.board.platform",

"ro.arch"

};

可以看到它其实是个字符串数组。站且不知道干什么的。继续看hw_get_module函数,进入for循环里面,看22行,其实它是将HAL_LIBRARY_PATH1, id, prop这三个串拼凑一个路径出来,

HAL_LIBRARY_PATH1定义如下:

/** Base path of the hal modules */

#define HAL_LIBRARY_PATH1 "/system/lib/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

id是上层提供的,prop这个变量的值是前面19行property_get(variant_keys[i], prop, NULL)函数获取到的,其实这个函数是通过ariant_keys数组的的属性查找到系统中对应的变种名称。不同的平台获取到prop值是不一样的。

假如在获取到的prop值是tout,需要获取的硬件模块的id是leds,那么最后path组成的串是/system/lib/hw/leds.tout.so。

后面24行access是检查这个路径下是否存在,如果有就break,跳出循环。如果没有,继续走下面,

可以看到下面几行和刚才形式差不多,

snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, id, prop);

if (access(path, R_OK) == 0) break;//检查vender路径是否有库文件

结合 HAL_LIBRARY_PATH2 为"/vendor/lib/hw",假设同样获取到的prop值是tout,需要获取的硬件模块的id是leds,这种情况下path拼出来的值是/vender/lib/hw/leds.tout.so,然后在判断文件是否存在。如果存在跳出循环。

从以上分析,其实这就是hal层搜索动态共享库的方式,从中我们可以得到两点:

1.动态共享库一般放在 "/system/lib/hw"和"/vendor/lib/hw"这两个路径下。

2.动态库的名称是以"id.variant.so"的形式命名的,其中id为上层提供,中间variant为变种名称,是随系统平台变化的。

接着,从29到32行我们可以看到,当所有变种名称形式的包都不存在时,就以"id.default.so"形式包名查找是否存在。

37行, if (i < HAL_VARIANT_KEYS_COUNT+1),如果i小于变种名称数组的话,表示找到了对应的库,那么38行load(id, path, module);//装载库,得到module。

以上就对hal层搜索库的规则搞清楚了。

下一篇我们将进入load函数,看看共享库是如何被加载的。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭