Android框架之Camera(2)HAL及so库的加载
来源:互联网 发布:java并发编程实战下载 编辑:程序博客网 时间:2024/06/08 00:15
HAL层作为纽带,把Framework层的APIs和底层驱动连接起来。简言之,上层需要什么操作接口,HAL层就负责实现之。
HAL在整个Camera框架中的位置如下图红框:
Android Camera框架及Camera服务HAL(红框)
HAL层的代码编译为so库,通常位于/system/lib/hw/或/vender/lib/hw/目录下。接下来看下so库的加载实现。
广而知之,C/C++的入口为main()函数,Android应用的入口是主Activity的onCreate(),那so库的入口呢?就是:
int hw_get_module(const char *id, const struct hw_module_t **module)参数id:模块的名称,HAL的so库命名规则:xxx.yyy.so,所以这里的id就是"xxx"。之所以这么定是和so的查找规则对应的,稍后详述。
参数module:通过她获取指向实际模块对象的指针。
对于Camera,启动加载流程的函数:
/** * The id of this module */#define CAMERA_HARDWARE_MODULE_ID "camera"CameraService.cpp (frameworks\av\services\camera\libcameraservice)camera_module_t *mModule;void CameraService::onFirstRef(){ if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&mModule) < 0) { ALOGE("Could not load camera HAL module"); mNumberOfCameras = 0; } else {// so成功加载 ALOGI("Loaded \"%s\" camera module", mModule->common.name); mNumberOfCameras = mModule->get_number_of_cameras(); .... }}(const hw_module_t **)&mModule就展示了如何通过参数module获取指向Camera模块camera_module_t指针的方法。这是如何做到的呢?
在定义自己模块的时候,把hw_module_t成员放在起始位置,如这里的camera_module_t:
typedef struct camera_module { hw_module_t common; int (*get_number_of_cameras)(void); int (*get_camera_info)(int camera_id, struct camera_info *info); int (*set_callbacks)(const camera_module_callbacks_t *callbacks); void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);} camera_module_t;结构体成员的内存地址是连续的(记得kernel中的container_of吧),此刻指向common成员的指针和指向整个模块的指针在数值上就是相等的(简单理解可以认为是同一个指针),这样通过common就获取了自己模块的指针。
整个模块在实现HAL的时候已经分配好了空间且已经初始化:
camera_module_t HAL_MODULE_INFO_SYM = { common: { // init code }, get_number_of_cameras: camera_get_number_of_cameras, get_camera_info: camera_get_camera_info, set_callbacks:NULL, get_vendor_tag_ops:NULL};所以就可以通过获取到的指针操作自定义的模块的所有成员。
这是对上,对下就是so库的加载,看函数hw_get_module:
int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}int hw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module){ int status; int i; const struct hw_module_t *hmi = NULL; char prop[PATH_MAX]; char path[PATH_MAX]; char name[PATH_MAX]; if (inst) snprintf(name, PATH_MAX, "%s.%s", class_id, inst); else strlcpy(name, class_id, PATH_MAX); /* * Here we rely on the fact that calling dlopen multiple times on * the same .so will simply increment a refcount (and not load * a new copy of the library). * We also assume that dlopen() is thread-safe. */ /* Loop through the configuration variants looking for a module */ for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, prop); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH1, name, prop); if (access(path, R_OK) == 0) break; } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH2, name); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH1, name); if (access(path, R_OK) == 0) break; } } status = -ENOENT; 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); } return status;}这个函数很简单,主要做两件事:
1、拼凑so库的路径:路径+name+属性+".so"
路径之前提到过,/system/lib/hw、/vendor/lib/hw。
name就是穿进来的id,比如camera。
属性,这里指定的属性有:
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.product.device", "ro.board.platform", "ro.arch"};
so库的完整路径比如/system/lib/hw/camera.default.so等等。
2、查找库是否存在
我们看到,这些so是有优先级的,找到满意的即刻break,正应了句老话:弱水三千,只取一瓢饮。有了so库,调用load加载之。
扩展:onFirstRef()的来源及调用
C++里面有智能指针的概念,用于对象内存的自动释放;类似地,Android实现类似功能的是sp(Strong Pointer)、wp(Weak Pointer),要使用它们需要在定义自己类的时候继承RefBase类。RefBase概览:
class RefBase{public:voidincStrong(const void* id) const;voiddecStrong(const void* id) const;protected: RefBase(); virtual~RefBase virtual void onFirstRef();};onFirstRef()的来源有了。来看其调用过程:
void RefBase::incStrong(const void* id) const{ weakref_impl* const refs = mRefs; refs->incWeak(id); refs->addStrongRef(id); const int32_t c = android_atomic_inc(&refs->mStrong); ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);#if PRINT_REFS ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);#endif if (c != INITIAL_STRONG_VALUE) { return; } android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); refs->mBase->onFirstRef();}创建一个对象,它的引用计数就自动加1;如果是第一次引用,12行分支不执行,则onFirstRef()函数会被调用,即CameraService#onFirstRef()。
我们写一个小程序体验下:
#include <utils/Errors.h>#include <utils/RefBase.h>#include <utils/String16.h>#include <utils/Vector.h>namespace android {class ITest: public virtual RefBase{public:ITest() {printf("ITest create.\n");}private:virtual void onFirstRef();};void ITest::onFirstRef(){printf("onFirstRef\n");}};using namespace android;int main(int argc, char **argv){sp<ITest> spTest(new ITest());return 0;}Log:
ITest create.onFirstRef
阅读全文
0 0
- Android框架之Camera(2)HAL及so库的加载
- HAL so库加载机制---之二
- Android Camera的HAL接口
- Android开发之fsl在HAL层Camera的实现
- Android开发之fsl在HAL层Camera的实现
- camera-HAL框架
- 插件框架篇一之插件so库的加载
- HAL so库加载机制---之一
- Android之Camera拍照插值算法 &&Android4.2之Camera系统HAL调用流程
- Android Camera Hal 的初步实现1
- Android Camera Hal 的初步实现1
- Android 加载 SO 库 UnsatisfiedLinkError 错误的原因及解决方案
- Android之 Camera 框架
- android camera HAL
- Android Camera HAL浅析
- Android Camera HAL浅析
- android camera HAL
- Android Camera HAL浅析
- myecplise+mysql代码测试
- 商城项目实战17:商品类目选择的实现
- 数据结构_4_迷宫问题
- hosts文件
- Intermediate Python笔记
- Android框架之Camera(2)HAL及so库的加载
- MATLAB作图技巧汇总
- 商城项目实战18:分布式文件系统FastDFS
- 奇异值分解(SVD)的理解
- 单链表
- Spark统计唯一值、缺失值和单值的算子(scala实现)
- USACO-Secition1.3 Barn Repair [贪心]
- android高斯模糊的简单实现
- 美丽心灵的永恒阳光