Android HAL的被调用流程

来源:互联网 发布:折半查找递归算法 编辑:程序博客网 时间:2024/06/05 08:52
在Android系统中,对于硬件的操作,使用HAL Stub的方式来实现。HAL Stub的具体写法请参照Android中HAL如何向上层提供接口总结
在我们写完HAL Stub之后,这个HAL Stub是如何被应用获取,如何被应用程序调用的呢?
显然,由于HAL Stub本质上是一个.so,在调用之后,需要上层应用对其进行加载,然后才能调用。哪么,HAL Stub的加载器是如何实现对不同的Hardware HAL Stub进行通用性调用的呢? 按常规,每个Hareware HAL Stub应该有一个唯一的名字,且有一个通用的规则和一个入口函数。下面看看HAL Stub是如何实现这两个功能的。下面的描述以gralloc为例。

1. 唯一的id

[cpp] view plaincopyprint?

  1. #define GRALLOC_HARDWARE_MODULE_ID “gralloc”

[cpp] view plain copy
print?
  1. #define GRALLOC_HARDWARE_MODULE_ID “gralloc”  
#define GRALLOC_HARDWARE_MODULE_ID "gralloc"


2. hw_module_t实例

每个硬件模块都有一个包含hw_module_t(为第一个成员)数据结构的实例,且实例的名字为:HAL_MODULE_INFO_SYM,它本身是一个宏定义,其定义如下:

hardware.h (通用的东东都在hardware.h和hardware.c中)

[cpp] view plaincopyprint?

  1. /*
  2. Name of the hal_module_info
  3. */
  4. #define HAL_MODULE_INFO_SYM HMI //.so中将一个符号HMI,获取此符号的地址,就获取到了对应的hw_module_t地址
  5. /*
  6. Name of the hal_module_info as a string
  7. */
  8. #define HAL_MODULE_INFO_SYM_AS_STR “HMI”

[cpp] view plain copy
print?
  1. /** 
  2.  * Name of the hal_module_info 
  3.  */  
  4. #define HAL_MODULE_INFO_SYM         HMI //.so中将一个符号HMI,获取此符号的地址,就获取到了对应的hw_module_t地址  
  5.   
  6. /** 
  7.  * Name of the hal_module_info as a string 
  8.  */  
  9. #define HAL_MODULE_INFO_SYM_AS_STR  “HMI”  
/** * Name of the hal_module_info */
#define HAL_MODULE_INFO_SYM HMI //.so中将一个符号HMI,获取此符号的地址,就获取到了对应的hw_module_t地址/** * Name of the hal_module_info as a string */#define HAL_MODULE_INFO_SYM_AS_STR "HMI"

[cpp] view plaincopyprint?

  1. /*
  2. Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
  3. * and the fields of this data structure must begin with hw_module_t
  4. * followed by module specific information.
  5. */
  6. typedef struct gralloc_module_t {
  7. struct hw_module_t common;
  8. int (*registerBuffer)(struct gralloc_module_t
    const* module,
  9. buffer_handle_t handle);
  10. int (*unregisterBuffer)(struct gralloc_module_t
    const* module,
  11. buffer_handle_t handle);
  12. int (*lock)(struct gralloc_module_t
    const* module,
  13. buffer_handle_t handle, int usage,
  14. int l, int t,
    int w, int h,
  15. void** vaddr);
  16. int (*unlock)(struct gralloc_module_t
    const* module,
  17. buffer_handle_t handle);
  18. /* reserved for future use */
  19. int (*perform)(struct gralloc_module_t
    const* module,
  20. int operation, … );
  21. /* reserved for future use */
  22. void* reserved_proc[7];
  23. }

[cpp] view plain copy
print?
  1. /** 
  2.  * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM 
  3.  * and the fields of this data structure must begin with hw_module_t 
  4.  * followed by module specific information. 
  5.  */  
  6. typedef struct gralloc_module_t {  
  7.     struct hw_module_t common;  
  8.       
  9.     int (*registerBuffer)(struct gralloc_module_t const* module,  
  10.             buffer_handle_t handle);  
  11.   
  12.     int (*unregisterBuffer)(struct gralloc_module_t const* module,  
  13.             buffer_handle_t handle);  
  14.       
  15.     int (*lock)(struct gralloc_module_t const* module,  
  16.             buffer_handle_t handle, int usage,  
  17.             int l, int t, int w, int h,  
  18.             void** vaddr);  
  19.       
  20.     int (*unlock)(struct gralloc_module_t const* module,  
  21.             buffer_handle_t handle);  
  22.   
  23.     /* reserved for future use */  
  24.     int (*perform)(struct gralloc_module_t const* module,  
  25.             int operation, … );  
  26.     /* reserved for future use */  
  27.     void* reserved_proc[7];  
  28. }  
/** * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM * and the fields of this data structure must begin with hw_module_t * followed by module specific information. */typedef struct gralloc_module_t {    struct hw_module_t common;    int (*registerBuffer)(struct gralloc_module_t const* module,            buffer_handle_t handle);    int (*unregisterBuffer)(struct gralloc_module_t const* module,            buffer_handle_t handle);    int (*lock)(struct gralloc_module_t const* module,            buffer_handle_t handle, int usage,            int l, int t, int w, int h,            void** vaddr);    int (*unlock)(struct gralloc_module_t const* module,            buffer_handle_t handle);    /* reserved for future use */    int (*perform)(struct gralloc_module_t const* module,            int operation, ... );    /* reserved for future use */    void* reserved_proc[7];}
[cpp] view plaincopyprint?

  1. struct private_module_t {
  2. gralloc_module_t base;
  3. struct private_handle_t* framebuffer;
  4. uint32_t flags;
  5. uint32_t numBuffers;
  6. uint32_t bufferMask;
  7. pthread_mutex_t lock;
  8. buffer_handle_t currentBuffer;
  9. int pmem_master;
  10. void* pmem_master_base;
  11. unsigned long master_phys;
  12. int gpu;
  13. void* gpu_base;
  14. int fb_map_offset;
  15. struct fb_var_screeninfo info;
  16. struct fb_fix_screeninfo finfo;
  17. float xdpi;
  18. float ydpi;
  19. float fps;
  20. };

[cpp] view plain copy
print?
  1. struct private_module_t {  
  2.     gralloc_module_t base;  
  3.   
  4.     struct private_handle_t* framebuffer;  
  5.     uint32_t flags;  
  6.     uint32_t numBuffers;  
  7.     uint32_t bufferMask;  
  8.     pthread_mutex_t lock;  
  9.     buffer_handle_t currentBuffer;  
  10.     int pmem_master;  
  11.     void* pmem_master_base;  
  12.     unsigned long master_phys;  
  13.     int gpu;  
  14.     void* gpu_base;  
  15.     int fb_map_offset;  
  16.   
  17.     struct fb_var_screeninfo info;  
  18.     struct fb_fix_screeninfo finfo;  
  19.     float xdpi;  
  20.     float ydpi;  
  21.     float fps;  
  22. };  
struct private_module_t {    gralloc_module_t base;    struct private_handle_t* framebuffer;    uint32_t flags;    uint32_t numBuffers;    uint32_t bufferMask;    pthread_mutex_t lock;    buffer_handle_t currentBuffer;    int pmem_master;    void* pmem_master_base;    unsigned long master_phys;    int gpu;    void* gpu_base;    int fb_map_offset;    struct fb_var_screeninfo info;    struct fb_fix_screeninfo finfo;    float xdpi;    float ydpi;    float fps;};

其实例为:

[cpp] view plaincopyprint?

  1. static struct hw_module_methods_t gralloc_module_methods = {
  2. open: gralloc_device_open
  3. };

[cpp] view plain copy
print?
  1. static struct hw_module_methods_t gralloc_module_methods = {  
  2.         open: gralloc_device_open  
  3. };  
static struct hw_module_methods_t gralloc_module_methods = {        open: gralloc_device_open};

[cpp] view plaincopyprint?

  1. struct private_module_t HAL_MODULE_INFO_SYM = {
  2. base: {
  3. common: {
  4. tag: HARDWARE_MODULE_TAG,
  5. version_major: 1,
  6. version_minor: 0,
  7. id: GRALLOC_HARDWARE_MODULE_ID,
  8. name: “Graphics Memory Allocator Module”,
  9. author: “The Android Open Source Project”,
  10. methods: &gralloc_module_methods
  11. },
  12. registerBuffer: gralloc_register_buffer,
  13. unregisterBuffer: gralloc_unregister_buffer,
  14. lock: gralloc_lock,
  15. unlock: gralloc_unlock,
  16. },
  17. framebuffer: 0,
  18. flags: 0,
  19. numBuffers: 0,
  20. bufferMask: 0,
  21. lock: PTHREAD_MUTEX_INITIALIZER,
  22. currentBuffer: 0,
  23. };

[cpp] view plain copy
print?
  1. struct private_module_t HAL_MODULE_INFO_SYM = {  
  2.     base: {  
  3.         common: {  
  4.             tag: HARDWARE_MODULE_TAG,  
  5.             version_major: 1,  
  6.             version_minor: 0,  
  7.             id: GRALLOC_HARDWARE_MODULE_ID,  
  8.             name: ”Graphics Memory Allocator Module”,  
  9.             author: ”The Android Open Source Project”,  
  10.             methods: &gralloc_module_methods  
  11.         },  
  12.         registerBuffer: gralloc_register_buffer,  
  13.         unregisterBuffer: gralloc_unregister_buffer,  
  14.         lock: gralloc_lock,  
  15.         unlock: gralloc_unlock,  
  16.     },  
  17.     framebuffer: 0,  
  18.     flags: 0,  
  19.     numBuffers: 0,  
  20.     bufferMask: 0,  
  21.     lock: PTHREAD_MUTEX_INITIALIZER,  
  22.     currentBuffer: 0,  
  23. };  
