话说上一篇说道
else if ( window == 0 ) {
result = mHardware->setPreviewWindow(window);//将window设置到hal层, Android代码架构真正的实现就止于此,hal层的东西就看具体厂家根据自身情况进行实现了。 }
那究竟mHardware是如何和hal联系起来的的呢?
1.在CameraClient.cpp中:
status_t CameraClient::initialize(camera_module_t *module) { int callingPid = getCallingPid(); LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); char camera_device_name[10]; status_t res; snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); mHardware = new CameraHardwareInterface(camera_device_name);//注意到此处。 res = mHardware->initialize(&module->common);//注意此处 if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mHardware.clear(); return NO_INIT; } mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)mCameraId); // Enable zoom, error, focus, and metadata messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE); //!++ #ifdef MTK_CAMERA_BSP_SUPPORT // Enable MTK-extended messages by default enableMsgType(MTK_CAMERA_MSG_EXT_NOTIFY | MTK_CAMERA_MSG_EXT_DATA); #endif //!-- LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId); return OK; }
mHardware = new CameraHardwareInterface(camera_device_name);//注意到此处。
mHardware 定义是 CameraHardwareInterface, 他也是Android的通用接口。 各个厂家提供的功能都要通过CameraHardwareInterface适配向CameraService提供硬件操作接口。
这篇的主题就是主要分享CameraHardwareInterface如何进行适配的。
2. 接着1中的代码片段:
res = mHardware->initialize(&module->common);//涉及到module,module即为CameraClient::initialize(camera_module_t *module)传进来的参数, 为一个结构体变量的指针。
CameraClient::initialize(camera_module_t *module)调用的地方为CameraService中connect camera的时候调用:
sp<ICamera> CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId) { #ifdef MTK_CAMERAPROFILE_SUPPORT initCameraProfile(); AutoCPTLog cptlog(Event_CS_connect); #endif int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId); if (!mModule) { ALOGE("Camera HAL module not loaded"); ........................... ............................ #endif if (client->initialize(mModule) != OK) {//在这里调用CameraClient的initialize, 而传入的参数为mModule。 #ifdef MTK_CAMERAPROFILE_SUPPORT CPTLogStr(Event_CS_newCamHwIF, CPTFlagEnd, "new CameraHardwareInterface failed"); #endif #ifdef MTK_CAMERA_BSP_SUPPORT
Mutex mSoundLock; sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS]; int mSoundRef; // reference count (release all MediaPlayer when 0) camera_module_t *mModule;//
为一个camera_module_t结构体变量的指针。
Camera最先被使用到的地方是在onFirstRef()函数中, 在这里主要是初始化了mModule的一些变量。 至于onFirstRef何时调用, 后续进行相关的分享, 这里大家只要记住,这个是和sp相关的, 并且在构建sp的时候就会调用。 可以参考这位的博客:http://blog.csdn.net/gzzaigcnforever/article/details/20649781
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef();
if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,//这个定义为"came"
(const hw_module_t **)&mModule) < 0) {//注意这个函数调用
ALOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
else {
mNumberOfCameras = mModule->get_number_of_cameras();
if (mNumberOfCameras > MAX_CAMERAS) {
ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
mNumberOfCameras = MAX_CAMERAS;
}
for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
}
}
}
/** Base path of the hal modules */
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#define HAL_LIBRARY_PATH3 "/system/lib"
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);//class_id为camera, inst为null, 所以现在name=“camera”
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);//path=/vendor/lib/hw/camera.**.so, 根据属性的配置值生成文件名。
if (access(path, R_OK) == 0) break;//判断是否有读文件权限。
snprintf(path, sizeof(path), "%s/%s.%s.so",//path=/system/lib/hw/camera.**.so
HAL_LIBRARY_PATH1, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH3, name, prop);//path=/system/lib/camera.**.so
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);//path=/vendor/lib/hw/camera.default.so
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.default.so",//path=/system/lib/camera.default.so
HAL_LIBRARY_PATH3, 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;
}
上面的思路就是:
遍历
#define HAL_LIBRARY_PATH1 "/system/lib/hw" #define HAL_LIBRARY_PATH2 "/vendor/lib/hw" #define HAL_LIBRARY_PATH3 "/system/lib"这几个目录下的so库,so库的名字为: a.camera.属性名.so和b.camera.default.so。 其中会优先找到a, 在没找到a后再去找到b。 在mtk平台上, 编译生成的so库就为 camera.default.so, 所以最终加载的会是camera.default.so这个库。
继续看看:load(class_id, path, module);:
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(); ALOGE("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) { ALOGE("load: couldn‘t find symbol %s", sym); status = -EINVAL; goto done; } /* Check that the id matches */ if (strcmp(id, hmi->id) != 0) { ALOGE("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 { ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi; return status; }
关注这两句:
const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym);//关注这两句
HAL_MODULE_INFO_SYM_AS_STR:
/** * Name of the hal_module_info */ #define HAL_MODULE_INFO_SYM HMI /** * Name of the hal_module_info as a string */ #define HAL_MODULE_INFO_SYM_AS_STR "HMI"从上面可以看出就是要获取名为“HMI”函数的指针, 而HMI又是HAL_MODULE_INFO_SYM 的宏定义, 所以最终就是要找HAL_MODULE_INFO_SYM实现的地方:
static camera_module instantiate_camera_module() { CAM_LOGD("[%s]", __FUNCTION__); // // (1) Prepare One-shot init. MtkCamUtils::Property::clear(); // (2) camera_module module = { common: { tag: HARDWARE_MODULE_TAG, module_api_version: 1, hal_api_version: 0, id: CAMERA_HARDWARE_MODULE_ID, name: "MTK Camera Module", author: "MTK", methods: CamDeviceManager::get_module_methods(), dso: NULL, reserved: {0}, }, get_number_of_cameras: CamDeviceManager::get_number_of_cameras, get_camera_info: CamDeviceManager::get_camera_info, }; return module; } /******************************************************************************* * Implementation of camera_module *******************************************************************************/ camera_module HAL_MODULE_INFO_SYM = instantiate_camera_module();
3.继续2关注到CamDeviceManager::get_module_methods()这个函数:
hw_module_methods_t* CamDeviceManager:: get_module_methods() { static hw_module_methods_t _methods = { open: CamDeviceManager::open_device }; return &_methods; }
呵呵, 可以看到通过mModule->common->methods-->open可以引用到CamDeviceManager::open_device。
通过名字可以猜测到这个方法应该是在Camera启动的时候会去调用。
所以我们看看何时调用CamDeviceManager::open_device这个方法:
回到CameraService:CameraClient:
status_t CameraClient::initialize(camera_module_t *module) { int callingPid = getCallingPid(); LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); char camera_device_name[10]; status_t res; snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); mHardware = new CameraHardwareInterface(camera_device_name); res = mHardware->initialize(&module->common);//这里初始化了, 并且传入的module->common
回到CameraHardwareInterface:
status_t initialize(hw_module_t *module) { ALOGI("Opening camera %s", mName.string()); int rc = module->methods->open(module, mName.string(), (hw_device_t **)&mDevice);//这里进行了打开camera的操作, 这里调用到的已经是MTK hal层的方法了, 注意最后一个参数。 if (rc != OK) { ALOGE("Could not open camera %s: %d", mName.string(), rc); return rc; } initHalPreviewWindow(); return rc; }
int CamDeviceManager:: open_device(const hw_module_t* module, const char* name, hw_device_t** device) { return CamDeviceManager::getInstance().openDevice(module, name, device); } int CamDeviceManager:: openDevice(const hw_module_t* module, const char* name, hw_device_t** device) { int err = OK; // ICamDevice* pdev = NULL; int32_t i4OpenId = 0; // Mutex::Autolock lock(mMtxOpenLock); // MY_LOGI("+ mi4OpenNum(%d), mi4DeviceNum(%d)", mi4OpenNum, mi4DeviceNum); if (name != NULL) { i4OpenId = ::atoi(name); // if ( DevMetaInfo::queryNumberOfDevice() < i4OpenId ) { err = -EINVAL; goto lbExit; } // if ( MAX_SIMUL_CAMERAS_SUPPORTED <= mi4OpenNum ) { MY_LOGW("open number(%d) >= maximum number(%d)", mi4OpenNum, MAX_SIMUL_CAMERAS_SUPPORTED); MY_LOGE("does not support multi-open"); err = -ENOMEM; goto lbExit; } // pdev = createIDevice( i4OpenId, *get_hw_device(), module );//注意此处, 进行camDevice的创建 // if ( ! pdev ) { MY_LOGE("camera device allocation fail: pdev(0)"); err = -ENOMEM; goto lbExit; } *device = pdev->get_hw_device();//此处将CamDevice的指针付给传进来形参, 最终是CameraHardwareInterface中的mDevice指向了CamDevice。 // mi4OpenNum++; } lbExit: if ( OK != err ) { if ( pdev ) { destroyDevice(pdev); pdev = NULL; } // *device = NULL; } MY_LOGI("- mi4OpenNum(%d)", mi4OpenNum); return err; }
4.继续往下关注到
pdev = createIDevice( i4OpenId, *get_hw_device(), module );的实现:
static ICamDevice* createIDevice( int32_t const i4DevOpenId, hw_device_t const& hwdevice, hw_module_t const*const hwmodule ) { g_s8ClientAppMode = queryClientAppMode(); // MY_LOGI("+ tid:%d OpenID:%d ClientAppMode:%s", ::gettid(), i4DevOpenId, g_s8ClientAppMode.string()); // ICamDevice* pdev = NSCamDevice::createDevice(g_s8ClientAppMode, i4DevOpenId);//pDeve 指向的就是ICamDevice的一个对象 // if ( pdev != 0 ) { pdev->incStrong(pdev); // hw_device_t* hwdev = pdev->get_hw_device();// *hwdev = hwdevice; hwdev->module = const_cast<hw_module_t*>(hwmodule); // if ( ! pdev->init() )//在这里初始化了ICamDvice { MY_LOGE("fail to initialize a newly-created instance"); pdev->uninit(); pdev = NULL; } } // MY_LOGI("- created instance=%p", &(*pdev)); return pdev;//返回创建的ICamDevice。 }
注意到ICamDevice对象的构造函数:
ICamDevice:: ICamDevice() : camera_device_t() , RefBase() , mDevOps() // , mMtxLock() // { MY_LOGD("ctor"); ::memset(static_cast<camera_device_t*>(this), 0, sizeof(camera_device_t)); this->priv = this; this->ops = &mDevOps;//ops指向了mDevOps mDevOps = gCameraDevOps;//mDevOps为gCameraDevOps指向的结构体 }
gCameraDevOps:
static camera_device_ops_t const gCameraDevOps = { set_preview_window: camera_set_preview_window, set_callbacks: camera_set_callbacks, enable_msg_type: camera_enable_msg_type, disable_msg_type: camera_disable_msg_type, msg_type_enabled: camera_msg_type_enabled, start_preview: camera_start_preview, stop_preview: camera_stop_preview, preview_enabled: camera_preview_enabled, store_meta_data_in_buffers: camera_store_meta_data_in_buffers, start_recording: camera_start_recording, stop_recording: camera_stop_recording, recording_enabled: camera_recording_enabled, release_recording_frame: camera_release_recording_frame, auto_focus: camera_auto_focus, cancel_auto_focus: camera_cancel_auto_focus, take_picture: camera_take_picture, cancel_picture: camera_cancel_picture, set_parameters: camera_set_parameters, get_parameters: camera_get_parameters, put_parameters: camera_put_parameters, send_command: camera_send_command, release: camera_release, dump: camera_dump, };
mDevice->ops->set_preview_window(mDevice, 0)类似的方法就可以调用到ICamDevice中对应的方法了。
5. 我们回到Camera显示相关的东西,
在CameraClient中//!++
else if ( window == 0 ) {
result = mHardware->setPreviewWindow(window);
}
进而在CameraHardwareInterface中:
/** Set the ANativeWindow to which preview frames are sent */ status_t setPreviewWindow(const sp<ANativeWindow>& buf) { ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get()); if (mDevice->ops->set_preview_window) { //!++ if ( buf == 0 ) { ALOGD("set_preview_window(0) before mPreviewWindow = 0"); mDevice->ops->set_preview_window(mDevice, 0);//直接调用了ICamDevice的相关的方法。 mPreviewWindow = 0; return OK; } //!-- mPreviewWindow = buf; mHalPreviewWindow.user = this; ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__, &mHalPreviewWindow, mHalPreviewWindow.user); return mDevice->ops->set_preview_window(mDevice, buf.get() ? &mHalPreviewWindow.nw : 0); } return INVALID_OPERATION; }
具体思路就是:
a.CameraHardwareInterface是Android原生定义的和硬件hal层连接的适配接口。各个厂家根据需要去具体实现这些接口,并具体实现底层的相关功能。
b.为了代码通用性和模块的分离性, 对hal层模块的实现封装成动态库(so), CameraService根据需要动态加载hal层的库。
c.CamDeviceManager是Hal层的一个入口类, 从CameraService打开关闭camera的时候都是通过它进行总的安排。
d.hal层下具体的实现都是不断的适配CameraHardwareInterface向上提供的接口的一个过程。
附上以一个打开Camera的流程图供参考:
Camera显示之Hal层的适配,布布扣,bubuko.com
原文:http://blog.csdn.net/wsb1321/article/details/21975951