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