struct private_module_t HAL_MODULE_INFO_SYM = {    base: {        common: {            tag: HARDWARE_MODULE_TAG,            version_major: 1,            version_minor: 0,            id: GRALLOC_HARDWARE_MODULE_ID,            name: "Graphics Memory Allocator Module",            author: "The Android Open Source Project",            methods: &gralloc_module_methods        },        registerBuffer: gralloc_register_buffer,        unregisterBuffer: gralloc_unregister_buffer,        lock: gralloc_lock,        unlock: gralloc_unlock,    },    framebuffer: 0,    flags: 0,    numBuffers: 0,    bufferMask: 0,    lock: PTHREAD_MUTEX_INITIALIZER,    currentBuffer: 0,};


3. 从HAL Stub(.so)中获取hw_module_t(即private_module_t)

调用函数int hw_get_module(const char *id, const struct hw_module_t **module),其中id为就是1中所讲的GRALLOC_HARDWARE_MODULE_ID,第二个参数为我们要获取的hw_module_t。

下面以在FramebufferNativeWindow::FramebufferNativeWindow中的调用流程为例(FramebufferNativeWindow实现FrameBuffer的管理,它主要被SurfaceFlinger使用,也可以被OpenGL Native程序使用。在本质上,它在Framebuffer之上实现了一个ANativeWindow,目前它只管理两个buffers:front and back buffer.)

[cpp] view plaincopyprint?

  1. FramebufferNativeWindow::FramebufferNativeWindow()
  2. : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
  3. {
  4. hw_module_t const* module;
  5. if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
  6. int stride;
  7. int err;
  8. int i;
  9. err = framebuffer_open(module, &fbDev);
  10. LOGE_IF(err, “couldn’t open framebuffer HAL (%s)”, strerror(-err));
  11. err = gralloc_open(module, &grDev);
  12. LOGE_IF(err, “couldn’t open gralloc HAL (%s)”, strerror(-err));
  13. // bail out if we can’t initialize the modules
  14. if (!fbDev || !grDev)
  15. return;
  16. mUpdateOnDemand = (fbDev->setUpdateRect != 0);
  17. // initialize the buffer FIFO
  18. mNumBuffers = NUM_FRAME_BUFFERS;
  19. mNumFreeBuffers = NUM_FRAME_BUFFERS;
  20. mBufferHead = mNumBuffers-1;
  21. for (i = 0; i < mNumBuffers; i++)
  22. {
  23. buffers[i] = new NativeBuffer(
  24. fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
  25. }
  26. for (i = 0; i < mNumBuffers; i++)
  27. {
  28. err = grDev->alloc(grDev,
  29. fbDev->width, fbDev->height, fbDev->format,
  30. GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
  31. LOGE_IF(err, “fb buffer %d allocation failed w=%d, h=%d, err=%s”,
  32. i, fbDev->width, fbDev->height, strerror(-err));
  33. if (err)
  34. {
  35. mNumBuffers = i;
  36. mNumFreeBuffers = i;
  37. mBufferHead = mNumBuffers-1;
  38. break;
  39. }
  40. }
  41. const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
  42. const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
  43. const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
  44. const_cast<int&>(ANativeWindow::minSwapInterval) =
  45. fbDev->minSwapInterval;
  46. const_cast<int&>(ANativeWindow::maxSwapInterval) =
  47. fbDev->maxSwapInterval;
  48. }
  49. else
  50. {
  51. LOGE(“Couldn’t get gralloc module”);
  52. }
  53. ANativeWindow::setSwapInterval = setSwapInterval;
  54. ANativeWindow::dequeueBuffer = dequeueBuffer;
  55. ANativeWindow::lockBuffer = lockBuffer;
  56. ANativeWindow::queueBuffer = queueBuffer;
  57. ANativeWindow::query = query;
  58. ANativeWindow::perform = perform;
  59. }

[cpp] view plain copy
print?
  1. FramebufferNativeWindow::FramebufferNativeWindow()   
  2.     : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)  
  3. {  
  4.     hw_module_t const* module;  
  5.     if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {  
  6.         int stride;  
  7.         int err;  
  8.         int i;  
  9.         err = framebuffer_open(module, &fbDev);  
  10.         LOGE_IF(err, ”couldn’t open framebuffer HAL (%s)”, strerror(-err));  
  11.           
  12.         err = gralloc_open(module, &grDev);  
  13.         LOGE_IF(err, ”couldn’t open gralloc HAL (%s)”, strerror(-err));  
  14.   
  15.         // bail out if we can’t initialize the modules  
  16.         if (!fbDev || !grDev)  
  17.             return;  
  18.           
  19.         mUpdateOnDemand = (fbDev->setUpdateRect != 0);  
  20.           
  21.         // initialize the buffer FIFO  
  22.         mNumBuffers = NUM_FRAME_BUFFERS;  
  23.         mNumFreeBuffers = NUM_FRAME_BUFFERS;  
  24.         mBufferHead = mNumBuffers-1;  
  25.   
  26.         for (i = 0; i < mNumBuffers; i++)  
  27.         {  
  28.                 buffers[i] = new NativeBuffer(  
  29.                         fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);  
  30.         }  
  31.   
  32.         for (i = 0; i < mNumBuffers; i++)  
  33.         {  
  34.                 err = grDev->alloc(grDev,  
  35.                         fbDev->width, fbDev->height, fbDev->format,  
  36.                         GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);  
  37.   
  38.                 LOGE_IF(err, ”fb buffer %d allocation failed w=%d, h=%d, err=%s”,  
  39.                         i, fbDev->width, fbDev->height, strerror(-err));  
  40.   
  41.                 if (err)  
  42.                 {  
  43.                         mNumBuffers = i;  
  44.                         mNumFreeBuffers = i;  
  45.                         mBufferHead = mNumBuffers-1;  
  46.                         break;  
  47.                 }  
  48.         }  
  49.   
  50.         const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;   
  51.         const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;  
  52.         const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;  
  53.         const_cast<int&>(ANativeWindow::minSwapInterval) =   
  54.             fbDev->minSwapInterval;  
  55.         const_cast<int&>(ANativeWindow::maxSwapInterval) =   
  56.             fbDev->maxSwapInterval;  
  57.     }   
  58.     else   
  59.     {  
  60.          LOGE(”Couldn’t get gralloc module”);  
  61.     }  
  62.   
  63.     ANativeWindow::setSwapInterval = setSwapInterval;  
  64.     ANativeWindow::dequeueBuffer = dequeueBuffer;  
  65.     ANativeWindow::lockBuffer = lockBuffer;  
  66.     ANativeWindow::queueBuffer = queueBuffer;  
  67.     ANativeWindow::query = query;  
  68.     ANativeWindow::perform = perform;  
  69. }  
