1 /* 2 ** 3 ** Copyright 2008, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 //#define LOG_NDEBUG 0 19 #define LOG_TAG "Camera-JNI" 20 #include <utils/Log.h> 21 22 #include "jni.h" 23 #include "JNIHelp.h" 24 #include "android_runtime/AndroidRuntime.h" 25 #include <android_runtime/android_graphics_SurfaceTexture.h> 26 #include <android_runtime/android_view_Surface.h> 27 28 #include <cutils/properties.h> 29 #include <utils/Vector.h> 30 #include <utils/Errors.h> 31 32 #include <gui/GLConsumer.h> 33 #include <gui/Surface.h> 34 #include <camera/Camera.h> 35 #include <binder/IMemory.h> 36 37 using namespace android; 38 39 enum { 40 // Keep up to date with Camera.java 41 CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2, 42 }; 43 44 struct fields_t { 45 jfieldID context; 46 jfieldID facing; 47 jfieldID orientation; 48 jfieldID canDisableShutterSound; 49 jfieldID face_rect; 50 jfieldID face_score; 51 jfieldID rect_left; 52 jfieldID rect_top; 53 jfieldID rect_right; 54 jfieldID rect_bottom; 55 jmethodID post_event; 56 jmethodID rect_constructor; 57 jmethodID face_constructor; 58 }; 59 60 static fields_t fields; 61 static Mutex sLock; 62 63 // provides persistent context for calls from native code to Java 64 class JNICameraContext: public CameraListener 65 { 66 public: 67 JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera); 68 ~JNICameraContext() { release(); } 69 virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); 70 virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, 71 camera_frame_metadata_t *metadata); 72 virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); 73 void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata); 74 void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType); 75 void setCallbackMode(JNIEnv *env, bool installed, bool manualMode); 76 sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; } 77 bool isRawImageCallbackBufferAvailable() const; 78 void release(); 79 80 private: 81 void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType); 82 void clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers); 83 void clearCallbackBuffers_l(JNIEnv *env); 84 jbyteArray getCallbackBuffer(JNIEnv *env, Vector<jbyteArray> *buffers, size_t bufferSize); 85 86 jobject mCameraJObjectWeak; // weak reference to java object 87 jclass mCameraJClass; // strong reference to java class 88 sp<Camera> mCamera; // strong reference to native object 89 jclass mFaceClass; // strong reference to Face class 90 jclass mRectClass; // strong reference to Rect class 91 Mutex mLock; 92 93 /* 94 * Global reference application-managed raw image buffer queue. 95 * 96 * Manual-only mode is supported for raw image callbacks, which is 97 * set whenever method addCallbackBuffer() with msgType = 98 * CAMERA_MSG_RAW_IMAGE is called; otherwise, null is returned 99 * with raw image callbacks. 100 */ 101 Vector<jbyteArray> mRawImageCallbackBuffers; 102 103 /* 104 * Application-managed preview buffer queue and the flags 105 * associated with the usage of the preview buffer callback. 106 */ 107 Vector<jbyteArray> mCallbackBuffers; // Global reference application managed byte[] 108 bool mManualBufferMode; // Whether to use application managed buffers. 109 bool mManualCameraCallbackSet; // Whether the callback has been set, used to 110 // reduce unnecessary calls to set the callback. 111 }; 112 113 bool JNICameraContext::isRawImageCallbackBufferAvailable() const 114 { 115 return !mRawImageCallbackBuffers.isEmpty(); 116 } 117 118 sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext) 119 { 120 sp<Camera> camera; 121 Mutex::Autolock _l(sLock); 122 JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); 123 if (context != NULL) { 124 camera = context->getCamera(); 125 } 126 ALOGV("get_native_camera: context=%p, camera=%p", context, camera.get()); 127 if (camera == 0) { 128 jniThrowRuntimeException(env, "Method called after release()"); 129 } 130 131 if (pContext != NULL) *pContext = context; 132 return camera; 133 } 134 135 JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera) 136 { 137 mCameraJObjectWeak = env->NewGlobalRef(weak_this); 138 mCameraJClass = (jclass)env->NewGlobalRef(clazz); 139 mCamera = camera; 140 141 jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); 142 mFaceClass = (jclass) env->NewGlobalRef(faceClazz); 143 144 jclass rectClazz = env->FindClass("android/graphics/Rect"); 145 mRectClass = (jclass) env->NewGlobalRef(rectClazz); 146 147 mManualBufferMode = false; 148 mManualCameraCallbackSet = false; 149 } 150 151 void JNICameraContext::release() 152 { 153 ALOGV("release"); 154 Mutex::Autolock _l(mLock); 155 JNIEnv *env = AndroidRuntime::getJNIEnv(); 156 157 if (mCameraJObjectWeak != NULL) { 158 env->DeleteGlobalRef(mCameraJObjectWeak); 159 mCameraJObjectWeak = NULL; 160 } 161 if (mCameraJClass != NULL) { 162 env->DeleteGlobalRef(mCameraJClass); 163 mCameraJClass = NULL; 164 } 165 if (mFaceClass != NULL) { 166 env->DeleteGlobalRef(mFaceClass); 167 mFaceClass = NULL; 168 } 169 if (mRectClass != NULL) { 170 env->DeleteGlobalRef(mRectClass); 171 mRectClass = NULL; 172 } 173 clearCallbackBuffers_l(env); 174 mCamera.clear(); 175 } 176 177 void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2) 178 { 179 ALOGV("notify"); 180 181 // VM pointer will be NULL if object is released 182 Mutex::Autolock _l(mLock); 183 if (mCameraJObjectWeak == NULL) { 184 ALOGW("callback on dead camera object"); 185 return; 186 } 187 JNIEnv *env = AndroidRuntime::getJNIEnv(); 188 189 /* 190 * If the notification or msgType is CAMERA_MSG_RAW_IMAGE_NOTIFY, change it 191 * to CAMERA_MSG_RAW_IMAGE since CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed 192 * to the Java app. 193 */ 194 if (msgType == CAMERA_MSG_RAW_IMAGE_NOTIFY) { 195 msgType = CAMERA_MSG_RAW_IMAGE; 196 } 197 198 env->CallStaticVoidMethod(mCameraJClass, fields.post_event, 199 mCameraJObjectWeak, msgType, ext1, ext2, NULL); 200 } 201 202 jbyteArray JNICameraContext::getCallbackBuffer( 203 JNIEnv* env, Vector<jbyteArray>* buffers, size_t bufferSize) 204 { 205 jbyteArray obj = NULL; 206 207 // Vector access should be protected by lock in postData() 208 if (!buffers->isEmpty()) { 209 ALOGV("Using callback buffer from queue of length %d", buffers->size()); 210 jbyteArray globalBuffer = buffers->itemAt(0); 211 buffers->removeAt(0); 212 213 obj = (jbyteArray)env->NewLocalRef(globalBuffer); 214 env->DeleteGlobalRef(globalBuffer); 215 216 if (obj != NULL) { 217 jsize bufferLength = env->GetArrayLength(obj); 218 if ((int)bufferLength < (int)bufferSize) { 219 ALOGE("Callback buffer was too small! Expected %d bytes, but got %d bytes!", 220 bufferSize, bufferLength); 221 env->DeleteLocalRef(obj); 222 return NULL; 223 } 224 } 225 } 226 227 return obj; 228 } 229 230 void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType) 231 { 232 jbyteArray obj = NULL; 233 234 // allocate Java byte array and copy data 235 if (dataPtr != NULL) { 236 ssize_t offset; 237 size_t size; 238 sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size); 239 ALOGV("copyAndPost: off=%zd, size=%zu", offset, size); 240 uint8_t *heapBase = (uint8_t*)heap->base(); 241 242 if (heapBase != NULL) { 243 const jbyte* data = reinterpret_cast<const jbyte*>(heapBase + offset); 244 245 if (msgType == CAMERA_MSG_RAW_IMAGE) { 246 obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size); 247 } else if (msgType == CAMERA_MSG_PREVIEW_FRAME && mManualBufferMode) { 248 obj = getCallbackBuffer(env, &mCallbackBuffers, size); 249 250 if (mCallbackBuffers.isEmpty()) { 251 ALOGV("Out of buffers, clearing callback!"); 252 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); 253 mManualCameraCallbackSet = false; 254 255 if (obj == NULL) { 256 return; 257 } 258 } 259 } else { 260 ALOGV("Allocating callback buffer"); 261 obj = env->NewByteArray(size); 262 } 263 264 if (obj == NULL) { 265 ALOGE("Couldn't allocate byte array for JPEG data"); 266 env->ExceptionClear(); 267 } else { 268 env->SetByteArrayRegion(obj, 0, size, data); 269 } 270 } else { 271 ALOGE("image heap is NULL"); 272 } 273 } 274 275 // post image data to Java 276 env->CallStaticVoidMethod(mCameraJClass, fields.post_event, 277 mCameraJObjectWeak, msgType, 0, 0, obj); 278 if (obj) { 279 env->DeleteLocalRef(obj); 280 } 281 } 282 283 void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, 284 camera_frame_metadata_t *metadata) 285 { 286 // VM pointer will be NULL if object is released 287 Mutex::Autolock _l(mLock); 288 JNIEnv *env = AndroidRuntime::getJNIEnv(); 289 if (mCameraJObjectWeak == NULL) { 290 ALOGW("callback on dead camera object"); 291 return; 292 } 293 294 int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA; 295 296 // return data based on callback type 297 switch (dataMsgType) { 298 case CAMERA_MSG_VIDEO_FRAME: 299 // should never happen 300 break; 301 302 // For backward-compatibility purpose, if there is no callback 303 // buffer for raw image, the callback returns null. 304 case CAMERA_MSG_RAW_IMAGE: 305 ALOGV("rawCallback"); 306 if (mRawImageCallbackBuffers.isEmpty()) { 307 env->CallStaticVoidMethod(mCameraJClass, fields.post_event, 308 mCameraJObjectWeak, dataMsgType, 0, 0, NULL); 309 } else { 310 copyAndPost(env, dataPtr, dataMsgType); 311 } 312 break; 313 314 // There is no data. 315 case 0: 316 break; 317 318 default: 319 ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get()); 320 copyAndPost(env, dataPtr, dataMsgType); 321 break; 322 } 323 324 // post frame metadata to Java 325 if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) { 326 postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata); 327 } 328 } 329 330 void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) 331 { 332 // TODO: plumb up to Java. For now, just drop the timestamp 333 postData(msgType, dataPtr, NULL); 334 } 335 336 void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata) 337 { 338 jobjectArray obj = NULL; 339 obj = (jobjectArray) env->NewObjectArray(metadata->number_of_faces, 340 mFaceClass, NULL); 341 if (obj == NULL) { 342 ALOGE("Couldn't allocate face metadata array"); 343 return; 344 } 345 346 for (int i = 0; i < metadata->number_of_faces; i++) { 347 jobject face = env->NewObject(mFaceClass, fields.face_constructor); 348 env->SetObjectArrayElement(obj, i, face); 349 350 jobject rect = env->NewObject(mRectClass, fields.rect_constructor); 351 env->SetIntField(rect, fields.rect_left, metadata->faces[i].rect[0]); 352 env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); 353 env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); 354 env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); 355 356 env->SetObjectField(face, fields.face_rect, rect); 357 env->SetIntField(face, fields.face_score, metadata->faces[i].score); 358 359 env->DeleteLocalRef(face); 360 env->DeleteLocalRef(rect); 361 } 362 env->CallStaticVoidMethod(mCameraJClass, fields.post_event, 363 mCameraJObjectWeak, msgType, 0, 0, obj); 364 env->DeleteLocalRef(obj); 365 } 366 367 void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualMode) 368 { 369 Mutex::Autolock _l(mLock); 370 mManualBufferMode = manualMode; 371 mManualCameraCallbackSet = false; 372 373 // In order to limit the over usage of binder threads, all non-manual buffer 374 // callbacks use CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER mode now. 375 // 376 // Continuous callbacks will have the callback re-registered from handleMessage. 377 // Manual buffer mode will operate as fast as possible, relying on the finite supply 378 // of buffers for throttling. 379 380 if (!installed) { 381 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); 382 clearCallbackBuffers_l(env, &mCallbackBuffers); 383 } else if (mManualBufferMode) { 384 if (!mCallbackBuffers.isEmpty()) { 385 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_CAMERA); 386 mManualCameraCallbackSet = true; 387 } 388 } else { 389 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER); 390 clearCallbackBuffers_l(env, &mCallbackBuffers); 391 } 392 } 393 394 void JNICameraContext::addCallbackBuffer( 395 JNIEnv *env, jbyteArray cbb, int msgType) 396 { 397 ALOGV("addCallbackBuffer: 0x%x", msgType); 398 if (cbb != NULL) { 399 Mutex::Autolock _l(mLock); 400 switch (msgType) { 401 case CAMERA_MSG_PREVIEW_FRAME: { 402 jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb); 403 mCallbackBuffers.push(callbackBuffer); 404 405 ALOGV("Adding callback buffer to queue, %d total", 406 mCallbackBuffers.size()); 407 408 // We want to make sure the camera knows we're ready for the 409 // next frame. This may have come unset had we not had a 410 // callbackbuffer ready for it last time. 411 if (mManualBufferMode && !mManualCameraCallbackSet) { 412 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_CAMERA); 413 mManualCameraCallbackSet = true; 414 } 415 break; 416 } 417 case CAMERA_MSG_RAW_IMAGE: { 418 jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb); 419 mRawImageCallbackBuffers.push(callbackBuffer); 420 break; 421 } 422 default: { 423 jniThrowException(env, 424 "java/lang/IllegalArgumentException", 425 "Unsupported message type"); 426 return; 427 } 428 } 429 } else { 430 ALOGE("Null byte array!"); 431 } 432 } 433 434 void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env) 435 { 436 clearCallbackBuffers_l(env, &mCallbackBuffers); 437 clearCallbackBuffers_l(env, &mRawImageCallbackBuffers); 438 } 439 440 void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers) { 441 ALOGV("Clearing callback buffers, %d remained", buffers->size()); 442 while (!buffers->isEmpty()) { 443 env->DeleteGlobalRef(buffers->top()); 444 buffers->pop(); 445 } 446 } 447 448 static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz) 449 { 450 return Camera::getNumberOfCameras(); 451 } 452 453 static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, 454 jint cameraId, jobject info_obj) 455 { 456 CameraInfo cameraInfo; 457 status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo); 458 if (rc != NO_ERROR) { 459 jniThrowRuntimeException(env, "Fail to get camera info"); 460 return; 461 } 462 env->SetIntField(info_obj, fields.facing, cameraInfo.facing); 463 env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation); 464 465 char value[PROPERTY_VALUE_MAX]; 466 property_get("ro.camera.sound.forced", value, "0"); 467 jboolean canDisableShutterSound = (strncmp(value, "0", 2) == 0); 468 env->SetBooleanField(info_obj, fields.canDisableShutterSound, 469 canDisableShutterSound); 470 } 471 472 // connect to camera service 473 static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, 474 jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) 475 { 476 // Convert jstring to String16 477 const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL); 478 jsize rawClientNameLen = env->GetStringLength(clientPackageName); 479 String16 clientName(rawClientName, rawClientNameLen); 480 env->ReleaseStringChars(clientPackageName, rawClientName); 481 482 sp<Camera> camera; 483 if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) { 484 // Default path: hal version is don't care, do normal camera connect. 485 camera = Camera::connect(cameraId, clientName, 486 Camera::USE_CALLING_UID); 487 } else { 488 jint status = Camera::connectLegacy(cameraId, halVersion, clientName, 489 Camera::USE_CALLING_UID, camera); 490 if (status != NO_ERROR) { 491 return status; 492 } 493 } 494 495 if (camera == NULL) { 496 return -EACCES; 497 } 498 499 // make sure camera hardware is alive 500 if (camera->getStatus() != NO_ERROR) { 501 return NO_INIT; 502 } 503 504 jclass clazz = env->GetObjectClass(thiz); 505 if (clazz == NULL) { 506 // This should never happen 507 jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); 508 return INVALID_OPERATION; 509 } 510 511 // We use a weak reference so the Camera object can be garbage collected. 512 // The reference is only used as a proxy for callbacks. 513 sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); 514 context->incStrong((void*)android_hardware_Camera_native_setup); 515 camera->setListener(context); 516 517 // save context in opaque field 518 env->SetLongField(thiz, fields.context, (jlong)context.get()); 519 return NO_ERROR; 520 } 521 522 // disconnect from camera service 523 // It's okay to call this when the native camera context is already null. 524 // This handles the case where the user has called release() and the 525 // finalizer is invoked later. 526 static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) 527 { 528 ALOGV("release camera"); 529 JNICameraContext* context = NULL; 530 sp<Camera> camera; 531 { 532 Mutex::Autolock _l(sLock); 533 context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); 534 535 // Make sure we do not attempt to callback on a deleted Java object. 536 env->SetLongField(thiz, fields.context, 0); 537 } 538 539 // clean up if release has not been called before 540 if (context != NULL) { 541 camera = context->getCamera(); 542 context->release(); 543 ALOGV("native_release: context=%p camera=%p", context, camera.get()); 544 545 // clear callbacks 546 if (camera != NULL) { 547 camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); 548 camera->disconnect(); 549 } 550 551 // remove context to prevent further Java access 552 context->decStrong((void*)android_hardware_Camera_native_setup); 553 } 554 } 555 556 static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface) 557 { 558 ALOGV("setPreviewSurface"); 559 sp<Camera> camera = get_native_camera(env, thiz, NULL); 560 if (camera == 0) return; 561 562 sp<IGraphicBufferProducer> gbp; 563 sp<Surface> surface; 564 if (jSurface) { 565 surface = android_view_Surface_getSurface(env, jSurface); 566 if (surface != NULL) { 567 gbp = surface->getIGraphicBufferProducer(); 568 } 569 } 570 571 if (camera->setPreviewTarget(gbp) != NO_ERROR) { 572 jniThrowException(env, "java/io/IOException", "setPreviewTexture failed"); 573 } 574 } 575 576 static void android_hardware_Camera_setPreviewTexture(JNIEnv *env, 577 jobject thiz, jobject jSurfaceTexture) 578 { 579 ALOGV("setPreviewTexture"); 580 sp<Camera> camera = get_native_camera(env, thiz, NULL); 581 if (camera == 0) return; 582 583 sp<IGraphicBufferProducer> producer = NULL; 584 if (jSurfaceTexture != NULL) { 585 producer = SurfaceTexture_getProducer(env, jSurfaceTexture); 586 if (producer == NULL) { 587 jniThrowException(env, "java/lang/IllegalArgumentException", 588 "SurfaceTexture already released in setPreviewTexture"); 589 return; 590 } 591 592 } 593 594 if (camera->setPreviewTarget(producer) != NO_ERROR) { 595 jniThrowException(env, "java/io/IOException", 596 "setPreviewTexture failed"); 597 } 598 } 599 600 static void android_hardware_Camera_setPreviewCallbackSurface(JNIEnv *env, 601 jobject thiz, jobject jSurface) 602 { 603 ALOGV("setPreviewCallbackSurface"); 604 JNICameraContext* context; 605 sp<Camera> camera = get_native_camera(env, thiz, &context); 606 if (camera == 0) return; 607 608 sp<IGraphicBufferProducer> gbp; 609 sp<Surface> surface; 610 if (jSurface) { 611 surface = android_view_Surface_getSurface(env, jSurface); 612 if (surface != NULL) { 613 gbp = surface->getIGraphicBufferProducer(); 614 } 615 } 616 // Clear out normal preview callbacks 617 context->setCallbackMode(env, false, false); 618 // Then set up callback surface 619 if (camera->setPreviewCallbackTarget(gbp) != NO_ERROR) { 620 jniThrowException(env, "java/io/IOException", "setPreviewCallbackTarget failed"); 621 } 622 } 623 624 static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz) 625 { 626 ALOGV("startPreview"); 627 sp<Camera> camera = get_native_camera(env, thiz, NULL); 628 if (camera == 0) return; 629 630 if (camera->startPreview() != NO_ERROR) { 631 jniThrowRuntimeException(env, "startPreview failed"); 632 return; 633 } 634 } 635 636 static void android_hardware_Camera_stopPreview(JNIEnv *env, jobject thiz) 637 { 638 ALOGV("stopPreview"); 639 sp<Camera> c = get_native_camera(env, thiz, NULL); 640 if (c == 0) return; 641 642 c->stopPreview(); 643 } 644 645 static jboolean android_hardware_Camera_previewEnabled(JNIEnv *env, jobject thiz) 646 { 647 ALOGV("previewEnabled"); 648 sp<Camera> c = get_native_camera(env, thiz, NULL); 649 if (c == 0) return JNI_FALSE; 650 651 return c->previewEnabled() ? JNI_TRUE : JNI_FALSE; 652 } 653 654 static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean manualBuffer) 655 { 656 ALOGV("setHasPreviewCallback: installed:%d, manualBuffer:%d", (int)installed, (int)manualBuffer); 657 // Important: Only install preview_callback if the Java code has called 658 // setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy 659 // each preview frame for nothing. 660 JNICameraContext* context; 661 sp<Camera> camera = get_native_camera(env, thiz, &context); 662 if (camera == 0) return; 663 664 // setCallbackMode will take care of setting the context flags and calling 665 // camera->setPreviewCallbackFlags within a mutex for us. 666 context->setCallbackMode(env, installed, manualBuffer); 667 } 668 669 static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) { 670 ALOGV("addCallbackBuffer: 0x%x", msgType); 671 672 JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); 673 674 if (context != NULL) { 675 context->addCallbackBuffer(env, bytes, msgType); 676 } 677 } 678 679 static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz) 680 { 681 ALOGV("autoFocus"); 682 JNICameraContext* context; 683 sp<Camera> c = get_native_camera(env, thiz, &context); 684 if (c == 0) return; 685 686 if (c->autoFocus() != NO_ERROR) { 687 jniThrowRuntimeException(env, "autoFocus failed"); 688 } 689 } 690 691 static void android_hardware_Camera_cancelAutoFocus(JNIEnv *env, jobject thiz) 692 { 693 ALOGV("cancelAutoFocus"); 694 JNICameraContext* context; 695 sp<Camera> c = get_native_camera(env, thiz, &context); 696 if (c == 0) return; 697 698 if (c->cancelAutoFocus() != NO_ERROR) { 699 jniThrowRuntimeException(env, "cancelAutoFocus failed"); 700 } 701 } 702 703 static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType) 704 { 705 ALOGV("takePicture"); 706 JNICameraContext* context; 707 sp<Camera> camera = get_native_camera(env, thiz, &context); 708 if (camera == 0) return; 709 710 /* 711 * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback 712 * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the 713 * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY 714 * is enabled to receive the callback notification but no data. 715 * 716 * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the 717 * Java application. 718 */ 719 if (msgType & CAMERA_MSG_RAW_IMAGE) { 720 ALOGV("Enable raw image callback buffer"); 721 if (!context->isRawImageCallbackBufferAvailable()) { 722 ALOGV("Enable raw image notification, since no callback buffer exists"); 723 msgType &= ~CAMERA_MSG_RAW_IMAGE; 724 msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY; 725 } 726 } 727 728 if (camera->takePicture(msgType) != NO_ERROR) { 729 jniThrowRuntimeException(env, "takePicture failed"); 730 return; 731 } 732 } 733 734 static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params) 735 { 736 ALOGV("setParameters"); 737 sp<Camera> camera = get_native_camera(env, thiz, NULL); 738 if (camera == 0) return; 739 740 const jchar* str = env->GetStringCritical(params, 0); 741 String8 params8; 742 if (params) { 743 params8 = String8(str, env->GetStringLength(params)); 744 env->ReleaseStringCritical(params, str); 745 } 746 if (camera->setParameters(params8) != NO_ERROR) { 747 jniThrowRuntimeException(env, "setParameters failed"); 748 return; 749 } 750 } 751 752 static jstring android_hardware_Camera_getParameters(JNIEnv *env, jobject thiz) 753 { 754 ALOGV("getParameters"); 755 sp<Camera> camera = get_native_camera(env, thiz, NULL); 756 if (camera == 0) return 0; 757 758 String8 params8 = camera->getParameters(); 759 if (params8.isEmpty()) { 760 jniThrowRuntimeException(env, "getParameters failed (empty parameters)"); 761 return 0; 762 } 763 return env->NewStringUTF(params8.string()); 764 } 765 766 static void android_hardware_Camera_reconnect(JNIEnv *env, jobject thiz) 767 { 768 ALOGV("reconnect"); 769 sp<Camera> camera = get_native_camera(env, thiz, NULL); 770 if (camera == 0) return; 771 772 if (camera->reconnect() != NO_ERROR) { 773 jniThrowException(env, "java/io/IOException", "reconnect failed"); 774 return; 775 } 776 } 777 778 static void android_hardware_Camera_lock(JNIEnv *env, jobject thiz) 779 { 780 ALOGV("lock"); 781 sp<Camera> camera = get_native_camera(env, thiz, NULL); 782 if (camera == 0) return; 783 784 if (camera->lock() != NO_ERROR) { 785 jniThrowRuntimeException(env, "lock failed"); 786 } 787 } 788 789 static void android_hardware_Camera_unlock(JNIEnv *env, jobject thiz) 790 { 791 ALOGV("unlock"); 792 sp<Camera> camera = get_native_camera(env, thiz, NULL); 793 if (camera == 0) return; 794 795 if (camera->unlock() != NO_ERROR) { 796 jniThrowRuntimeException(env, "unlock failed"); 797 } 798 } 799 800 static void android_hardware_Camera_startSmoothZoom(JNIEnv *env, jobject thiz, jint value) 801 { 802 ALOGV("startSmoothZoom"); 803 sp<Camera> camera = get_native_camera(env, thiz, NULL); 804 if (camera == 0) return; 805 806 status_t rc = camera->sendCommand(CAMERA_CMD_START_SMOOTH_ZOOM, value, 0); 807 if (rc == BAD_VALUE) { 808 char msg[64]; 809 sprintf(msg, "invalid zoom value=%d", value); 810 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 811 } else if (rc != NO_ERROR) { 812 jniThrowRuntimeException(env, "start smooth zoom failed"); 813 } 814 } 815 816 static void android_hardware_Camera_stopSmoothZoom(JNIEnv *env, jobject thiz) 817 { 818 ALOGV("stopSmoothZoom"); 819 sp<Camera> camera = get_native_camera(env, thiz, NULL); 820 if (camera == 0) return; 821 822 if (camera->sendCommand(CAMERA_CMD_STOP_SMOOTH_ZOOM, 0, 0) != NO_ERROR) { 823 jniThrowRuntimeException(env, "stop smooth zoom failed"); 824 } 825 } 826 827 static void android_hardware_Camera_setDisplayOrientation(JNIEnv *env, jobject thiz, 828 jint value) 829 { 830 ALOGV("setDisplayOrientation"); 831 sp<Camera> camera = get_native_camera(env, thiz, NULL); 832 if (camera == 0) return; 833 834 if (camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION, value, 0) != NO_ERROR) { 835 jniThrowRuntimeException(env, "set display orientation failed"); 836 } 837 } 838 839 static jboolean android_hardware_Camera_enableShutterSound(JNIEnv *env, jobject thiz, 840 jboolean enabled) 841 { 842 ALOGV("enableShutterSound"); 843 sp<Camera> camera = get_native_camera(env, thiz, NULL); 844 if (camera == 0) return JNI_FALSE; 845 846 int32_t value = (enabled == JNI_TRUE) ? 1 : 0; 847 status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0); 848 if (rc == NO_ERROR) { 849 return JNI_TRUE; 850 } else if (rc == PERMISSION_DENIED) { 851 return JNI_FALSE; 852 } else { 853 jniThrowRuntimeException(env, "enable shutter sound failed"); 854 return JNI_FALSE; 855 } 856 } 857 858 static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz, 859 jint type) 860 { 861 ALOGV("startFaceDetection"); 862 JNICameraContext* context; 863 sp<Camera> camera = get_native_camera(env, thiz, &context); 864 if (camera == 0) return; 865 866 status_t rc = camera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, type, 0); 867 if (rc == BAD_VALUE) { 868 char msg[64]; 869 snprintf(msg, sizeof(msg), "invalid face detection type=%d", type); 870 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 871 } else if (rc != NO_ERROR) { 872 jniThrowRuntimeException(env, "start face detection failed"); 873 } 874 } 875 876 static void android_hardware_Camera_stopFaceDetection(JNIEnv *env, jobject thiz) 877 { 878 ALOGV("stopFaceDetection"); 879 sp<Camera> camera = get_native_camera(env, thiz, NULL); 880 if (camera == 0) return; 881 882 if (camera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0) != NO_ERROR) { 883 jniThrowRuntimeException(env, "stop face detection failed"); 884 } 885 } 886 887 static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject thiz, jint enable) 888 { 889 ALOGV("enableFocusMoveCallback"); 890 sp<Camera> camera = get_native_camera(env, thiz, NULL); 891 if (camera == 0) return; 892 893 if (camera->sendCommand(CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG, enable, 0) != NO_ERROR) { 894 jniThrowRuntimeException(env, "enable focus move callback failed"); 895 } 896 } 897 898 //------------------------------------------------- 899 900 static JNINativeMethod camMethods[] = { 901 { "getNumberOfCameras", 902 "()I", 903 (void *)android_hardware_Camera_getNumberOfCameras }, 904 { "_getCameraInfo", 905 "(ILandroid/hardware/Camera$CameraInfo;)V", 906 (void*)android_hardware_Camera_getCameraInfo }, 907 { "native_setup", 908 "(Ljava/lang/Object;IILjava/lang/String;)I", 909 (void*)android_hardware_Camera_native_setup }, 910 { "native_release", 911 "()V", 912 (void*)android_hardware_Camera_release }, 913 { "setPreviewSurface", 914 "(Landroid/view/Surface;)V", 915 (void *)android_hardware_Camera_setPreviewSurface }, 916 { "setPreviewTexture", 917 "(Landroid/graphics/SurfaceTexture;)V", 918 (void *)android_hardware_Camera_setPreviewTexture }, 919 { "setPreviewCallbackSurface", 920 "(Landroid/view/Surface;)V", 921 (void *)android_hardware_Camera_setPreviewCallbackSurface }, 922 { "startPreview", 923 "()V", 924 (void *)android_hardware_Camera_startPreview }, 925 { "_stopPreview", 926 "()V", 927 (void *)android_hardware_Camera_stopPreview }, 928 { "previewEnabled", 929 "()Z", 930 (void *)android_hardware_Camera_previewEnabled }, 931 { "setHasPreviewCallback", 932 "(ZZ)V", 933 (void *)android_hardware_Camera_setHasPreviewCallback }, 934 { "_addCallbackBuffer", 935 "([BI)V", 936 (void *)android_hardware_Camera_addCallbackBuffer }, 937 { "native_autoFocus", 938 "()V", 939 (void *)android_hardware_Camera_autoFocus }, 940 { "native_cancelAutoFocus", 941 "()V", 942 (void *)android_hardware_Camera_cancelAutoFocus }, 943 { "native_takePicture", 944 "(I)V", 945 (void *)android_hardware_Camera_takePicture }, 946 { "native_setParameters", 947 "(Ljava/lang/String;)V", 948 (void *)android_hardware_Camera_setParameters }, 949 { "native_getParameters", 950 "()Ljava/lang/String;", 951 (void *)android_hardware_Camera_getParameters }, 952 { "reconnect", 953 "()V", 954 (void*)android_hardware_Camera_reconnect }, 955 { "lock", 956 "()V", 957 (void*)android_hardware_Camera_lock }, 958 { "unlock", 959 "()V", 960 (void*)android_hardware_Camera_unlock }, 961 { "startSmoothZoom", 962 "(I)V", 963 (void *)android_hardware_Camera_startSmoothZoom }, 964 { "stopSmoothZoom", 965 "()V", 966 (void *)android_hardware_Camera_stopSmoothZoom }, 967 { "setDisplayOrientation", 968 "(I)V", 969 (void *)android_hardware_Camera_setDisplayOrientation }, 970 { "_enableShutterSound", 971 "(Z)Z", 972 (void *)android_hardware_Camera_enableShutterSound }, 973 { "_startFaceDetection", 974 "(I)V", 975 (void *)android_hardware_Camera_startFaceDetection }, 976 { "_stopFaceDetection", 977 "()V", 978 (void *)android_hardware_Camera_stopFaceDetection}, 979 { "enableFocusMoveCallback", 980 "(I)V", 981 (void *)android_hardware_Camera_enableFocusMoveCallback}, 982 }; 983 984 struct field { 985 const char *class_name; 986 const char *field_name; 987 const char *field_type; 988 jfieldID *jfield; 989 }; 990 991 static int find_fields(JNIEnv *env, field *fields, int count) 992 { 993 for (int i = 0; i < count; i++) { 994 field *f = &fields[i]; 995 jclass clazz = env->FindClass(f->class_name); 996 if (clazz == NULL) { 997 ALOGE("Can't find %s", f->class_name); 998 return -1; 999 } 1000 1001 jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type); 1002 if (field == NULL) { 1003 ALOGE("Can't find %s.%s", f->class_name, f->field_name); 1004 return -1; 1005 } 1006 1007 *(f->jfield) = field; 1008 } 1009 1010 return 0; 1011 } 1012 1013 // Get all the required offsets in java class and register native functions 1014 int register_android_hardware_Camera(JNIEnv *env) 1015 { 1016 field fields_to_find[] = { 1017 { "android/hardware/Camera", "mNativeContext", "J", &fields.context }, 1018 { "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing }, 1019 { "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation }, 1020 { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z", 1021 &fields.canDisableShutterSound }, 1022 { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, 1023 { "android/hardware/Camera$Face", "score", "I", &fields.face_score }, 1024 { "android/graphics/Rect", "left", "I", &fields.rect_left }, 1025 { "android/graphics/Rect", "top", "I", &fields.rect_top }, 1026 { "android/graphics/Rect", "right", "I", &fields.rect_right }, 1027 { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom }, 1028 }; 1029 1030 if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0) 1031 return -1; 1032 1033 jclass clazz = env->FindClass("android/hardware/Camera"); 1034 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", 1035 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 1036 if (fields.post_event == NULL) { 1037 ALOGE("Can't find android/hardware/Camera.postEventFromNative"); 1038 return -1; 1039 } 1040 1041 clazz = env->FindClass("android/graphics/Rect"); 1042 fields.rect_constructor = env->GetMethodID(clazz, "<init>", "()V"); 1043 if (fields.rect_constructor == NULL) { 1044 ALOGE("Can't find android/graphics/Rect.Rect()"); 1045 return -1; 1046 } 1047 1048 clazz = env->FindClass("android/hardware/Camera$Face"); 1049 fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V"); 1050 if (fields.face_constructor == NULL) { 1051 ALOGE("Can't find android/hardware/Camera$Face.Face()"); 1052 return -1; 1053 } 1054 1055 // Register native functions 1056 return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", 1057 camMethods, NELEM(camMethods)); 1058 } 1059