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