FramebufferNativeWindow::FramebufferNativeWindow()     : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false){    hw_module_t const* module;    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {        int stride;        int err;        int i;        err = framebuffer_open(module, &fbDev);        LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));        err = gralloc_open(module, &grDev);        LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));        // bail out if we can't initialize the modules        if (!fbDev || !grDev)            return;        mUpdateOnDemand = (fbDev->setUpdateRect != 0);        // initialize the buffer FIFO        mNumBuffers = NUM_FRAME_BUFFERS;        mNumFreeBuffers = NUM_FRAME_BUFFERS;        mBufferHead = mNumBuffers-1;        for (i = 0; i < mNumBuffers; i++)        {                buffers[i] = new NativeBuffer(                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);        }        for (i = 0; i < mNumBuffers; i++)        {                err = grDev->alloc(grDev,                        fbDev->width, fbDev->height, fbDev->format,                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",                        i, fbDev->width, fbDev->height, strerror(-err));                if (err)                {                        mNumBuffers = i;                        mNumFreeBuffers = i;                        mBufferHead = mNumBuffers-1;                        break;                }        }        const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;         const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;        const_cast<int&>(ANativeWindow::minSwapInterval) =             fbDev->minSwapInterval;        const_cast<int&>(ANativeWindow::maxSwapInterval) =             fbDev->maxSwapInterval;    }     else     {         LOGE("Couldn't get gralloc module");    }    ANativeWindow::setSwapInterval = setSwapInterval;    ANativeWindow::dequeueBuffer = dequeueBuffer;    ANativeWindow::lockBuffer = lockBuffer;    ANativeWindow::queueBuffer = queueBuffer;    ANativeWindow::query = query;    ANativeWindow::perform = perform;}


看看关键的hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)都做了些什么?它在hardware.c中实现。相关代码如下:

