以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当中。