工作记录 从JNI往下看
JNI : frameworks/base/core/jni/android_hardware_camera.cpp
static JNINativeMethod camMethods[] = { { "getNumberOfCameras", "()I", (void *)android_hardware_Camera_getNumberOfCameras }, { "getCameraInfo", "(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo }, { "native_setup", "(Ljava/lang/Object;II)V", (void*)android_hardware_Camera_native_setup }, { "native_release", "()V", (void*)android_hardware_Camera_release }, { "setPreviewDisplay", "(Landroid/view/Surface;)V", (void *)android_hardware_Camera_setPreviewDisplay }, { "startPreview", "()V", (void *)android_hardware_Camera_startPreview }, { "stopPreview", "()V", (void *)android_hardware_Camera_stopPreview }, { "previewEnabled", "()Z", (void *)android_hardware_Camera_previewEnabled }, { "setHasPreviewCallback", "(ZZ)V", (void *)android_hardware_Camera_setHasPreviewCallback }, { "addCallbackBuffer", "([B)V", (void *)android_hardware_Camera_addCallbackBuffer }, { "native_autoFocus", "()V", (void *)android_hardware_Camera_autoFocus }, { "native_encodeData", "()V", (void *)android_hardware_Camera_encodeData }, { "native_cancelAutoFocus", "()V", (void *)android_hardware_Camera_cancelAutoFocus }, { "native_takePicture", "()V", (void *)android_hardware_Camera_takePicture }, { "native_setHistogramMode", "(Z)V", (void *)android_hardware_Camera_setHistogramMode }, { "native_sendHistogramData", "()V", (void *)android_hardware_Camera_sendHistogramData }, { "native_setFaceDetectionCb", "(Z)V", (void *)android_hardware_Camera_setFaceDetectionCb }, { "native_sendMetaData", "()V", (void *)android_hardware_Camera_sendMetaData }, { "native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters }, { "native_getParameters", "()Ljava/lang/String;", (void *)android_hardware_Camera_getParameters }, { "reconnect", "()V", (void*)android_hardware_Camera_reconnect }, { "lock", "()V", (void*)android_hardware_Camera_lock }, { "unlock", "()V", (void*)android_hardware_Camera_unlock }, { "startSmoothZoom", "(I)V", (void *)android_hardware_Camera_startSmoothZoom }, { "stopSmoothZoom", "()V", (void *)android_hardware_Camera_stopSmoothZoom }, { "setDisplayOrientation", "(I)V", (void *)android_hardware_Camera_setDisplayOrientation },};
====================================================================================
static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz){ return Camera::getNumberOfCameras();}
此处调到/framework/base/libs/camera/camera.cpp 中。
int32_t Camera::getNumberOfCameras(){ const sp<ICameraService>& cs = getCameraService(); if (cs == 0) return 0; return cs->getNumberOfCameras();}
此处调用到/framework/base/service/camera/libcameraservice/cameraservice.cpp中借口
int32_t CameraService::getNumberOfCameras() { return mNumberOfCameras;}
而,此处mNumberOfCameras由cameraservice.cpp中
mNumberOfCameras =HAL_getNumberOfCameras(); 获得。
HAL_getNumberOfCameras()函数,调用\vendor\qcom\android-open\libcamera2\QualcommCameraHardware.cpp中的接口。
extern "C" int HAL_getNumberOfCameras(){ QualcommCameraHardware::getCameraInfo(); return HAL_numOfCameras;}
接下来看下getCameraInfo()
void QualcommCameraHardware::getCameraInfo(){ LOGI("getCameraInfo: IN"); mm_camera_status_t status;#if DLOPEN_LIBMMCAMERA void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW); LOGI("getCameraInfo: loading libqcamera at %p", libhandle); if (!libhandle) { LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); } *(void **)&LINK_mm_camera_get_camera_info = ::dlsym(libhandle, "mm_camera_get_camera_info");#endif storeTargetType(); status = LINK_mm_camera_get_camera_info(HAL_cameraInfo, &HAL_numOfCameras); LOGI("getCameraInfo: numOfCameras = %d", HAL_numOfCameras); for(int i = 0; i < HAL_numOfCameras; i++) { if((HAL_cameraInfo[i].position == BACK_CAMERA )&& mCurrentTarget == TARGET_MSM8660){ HAL_cameraInfo[i].modes_supported |= CAMERA_ZSL_MODE; } else{ HAL_cameraInfo[i].modes_supported |= CAMERA_NONZSL_MODE; } LOGI("Camera sensor %d info:", i); LOGI("camera_id: %d", HAL_cameraInfo[i].camera_id); LOGI("modes_supported: %x", HAL_cameraInfo[i].modes_supported); LOGI("position: %d", HAL_cameraInfo[i].position); LOGI("sensor_mount_angle: %d", HAL_cameraInfo[i].sensor_mount_angle); }#if DLOPEN_LIBMMCAMERA if (libhandle) { ::dlclose(libhandle); LOGV("getCameraInfo: dlclose(libqcamera)"); }#endif LOGI("getCameraInfo: OUT");}
在前面有#define LINK_mm_camera_get_camera_info mm_camera_get_camera_info ,所以我们接下来到
mm_camera_get_camera_info(HAL_cameraInfo, &HAL_numOfCameras);调用到哪。
在 vendor\qcom\proprietary\mm-camera\apps\appslib\mm_camera_interface.c中有定义
mm_camera_status_t mm_camera_get_camera_info(camera_info_t* p_cam_info, int* p_num_cameras){ int i = 0; int controlfd = -1; char device[MAX_DEV_NAME_LEN]; CDBG("%s: [S]\n", __func__); mm_camera_status_t status = MM_CAMERA_SUCCESS; struct msm_camera_info cameraInfo; if (NULL == p_cam_info) { status = MM_CAMERA_ERR_INVALID_INPUT; goto ERROR; } sprintf (device, MSM_CAMERA_CONTROL, 0); controlfd = open(device, O_RDWR);
//此处打开的是内核注册的控制节点 "/dev/msm_camera/control%d"
// 内核一共注册了四个节点,control、config、frame、pic 对应了四组操作函数。老一点的版本是三组节点。
if (controlfd < 0) { CDBG_HIGH("%s: controlfd is invalid %s", __func__, strerror(errno)); status = MM_CAMERA_ERR_GENERAL; goto ERROR; } if (ioctl(controlfd, MSM_CAM_IOCTL_GET_CAMERA_INFO, &cameraInfo) < 0) { //此处获得内核注册camera信息 CDBG_HIGH("%s: error (%s)", __func__, strerror(errno)); status = MM_CAMERA_ERR_GENERAL; goto ERROR; } CDBG("%s: num %d\n", __func__, cameraInfo.num_cameras); for (i=0; i < cameraInfo.num_cameras; i++) { p_cam_info[i].camera_id = i; p_cam_info[i].modes_supported = (!cameraInfo.has_3d_support[i]) ? CAMERA_MODE_2D : //前置摄像头只支持2D CAMERA_MODE_2D | CAMERA_MODE_3D; p_cam_info[i].position = //在内核前置摄像头is_internal_cam[i]定义为1,后置摄像头默认为0. (cameraInfo.is_internal_cam[i]) ? FRONT_CAMERA : BACK_CAMERA;
//到此用户层将前置和后置摄像头区分开 p_cam_info[i].sensor_mount_angle = cameraInfo.s_mount_angle[i]; } *p_num_cameras = cameraInfo.num_cameras; ERROR: if (controlfd > 0) { close(controlfd); } CDBG("%s: %d [E]", __func__, status); return status;}
至此 android_hardware_Camera_getNumberOfCameras 的流程完成。
====================================================================================
2、android_hardware_Camera_getCameraInfo(JNI)
static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jint cameraId, jobject info_obj){ CameraInfo cameraInfo; status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
if (rc != NO_ERROR) { jniThrowException(env, "java/lang/RuntimeException", "Fail to get camera info"); return; } env->SetIntField(info_obj, fields.facing, cameraInfo.facing); env->SetIntField(info_obj, fields.mode, cameraInfo.mode); env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation);}
此处getCameraInfo调到/framework/base/libs/camera/camera.cpp 中接口。
status_t Camera::getCameraInfo(int cameraId, struct CameraInfo* cameraInfo) { const sp<ICameraService>& cs = getCameraService(); if (cs == 0) return UNKNOWN_ERROR; return cs->getCameraInfo(cameraId, cameraInfo);}
此处调用到/framework/base/service/camera/libcameraservice/cameraservice.cpp中接口。
status_t CameraService::getCameraInfo(int cameraId, struct CameraInfo* cameraInfo) { if (cameraId < 0 || cameraId >= mNumberOfCameras) { return BAD_VALUE; }
HAL_getCameraInfo(cameraId, cameraInfo); return OK;}
HAL_getCameraInfo函数,调用\vendor\qcom\android-open\libcamera2\QualcommCameraHardware.cpp中的接口。
extern "C" voidHAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo){ int i; char mDeviceName[PROPERTY_VALUE_MAX]; if(cameraInfo == NULL) { LOGE("cameraInfo is NULL"); return; }
property_get("ro.product.device",mDeviceName," ");//获取系统属性
for(i = 0; i < HAL_numOfCameras; i++) { if(i == cameraId) { LOGI("Found a matching camera info for ID %d", cameraId); cameraInfo->facing = (HAL_cameraInfo[i].position == BACK_CAMERA)? CAMERA_FACING_BACK : CAMERA_FACING_FRONT; // App Orientation not needed for 7x27 , sensor mount angle 0 is // enough. if(cameraInfo->facing == CAMERA_FACING_FRONT) cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; else if( !strncmp(mDeviceName, "msm7625a", 8)) cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; else if( !strncmp(mDeviceName, "msm7627a", 8)) cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; else if( !strncmp(mDeviceName, "msm7627", 7)) cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; else if( !strncmp(mDeviceName, "msm8660", 7)) cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; else cameraInfo->orientation = ((APP_ORIENTATION - HAL_cameraInfo[i].sensor_mount_angle) + 360)%360;
LOGI("%s: orientation = %d", __FUNCTION__, cameraInfo->orientation); cameraInfo->mode = 0; if(HAL_cameraInfo[i].modes_supported & CAMERA_MODE_2D) cameraInfo->mode |= CAMERA_SUPPORT_MODE_2D; if(HAL_cameraInfo[i].modes_supported & CAMERA_MODE_3D) cameraInfo->mode |= CAMERA_SUPPORT_MODE_3D; if((HAL_cameraInfo[i].position == BACK_CAMERA )&& !strncmp(mDeviceName, "msm8660", 7)){ cameraInfo->mode |= CAMERA_ZSL_MODE; } else{ cameraInfo->mode |= CAMERA_NONZSL_MODE; }
LOGI("%s: modes supported = %d", __FUNCTION__, cameraInfo->mode);
return; } } LOGE("Unable to find matching camera info for ID %d", cameraId);}
}; // namespace android
在这里,应为前面在获取camera number时已经获得了HAL_cameraInfo相关信息,所以这里只是做了一些相关的配置。
===============================================================================================================
三 android_hardware_Camera_native_setup(JNI)
static voidandroid_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId, jint mode){ sp<Camera> camera = Camera::connect(cameraId, mode);
if (camera == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Fail to connect to camera service"); return; }
// make sure camera hardware is alive if (camera->getStatus() != NO_ERROR) { jniThrowException(env, "java/lang/RuntimeException", "Camera initialization failed"); return; }
jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Can't find android/hardware/Camera"); return; }
// We use a weak reference so the Camera object can be garbage collected. // The reference is only used as a proxy for callbacks. sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); context->incStrong(thiz); camera->setListener(context);
// save context in opaque field env->SetIntField(thiz, fields.context, (int)context.get());}
接下来我们看看connect 和 getstatus做了些什么。代码路径同上
sp<Camera> Camera::connect(int cameraId, int mode){ LOGV("connect"); sp<Camera> c = new Camera(); const sp<ICameraService>& cs = getCameraService(); if (cs != 0) { c->mCamera = cs->connect(c, cameraId, mode); } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { c.clear(); } return c;}
sp<ICamera> CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId, int mode) { int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d, id %d mode %d)", callingPid, cameraId, mode);
sp<Client> client; if (cameraId < 0 || cameraId >= mNumberOfCameras) { LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).", callingPid, cameraId); return NULL; }
Mutex::Autolock lock(mServiceLock); if (mClient[cameraId] != 0) { client = mClient[cameraId].promote(); if (client != 0) { if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { LOG1("CameraService::connect X (pid %d) (the same client)", callingPid); return client; } else { LOGW("CameraService::connect X (pid %d) rejected (existing client).", callingPid); return NULL; } } mClient[cameraId].clear(); }
if (mBusy[cameraId]) { LOGW("CameraService::connect X (pid %d) rejected" " (camera %d is still busy).", callingPid, cameraId); return NULL; }
sp<CameraHardwareInterface> hardware = HAL_openCameraHardware(cameraId, mode); if (hardware == NULL) { LOGE("Fail to open camera hardware (id=%d)", cameraId); return NULL; } CameraInfo info; HAL_getCameraInfo(cameraId, &info); client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid); mClient[cameraId] = client; LOG1("CameraService::connect X"); return client;}
\vendor\qcom\android-open\libcamera2\QualcommCameraHardware.cpp
extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId, int mode){ int i; LOGI("openCameraHardware: call createInstance"); for(i = 0; i < HAL_numOfCameras; i++) { if(HAL_cameraInfo[i].camera_id == cameraId) { LOGI("openCameraHardware:Valid camera ID %d", cameraId); LOGI("openCameraHardware:camera mode %d", mode); parameter_string_initialized = false; HAL_currentCameraId = cameraId; HAL_currentCameraMode = CAMERA_MODE_2D; /* The least significant two bits of mode parameter indicates the sensor mode of 2D or 3D. The next two bits indicates the snapshot mode of ZSL or NONZSL */ int sensorModeMask = 0x03 & mode; if(sensorModeMask & HAL_cameraInfo[i].modes_supported){ HAL_currentCameraMode = sensorModeMask; }else{ LOGE("openCameraHardware:Invalid camera mode (%d) requested", mode); return NULL; } HAL_currentSnapshotMode = CAMERA_SNAPSHOT_NONZSL; //Remove values set by app other than supported values mode = mode & HAL_cameraInfo[cameraId].modes_supported; if((mode & CAMERA_SNAPSHOT_ZSL) == CAMERA_SNAPSHOT_ZSL) HAL_currentSnapshotMode = CAMERA_SNAPSHOT_ZSL; LOGI("%s: HAL_currentSnapshotMode = %d", __FUNCTION__, HAL_currentSnapshotMode);
return QualcommCameraHardware::createInstance(); //重点在这句 } } LOGE("openCameraHardware:Invalid camera ID %d", cameraId); return NULL;}
sp<CameraHardwareInterface> QualcommCameraHardware::createInstance() // 创建一个实例对象,如果硬件已经存在,则还回当前对象的指针,如果没有,
//则创建一个硬件对象,并还回。{ LOGI("createInstance: E");
singleton_lock.lock();
// Wait until the previous release is done. while (singleton_releasing) { if((singleton_releasing_start_time != 0) && (systemTime() - singleton_releasing_start_time) > SINGLETON_RELEASING_WAIT_TIME){ LOGV("in createinstance system time is %lld %lld %lld ", systemTime(), singleton_releasing_start_time, SINGLETON_RELEASING_WAIT_TIME); singleton_lock.unlock(); LOGE("Previous singleton is busy and time out exceeded. Returning null"); return NULL; } LOGI("Wait for previous release."); singleton_wait.waitRelative(singleton_lock, SINGLETON_RELEASING_RECHECK_TIMEOUT); LOGI("out of Wait for previous release."); }
if (singleton != 0) { sp<CameraHardwareInterface> hardware = singleton.promote(); if (hardware != 0) { LOGD("createInstance: X return existing hardware=%p", &(*hardware)); singleton_lock.unlock(); return hardware; } }
{ struct stat st; int rc = stat("/dev/oncrpc", &st); if (rc < 0) { LOGD("createInstance: X failed to create hardware: %s", strerror(errno)); singleton_lock.unlock(); return NULL; } }
QualcommCameraHardware *cam = new QualcommCameraHardware(); sp<QualcommCameraHardware> hardware(cam); singleton = hardware;
LOGI("createInstance: created hardware=%p", &(*hardware)); if (!cam->startCamera()) { LOGE("%s: startCamera failed!", __FUNCTION__); singleton_lock.unlock(); return NULL; }
cam->initDefaultParameters(); singleton_lock.unlock(); LOGI("createInstance: X"); return hardware;}
四 android_hardware_Camera_setPreviewDisplay(JNI)
这个接口函数的作用是为Preview分配内存。
static voidandroid_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface){ LOGV("setPreviewDisplay"); sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) return;
sp<Surface> surface = NULL; if (jSurface != NULL) { surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); } if (camera->setPreviewDisplay(surface) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); }}
在camera.cpp中;
status_t Camera::setPreviewDisplay(const sp<Surface>& surface){ LOGV("setPreviewDisplay"); sp <ICamera> c = mCamera; if (c == 0) return NO_INIT; if (surface != 0) { return c->setPreviewDisplay(surface->getISurface()); } else { LOGD("app passed NULL surface"); return c->setPreviewDisplay(0); }}
这里跳到cameraservice.cpp 中。
status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) { LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result;
result = NO_ERROR;
// return if no change in surface. // asBinder() is safe on NULL (returns NULL) if (surface->asBinder() == mSurface->asBinder()) { return result; }
if (mSurface != 0) { LOG1("clearing old preview surface %p", mSurface.get()); if (mUseOverlay) { // Force the destruction of any previous overlay sp<Overlay> dummy; mHardware->setOverlay(dummy); mOverlayRef = 0; } else { mSurface->unregisterBuffers(); } } mSurface = surface; mOverlayRef = 0; // If preview has been already started, set overlay or register preview // buffers now. if (mHardware->previewEnabled() || mUseOverlay) { if (mUseOverlay) { if( mSurface != NULL) result = setOverlay(); //创建、初始化overlay
//在实际中对这些Surface 进行merge 可以采用两种方式,一种就是采用软件的形式来merge ,还一种就是采用硬件的方式,软件的方式就是我们的SurfaceFlinger ,而硬件的方式就是Overlay } else if (mSurface != 0) { result = registerPreviewBuffers(); //注册preview buffer } }
return result;}