以TI的platform为例子,也就是这两个文件
/path/to/aosp/frameworks/av/services/camera/libcameraservice/CameraHardwareInterface.h
和
/path/to/aosp/hardware/ti/omap4xxx/camera/CameraHal.cpp
是如何关联的。
谁来加载camera.$platform$.so,这个是真正的HAL的实现,里面实际最终会去调用Driver(中间透过rpmsg-omx1)。
好突然,可能你现在还不知道camera.$platform$.so是什么?是这样的,但是到你看到后面你就会发现Vendor的HAL实现是包成一个so档的,也就是这个。
void CameraService::onFirstRef() { BnCameraService::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 { 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); } } }
在/path/to/aosp/hardware/libhardware/hardware.c当中有下面这些方法
hw_get_module(const char *id, const struct hw_module_t **module) // 这里定义的是hw_module_t,但是Vendor HAL当中实现的是camera_module_t
/* 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; } }
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]));
/path/to/aosp/out/target/product/panda/system/build.prop
这里面有platform或者arch相关的数据
/* * 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); /* 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; } *pHmi = hmi; // 动态加载Vendor HAL之后要返回这个hw_module_t结构体供Android Service/HAL层使用
这个load出来的HAL_MODULE_INFO_SYM_AS_STR是什么?
先看它是什么,定义位于hardware.h当中
/** * 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"
理论上来说dlsym就是会去load一个名字为”HMI”的变量/函数,也就是说在Vendor HAL当中必然有名字为”HMI”的这样一个东西。
看看hw_module_t的定义。
/** * 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 hw_module_t { /** tag must be initialized to HARDWARE_MODULE_TAG */ uint32_t tag; /** * The API version of the implemented module. The module owner is * responsible for updating the version when a module interface has * changed. * * The derived modules such as gralloc and audio own and manage this field. * The module user must interpret the version field to decide whether or * not to inter-operate with the supplied module implementation. * For example, SurfaceFlinger is responsible for making sure that * it knows how to manage different versions of the gralloc-module API, * and AudioFlinger must know how to do the same for audio-module API. * * The module API version should include a major and a minor component. * For example, version 1.0 could be represented as 0x0100. This format * implies that versions 0x0100-0x01ff are all API-compatible. * * In the future, libhardware will expose a hw_get_module_version() * (or equivalent) function that will take minimum/maximum supported * versions as arguments and would be able to reject modules with * versions outside of the supplied range. */ uint16_t module_api_version; #define version_major module_api_version /** * version_major/version_minor defines are supplied here for temporary * source code compatibility. They will be removed in the next version. * ALL clients must convert to the new version format. */ /** * The API version of the HAL module interface. This is meant to * version the hw_module_t, hw_module_methods_t, and hw_device_t * structures and definitions. * * The HAL interface owns this field. Module users/implementations * must NOT rely on this value for version information. * * Presently, 0 is the only valid value. */ uint16_t hal_api_version; #define version_minor hal_api_version /** 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;
定义位于hardware.h当中
对于TI的hardware来讲,load的就是camera.omap4.so(也就是前面所说的camera.$platform$.so)的名字为HMI的结构体。
这个需要仔细看下才能发现HAL_MODULE_INFO_SYM实际就是HMI,hardware.h当中定义的那个macro。
HMI位于
/path/to/aosp/hardware/ti/omap4xxx/camera/CameraHal_Module.cpp
当中
camera_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: CAMERA_HARDWARE_MODULE_ID, name: "TI OMAP CameraHal Module", author: "TI", methods: &camera_module_methods, dso: NULL, /* remove compilation warnings */ reserved: {0}, /* remove compilation warnings */ }, get_number_of_cameras: camera_get_number_of_cameras, get_camera_info: camera_get_camera_info, };
通过’arm-eabi-objdump’ -t camera.omap4.so | grep ‘HMI’
也可以验证这一点
而再仔细看看这个common实际上就是hw_module_t这个结构体,这也就印证了前面hw_module_t定义的地方所说的
/**
* 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.
*/
这里需要注意的是hardware.h当中定义的都是hw_module_t,但是Vendor HAL实现的都是自己的xxx_module_t,比如方法定义的类型和实际类型不一样,这个能工作有什么样的奥秘?
其实就是指针的第一个地址,Vendor HAL当中定义的结构必须要求第一个域是hw_module_t,这样地址就可以对应起来。
总之Android使用的这种技法需要理解,要不然都无法知道他们之间是怎么串起来的,指针强大,但小心使用,否则也可能伤身!
camera_device_t和hw_device_t也是一样的用法!
#define CAMERA_HARDWARE_MODULE_ID "camera"
定义位于camera_common.h当中
其他一些使用到的宏之类的
#ifndef _LINUX_LIMITS_H #define _LINUX_LIMITS_H #define NR_OPEN 1024 #define NGROUPS_MAX 65536 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define ARG_MAX 131072 #define CHILD_MAX 999 #define OPEN_MAX 256 #define LINK_MAX 127 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define MAX_CANON 255 #define MAX_INPUT 255 #define NAME_MAX 255 #define PATH_MAX 4096 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define PIPE_BUF 4096 #define XATTR_NAME_MAX 255 #define XATTR_SIZE_MAX 65536 #define XATTR_LIST_MAX 65536 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define RTSIG_MAX 32 #endif
对于Camera HAL来说,你需要找到
typedef struct camera_device { /** * camera_device.common.version must be in the range * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is * recommended. */ hw_device_t common; camera_device_ops_t *ops; void *priv; } camera_device_t;
位于camera.h当中
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); } camera_module_t;
位于camera_common.h当中
扫平这些障碍之后,后面就会顺利多了。
比如takePicture这个动作,在CameraHal_Module当中会被于CameraHal关联起来,上层调用就会进入到CameraHal当中对应的方法
status_t CameraHal::takePicture( ) { status_t ret = NO_ERROR; CameraFrame frame; CameraAdapter::BuffersDescriptor desc; int burst; const char *valstr = NULL; unsigned int bufferCount = 1; Mutex::Autolock lock(mLock); #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS gettimeofday(&mStartCapture, NULL); #endif LOG_FUNCTION_NAME; if(!previewEnabled() && !mDisplayPaused) { LOG_FUNCTION_NAME_EXIT; CAMHAL_LOGEA("Preview not started..."); return NO_INIT; } // return error if we are already capturing if ( (mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE && mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) || (mCameraAdapter->getState() == CameraAdapter::VIDEO_CAPTURE_STATE && mCameraAdapter->getNextState() != CameraAdapter::VIDEO_STATE) ) { CAMHAL_LOGEA("Already capturing an image..."); return NO_INIT; } // we only support video snapshot if we are in video mode (recording hint is set) valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE); if ( (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) && (valstr && strcmp(valstr, TICameraParameters::VIDEO_MODE)) ) { CAMHAL_LOGEA("Trying to capture while recording without recording hint set..."); return INVALID_OPERATION; } if ( !mBracketingRunning ) { if ( NO_ERROR == ret ) { burst = mParameters.getInt(TICameraParameters::KEY_BURST); } //Allocate all buffers only in burst capture case if ( burst > 1 ) { bufferCount = CameraHal::NO_BUFFERS_IMAGE_CAPTURE; if ( NULL != mAppCallbackNotifier.get() ) { mAppCallbackNotifier->setBurst(true); } } else { if ( NULL != mAppCallbackNotifier.get() ) { mAppCallbackNotifier->setBurst(false); } } // 这就是为什么我们正常拍照,preview就会stop住,拍完一张之后需要去startPreview // pause preview during normal image capture // do not pause preview if recording (video state) if (NO_ERROR == ret && NULL != mDisplayAdapter.get() && burst < 1) { if (mCameraAdapter->getState() != CameraAdapter::VIDEO_STATE) { mDisplayPaused = true; mPreviewEnabled = false; ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); // since preview is paused we should stop sending preview frames too if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) { mAppCallbackNotifier->disableMsgType (CAMERA_MSG_PREVIEW_FRAME); } } #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS mDisplayAdapter->setSnapshotTimeRef(&mStartCapture); #endif } // if we taking video snapshot... if ((NO_ERROR == ret) && (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE)) { // enable post view frames if not already enabled so we can internally // save snapshot frames for generating thumbnail if((mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME) == 0) { mAppCallbackNotifier->enableMsgType(CAMERA_MSG_POSTVIEW_FRAME); } } if ( (NO_ERROR == ret) && (NULL != mCameraAdapter) ) { if ( NO_ERROR == ret ) ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE, ( int ) &frame, bufferCount); if ( NO_ERROR != ret ) { CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret); } } if ( NO_ERROR == ret ) { mParameters.getPictureSize(( int * ) &frame.mWidth, ( int * ) &frame.mHeight); // 分配buffer ret = allocImageBufs(frame.mWidth, frame.mHeight, frame.mLength, mParameters.getPictureFormat(), bufferCount); if ( NO_ERROR != ret ) { CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret); } } if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) ) { desc.mBuffers = mImageBufs; desc.mOffsets = mImageOffsets; desc.mFd = mImageFd; desc.mLength = mImageLength; desc.mCount = ( size_t ) bufferCount; desc.mMaxQueueable = ( size_t ) bufferCount; ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE, ( int ) &desc); } } if ( ( NO_ERROR == ret ) && ( NULL != mCameraAdapter ) ) { #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS //pass capture timestamp along with the camera adapter command ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE, (int) &mStartCapture); #else ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE); #endif } return ret; }
经过BaseCameraAdapter(这个当中的takePicture实现只是Stub)会到
status_t OMXCameraAdapter::takePicture(),然后会将该动作加入到Command队列当中去执行,最终实现在OMXCapture::startImageCapture()当中。
这里就会透过OMX_FillThisBuffer压入buffer到capture port,当capture完成之后会收到FillBufferDone这个callback,进入回调函数。
OMX_ERRORTYPE OMXCameraAdapter::OMXCameraGetHandle(OMX_HANDLETYPE *handle, OMX_PTR pAppData ) { OMX_ERRORTYPE eError = OMX_ErrorUndefined; for ( int i = 0; i < 5; ++i ) { if ( i > 0 ) { // sleep for 100 ms before next attempt usleep(100000); } // setup key parameters to send to Ducati during init OMX_CALLBACKTYPE oCallbacks; // initialize the callback handles // 注册callback oCallbacks.EventHandler = android::OMXCameraAdapterEventHandler; oCallbacks.EmptyBufferDone = android::OMXCameraAdapterEmptyBufferDone; oCallbacks.FillBufferDone = android::OMXCameraAdapterFillBufferDone; // get handle eError = OMX_GetHandle(handle, (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", pAppData, &oCallbacks); // 注意这个library,实际就是/path/to/aosp/hardware/ti/omap4xxx/domx/omx_proxy_component/omx_camera/src/omx_proxy_camera.c // 最终通过pRPCCtx->fd_omx = open("/dev/rpmsg-omx1", O_RDWR);跟底层交互 if ( eError == OMX_ErrorNone ) { return OMX_ErrorNone; } CAMHAL_LOGEB("OMX_GetHandle() failed, error: 0x%x", eError); } *handle = 0; return eError; }
有了回调函数就会一直往上层传,最终就用户就得到了拍摄的照片数据。
CameraAdapter_Factory(size_t sensor_index)在OMXCameraAdapter当中。
另外TI Omap还有实现一套通过V4L2交互的方式,只是默认没有启用。
它是经过V4LCameraAdapter::UseBuffersPreview
最终会走向V4L2中去
而CameraAdapter_Factory()在V4LCameraAdapter当中。