[cpp] view plaincopyprint?

  1. /* Base path of the hal modules /
  2. #define HAL_LIBRARY_PATH1 “/system/lib/hw”
  3. #define HAL_LIBRARY_PATH2 “/vendor/lib/hw”
  4. /*
  5. There are a set of variant filename for modules. The form of the filename
  6. * is “<MODULE_ID>.variant.so” so for the led module the Dream variants
  7. * of base “ro.product.board”, “ro.board.platform” and “ro.arch” would be:
  8. led.trout.so
  9. * led.msm7k.so
  10. * led.ARMV6.so
  11. * led.default.so
  12. */
  13. static const
    char *variant_keys[] = {
  14. “ro.hardware”,
    /* This goes first so that it can pick up a different
  15. file on the emulator. */
  16. “ro.product.board”,
  17. “ro.board.platform”,
  18. “ro.arch”
  19. };
  20. static const
    int HAL_VARIANT_KEYS_COUNT =
  21. (sizeof(variant_keys)/sizeof(variant_keys[0]));
  22. /*
  23. Load the file defined by the variant and if successful
  24. * return the dlopen handle and the hmi.
  25. * @return 0 = success, !0 = failure.
  26. */
  27. static int load(const
    char *id,
  28. const char *path,
  29. const struct hw_module_t **pHmi)
  30. {
  31. int status;
  32. void *handle;
  33. struct hw_module_t *hmi;
  34. /
  35. load the symbols resolving undefined symbols before
  36. * dlopen returns. Since RTLD_GLOBAL is not or’d in with
  37. * RTLD_NOW the external symbols will not be global
  38. */
  39. handle = dlopen(path, RTLD_NOW);
  40. if (handle == NULL) {
  41. char const *err_str = dlerror();
  42. LOGE(“load: module=%s\n%s”, path, err_str?err_str:“unknown”);
  43. status = -EINVAL;
  44. goto done;
  45. }
  46. /* Get the address of the struct hal_module_info. */
  47. const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
  48. hmi = (struct hw_module_t *)dlsym(handle, sym);
  49. if (hmi == NULL) {
  50. LOGE(“load: couldn’t find symbol %s”, sym);
  51. status = -EINVAL;
  52. goto done;
  53. }
  54. /* Check that the id matches */
  55. if (strcmp(id, hmi->id) != 0) {
  56. LOGE(“load: id=%s != hmi->id=%s”, id, hmi->id);
  57. status = -EINVAL;
  58. goto done;
  59. }
  60. hmi->dso = handle;
  61. /* success */
  62. status = 0;
  63. done:
  64. if (status != 0) {
  65. hmi = NULL;
  66. if (handle != NULL) {
  67. dlclose(handle);
  68. handle = NULL;
  69. }
  70. } else {
  71. LOGV(“loaded HAL id=%s path=%s hmi=%p handle=%p”,
  72. id, path, *pHmi, handle);
  73. }
  74. *pHmi = hmi;
  75. return status;
  76. }
  77. int hw_get_module_by_class(const
    char *class_id, const
    char *inst,
  78. const struct hw_module_t **module)
  79. {
  80. int status;
  81. int i;
  82. const struct hw_module_t *hmi = NULL;
  83. char prop[PATH_MAX];
  84. char path[PATH_MAX];
  85. char name[PATH_MAX];
  86. if (inst)
  87. snprintf(name, PATH_MAX, “%s.%s”, class_id, inst);
  88. else
  89. strlcpy(name, class_id, PATH_MAX);
  90. /
  91. Here we rely on the fact that calling dlopen multiple times on
  92. * the same .so will simply increment a refcount (and not load
  93. * a new copy of the library).
  94. * We also assume that dlopen() is thread-safe.
  95. /
  96. / Loop through the configuration variants looking for a module */
  97. for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
  98. if (i < HAL_VARIANT_KEYS_COUNT) {
  99. if (property_get(variant_keys[i], prop, NULL) == 0) {
  100. continue;
  101. }
  102. snprintf(path, sizeof(path),
    “%s/%s.%s.so”,
  103. HAL_LIBRARY_PATH2, name, prop);
  104. if (access(path, R_OK) == 0)
    break;
  105. snprintf(path, sizeof(path),
    “%s/%s.%s.so”,
  106. HAL_LIBRARY_PATH1, name, prop);
  107. if (access(path, R_OK) == 0)
    break;
  108. } else {
  109. snprintf(path, sizeof(path),
    “%s/%s.default.so”,
  110. HAL_LIBRARY_PATH1, name);
  111. if (access(path, R_OK) == 0)
    break;
  112. }
  113. }
  114. status = -ENOENT;
  115. if (i < HAL_VARIANT_KEYS_COUNT+1) {
  116. /* load the module, if this fails, we’re doomed, and we should not try
  117. * to load a different variant. */
  118. status = load(class_id, path, module);
  119. }
  120. return status;
  121. }
  122. int hw_get_module(const
    char *id, const
    struct hw_module_t **module)
  123. {
  124. return hw_get_module_by_class(id, NULL, module);
  125. }

