// disconnect from camera service // It's okay to call this when the native camera context is already null. // This handles the case where the user has called release() and the // finalizer is invoked later. static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) { // TODO: Change to LOGV LOGV("release camera"); JNICameraContext* context = NULL; sp<Camera> camera; { Mutex::Autolock _l(sLock); context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context)); // Make sure we do not attempt to callback on a deleted Java object. env->SetIntField(thiz, fields.context, 0); } // clean up if release has not been called before if (context != NULL) { camera = context->getCamera(); context->release(); LOGV("native_release: context=%p camera=%p", context, camera.get()); // clear callbacks if (camera != NULL) { camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); camera->disconnect(); } // remove context to prevent further Java access context->decStrong(thiz); } }
static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, int msgType) { LOGV("takePicture"); JNICameraContext* context; sp<Camera> camera = get_native_camera(env, thiz, &context); if (camera == 0) return; /* * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY * is enabled to receive the callback notification but no data. * * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the * Java application. */ if (msgType & CAMERA_MSG_RAW_IMAGE) { LOGV("Enable raw image callback buffer"); if (!context->isRawImageCallbackBufferAvailable()) { LOGV("Enable raw image notification, since no callback buffer exists"); msgType &= ~CAMERA_MSG_RAW_IMAGE; msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY; } } if (camera->takePicture(msgType) != NO_ERROR) { jniThrowRuntimeException(env, "takePicture failed"); return; } }
static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) { LOGV("addCallbackBuffer: 0x%x", msgType); JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context)); if (context != NULL) { context->addCallbackBuffer(env, bytes, msgType); } }
// disconnect from camera service // It's okay to call this when the native camera context is already null. // This handles the case where the user has called release() and the // finalizer is invoked later. static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) { // TODO: Change to ALOGV ALOGV("release camera"); JNICameraContext* context = NULL; sp<Camera> camera; { Mutex::Autolock _l(sLock); context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context)); // Make sure we do not attempt to callback on a deleted Java object. env->SetIntField(thiz, fields.context, 0); } // clean up if release has not been called before if (context != NULL) { camera = context->getCamera(); context->release(); ALOGV("native_release: context=%p camera=%p", context, camera.get()); //!++ //#ifdef MTK_CAMERA_BSP_SUPPORT #if 1 ALOGD("(tid:%d)[native_release] + context=%p camera=%p \n", ::gettid(), context, camera.get()); // clear callbacks if (camera != NULL) { ALOGD("[native_release] context->getStrongCount(%d) camera->getStrongCount(%d) \n", context->getStrongCount(), camera->getStrongCount()); camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); camera->disconnect(); camera = NULL; } ALOGD("(tid:%d)[native_release] - context=%p camera=%p \n", ::gettid(), context, camera.get()); #else // clear callbacks if (camera != NULL) { camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); camera->disconnect(); } #endif //MTK_CAMERA_BSP_SUPPORT //!-- // remove context to prevent further Java access context->decStrong((void*)android_hardware_Camera_native_setup); } //!++ //#ifdef MTK_CAMERA_BSP_SUPPORT ALOGD("(tid:%d)[release camera] - X context=%p \n", ::gettid(), context); //#endif //!-- }
static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean manualBuffer) { LOGV("setHasPreviewCallback: installed:%d, manualBuffer:%d", (int)installed, (int)manualBuffer); // Important: Only install preview_callback if the Java code has called // setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy // each preview frame for nothing. JNICameraContext* context; sp<Camera> camera = get_native_camera(env, thiz, &context); if (camera == 0) return; // setCallbackMode will take care of setting the context flags and calling // camera->setPreviewCallbackFlags within a mutex for us. context->setCallbackMode(env, installed, manualBuffer); }
sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext) { sp<Camera> camera; Mutex::Autolock _l(sLock); JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context)); if (context != NULL) { camera = context->getCamera(); } LOGV("get_native_camera: context=%p, camera=%p", context, camera.get()); if (camera == 0) { jniThrowRuntimeException(env, "Method called after release()"); } if (pContext != NULL) *pContext = context; return camera; }
static void android_hardware_Camera_setPreviewCallbackSurface(JNIEnv *env, jobject thiz, jobject jSurface) { ALOGV("setPreviewCallbackSurface"); JNICameraContext* context; sp<Camera> camera = get_native_camera(env, thiz, &context); if (camera == 0) return; sp<IGraphicBufferProducer> gbp; sp<Surface> surface; if (jSurface) { surface = android_view_Surface_getSurface(env, jSurface); if (surface != NULL) { gbp = surface->getIGraphicBufferProducer(); } } // Clear out normal preview callbacks context->setCallbackMode(env, false, false); // Then set up callback surface if (camera->setPreviewCallbackTarget(gbp) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewCallbackTarget failed"); } }