?? 函數load也是實現在文件hardware/libhardware/hardware.c文件中,如下所示:
- 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;??
- }??
- #define?HAL_MODULE_INFO_SYM_AS_STR??"HMI"??
?? ? ? 將Gralloc模塊加載到內存中來之后,就可以調用函數dlsym來獲得它所導出的符號HMI。由于這個符號指向的是一個hw_module_t結構體,因此,最后函數load就可以強制地將這個符號轉換為一個hw_module_t結構體指針,并且保存在輸出參數pHmi中返回給調用者。調用者獲得了這個hw_module_t結構體指針之后,就可以創建一個gralloc設備或者一個fb設備。
?? ? ? 模塊Gralloc實現在目錄hardware/libhardware/modules/gralloc中,它導出的符號HMI定義在文件hardware/libhardware/modules/gralloc/gralloc.cpp文件中,如下所示:
- static?struct?hw_module_methods_t?gralloc_module_methods?=?{??
- ????????open:?gralloc_device_open??
- };??
- ??
- 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,??
- };??
?? ? ??HAL_MODULE_INFO_SYM也是一個宏,它的值是與宏HAL_MODULE_INFO_SYM_AS_STR對應的,它也是定義在文件hardware/libhardware/include/hardware/hardware.h文件中,如下所示:
圖1 private_module_t結構體定義
?? ?結構體private_module_t的第一個成員變量base指向一個gralloc_module_t結構體,而gralloc_module_t結構體的第一個成員變量common又指向了一個hw_module_t結構體,這意味著,指向一個private_module_t結構體的指針同時可以用作一個gralloc_module_t或者hw_module_t結構體提針來使用。事實上,這是使用C語言來實現的一種繼承關系,等價于結構體private_module_t繼承結構體gralloc_module_t,而結構體gralloc_module_t繼承hw_module_t結構體。這樣,我們就可以把在Gralloc模塊中定義的符號HAL_MODULE_INFO_SYM看作是一個hw_module_t結構體。
? ? ? ? hw_module_t結構體有一個重要的成員變量methods,它的類型為hw_module_methods_t,它用來描述一個HAL模塊的操作方法列表。結構體hw_module_methods_t只定義有一個操作方法open,用來打開一個指定的設備。在Gralloc模塊中,用來打開指定設備的函數被指定為gralloc_device_open,通過這個函數就可以打開Gralloc模塊中的gralloc或者fb設備,后面我們再詳細分析。