[cpp] view plain copy
print?
  1. /** Base path of the hal modules */  
  2. #define HAL_LIBRARY_PATH1 ”/system/lib/hw”  
  3. #define HAL_LIBRARY_PATH2 ”/vendor/lib/hw”  
  4.   
  5. /** 
  6.  * There are a set of variant filename for modules. The form of the filename 
  7.  * is ”<MODULE_ID>.variant.so” so for the led module the Dream variants  
  8.  * of base “ro.product.board”, “ro.board.platform” and “ro.arch” would be: 
  9.  * 
  10.  * led.trout.so 
  11.  * led.msm7k.so 
  12.  * led.ARMV6.so 
  13.  * led.default.so 
  14.  */  
  15.   
  16. static const char *variant_keys[] = {  
  17.     ”ro.hardware”,  /* This goes first so that it can pick up a different 
  18.                        file on the emulator. */  
  19.     ”ro.product.board”,  
  20.     ”ro.board.platform”,  
  21.     ”ro.arch”  
  22. };  
  23.   
  24. static const int HAL_VARIANT_KEYS_COUNT =  
  25.     (sizeof(variant_keys)/sizeof(variant_keys[0]));  
  26.   
  27. /** 
  28.  * Load the file defined by the variant and if successful 
  29.  * return the dlopen handle and the hmi. 
  30.  * @return 0 = success, !0 = failure. 
  31.  */  
  32. static int load(const char *id,  
  33.         const char *path,  
  34.         const struct hw_module_t **pHmi)  
  35. {  
  36.     int status;  
  37.     void *handle;  
  38.     struct hw_module_t *hmi;  
  39.   
  40.     /* 
  41.      * load the symbols resolving undefined symbols before 
  42.      * dlopen returns. Since RTLD_GLOBAL is not or’d in with 
  43.      * RTLD_NOW the external symbols will not be global 
  44.      */  
  45.     handle = dlopen(path, RTLD_NOW);  
  46.     if (handle == NULL) {  
  47.         char const *err_str = dlerror();  
  48.         LOGE(”load: module=%s\n%s”, path, err_str?err_str:“unknown”);  
  49.         status = -EINVAL;  
  50.         goto done;  
  51.     }  
  52.   
  53.     /* Get the address of the struct hal_module_info. */  
  54.     const char *sym = HAL_MODULE_INFO_SYM_AS_STR;  
  55.     hmi = (struct hw_module_t *)dlsym(handle, sym);  
  56.     if (hmi == NULL) {  
  57.         LOGE(”load: couldn’t find symbol %s”, sym);  
  58.         status = -EINVAL;  
  59.         goto done;  
  60.     }  
  61.   
  62.     /* Check that the id matches */  
  63.     if (strcmp(id, hmi->id) != 0) {  
  64.         LOGE(”load: id=%s != hmi->id=%s”, id, hmi->id);  
  65.         status = -EINVAL;  
  66.         goto done;  
  67.     }  
  68.   
  69.     hmi->dso = handle;  
  70.   
  71.     /* success */  
  72.     status = 0;  
  73.   
  74.     done:  
  75.     if (status != 0) {  
  76.         hmi = NULL;  
  77.         if (handle != NULL) {  
  78.             dlclose(handle);  
  79.             handle = NULL;  
  80.         }  
  81.     } else {  
  82.         LOGV(”loaded HAL id=%s path=%s hmi=%p handle=%p”,  
  83.                 id, path, *pHmi, handle);  
  84.     }  
  85.   
  86.     *pHmi = hmi;  
  87.   
  88.     return status;  
  89. }  
  90.   
  91. int hw_get_module_by_class(const char *class_id, const char *inst,  
  92.                            const struct hw_module_t **module)  
  93. {  
  94.     int status;  
  95.     int i;  
  96.     const struct hw_module_t *hmi = NULL;  
  97.     char prop[PATH_MAX];  
  98.     char path[PATH_MAX];  
  99.     char name[PATH_MAX];  
  100.   
  101.     if (inst)  
  102.         snprintf(name, PATH_MAX, ”%s.%s”, class_id, inst);  
  103.     else  
  104.         strlcpy(name, class_id, PATH_MAX);  
  105.   
  106.     /* 
  107.      * Here we rely on the fact that calling dlopen multiple times on 
  108.      * the same .so will simply increment a refcount (and not load 
  109.      * a new copy of the library). 
  110.      * We also assume that dlopen() is thread-safe. 
  111.      */  
  112.   
  113.     /* Loop through the configuration variants looking for a module */  
  114.     for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {  
  115.         if (i < HAL_VARIANT_KEYS_COUNT) {  
  116.             if (property_get(variant_keys[i], prop, NULL) == 0) {  
  117.                 continue;  
  118.             }  
  119.             snprintf(path, sizeof(path), “%s/%s.%s.so”,  
  120.                      HAL_LIBRARY_PATH2, name, prop);  
  121.             if (access(path, R_OK) == 0) break;  
  122.   
  123.             snprintf(path, sizeof(path), “%s/%s.%s.so”,  
  124.                      HAL_LIBRARY_PATH1, name, prop);  
  125.             if (access(path, R_OK) == 0) break;  
  126.         } else {  
  127.             snprintf(path, sizeof(path), “%s/%s.default.so”,  
  128.                      HAL_LIBRARY_PATH1, name);  
  129.             if (access(path, R_OK) == 0) break;  
  130.         }  
  131.     }  
  132.   
  133.     status = -ENOENT;  
  134.     if (i < HAL_VARIANT_KEYS_COUNT+1) {  
  135.         /* load the module, if this fails, we’re doomed, and we should not try 
  136.          * to load a different variant. */  
  137.         status = load(class_id, path, module);  
  138.     }  
  139.   
  140.     return status;  
  141. }  
  142.   
  143. int hw_get_module(const char *id, const struct hw_module_t **module)  
  144. {  
  145.     return hw_get_module_by_class(id, NULL, module);  
  146. }  
