ICS 中 沿用了linux驱动模块化的方式,把camera hal 形成一个hardware module,这点跟HC明显不同。
打开camera时, cameraservice 会先打开camera hw_moudle, 如下代码所示:
void CameraService::onFirstRef() { BnCameraService::onFirstRef(); if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, //获得camera 模块, (const hw_module_t **)&mModule) < 0) { //&mModule 应该就是camera.medfield.so. LOGE("Could not load camera HAL module"); mNumberOfCameras = 0; } else { mNumberOfCameras = mModule->get_number_of_cameras(); //调用camera hal 层函数。 if (mNumberOfCameras > MAX_CAMERAS) { LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).", mNumberOfCameras, MAX_CAMERAS); mNumberOfCameras = MAX_CAMERAS; } for (int i = 0; i < mNumberOfCameras; i++) { setCameraFree(i); } } // Read the system property to determine if we have to use the // AUDIO_STREAM_ENFORCED_AUDIBLE type. char value[PROPERTY_VALUE_MAX]; property_get("ro.camera.sound.forced", value, "0"); if (strcmp(value, "0") != 0) { mAudioStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE; } else { mAudioStreamType = AUDIO_STREAM_MUSIC; } }1. 这里的
int hw_get_module(const char *id, const struct hw_module_t **module) { return hw_get_module_by_class(id, NULL, module); } const char *id ------- 应该是module name const struct hw_module_t **module -----应该是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 应该是medfield, 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; }load(class_id, path, module) 代码如下:
/** * 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; }2. mNumberOfCameras = mModule->get_number_of_cameras();
camera_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: CAMERA_HARDWARE_MODULE_ID, name: "Intel CameraHardware Module", author: "Intel", methods: &camera_module_methods, //这里面定义了各种函数接口。 dso: NULL, /* remove compilation warnings */ reserved: {0}, /* remove compilation warnings */ }, get_number_of_cameras: HAL_GetNumberOfCameras, //cameraservice 中会调用这两个函数。 get_camera_info: HAL_GetCameraInfo, };a. get_number_of_cameras: HAL_GetNumberOfCameras,
int HAL_GetNumberOfCameras(void) { return android::CameraHardware::getNumberOfCameras(); } /* This function will be called when the camera service is created. * Do some init work in this function. */ int CameraHardware::getNumberOfCameras() { LogEntry(LOG_TAG, __FUNCTION__); if (num_cameras != 0) return num_cameras; int ret; struct v4l2_input input; int fd = -1; char *dev_name = "/dev/video0"; fd = open(dev_name, O_RDWR); if (fd <= 0) { LogError("Error opening video device %s: %s", dev_name, strerror(errno)); return 0; } int i; for (i = 0; i < MAX_CAMERAS; i++) { memset(&input, 0, sizeof(input)); input.index = i; ret = ioctl(fd, VIDIOC_ENUMINPUT, &input); //从kernel 获得相应信息,枚举input通道信息。 if (ret < 0) { break; } camInfo[i].port = input.reserved[1]; strncpy(camInfo[i].name, (const char *)input.name, MAX_SENSOR_NAME_LENGTH); } close(fd); num_cameras = i; return num_cameras; }b. get_camera_info: HAL_GetCameraInfo,
int HAL_GetCameraInfo(int camera_id, struct camera_info *info) { return android::CameraHardware::getCameraInfo(camera_id, info); } int CameraHardware::getCameraInfo(int cameraId, struct camera_info* cameraInfo) { LogEntry(LOG_TAG, __FUNCTION__); if (cameraId >= MAX_CAMERAS) return -EINVAL; memcpy(cameraInfo, &HAL_cameraInfo[cameraId], sizeof(camera_info)); //从HAL_cameraInfo[cameraId] 中获得信息。 return 0; }HAL_cameraInfo[cameraId] 定义如下:
static camera_info HAL_cameraInfo[MAX_CAMERAS] = { { CAMERA_FACING_FRONT, 180, }, { CAMERA_FACING_BACK, 0, } };c. methods: &camera_module_methods, //这里面定义了各种函数接口。
static struct hw_module_methods_t camera_module_methods = { open: HAL_OpenCameraHardware // 也就是这个函数 }; open: HAL_OpenCameraHardware, int HAL_OpenCameraHardware(const hw_module_t* module, const char* name, hw_device_t** device) { int rv = 0; int num_cameras = 0; int cameraid; intel_camera_device_t* camera_device = NULL; camera_device_ops_t* camera_ops = NULL; android::CameraHardware* camera = NULL; android::Mutex::Autolock lock(gCameraHalDeviceLock); LOGI("camera_device open"); if (name != NULL) { cameraid = atoi(name); num_cameras = android::CameraHardware::getNumberOfCameras(); if(cameraid > num_cameras) { LOGE("camera service provided cameraid out of bounds, " "cameraid = %d, num supported = %d", cameraid, num_cameras); rv = -EINVAL; goto fail; } if(gCamerasOpen >= MAX_CAMERAS) { LOGE("maximum number of cameras already open"); rv = -ENOMEM; goto fail; } camera_device = (intel_camera_device_t*)malloc(sizeof(*camera_device)); if(!camera_device) { LOGE("camera_device allocation fail"); rv = -ENOMEM; goto fail; } camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops)); if(!camera_ops) { LOGE("camera_ops allocation fail"); rv = -ENOMEM; goto fail; } memset(camera_device, 0, sizeof(*camera_device)); memset(camera_ops, 0, sizeof(*camera_ops)); camera_device->device.common.tag = HARDWARE_DEVICE_TAG; camera_device->device.common.version = 0; camera_device->device.common.module = (hw_module_t *)(module); camera_device->device.common.close = HAL_CloseCameraHardware; camera_device->device.ops = camera_ops; camera_ops->set_preview_window = camera_set_preview_window; camera_ops->set_callbacks = camera_set_callbacks; camera_ops->enable_msg_type = camera_enable_msg_type; camera_ops->disable_msg_type = camera_disable_msg_type; camera_ops->msg_type_enabled = camera_msg_type_enabled; camera_ops->start_preview = camera_start_preview; camera_ops->stop_preview = camera_stop_preview; camera_ops->preview_enabled = camera_preview_enabled; camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers; camera_ops->start_recording = camera_start_recording; camera_ops->stop_recording = camera_stop_recording; camera_ops->recording_enabled = camera_recording_enabled; camera_ops->release_recording_frame = camera_release_recording_frame; camera_ops->auto_focus = camera_auto_focus; camera_ops->cancel_auto_focus = camera_cancel_auto_focus; camera_ops->take_picture = camera_take_picture; camera_ops->cancel_picture = camera_cancel_picture; camera_ops->set_parameters = camera_set_parameters; camera_ops->get_parameters = camera_get_parameters; camera_ops->put_parameters = camera_put_parameters; camera_ops->send_command = camera_send_command; camera_ops->release = camera_release; camera_ops->dump = camera_dump; *device = &camera_device->device.common; camera_device->cameraId = cameraid; camera = new android::CameraHardware(cameraid); if(!camera) { LOGE("Couldn't create instance of CameraHardware class!"); rv = -ENOMEM; goto fail; } gCameraHals[cameraid] = camera; gCamerasOpen++; } return rv; fail: if(camera_device) { free(camera_device); camera_device = NULL; } if(camera_ops) { free(camera_ops); camera_ops = NULL; } if(camera) { delete camera; camera = NULL; } *device = NULL; return rv; }这个函数里 封装了一系列 camera interface。 但是cameraservice 并没有用到这些接口,还是老的调用方式,直接调用了 camerahardware, 而没经过这里的接口。