最近一直在研究GPS的HAL,细节之处还不是很熟悉,但是看了两周的代码,有了自己的一些浅薄之见。 先来看看整体的架构。 - LocationManager --- AP
- LocationManagerService --- Framework
- GpsLocationProvider --- Framework
- Com_android_server_location_GpsLocationProvider --- JNI
- GPS HAL --- HAL
- GPS driver --- driver
- GPS devices --- hardware devices
复制代码以上是从上至下的整体架构(人懒,没画图)。整个的调用流程就是这样的。从AP到JNI的调用流程在此不再赘述。我们看下JNI到driver的调用流程。重点看下HAL的架构。
HAL的演进 HAL以前是以module来被调用的。所谓modlue,就是将c文件编译成so文件,然后在jni中加载调用。此种方式现在在源码的libhardware_legacy文件夹下。后来hal的架构改变,变成了以stub的形式来被上层调用。这样就有种面向对象的思想了。虽然也是编译成so文件然后加载,但是JNI是直接调用c对象。这种层次更清晰,而且更易于维护和扩展。
GPS HAL的详细架构
以上,我们可以看到,gps_module_t继承hw_device_t。而hw_device_t的结构如右图。 可能我们看到这副架构图还是有点不能理解,那么下面我们看代码,来了解下。 首先,从JNI调用开始。 代码路径:framework/base/services/jni/Com_android_server_location_GpsLocationProvider.cpp 由于此文件中的函数android_location_provider_class_init_native()在java的static块中运行,所以此函数最先被调用。 在此函数中,主要做了一下几件事情。 JNI层传入module ID,hw_get_module传入ID得到hw_module_t。
这一步主要实现是在hardward.c中 代码路径:libhardware/hardware.c - int hw_get_module(const char *id,const struct hw_module_t **module)
- {
- return hw_get_module_by_class(id, NULL, module);
- }
复制代码 继续追踪hw_get_module_by_class(id, NULL, module),代码仍然在hardware.c中- int hw_get_module_by_class(const char *class_id, const char *inst,const struct hw_module_t **module){
- if (i < HAL_VARIANT_KEYS_COUNT+1) {
- /* load the module, if this fails, we're doomed,and we should not try
- * to load a different variant. */
- status = load(class_id, path, module);
- }
复制代码 load函数真正加载id得到hw_module_t。
紧接着在JNI中gps_module_t向上转型成为hw_device_t
然后利用hw_module_t调用open。
调用了open之后,就会走到厂商自定义的接口里了,对gps_module_t进行赋值并向下转型。那么我们就拿到了最终要调用的对象gps_module_t了
利用gps_module_t,我们可以访问HAL里的函数,就达到了JNI调用HAL的目的了。
|