/** Base path of the hal modules */
#define HAL_LIBRARY_PATH1 "/system/lib/hw"#define HAL_LIBRARY_PATH2 “/vendor/lib/hw”/** * There are a set of variant filename for modules. The form of the filename * is “<MODULE_ID>.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”};static const int HAL_VARIANT_KEYS_COUNT = (sizeof(variant_keys)/sizeof(variant_keys[0]));/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */static int load(const char *id, const char *path, const struct hw_module_t **pHmi){ int status; void *handle; struct hw_module_t *hmi; /* * load the symbols resolving undefined symbols before * dlopen returns. Since RTLD_GLOBAL is not or’d in with * RTLD_NOW the external symbols will not be global */ handle = dlopen(path, RTLD_NOW); if (handle == NULL) { char const *err_str = dlerror(); LOGE(“load: module=%s\n%s”, path, err_str?err_str:”unknown”); status = -EINVAL; goto done; } /* Get the address of the struct hal_module_info. */ const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym); if (hmi == NULL) { LOGE(“load: couldn’t find symbol %s”, sym); status = -EINVAL; goto done; } /* Check that the id matches */ if (strcmp(id, hmi->id) != 0) { LOGE(“load: id=%s != hmi->id=%s”, id, hmi->id); status = -EINVAL; goto done; } hmi->dso = handle; /* success */ status = 0; done: if (status != 0) { hmi = NULL; if (handle != NULL) { dlclose(handle); handle = NULL; } } else { LOGV(“loaded HAL id=%s path=%s hmi=%p handle=%p”, id, path, *pHmi, handle); } *pHmi = hmi; return status;}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_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;}int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}


其关键在于load函数中的下面两行代码:

[cpp] view plaincopyprint?

  1. const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
  2. hmi = (struct hw_module_t *)dlsym(handle, sym);

[cpp] view plain copy
print?
  1. const char *sym = HAL_MODULE_INFO_SYM_AS_STR;  
  2. hmi = (struct hw_module_t *)dlsym(handle, sym);  
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;    hmi = (struct hw_module_t *)dlsym(handle, sym);


在打开的.so中查找HMI符号的地址,并保存在hmi中。至此,.so中的hw_module_t已经被成功获取,从而可以根据它获取别的相关接口。

4. 使用实例

代码如下:

[cpp] view plaincopyprint?

  1. GraphicBufferAllocator::GraphicBufferAllocator()
  2. : mAllocDev(0)
  3. {
  4. hw_module_t const* module;
  5. int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
  6. LOGE_IF(err, “FATAL: can’t find the %s module”, GRALLOC_HARDWARE_MODULE_ID);
  7. if (err == 0) {
  8. gralloc_open(module, &mAllocDev);
  9. }
  10. }

[cpp] view plain copy
print?
  1. GraphicBufferAllocator::GraphicBufferAllocator()  
  2.     : mAllocDev(0)  
  3. {  
  4.     hw_module_t const* module;  
  5.     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);  
  6.     LOGE_IF(err, ”FATAL: can’t find the %s module”, GRALLOC_HARDWARE_MODULE_ID);  
  7.     if (err == 0) {  
  8.         gralloc_open(module, &mAllocDev);  
  9.     }  
  10. }  
GraphicBufferAllocator::GraphicBufferAllocator()    : mAllocDev(0){    hw_module_t const* module;    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);    if (err == 0) {        gralloc_open(module, &mAllocDev);    }}


5. 总结

1)HAL通过hw_get_module函数获取hw_module_t

2)HAL通过hw_module_t->methods->open获取hw_device_t指针,并在此open函数中初始化hw_device_t的包装结构中的函数及hw_device_t中的close函数,如gralloc_device_open。
3)三个重要的数据结构:

a) struct hw_device_t: 表示硬件设备,存储了各种硬件设备的公共属性和方法

b)struct hw_module_t: 可用hw_get_module进行加载的module

c)struct hw_module_methods_t: 用于定义操作设备的方法,其中只定义了一个打开设备的方法open.

