2019独角兽企业重金招聘Python工程师标准>>>
工作记录 从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
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
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
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
context->incStrong(thiz);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context, (int)context.get());
}
接下来我们看看connect 和 getstatus做了些什么。代码路径同上
sp
{
LOGV("connect");
sp
const sp
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
const sp
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d, id %d mode %d)", callingPid, cameraId, mode);
sp
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
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
{
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
//则创建一个硬件对象,并还回。
{
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
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
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
if (camera == 0) return;
sp
if (jSurface != NULL) {
surface = reinterpret_cast
}
if (camera->setPreviewDisplay(surface) != NO_ERROR) {
jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
}
}
在camera.cpp中;
status_t Camera::setPreviewDisplay(const sp
{
LOGV("setPreviewDisplay");
sp
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
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
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;
}