android_hardware_Camera.cpp revision ed6b9dff563c5e22f040ff37e12c0d771e0478ae
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 "core_jni_helpers.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 37using namespace android; 38 39enum { 40 // Keep up to date with Camera.java 41 CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2, 42}; 43 44struct 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 60static fields_t fields; 61static Mutex sLock; 62 63// provides persistent context for calls from native code to Java 64class JNICameraContext: public CameraListener 65{ 66public: 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 80private: 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 113bool JNICameraContext::isRawImageCallbackBufferAvailable() const 114{ 115 return !mRawImageCallbackBuffers.isEmpty(); 116} 117 118sp<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 135JNICameraContext::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 151void 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 177void 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 202jbyteArray 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 %zu", 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 %zu bytes, but got %d bytes!", 220 bufferSize, bufferLength); 221 env->DeleteLocalRef(obj); 222 return NULL; 223 } 224 } 225 } 226 227 return obj; 228} 229 230void 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 283void 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 330void 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 336void 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 367void 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 394void 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, %zu 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 434void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env) 435{ 436 clearCallbackBuffers_l(env, &mCallbackBuffers); 437 clearCallbackBuffers_l(env, &mRawImageCallbackBuffers); 438} 439 440void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers) { 441 ALOGV("Clearing callback buffers, %zu remained", buffers->size()); 442 while (!buffers->isEmpty()) { 443 env->DeleteGlobalRef(buffers->top()); 444 buffers->pop(); 445 } 446} 447 448static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz) 449{ 450 return Camera::getNumberOfCameras(); 451} 452 453static 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 473static 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 = reinterpret_cast<const char16_t*>( 478 env->GetStringChars(clientPackageName, NULL)); 479 jsize rawClientNameLen = env->GetStringLength(clientPackageName); 480 String16 clientName(rawClientName, rawClientNameLen); 481 env->ReleaseStringChars(clientPackageName, 482 reinterpret_cast<const jchar*>(rawClientName)); 483 484 sp<Camera> camera; 485 if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) { 486 // Default path: hal version is don't care, do normal camera connect. 487 camera = Camera::connect(cameraId, clientName, 488 Camera::USE_CALLING_UID); 489 } else { 490 jint status = Camera::connectLegacy(cameraId, halVersion, clientName, 491 Camera::USE_CALLING_UID, camera); 492 if (status != NO_ERROR) { 493 return status; 494 } 495 } 496 497 if (camera == NULL) { 498 return -EACCES; 499 } 500 501 // make sure camera hardware is alive 502 if (camera->getStatus() != NO_ERROR) { 503 return NO_INIT; 504 } 505 506 jclass clazz = env->GetObjectClass(thiz); 507 if (clazz == NULL) { 508 // This should never happen 509 jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); 510 return INVALID_OPERATION; 511 } 512 513 // We use a weak reference so the Camera object can be garbage collected. 514 // The reference is only used as a proxy for callbacks. 515 sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); 516 context->incStrong((void*)android_hardware_Camera_native_setup); 517 camera->setListener(context); 518 519 // save context in opaque field 520 env->SetLongField(thiz, fields.context, (jlong)context.get()); 521 return NO_ERROR; 522} 523 524// disconnect from camera service 525// It's okay to call this when the native camera context is already null. 526// This handles the case where the user has called release() and the 527// finalizer is invoked later. 528static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) 529{ 530 ALOGV("release camera"); 531 JNICameraContext* context = NULL; 532 sp<Camera> camera; 533 { 534 Mutex::Autolock _l(sLock); 535 context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); 536 537 // Make sure we do not attempt to callback on a deleted Java object. 538 env->SetLongField(thiz, fields.context, 0); 539 } 540 541 // clean up if release has not been called before 542 if (context != NULL) { 543 camera = context->getCamera(); 544 context->release(); 545 ALOGV("native_release: context=%p camera=%p", context, camera.get()); 546 547 // clear callbacks 548 if (camera != NULL) { 549 camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); 550 camera->disconnect(); 551 } 552 553 // remove context to prevent further Java access 554 context->decStrong((void*)android_hardware_Camera_native_setup); 555 } 556} 557 558static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface) 559{ 560 ALOGV("setPreviewSurface"); 561 sp<Camera> camera = get_native_camera(env, thiz, NULL); 562 if (camera == 0) return; 563 564 sp<IGraphicBufferProducer> gbp; 565 sp<Surface> surface; 566 if (jSurface) { 567 surface = android_view_Surface_getSurface(env, jSurface); 568 if (surface != NULL) { 569 gbp = surface->getIGraphicBufferProducer(); 570 } 571 } 572 573 if (camera->setPreviewTarget(gbp) != NO_ERROR) { 574 jniThrowException(env, "java/io/IOException", "setPreviewTexture failed"); 575 } 576} 577 578static void android_hardware_Camera_setPreviewTexture(JNIEnv *env, 579 jobject thiz, jobject jSurfaceTexture) 580{ 581 ALOGV("setPreviewTexture"); 582 sp<Camera> camera = get_native_camera(env, thiz, NULL); 583 if (camera == 0) return; 584 585 sp<IGraphicBufferProducer> producer = NULL; 586 if (jSurfaceTexture != NULL) { 587 producer = SurfaceTexture_getProducer(env, jSurfaceTexture); 588 if (producer == NULL) { 589 jniThrowException(env, "java/lang/IllegalArgumentException", 590 "SurfaceTexture already released in setPreviewTexture"); 591 return; 592 } 593 594 } 595 596 if (camera->setPreviewTarget(producer) != NO_ERROR) { 597 jniThrowException(env, "java/io/IOException", 598 "setPreviewTexture failed"); 599 } 600} 601 602static void android_hardware_Camera_setPreviewCallbackSurface(JNIEnv *env, 603 jobject thiz, jobject jSurface) 604{ 605 ALOGV("setPreviewCallbackSurface"); 606 JNICameraContext* context; 607 sp<Camera> camera = get_native_camera(env, thiz, &context); 608 if (camera == 0) return; 609 610 sp<IGraphicBufferProducer> gbp; 611 sp<Surface> surface; 612 if (jSurface) { 613 surface = android_view_Surface_getSurface(env, jSurface); 614 if (surface != NULL) { 615 gbp = surface->getIGraphicBufferProducer(); 616 } 617 } 618 // Clear out normal preview callbacks 619 context->setCallbackMode(env, false, false); 620 // Then set up callback surface 621 if (camera->setPreviewCallbackTarget(gbp) != NO_ERROR) { 622 jniThrowException(env, "java/io/IOException", "setPreviewCallbackTarget failed"); 623 } 624} 625 626static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz) 627{ 628 ALOGV("startPreview"); 629 sp<Camera> camera = get_native_camera(env, thiz, NULL); 630 if (camera == 0) return; 631 632 if (camera->startPreview() != NO_ERROR) { 633 jniThrowRuntimeException(env, "startPreview failed"); 634 return; 635 } 636} 637 638static void android_hardware_Camera_stopPreview(JNIEnv *env, jobject thiz) 639{ 640 ALOGV("stopPreview"); 641 sp<Camera> c = get_native_camera(env, thiz, NULL); 642 if (c == 0) return; 643 644 c->stopPreview(); 645} 646 647static jboolean android_hardware_Camera_previewEnabled(JNIEnv *env, jobject thiz) 648{ 649 ALOGV("previewEnabled"); 650 sp<Camera> c = get_native_camera(env, thiz, NULL); 651 if (c == 0) return JNI_FALSE; 652 653 return c->previewEnabled() ? JNI_TRUE : JNI_FALSE; 654} 655 656static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean manualBuffer) 657{ 658 ALOGV("setHasPreviewCallback: installed:%d, manualBuffer:%d", (int)installed, (int)manualBuffer); 659 // Important: Only install preview_callback if the Java code has called 660 // setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy 661 // each preview frame for nothing. 662 JNICameraContext* context; 663 sp<Camera> camera = get_native_camera(env, thiz, &context); 664 if (camera == 0) return; 665 666 // setCallbackMode will take care of setting the context flags and calling 667 // camera->setPreviewCallbackFlags within a mutex for us. 668 context->setCallbackMode(env, installed, manualBuffer); 669} 670 671static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) { 672 ALOGV("addCallbackBuffer: 0x%x", msgType); 673 674 JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); 675 676 if (context != NULL) { 677 context->addCallbackBuffer(env, bytes, msgType); 678 } 679} 680 681static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz) 682{ 683 ALOGV("autoFocus"); 684 JNICameraContext* context; 685 sp<Camera> c = get_native_camera(env, thiz, &context); 686 if (c == 0) return; 687 688 if (c->autoFocus() != NO_ERROR) { 689 jniThrowRuntimeException(env, "autoFocus failed"); 690 } 691} 692 693static void android_hardware_Camera_cancelAutoFocus(JNIEnv *env, jobject thiz) 694{ 695 ALOGV("cancelAutoFocus"); 696 JNICameraContext* context; 697 sp<Camera> c = get_native_camera(env, thiz, &context); 698 if (c == 0) return; 699 700 if (c->cancelAutoFocus() != NO_ERROR) { 701 jniThrowRuntimeException(env, "cancelAutoFocus failed"); 702 } 703} 704 705static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType) 706{ 707 ALOGV("takePicture"); 708 JNICameraContext* context; 709 sp<Camera> camera = get_native_camera(env, thiz, &context); 710 if (camera == 0) return; 711 712 /* 713 * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback 714 * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the 715 * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY 716 * is enabled to receive the callback notification but no data. 717 * 718 * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the 719 * Java application. 720 */ 721 if (msgType & CAMERA_MSG_RAW_IMAGE) { 722 ALOGV("Enable raw image callback buffer"); 723 if (!context->isRawImageCallbackBufferAvailable()) { 724 ALOGV("Enable raw image notification, since no callback buffer exists"); 725 msgType &= ~CAMERA_MSG_RAW_IMAGE; 726 msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY; 727 } 728 } 729 730 if (camera->takePicture(msgType) != NO_ERROR) { 731 jniThrowRuntimeException(env, "takePicture failed"); 732 return; 733 } 734} 735 736static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params) 737{ 738 ALOGV("setParameters"); 739 sp<Camera> camera = get_native_camera(env, thiz, NULL); 740 if (camera == 0) return; 741 742 const jchar* str = env->GetStringCritical(params, 0); 743 String8 params8; 744 if (params) { 745 params8 = String8(reinterpret_cast<const char16_t*>(str), 746 env->GetStringLength(params)); 747 env->ReleaseStringCritical(params, str); 748 } 749 if (camera->setParameters(params8) != NO_ERROR) { 750 jniThrowRuntimeException(env, "setParameters failed"); 751 return; 752 } 753} 754 755static jstring android_hardware_Camera_getParameters(JNIEnv *env, jobject thiz) 756{ 757 ALOGV("getParameters"); 758 sp<Camera> camera = get_native_camera(env, thiz, NULL); 759 if (camera == 0) return 0; 760 761 String8 params8 = camera->getParameters(); 762 if (params8.isEmpty()) { 763 jniThrowRuntimeException(env, "getParameters failed (empty parameters)"); 764 return 0; 765 } 766 return env->NewStringUTF(params8.string()); 767} 768 769static void android_hardware_Camera_reconnect(JNIEnv *env, jobject thiz) 770{ 771 ALOGV("reconnect"); 772 sp<Camera> camera = get_native_camera(env, thiz, NULL); 773 if (camera == 0) return; 774 775 if (camera->reconnect() != NO_ERROR) { 776 jniThrowException(env, "java/io/IOException", "reconnect failed"); 777 return; 778 } 779} 780 781static void android_hardware_Camera_lock(JNIEnv *env, jobject thiz) 782{ 783 ALOGV("lock"); 784 sp<Camera> camera = get_native_camera(env, thiz, NULL); 785 if (camera == 0) return; 786 787 if (camera->lock() != NO_ERROR) { 788 jniThrowRuntimeException(env, "lock failed"); 789 } 790} 791 792static void android_hardware_Camera_unlock(JNIEnv *env, jobject thiz) 793{ 794 ALOGV("unlock"); 795 sp<Camera> camera = get_native_camera(env, thiz, NULL); 796 if (camera == 0) return; 797 798 if (camera->unlock() != NO_ERROR) { 799 jniThrowRuntimeException(env, "unlock failed"); 800 } 801} 802 803static void android_hardware_Camera_startSmoothZoom(JNIEnv *env, jobject thiz, jint value) 804{ 805 ALOGV("startSmoothZoom"); 806 sp<Camera> camera = get_native_camera(env, thiz, NULL); 807 if (camera == 0) return; 808 809 status_t rc = camera->sendCommand(CAMERA_CMD_START_SMOOTH_ZOOM, value, 0); 810 if (rc == BAD_VALUE) { 811 char msg[64]; 812 sprintf(msg, "invalid zoom value=%d", value); 813 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 814 } else if (rc != NO_ERROR) { 815 jniThrowRuntimeException(env, "start smooth zoom failed"); 816 } 817} 818 819static void android_hardware_Camera_stopSmoothZoom(JNIEnv *env, jobject thiz) 820{ 821 ALOGV("stopSmoothZoom"); 822 sp<Camera> camera = get_native_camera(env, thiz, NULL); 823 if (camera == 0) return; 824 825 if (camera->sendCommand(CAMERA_CMD_STOP_SMOOTH_ZOOM, 0, 0) != NO_ERROR) { 826 jniThrowRuntimeException(env, "stop smooth zoom failed"); 827 } 828} 829 830static void android_hardware_Camera_setDisplayOrientation(JNIEnv *env, jobject thiz, 831 jint value) 832{ 833 ALOGV("setDisplayOrientation"); 834 sp<Camera> camera = get_native_camera(env, thiz, NULL); 835 if (camera == 0) return; 836 837 if (camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION, value, 0) != NO_ERROR) { 838 jniThrowRuntimeException(env, "set display orientation failed"); 839 } 840} 841 842static jboolean android_hardware_Camera_enableShutterSound(JNIEnv *env, jobject thiz, 843 jboolean enabled) 844{ 845 ALOGV("enableShutterSound"); 846 sp<Camera> camera = get_native_camera(env, thiz, NULL); 847 if (camera == 0) return JNI_FALSE; 848 849 int32_t value = (enabled == JNI_TRUE) ? 1 : 0; 850 status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0); 851 if (rc == NO_ERROR) { 852 return JNI_TRUE; 853 } else if (rc == PERMISSION_DENIED) { 854 return JNI_FALSE; 855 } else { 856 jniThrowRuntimeException(env, "enable shutter sound failed"); 857 return JNI_FALSE; 858 } 859} 860 861static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz, 862 jint type) 863{ 864 ALOGV("startFaceDetection"); 865 JNICameraContext* context; 866 sp<Camera> camera = get_native_camera(env, thiz, &context); 867 if (camera == 0) return; 868 869 status_t rc = camera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, type, 0); 870 if (rc == BAD_VALUE) { 871 char msg[64]; 872 snprintf(msg, sizeof(msg), "invalid face detection type=%d", type); 873 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 874 } else if (rc != NO_ERROR) { 875 jniThrowRuntimeException(env, "start face detection failed"); 876 } 877} 878 879static void android_hardware_Camera_stopFaceDetection(JNIEnv *env, jobject thiz) 880{ 881 ALOGV("stopFaceDetection"); 882 sp<Camera> camera = get_native_camera(env, thiz, NULL); 883 if (camera == 0) return; 884 885 if (camera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0) != NO_ERROR) { 886 jniThrowRuntimeException(env, "stop face detection failed"); 887 } 888} 889 890static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject thiz, jint enable) 891{ 892 ALOGV("enableFocusMoveCallback"); 893 sp<Camera> camera = get_native_camera(env, thiz, NULL); 894 if (camera == 0) return; 895 896 if (camera->sendCommand(CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG, enable, 0) != NO_ERROR) { 897 jniThrowRuntimeException(env, "enable focus move callback failed"); 898 } 899} 900 901//------------------------------------------------- 902 903static JNINativeMethod camMethods[] = { 904 { "getNumberOfCameras", 905 "()I", 906 (void *)android_hardware_Camera_getNumberOfCameras }, 907 { "_getCameraInfo", 908 "(ILandroid/hardware/Camera$CameraInfo;)V", 909 (void*)android_hardware_Camera_getCameraInfo }, 910 { "native_setup", 911 "(Ljava/lang/Object;IILjava/lang/String;)I", 912 (void*)android_hardware_Camera_native_setup }, 913 { "native_release", 914 "()V", 915 (void*)android_hardware_Camera_release }, 916 { "setPreviewSurface", 917 "(Landroid/view/Surface;)V", 918 (void *)android_hardware_Camera_setPreviewSurface }, 919 { "setPreviewTexture", 920 "(Landroid/graphics/SurfaceTexture;)V", 921 (void *)android_hardware_Camera_setPreviewTexture }, 922 { "setPreviewCallbackSurface", 923 "(Landroid/view/Surface;)V", 924 (void *)android_hardware_Camera_setPreviewCallbackSurface }, 925 { "startPreview", 926 "()V", 927 (void *)android_hardware_Camera_startPreview }, 928 { "_stopPreview", 929 "()V", 930 (void *)android_hardware_Camera_stopPreview }, 931 { "previewEnabled", 932 "()Z", 933 (void *)android_hardware_Camera_previewEnabled }, 934 { "setHasPreviewCallback", 935 "(ZZ)V", 936 (void *)android_hardware_Camera_setHasPreviewCallback }, 937 { "_addCallbackBuffer", 938 "([BI)V", 939 (void *)android_hardware_Camera_addCallbackBuffer }, 940 { "native_autoFocus", 941 "()V", 942 (void *)android_hardware_Camera_autoFocus }, 943 { "native_cancelAutoFocus", 944 "()V", 945 (void *)android_hardware_Camera_cancelAutoFocus }, 946 { "native_takePicture", 947 "(I)V", 948 (void *)android_hardware_Camera_takePicture }, 949 { "native_setParameters", 950 "(Ljava/lang/String;)V", 951 (void *)android_hardware_Camera_setParameters }, 952 { "native_getParameters", 953 "()Ljava/lang/String;", 954 (void *)android_hardware_Camera_getParameters }, 955 { "reconnect", 956 "()V", 957 (void*)android_hardware_Camera_reconnect }, 958 { "lock", 959 "()V", 960 (void*)android_hardware_Camera_lock }, 961 { "unlock", 962 "()V", 963 (void*)android_hardware_Camera_unlock }, 964 { "startSmoothZoom", 965 "(I)V", 966 (void *)android_hardware_Camera_startSmoothZoom }, 967 { "stopSmoothZoom", 968 "()V", 969 (void *)android_hardware_Camera_stopSmoothZoom }, 970 { "setDisplayOrientation", 971 "(I)V", 972 (void *)android_hardware_Camera_setDisplayOrientation }, 973 { "_enableShutterSound", 974 "(Z)Z", 975 (void *)android_hardware_Camera_enableShutterSound }, 976 { "_startFaceDetection", 977 "(I)V", 978 (void *)android_hardware_Camera_startFaceDetection }, 979 { "_stopFaceDetection", 980 "()V", 981 (void *)android_hardware_Camera_stopFaceDetection}, 982 { "enableFocusMoveCallback", 983 "(I)V", 984 (void *)android_hardware_Camera_enableFocusMoveCallback}, 985}; 986 987struct field { 988 const char *class_name; 989 const char *field_name; 990 const char *field_type; 991 jfieldID *jfield; 992}; 993 994static void find_fields(JNIEnv *env, field *fields, int count) 995{ 996 for (int i = 0; i < count; i++) { 997 field *f = &fields[i]; 998 jclass clazz = FindClassOrDie(env, f->class_name); 999 jfieldID field = GetFieldIDOrDie(env, clazz, f->field_name, f->field_type); 1000 *(f->jfield) = field; 1001 } 1002} 1003 1004// Get all the required offsets in java class and register native functions 1005int register_android_hardware_Camera(JNIEnv *env) 1006{ 1007 field fields_to_find[] = { 1008 { "android/hardware/Camera", "mNativeContext", "J", &fields.context }, 1009 { "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing }, 1010 { "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation }, 1011 { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z", 1012 &fields.canDisableShutterSound }, 1013 { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, 1014 { "android/hardware/Camera$Face", "score", "I", &fields.face_score }, 1015 { "android/graphics/Rect", "left", "I", &fields.rect_left }, 1016 { "android/graphics/Rect", "top", "I", &fields.rect_top }, 1017 { "android/graphics/Rect", "right", "I", &fields.rect_right }, 1018 { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom }, 1019 }; 1020 1021 find_fields(env, fields_to_find, NELEM(fields_to_find)); 1022 1023 jclass clazz = FindClassOrDie(env, "android/hardware/Camera"); 1024 fields.post_event = GetStaticMethodIDOrDie(env, clazz, "postEventFromNative", 1025 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 1026 1027 clazz = FindClassOrDie(env, "android/graphics/Rect"); 1028 fields.rect_constructor = GetMethodIDOrDie(env, clazz, "<init>", "()V"); 1029 1030 clazz = FindClassOrDie(env, "android/hardware/Camera$Face"); 1031 fields.face_constructor = GetMethodIDOrDie(env, clazz, "<init>", "()V"); 1032 1033 // Register native functions 1034 return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); 1035} 1036