[cpp] view plaincopyprint?

  1. typedef struct hw_module_t {
  2. /* tag must be initialized to HARDWARE_MODULE_TAG /
  3. uint32_t tag;
  4. /* major version number for the module /
  5. uint16_t version_major;
  6. /* minor version number of the module /
  7. uint16_t version_minor;
  8. /* Identifier of module /
  9. const char *id;
  10. /* Name of this module /
  11. const char *name;
  12. /* Author/owner/implementor of the module /
  13. const char *author;
  14. /* Modules methods /
  15. struct hw_module_methods_t* methods;
  16. /* module’s dso /
  17. void* dso;
  18. /* padding to 128 bytes, reserved for future use /
  19. uint32_t reserved[32-7];
  20. } hw_module_t;
  21. typedef struct hw_module_methods_t {
  22. /* Open a specific device /
  23. int (*open)(const
    struct hw_module_t* module, const
    char* id,
  24. struct hw_device_t** device);
  25. } hw_module_methods_t;
  26. /*
  27. Every device data structure must begin with hw_device_t
  28. * followed by module specific public methods and attributes.
  29. */
  30. typedef struct hw_device_t {
  31. /* tag must be initialized to HARDWARE_DEVICE_TAG /
  32. uint32_t tag;
  33. /* version number for hw_device_t /
  34. uint32_t version;
  35. /* reference to the module this device belongs to /
  36. struct hw_module_t* module;
  37. /* padding reserved for future use /
  38. uint32_t reserved[12];
  39. /* Close this device /
  40. int (close)(struct hw_device_t device);
  41. } hw_device_t;

[cpp] view plain copy
print?
  1. typedef struct hw_module_t {  
  2.     /** tag must be initialized to HARDWARE_MODULE_TAG */  
  3.     uint32_t tag;  
  4.   
  5.     /** major version number for the module */  
  6.     uint16_t version_major;  
  7.   
  8.     /** minor version number of the module */  
  9.     uint16_t version_minor;  
  10.   
  11.     /** Identifier of module */  
  12.     const char *id;  
  13.   
  14.     /** Name of this module */  
  15.     const char *name;  
  16.   
  17.     /** Author/owner/implementor of the module */  
  18.     const char *author;  
  19.   
  20.     /** Modules methods */  
  21.     struct hw_module_methods_t* methods;  
  22.   
  23.     /** module’s dso */  
  24.     void* dso;  
  25.   
  26.     /** padding to 128 bytes, reserved for future use */  
  27.     uint32_t reserved[32-7];  
  28.   
  29. } hw_module_t;  
  30.   
  31. typedef struct hw_module_methods_t {  
  32.     /** Open a specific device */  
  33.     int (*open)(const struct hw_module_t* module, const char* id,  
  34.             struct hw_device_t** device);  
  35.   
  36. } hw_module_methods_t;  
  37.   
  38. /** 
  39.  * Every device data structure must begin with hw_device_t 
  40.  * followed by module specific public methods and attributes. 
  41.  */  
  42. typedef struct hw_device_t {  
  43.     /** tag must be initialized to HARDWARE_DEVICE_TAG */  
  44.     uint32_t tag;  
  45.   
  46.     /** version number for hw_device_t */  
  47.     uint32_t version;  
  48.   
  49.     /** reference to the module this device belongs to */  
  50.     struct hw_module_t* module;  
  51.   
  52.     /** padding reserved for future use */  
  53.     uint32_t reserved[12];  
  54.   
  55.     /** Close this device */  
  56.     int (*close)(struct hw_device_t* device);  
  57.   
  58. } hw_device_t;  
typedef struct hw_module_t {    /** tag must be initialized to HARDWARE_MODULE_TAG */    uint32_t tag;    /** major version number for the module */    uint16_t version_major;    /** minor version number of the module */    uint16_t version_minor;    /** Identifier of module */    const char *id;    /** Name of this module */    const char *name;    /** Author/owner/implementor of the module */    const char *author;    /** Modules methods */    struct hw_module_methods_t* methods;    /** module's dso */    void* dso;    /** padding to 128 bytes, reserved for future use */    uint32_t reserved[32-7];} hw_module_t;typedef struct hw_module_methods_t {    /** Open a specific device */    int (*open)(const struct hw_module_t* module, const char* id,            struct hw_device_t** device);} hw_module_methods_t;/** * Every device data structure must begin with hw_device_t * followed by module specific public methods and attributes. */typedef struct hw_device_t {    /** tag must be initialized to HARDWARE_DEVICE_TAG */    uint32_t tag;    /** version number for hw_device_t */    uint32_t version;    /** reference to the module this device belongs to */    struct hw_module_t* module;    /** padding reserved for future use */    uint32_t reserved[12];    /** Close this device */    int (*close)(struct hw_device_t* device);} hw_device_t;


hw_device_t通过open方法获取。

原创粉丝点击