blob: bc69735d74536ef0efb712bcda97201a6e6873c3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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"
Steven Moreland2279b252017-07-19 09:50:45 -070023#include <nativehelper/JNIHelp.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080024#include "core_jni_helpers.h"
Igor Murashkinc99db2b2012-10-29 13:38:10 -070025#include <android_runtime/android_graphics_SurfaceTexture.h>
Mathias Agopian3866f0d2013-02-11 22:08:48 -080026#include <android_runtime/android_view_Surface.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
Eino-Ville Talvalaf7c6c5a2012-09-19 11:46:11 -070028#include <cutils/properties.h>
Andrew Harp94927df2009-10-20 01:47:05 -040029#include <utils/Vector.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070030#include <utils/Errors.h>
Andrew Harp94927df2009-10-20 01:47:05 -040031
Andy McFaddend47f7d82012-12-18 09:48:38 -080032#include <gui/GLConsumer.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080033#include <gui/Surface.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080034#include <camera/Camera.h>
Mathias Agopian07952722009-05-19 19:08:10 -070035#include <binder/IMemory.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
37using namespace android;
38
Igor Murashkina1d66272014-06-20 11:22:11 -070039enum {
40 // Keep up to date with Camera.java
41 CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2,
42};
43
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044struct fields_t {
45 jfieldID context;
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +080046 jfieldID facing;
47 jfieldID orientation;
Eino-Ville Talvalaf7c6c5a2012-09-19 11:46:11 -070048 jfieldID canDisableShutterSound;
Wu-cheng Lif0d6a482011-07-28 05:30:59 +080049 jfieldID face_rect;
Wu-cheng Li4c2292e2011-07-22 02:37:11 +080050 jfieldID face_score;
Igor Murashkin0601ab12014-09-18 15:17:20 -070051 jfieldID face_id;
52 jfieldID face_left_eye;
53 jfieldID face_right_eye;
54 jfieldID face_mouth;
Wu-cheng Li4c2292e2011-07-22 02:37:11 +080055 jfieldID rect_left;
56 jfieldID rect_top;
57 jfieldID rect_right;
58 jfieldID rect_bottom;
Igor Murashkin0601ab12014-09-18 15:17:20 -070059 jfieldID point_x;
60 jfieldID point_y;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 jmethodID post_event;
Wu-cheng Libb1e2752011-07-30 05:00:37 +080062 jmethodID rect_constructor;
63 jmethodID face_constructor;
Igor Murashkin0601ab12014-09-18 15:17:20 -070064 jmethodID point_constructor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065};
66
67static fields_t fields;
68static Mutex sLock;
69
Dave Sparks5e271152009-06-23 17:30:11 -070070// provides persistent context for calls from native code to Java
71class JNICameraContext: public CameraListener
72{
73public:
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);
Wu-cheng Libb1e2752011-07-30 05:00:37 +080077 virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr,
78 camera_frame_metadata_t *metadata);
Dave Sparks59c1a932009-07-08 15:56:53 -070079 virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
Chien-Yu Chene2592712016-04-28 12:14:32 -070080 virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle);
Yin-Chia Yeh19ddea92017-03-21 18:48:44 -070081 virtual void postRecordingFrameHandleTimestampBatch(
82 const std::vector<nsecs_t>& timestamps,
83 const std::vector<native_handle_t*>& handles);
Wu-cheng Libb1e2752011-07-30 05:00:37 +080084 void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata);
James Donge00cab72011-02-17 16:38:06 -080085 void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType);
Andrew Harp94927df2009-10-20 01:47:05 -040086 void setCallbackMode(JNIEnv *env, bool installed, bool manualMode);
Dave Sparks5e271152009-06-23 17:30:11 -070087 sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
James Donge00cab72011-02-17 16:38:06 -080088 bool isRawImageCallbackBufferAvailable() const;
Dave Sparks5e271152009-06-23 17:30:11 -070089 void release();
90
91private:
92 void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType);
James Donge00cab72011-02-17 16:38:06 -080093 void clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers);
Andrew Harp94927df2009-10-20 01:47:05 -040094 void clearCallbackBuffers_l(JNIEnv *env);
James Donge00cab72011-02-17 16:38:06 -080095 jbyteArray getCallbackBuffer(JNIEnv *env, Vector<jbyteArray> *buffers, size_t bufferSize);
Dave Sparks5e271152009-06-23 17:30:11 -070096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 jobject mCameraJObjectWeak; // weak reference to java object
98 jclass mCameraJClass; // strong reference to java class
Wu-cheng Liffe1cf22009-09-10 16:49:17 +080099 sp<Camera> mCamera; // strong reference to native object
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800100 jclass mFaceClass; // strong reference to Face class
101 jclass mRectClass; // strong reference to Rect class
Igor Murashkin0601ab12014-09-18 15:17:20 -0700102 jclass mPointClass; // strong reference to Point class
Dave Sparks5e271152009-06-23 17:30:11 -0700103 Mutex mLock;
Andrew Harp94927df2009-10-20 01:47:05 -0400104
James Donge00cab72011-02-17 16:38:06 -0800105 /*
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 */
Andrew Harp94927df2009-10-20 01:47:05 -0400119 Vector<jbyteArray> mCallbackBuffers; // Global reference application managed byte[]
120 bool mManualBufferMode; // Whether to use application managed buffers.
James Donge00cab72011-02-17 16:38:06 -0800121 bool mManualCameraCallbackSet; // Whether the callback has been set, used to
122 // reduce unnecessary calls to set the callback.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123};
124
James Donge00cab72011-02-17 16:38:06 -0800125bool JNICameraContext::isRawImageCallbackBufferAvailable() const
126{
127 return !mRawImageCallbackBuffers.isEmpty();
128}
129
Dave Sparks5e271152009-06-23 17:30:11 -0700130sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131{
132 sp<Camera> camera;
133 Mutex::Autolock _l(sLock);
Ashok Bhat4838e332014-01-03 14:37:19 +0000134 JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 if (context != NULL) {
Dave Sparks5e271152009-06-23 17:30:11 -0700136 camera = context->getCamera();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 }
Steve Block71f2cf12011-10-20 11:56:00 +0100138 ALOGV("get_native_camera: context=%p, camera=%p", context, camera.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 if (camera == 0) {
Eino-Ville Talvalaf9133342015-01-12 17:01:11 -0800140 jniThrowRuntimeException(env,
141 "Camera is being used after Camera.release() was called");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 }
143
144 if (pContext != NULL) *pContext = context;
145 return camera;
146}
147
Dave Sparks5e271152009-06-23 17:30:11 -0700148JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149{
Dave Sparks5e271152009-06-23 17:30:11 -0700150 mCameraJObjectWeak = env->NewGlobalRef(weak_this);
151 mCameraJClass = (jclass)env->NewGlobalRef(clazz);
152 mCamera = camera;
Andrew Harp94927df2009-10-20 01:47:05 -0400153
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800154 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
Igor Murashkin0601ab12014-09-18 15:17:20 -0700160 jclass pointClazz = env->FindClass("android/graphics/Point");
161 mPointClass = (jclass) env->NewGlobalRef(pointClazz);
162
Andrew Harp94927df2009-10-20 01:47:05 -0400163 mManualBufferMode = false;
164 mManualCameraCallbackSet = false;
Dave Sparks5e271152009-06-23 17:30:11 -0700165}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166
Dave Sparks5e271152009-06-23 17:30:11 -0700167void JNICameraContext::release()
168{
Steve Block71f2cf12011-10-20 11:56:00 +0100169 ALOGV("release");
Dave Sparks5e271152009-06-23 17:30:11 -0700170 Mutex::Autolock _l(mLock);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 JNIEnv *env = AndroidRuntime::getJNIEnv();
Dave Sparks5e271152009-06-23 17:30:11 -0700172
173 if (mCameraJObjectWeak != NULL) {
174 env->DeleteGlobalRef(mCameraJObjectWeak);
175 mCameraJObjectWeak = NULL;
176 }
177 if (mCameraJClass != NULL) {
178 env->DeleteGlobalRef(mCameraJClass);
179 mCameraJClass = NULL;
180 }
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800181 if (mFaceClass != NULL) {
182 env->DeleteGlobalRef(mFaceClass);
183 mFaceClass = NULL;
184 }
185 if (mRectClass != NULL) {
186 env->DeleteGlobalRef(mRectClass);
187 mRectClass = NULL;
188 }
Igor Murashkin0601ab12014-09-18 15:17:20 -0700189 if (mPointClass != NULL) {
190 env->DeleteGlobalRef(mPointClass);
191 mPointClass = NULL;
192 }
Andrew Harp94927df2009-10-20 01:47:05 -0400193 clearCallbackBuffers_l(env);
Dave Sparks5e271152009-06-23 17:30:11 -0700194 mCamera.clear();
195}
196
197void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
198{
Steve Block71f2cf12011-10-20 11:56:00 +0100199 ALOGV("notify");
Dave Sparks5e271152009-06-23 17:30:11 -0700200
201 // VM pointer will be NULL if object is released
202 Mutex::Autolock _l(mLock);
203 if (mCameraJObjectWeak == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000204 ALOGW("callback on dead camera object");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 return;
206 }
Dave Sparks5e271152009-06-23 17:30:11 -0700207 JNIEnv *env = AndroidRuntime::getJNIEnv();
James Donge00cab72011-02-17 16:38:06 -0800208
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
Dave Sparksc62f9bd2009-06-26 13:33:32 -0700218 env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
Chih-Chung Chang6157de02009-09-24 15:29:35 -0700219 mCameraJObjectWeak, msgType, ext1, ext2, NULL);
Dave Sparks5e271152009-06-23 17:30:11 -0700220}
221
James Donge00cab72011-02-17 16:38:06 -0800222jbyteArray 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()) {
Dan Albert46d84442014-11-18 16:07:51 -0800229 ALOGV("Using callback buffer from queue of length %zu", buffers->size());
James Donge00cab72011-02-17 16:38:06 -0800230 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) {
Dan Albert46d84442014-11-18 16:07:51 -0800239 ALOGE("Callback buffer was too small! Expected %zu bytes, but got %d bytes!",
James Donge00cab72011-02-17 16:38:06 -0800240 bufferSize, bufferLength);
241 env->DeleteLocalRef(obj);
242 return NULL;
243 }
244 }
245 }
246
247 return obj;
248}
249
Dave Sparks5e271152009-06-23 17:30:11 -0700250void 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);
Yin-Chia Yeh3ef060e2019-04-18 15:55:05 -0700259 if (heap == NULL) {
260 ALOGV("copyAndPost: skipping null memory callback!");
261 return;
262 }
Glenn Kasten2fbf25b2014-03-28 15:41:58 -0700263 ALOGV("copyAndPost: off=%zd, size=%zu", offset, size);
Dave Sparks5e271152009-06-23 17:30:11 -0700264 uint8_t *heapBase = (uint8_t*)heap->base();
265
266 if (heapBase != NULL) {
Dave Sparksc4ca4202009-07-13 09:38:20 -0700267 const jbyte* data = reinterpret_cast<const jbyte*>(heapBase + offset);
Andrew Harp94927df2009-10-20 01:47:05 -0400268
Wu-cheng Li5f0ef5f2011-09-21 16:40:23 +0800269 if (msgType == CAMERA_MSG_RAW_IMAGE) {
270 obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size);
271 } else if (msgType == CAMERA_MSG_PREVIEW_FRAME && mManualBufferMode) {
272 obj = getCallbackBuffer(env, &mCallbackBuffers, size);
Andrew Harp94927df2009-10-20 01:47:05 -0400273
Wu-cheng Li5f0ef5f2011-09-21 16:40:23 +0800274 if (mCallbackBuffers.isEmpty()) {
Steve Block71f2cf12011-10-20 11:56:00 +0100275 ALOGV("Out of buffers, clearing callback!");
Wu-cheng Li5f0ef5f2011-09-21 16:40:23 +0800276 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
277 mManualCameraCallbackSet = false;
Andrew Harp94927df2009-10-20 01:47:05 -0400278
Wu-cheng Li5f0ef5f2011-09-21 16:40:23 +0800279 if (obj == NULL) {
Andrew Harp94927df2009-10-20 01:47:05 -0400280 return;
281 }
282 }
Wu-cheng Li5f0ef5f2011-09-21 16:40:23 +0800283 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100284 ALOGV("Allocating callback buffer");
Wu-cheng Li5f0ef5f2011-09-21 16:40:23 +0800285 obj = env->NewByteArray(size);
Andrew Harp94927df2009-10-20 01:47:05 -0400286 }
287
Dave Sparks5e271152009-06-23 17:30:11 -0700288 if (obj == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000289 ALOGE("Couldn't allocate byte array for JPEG data");
Dave Sparks5e271152009-06-23 17:30:11 -0700290 env->ExceptionClear();
291 } else {
Dave Sparksa95f4952009-07-10 18:13:36 -0700292 env->SetByteArrayRegion(obj, 0, size, data);
Dave Sparks5e271152009-06-23 17:30:11 -0700293 }
294 } else {
Steve Block3762c312012-01-06 19:20:56 +0000295 ALOGE("image heap is NULL");
Dave Sparks5e271152009-06-23 17:30:11 -0700296 }
297 }
298
299 // post image data to Java
300 env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
301 mCameraJObjectWeak, msgType, 0, 0, obj);
302 if (obj) {
303 env->DeleteLocalRef(obj);
304 }
305}
306
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800307void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr,
308 camera_frame_metadata_t *metadata)
Dave Sparks5e271152009-06-23 17:30:11 -0700309{
310 // VM pointer will be NULL if object is released
311 Mutex::Autolock _l(mLock);
312 JNIEnv *env = AndroidRuntime::getJNIEnv();
Dave Sparksd0cbb1a2009-06-29 19:03:33 -0700313 if (mCameraJObjectWeak == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000314 ALOGW("callback on dead camera object");
Dave Sparksd0cbb1a2009-06-29 19:03:33 -0700315 return;
316 }
Dave Sparks5e271152009-06-23 17:30:11 -0700317
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800318 int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA;
319
Dave Sparks5e271152009-06-23 17:30:11 -0700320 // return data based on callback type
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800321 switch (dataMsgType) {
James Donge00cab72011-02-17 16:38:06 -0800322 case CAMERA_MSG_VIDEO_FRAME:
323 // should never happen
324 break;
325
326 // For backward-compatibility purpose, if there is no callback
327 // buffer for raw image, the callback returns null.
328 case CAMERA_MSG_RAW_IMAGE:
Steve Block71f2cf12011-10-20 11:56:00 +0100329 ALOGV("rawCallback");
James Donge00cab72011-02-17 16:38:06 -0800330 if (mRawImageCallbackBuffers.isEmpty()) {
331 env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800332 mCameraJObjectWeak, dataMsgType, 0, 0, NULL);
James Donge00cab72011-02-17 16:38:06 -0800333 } else {
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800334 copyAndPost(env, dataPtr, dataMsgType);
James Donge00cab72011-02-17 16:38:06 -0800335 }
336 break;
337
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800338 // There is no data.
339 case 0:
James Donge00cab72011-02-17 16:38:06 -0800340 break;
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800341
342 default:
Steve Block71f2cf12011-10-20 11:56:00 +0100343 ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get());
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800344 copyAndPost(env, dataPtr, dataMsgType);
345 break;
346 }
347
348 // post frame metadata to Java
349 if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) {
350 postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata);
Dave Sparks5e271152009-06-23 17:30:11 -0700351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352}
353
Dave Sparks59c1a932009-07-08 15:56:53 -0700354void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
355{
356 // TODO: plumb up to Java. For now, just drop the timestamp
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800357 postData(msgType, dataPtr, NULL);
358}
359
Akhila musunuri44a59492016-07-21 13:33:11 +0530360void JNICameraContext::postRecordingFrameHandleTimestamp(nsecs_t, native_handle_t* handle) {
361 // Video buffers are not needed at app layer so just return the video buffers here.
362 // This may be called when stagefright just releases camera but there are still outstanding
363 // video buffers.
364 if (mCamera != nullptr) {
365 mCamera->releaseRecordingFrameHandle(handle);
366 } else {
367 native_handle_close(handle);
368 native_handle_delete(handle);
369 }
Chien-Yu Chene2592712016-04-28 12:14:32 -0700370}
371
Yin-Chia Yeh19ddea92017-03-21 18:48:44 -0700372void JNICameraContext::postRecordingFrameHandleTimestampBatch(
373 const std::vector<nsecs_t>&,
374 const std::vector<native_handle_t*>& handles) {
375 // Video buffers are not needed at app layer so just return the video buffers here.
376 // This may be called when stagefright just releases camera but there are still outstanding
377 // video buffers.
378 if (mCamera != nullptr) {
379 mCamera->releaseRecordingFrameHandleBatch(handles);
380 } else {
381 for (auto& handle : handles) {
382 native_handle_close(handle);
383 native_handle_delete(handle);
384 }
385 }
386}
387
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800388void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata)
389{
390 jobjectArray obj = NULL;
391 obj = (jobjectArray) env->NewObjectArray(metadata->number_of_faces,
392 mFaceClass, NULL);
393 if (obj == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000394 ALOGE("Couldn't allocate face metadata array");
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800395 return;
396 }
397
398 for (int i = 0; i < metadata->number_of_faces; i++) {
399 jobject face = env->NewObject(mFaceClass, fields.face_constructor);
400 env->SetObjectArrayElement(obj, i, face);
401
402 jobject rect = env->NewObject(mRectClass, fields.rect_constructor);
403 env->SetIntField(rect, fields.rect_left, metadata->faces[i].rect[0]);
404 env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]);
405 env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]);
406 env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]);
407
408 env->SetObjectField(face, fields.face_rect, rect);
409 env->SetIntField(face, fields.face_score, metadata->faces[i].score);
410
Igor Murashkin0601ab12014-09-18 15:17:20 -0700411 bool optionalFields = metadata->faces[i].id != 0
412 && metadata->faces[i].left_eye[0] != -2000 && metadata->faces[i].left_eye[1] != -2000
413 && metadata->faces[i].right_eye[0] != -2000 && metadata->faces[i].right_eye[1] != -2000
414 && metadata->faces[i].mouth[0] != -2000 && metadata->faces[i].mouth[1] != -2000;
415 if (optionalFields) {
416 int32_t id = metadata->faces[i].id;
417 env->SetIntField(face, fields.face_id, id);
418
419 jobject leftEye = env->NewObject(mPointClass, fields.point_constructor);
420 env->SetIntField(leftEye, fields.point_x, metadata->faces[i].left_eye[0]);
421 env->SetIntField(leftEye, fields.point_y, metadata->faces[i].left_eye[1]);
422 env->SetObjectField(face, fields.face_left_eye, leftEye);
423 env->DeleteLocalRef(leftEye);
424
425 jobject rightEye = env->NewObject(mPointClass, fields.point_constructor);
426 env->SetIntField(rightEye, fields.point_x, metadata->faces[i].right_eye[0]);
427 env->SetIntField(rightEye, fields.point_y, metadata->faces[i].right_eye[1]);
428 env->SetObjectField(face, fields.face_right_eye, rightEye);
429 env->DeleteLocalRef(rightEye);
430
431 jobject mouth = env->NewObject(mPointClass, fields.point_constructor);
432 env->SetIntField(mouth, fields.point_x, metadata->faces[i].mouth[0]);
433 env->SetIntField(mouth, fields.point_y, metadata->faces[i].mouth[1]);
434 env->SetObjectField(face, fields.face_mouth, mouth);
435 env->DeleteLocalRef(mouth);
436 }
437
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800438 env->DeleteLocalRef(face);
439 env->DeleteLocalRef(rect);
440 }
441 env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
442 mCameraJObjectWeak, msgType, 0, 0, obj);
443 env->DeleteLocalRef(obj);
Dave Sparks59c1a932009-07-08 15:56:53 -0700444}
445
Andrew Harp94927df2009-10-20 01:47:05 -0400446void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualMode)
447{
448 Mutex::Autolock _l(mLock);
449 mManualBufferMode = manualMode;
450 mManualCameraCallbackSet = false;
451
452 // In order to limit the over usage of binder threads, all non-manual buffer
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700453 // callbacks use CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER mode now.
Andrew Harp94927df2009-10-20 01:47:05 -0400454 //
455 // Continuous callbacks will have the callback re-registered from handleMessage.
456 // Manual buffer mode will operate as fast as possible, relying on the finite supply
457 // of buffers for throttling.
458
459 if (!installed) {
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700460 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
James Donge00cab72011-02-17 16:38:06 -0800461 clearCallbackBuffers_l(env, &mCallbackBuffers);
Andrew Harp94927df2009-10-20 01:47:05 -0400462 } else if (mManualBufferMode) {
463 if (!mCallbackBuffers.isEmpty()) {
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700464 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_CAMERA);
Andrew Harp94927df2009-10-20 01:47:05 -0400465 mManualCameraCallbackSet = true;
466 }
467 } else {
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700468 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER);
James Donge00cab72011-02-17 16:38:06 -0800469 clearCallbackBuffers_l(env, &mCallbackBuffers);
Andrew Harp94927df2009-10-20 01:47:05 -0400470 }
471}
472
James Donge00cab72011-02-17 16:38:06 -0800473void JNICameraContext::addCallbackBuffer(
474 JNIEnv *env, jbyteArray cbb, int msgType)
Andrew Harp94927df2009-10-20 01:47:05 -0400475{
Steve Block71f2cf12011-10-20 11:56:00 +0100476 ALOGV("addCallbackBuffer: 0x%x", msgType);
Andrew Harp94927df2009-10-20 01:47:05 -0400477 if (cbb != NULL) {
478 Mutex::Autolock _l(mLock);
James Donge00cab72011-02-17 16:38:06 -0800479 switch (msgType) {
480 case CAMERA_MSG_PREVIEW_FRAME: {
481 jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
482 mCallbackBuffers.push(callbackBuffer);
Andrew Harp94927df2009-10-20 01:47:05 -0400483
Dan Albert46d84442014-11-18 16:07:51 -0800484 ALOGV("Adding callback buffer to queue, %zu total",
James Donge00cab72011-02-17 16:38:06 -0800485 mCallbackBuffers.size());
Andrew Harp94927df2009-10-20 01:47:05 -0400486
James Donge00cab72011-02-17 16:38:06 -0800487 // We want to make sure the camera knows we're ready for the
488 // next frame. This may have come unset had we not had a
489 // callbackbuffer ready for it last time.
490 if (mManualBufferMode && !mManualCameraCallbackSet) {
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700491 mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_CAMERA);
James Donge00cab72011-02-17 16:38:06 -0800492 mManualCameraCallbackSet = true;
493 }
494 break;
495 }
496 case CAMERA_MSG_RAW_IMAGE: {
497 jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
498 mRawImageCallbackBuffers.push(callbackBuffer);
499 break;
500 }
501 default: {
502 jniThrowException(env,
503 "java/lang/IllegalArgumentException",
504 "Unsupported message type");
505 return;
506 }
Andrew Harp94927df2009-10-20 01:47:05 -0400507 }
508 } else {
Steve Block3762c312012-01-06 19:20:56 +0000509 ALOGE("Null byte array!");
Andrew Harp94927df2009-10-20 01:47:05 -0400510 }
511}
512
513void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env)
514{
James Donge00cab72011-02-17 16:38:06 -0800515 clearCallbackBuffers_l(env, &mCallbackBuffers);
516 clearCallbackBuffers_l(env, &mRawImageCallbackBuffers);
517}
518
519void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers) {
Dan Albert46d84442014-11-18 16:07:51 -0800520 ALOGV("Clearing callback buffers, %zu remained", buffers->size());
James Donge00cab72011-02-17 16:38:06 -0800521 while (!buffers->isEmpty()) {
522 env->DeleteGlobalRef(buffers->top());
523 buffers->pop();
Andrew Harp94927df2009-10-20 01:47:05 -0400524 }
525}
526
Chih-Chung Change25cc652010-05-06 16:36:58 +0800527static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528{
Chih-Chung Change25cc652010-05-06 16:36:58 +0800529 return Camera::getNumberOfCameras();
530}
531
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800532static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
533 jint cameraId, jobject info_obj)
534{
535 CameraInfo cameraInfo;
Eino-Ville Talvala57176122015-08-14 13:11:16 -0700536 if (cameraId >= Camera::getNumberOfCameras() || cameraId < 0) {
537 ALOGE("%s: Unknown camera ID %d", __FUNCTION__, cameraId);
538 jniThrowRuntimeException(env, "Unknown camera ID");
539 return;
540 }
541
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800542 status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
543 if (rc != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700544 jniThrowRuntimeException(env, "Fail to get camera info");
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800545 return;
546 }
547 env->SetIntField(info_obj, fields.facing, cameraInfo.facing);
548 env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation);
Eino-Ville Talvalaf7c6c5a2012-09-19 11:46:11 -0700549
550 char value[PROPERTY_VALUE_MAX];
551 property_get("ro.camera.sound.forced", value, "0");
552 jboolean canDisableShutterSound = (strncmp(value, "0", 2) == 0);
553 env->SetBooleanField(info_obj, fields.canDisableShutterSound,
554 canDisableShutterSound);
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800555}
556
Chih-Chung Change25cc652010-05-06 16:36:58 +0800557// connect to camera service
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700558static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
Zhijun He4c913802014-06-16 16:42:35 -0700559 jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
Chih-Chung Change25cc652010-05-06 16:36:58 +0800560{
Eino-Ville Talvala788717c2013-02-15 18:30:15 -0800561 // Convert jstring to String16
Dan Albert66987492014-11-20 11:41:21 -0800562 const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
563 env->GetStringChars(clientPackageName, NULL));
Eino-Ville Talvala788717c2013-02-15 18:30:15 -0800564 jsize rawClientNameLen = env->GetStringLength(clientPackageName);
565 String16 clientName(rawClientName, rawClientNameLen);
Dan Albert66987492014-11-20 11:41:21 -0800566 env->ReleaseStringChars(clientPackageName,
567 reinterpret_cast<const jchar*>(rawClientName));
Eino-Ville Talvala788717c2013-02-15 18:30:15 -0800568
Zhijun He4c913802014-06-16 16:42:35 -0700569 sp<Camera> camera;
Igor Murashkina1d66272014-06-20 11:22:11 -0700570 if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
571 // Default path: hal version is don't care, do normal camera connect.
Zhijun He4c913802014-06-16 16:42:35 -0700572 camera = Camera::connect(cameraId, clientName,
Chien-Yu Chen225257a2015-12-18 14:20:46 -0800573 Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
Zhijun He4c913802014-06-16 16:42:35 -0700574 } else {
575 jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
576 Camera::USE_CALLING_UID, camera);
577 if (status != NO_ERROR) {
578 return status;
579 }
580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581
582 if (camera == NULL) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700583 return -EACCES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 }
585
586 // make sure camera hardware is alive
587 if (camera->getStatus() != NO_ERROR) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700588 return NO_INIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 }
590
591 jclass clazz = env->GetObjectClass(thiz);
592 if (clazz == NULL) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700593 // This should never happen
Elliott Hughes69a017b2011-04-08 14:10:28 -0700594 jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700595 return INVALID_OPERATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 }
597
598 // We use a weak reference so the Camera object can be garbage collected.
599 // The reference is only used as a proxy for callbacks.
Dave Sparks5e271152009-06-23 17:30:11 -0700600 sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800601 context->incStrong((void*)android_hardware_Camera_native_setup);
Dave Sparks5e271152009-06-23 17:30:11 -0700602 camera->setListener(context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603
604 // save context in opaque field
Ashok Bhat4838e332014-01-03 14:37:19 +0000605 env->SetLongField(thiz, fields.context, (jlong)context.get());
Eino-Ville Talvala6c91e2c2016-03-25 11:54:39 -0700606
607 // Update default display orientation in case the sensor is reverse-landscape
608 CameraInfo cameraInfo;
609 status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
610 if (rc != NO_ERROR) {
Yin-Chia Yeh564ae822018-02-08 16:24:27 -0800611 ALOGE("%s: getCameraInfo error: %d", __FUNCTION__, rc);
Eino-Ville Talvala6c91e2c2016-03-25 11:54:39 -0700612 return rc;
613 }
614 int defaultOrientation = 0;
615 switch (cameraInfo.orientation) {
616 case 0:
617 break;
618 case 90:
619 if (cameraInfo.facing == CAMERA_FACING_FRONT) {
620 defaultOrientation = 180;
621 }
622 break;
623 case 180:
624 defaultOrientation = 180;
625 break;
626 case 270:
627 if (cameraInfo.facing != CAMERA_FACING_FRONT) {
628 defaultOrientation = 180;
629 }
630 break;
631 default:
632 ALOGE("Unexpected camera orientation %d!", cameraInfo.orientation);
633 break;
634 }
635 if (defaultOrientation != 0) {
636 ALOGV("Setting default display orientation to %d", defaultOrientation);
637 rc = camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION,
638 defaultOrientation, 0);
639 if (rc != NO_ERROR) {
640 ALOGE("Unable to update default orientation: %s (%d)",
641 strerror(-rc), rc);
642 return rc;
643 }
644 }
645
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700646 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647}
648
649// disconnect from camera service
650// It's okay to call this when the native camera context is already null.
651// This handles the case where the user has called release() and the
652// finalizer is invoked later.
653static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
654{
Steve Block71f2cf12011-10-20 11:56:00 +0100655 ALOGV("release camera");
Dave Sparks5e271152009-06-23 17:30:11 -0700656 JNICameraContext* context = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 sp<Camera> camera;
658 {
659 Mutex::Autolock _l(sLock);
Ashok Bhat4838e332014-01-03 14:37:19 +0000660 context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661
662 // Make sure we do not attempt to callback on a deleted Java object.
Ashok Bhat4838e332014-01-03 14:37:19 +0000663 env->SetLongField(thiz, fields.context, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 }
665
666 // clean up if release has not been called before
667 if (context != NULL) {
Dave Sparks5e271152009-06-23 17:30:11 -0700668 camera = context->getCamera();
669 context->release();
Steve Block71f2cf12011-10-20 11:56:00 +0100670 ALOGV("native_release: context=%p camera=%p", context, camera.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 // clear callbacks
673 if (camera != NULL) {
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700674 camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 camera->disconnect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 }
677
678 // remove context to prevent further Java access
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800679 context->decStrong((void*)android_hardware_Camera_native_setup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 }
681}
682
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700683static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684{
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700685 ALOGV("setPreviewSurface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 sp<Camera> camera = get_native_camera(env, thiz, NULL);
687 if (camera == 0) return;
688
Mathias Agopian4a05f432013-03-12 18:43:34 -0700689 sp<IGraphicBufferProducer> gbp;
Jesse Hallaa70f222013-02-21 15:06:27 -0800690 sp<Surface> surface;
691 if (jSurface) {
692 surface = android_view_Surface_getSurface(env, jSurface);
Mathias Agopian4a05f432013-03-12 18:43:34 -0700693 if (surface != NULL) {
694 gbp = surface->getIGraphicBufferProducer();
695 }
Jesse Hallaa70f222013-02-21 15:06:27 -0800696 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800697
Eino-Ville Talvala7b297792013-08-21 14:39:22 -0700698 if (camera->setPreviewTarget(gbp) != NO_ERROR) {
Mathias Agopian4a05f432013-03-12 18:43:34 -0700699 jniThrowException(env, "java/io/IOException", "setPreviewTexture failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 }
701}
702
Jamie Gennisfd6f39e2010-12-20 12:15:00 -0800703static void android_hardware_Camera_setPreviewTexture(JNIEnv *env,
704 jobject thiz, jobject jSurfaceTexture)
705{
Steve Block71f2cf12011-10-20 11:56:00 +0100706 ALOGV("setPreviewTexture");
Jamie Gennisfd6f39e2010-12-20 12:15:00 -0800707 sp<Camera> camera = get_native_camera(env, thiz, NULL);
708 if (camera == 0) return;
709
Mathias Agopian52a9a102013-08-02 01:38:38 -0700710 sp<IGraphicBufferProducer> producer = NULL;
Jamie Gennisfd6f39e2010-12-20 12:15:00 -0800711 if (jSurfaceTexture != NULL) {
Mathias Agopian52a9a102013-08-02 01:38:38 -0700712 producer = SurfaceTexture_getProducer(env, jSurfaceTexture);
713 if (producer == NULL) {
Daniel Lam2e76c992012-02-23 14:35:13 -0800714 jniThrowException(env, "java/lang/IllegalArgumentException",
715 "SurfaceTexture already released in setPreviewTexture");
716 return;
717 }
718
Jamie Gennisfd6f39e2010-12-20 12:15:00 -0800719 }
Daniel Lam2e76c992012-02-23 14:35:13 -0800720
Eino-Ville Talvala7b297792013-08-21 14:39:22 -0700721 if (camera->setPreviewTarget(producer) != NO_ERROR) {
Jamie Gennisfd6f39e2010-12-20 12:15:00 -0800722 jniThrowException(env, "java/io/IOException",
723 "setPreviewTexture failed");
724 }
725}
726
Eino-Ville Talvala7005b672013-04-02 15:46:38 -0700727static void android_hardware_Camera_setPreviewCallbackSurface(JNIEnv *env,
728 jobject thiz, jobject jSurface)
729{
730 ALOGV("setPreviewCallbackSurface");
731 JNICameraContext* context;
732 sp<Camera> camera = get_native_camera(env, thiz, &context);
733 if (camera == 0) return;
734
735 sp<IGraphicBufferProducer> gbp;
736 sp<Surface> surface;
737 if (jSurface) {
738 surface = android_view_Surface_getSurface(env, jSurface);
739 if (surface != NULL) {
740 gbp = surface->getIGraphicBufferProducer();
741 }
742 }
743 // Clear out normal preview callbacks
744 context->setCallbackMode(env, false, false);
745 // Then set up callback surface
746 if (camera->setPreviewCallbackTarget(gbp) != NO_ERROR) {
747 jniThrowException(env, "java/io/IOException", "setPreviewCallbackTarget failed");
748 }
749}
750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
752{
Steve Block71f2cf12011-10-20 11:56:00 +0100753 ALOGV("startPreview");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 sp<Camera> camera = get_native_camera(env, thiz, NULL);
755 if (camera == 0) return;
756
757 if (camera->startPreview() != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700758 jniThrowRuntimeException(env, "startPreview failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 return;
760 }
761}
762
763static void android_hardware_Camera_stopPreview(JNIEnv *env, jobject thiz)
764{
Steve Block71f2cf12011-10-20 11:56:00 +0100765 ALOGV("stopPreview");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 sp<Camera> c = get_native_camera(env, thiz, NULL);
767 if (c == 0) return;
768
769 c->stopPreview();
770}
771
Ashok Bhat4838e332014-01-03 14:37:19 +0000772static jboolean android_hardware_Camera_previewEnabled(JNIEnv *env, jobject thiz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773{
Steve Block71f2cf12011-10-20 11:56:00 +0100774 ALOGV("previewEnabled");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 sp<Camera> c = get_native_camera(env, thiz, NULL);
Ashok Bhat4838e332014-01-03 14:37:19 +0000776 if (c == 0) return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777
Ashok Bhat4838e332014-01-03 14:37:19 +0000778 return c->previewEnabled() ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779}
780
Andrew Harp94927df2009-10-20 01:47:05 -0400781static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean manualBuffer)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782{
Steve Block71f2cf12011-10-20 11:56:00 +0100783 ALOGV("setHasPreviewCallback: installed:%d, manualBuffer:%d", (int)installed, (int)manualBuffer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 // Important: Only install preview_callback if the Java code has called
785 // setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy
786 // each preview frame for nothing.
Dave Sparks5e271152009-06-23 17:30:11 -0700787 JNICameraContext* context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 sp<Camera> camera = get_native_camera(env, thiz, &context);
789 if (camera == 0) return;
790
Andrew Harp94927df2009-10-20 01:47:05 -0400791 // setCallbackMode will take care of setting the context flags and calling
792 // camera->setPreviewCallbackFlags within a mutex for us.
793 context->setCallbackMode(env, installed, manualBuffer);
794}
795
Ashok Bhat4838e332014-01-03 14:37:19 +0000796static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) {
Steve Block71f2cf12011-10-20 11:56:00 +0100797 ALOGV("addCallbackBuffer: 0x%x", msgType);
Andrew Harp94927df2009-10-20 01:47:05 -0400798
Ashok Bhat4838e332014-01-03 14:37:19 +0000799 JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context));
Andrew Harp94927df2009-10-20 01:47:05 -0400800
801 if (context != NULL) {
James Donge00cab72011-02-17 16:38:06 -0800802 context->addCallbackBuffer(env, bytes, msgType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804}
805
806static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz)
807{
Steve Block71f2cf12011-10-20 11:56:00 +0100808 ALOGV("autoFocus");
Dave Sparks5e271152009-06-23 17:30:11 -0700809 JNICameraContext* context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 sp<Camera> c = get_native_camera(env, thiz, &context);
811 if (c == 0) return;
812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 if (c->autoFocus() != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700814 jniThrowRuntimeException(env, "autoFocus failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 }
816}
817
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800818static void android_hardware_Camera_cancelAutoFocus(JNIEnv *env, jobject thiz)
819{
Steve Block71f2cf12011-10-20 11:56:00 +0100820 ALOGV("cancelAutoFocus");
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800821 JNICameraContext* context;
822 sp<Camera> c = get_native_camera(env, thiz, &context);
823 if (c == 0) return;
824
825 if (c->cancelAutoFocus() != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700826 jniThrowRuntimeException(env, "cancelAutoFocus failed");
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800827 }
828}
829
Ashok Bhat4838e332014-01-03 14:37:19 +0000830static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831{
Steve Block71f2cf12011-10-20 11:56:00 +0100832 ALOGV("takePicture");
Dave Sparks5e271152009-06-23 17:30:11 -0700833 JNICameraContext* context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 sp<Camera> camera = get_native_camera(env, thiz, &context);
835 if (camera == 0) return;
836
James Donge00cab72011-02-17 16:38:06 -0800837 /*
838 * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback
839 * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the
840 * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY
841 * is enabled to receive the callback notification but no data.
842 *
843 * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the
844 * Java application.
845 */
846 if (msgType & CAMERA_MSG_RAW_IMAGE) {
Steve Block71f2cf12011-10-20 11:56:00 +0100847 ALOGV("Enable raw image callback buffer");
James Donge00cab72011-02-17 16:38:06 -0800848 if (!context->isRawImageCallbackBufferAvailable()) {
Steve Block71f2cf12011-10-20 11:56:00 +0100849 ALOGV("Enable raw image notification, since no callback buffer exists");
James Donge00cab72011-02-17 16:38:06 -0800850 msgType &= ~CAMERA_MSG_RAW_IMAGE;
851 msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY;
852 }
853 }
854
855 if (camera->takePicture(msgType) != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700856 jniThrowRuntimeException(env, "takePicture failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 return;
858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859}
860
861static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params)
862{
Steve Block71f2cf12011-10-20 11:56:00 +0100863 ALOGV("setParameters");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 sp<Camera> camera = get_native_camera(env, thiz, NULL);
865 if (camera == 0) return;
866
867 const jchar* str = env->GetStringCritical(params, 0);
868 String8 params8;
869 if (params) {
Dan Albert66987492014-11-20 11:41:21 -0800870 params8 = String8(reinterpret_cast<const char16_t*>(str),
871 env->GetStringLength(params));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 env->ReleaseStringCritical(params, str);
873 }
874 if (camera->setParameters(params8) != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700875 jniThrowRuntimeException(env, "setParameters failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 return;
877 }
878}
879
880static jstring android_hardware_Camera_getParameters(JNIEnv *env, jobject thiz)
881{
Steve Block71f2cf12011-10-20 11:56:00 +0100882 ALOGV("getParameters");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 sp<Camera> camera = get_native_camera(env, thiz, NULL);
884 if (camera == 0) return 0;
885
Wu-cheng Lia1c41e12012-02-23 19:01:00 -0800886 String8 params8 = camera->getParameters();
887 if (params8.isEmpty()) {
888 jniThrowRuntimeException(env, "getParameters failed (empty parameters)");
889 return 0;
890 }
891 return env->NewStringUTF(params8.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892}
893
894static void android_hardware_Camera_reconnect(JNIEnv *env, jobject thiz)
895{
Steve Block71f2cf12011-10-20 11:56:00 +0100896 ALOGV("reconnect");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 sp<Camera> camera = get_native_camera(env, thiz, NULL);
898 if (camera == 0) return;
899
900 if (camera->reconnect() != NO_ERROR) {
901 jniThrowException(env, "java/io/IOException", "reconnect failed");
902 return;
903 }
904}
905
Wu-cheng Liffe1cf22009-09-10 16:49:17 +0800906static void android_hardware_Camera_lock(JNIEnv *env, jobject thiz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907{
Steve Block71f2cf12011-10-20 11:56:00 +0100908 ALOGV("lock");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 sp<Camera> camera = get_native_camera(env, thiz, NULL);
Wu-cheng Liffe1cf22009-09-10 16:49:17 +0800910 if (camera == 0) return;
911
912 if (camera->lock() != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700913 jniThrowRuntimeException(env, "lock failed");
Wu-cheng Liffe1cf22009-09-10 16:49:17 +0800914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915}
916
Wu-cheng Liffe1cf22009-09-10 16:49:17 +0800917static void android_hardware_Camera_unlock(JNIEnv *env, jobject thiz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918{
Steve Block71f2cf12011-10-20 11:56:00 +0100919 ALOGV("unlock");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 sp<Camera> camera = get_native_camera(env, thiz, NULL);
Wu-cheng Liffe1cf22009-09-10 16:49:17 +0800921 if (camera == 0) return;
922
923 if (camera->unlock() != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700924 jniThrowRuntimeException(env, "unlock failed");
Wu-cheng Liffe1cf22009-09-10 16:49:17 +0800925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926}
927
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700928static void android_hardware_Camera_startSmoothZoom(JNIEnv *env, jobject thiz, jint value)
929{
Steve Block71f2cf12011-10-20 11:56:00 +0100930 ALOGV("startSmoothZoom");
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700931 sp<Camera> camera = get_native_camera(env, thiz, NULL);
932 if (camera == 0) return;
933
Wu-cheng Li0ca25192010-03-29 16:21:12 +0800934 status_t rc = camera->sendCommand(CAMERA_CMD_START_SMOOTH_ZOOM, value, 0);
935 if (rc == BAD_VALUE) {
936 char msg[64];
937 sprintf(msg, "invalid zoom value=%d", value);
938 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
939 } else if (rc != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700940 jniThrowRuntimeException(env, "start smooth zoom failed");
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700941 }
942}
943
944static void android_hardware_Camera_stopSmoothZoom(JNIEnv *env, jobject thiz)
945{
Steve Block71f2cf12011-10-20 11:56:00 +0100946 ALOGV("stopSmoothZoom");
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700947 sp<Camera> camera = get_native_camera(env, thiz, NULL);
948 if (camera == 0) return;
949
950 if (camera->sendCommand(CAMERA_CMD_STOP_SMOOTH_ZOOM, 0, 0) != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700951 jniThrowRuntimeException(env, "stop smooth zoom failed");
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700952 }
953}
954
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800955static void android_hardware_Camera_setDisplayOrientation(JNIEnv *env, jobject thiz,
956 jint value)
957{
Steve Block71f2cf12011-10-20 11:56:00 +0100958 ALOGV("setDisplayOrientation");
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800959 sp<Camera> camera = get_native_camera(env, thiz, NULL);
960 if (camera == 0) return;
961
962 if (camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION, value, 0) != NO_ERROR) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700963 jniThrowRuntimeException(env, "set display orientation failed");
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800964 }
965}
966
Eino-Ville Talvala69fe5272012-09-07 12:26:40 -0700967static jboolean android_hardware_Camera_enableShutterSound(JNIEnv *env, jobject thiz,
968 jboolean enabled)
969{
970 ALOGV("enableShutterSound");
971 sp<Camera> camera = get_native_camera(env, thiz, NULL);
972 if (camera == 0) return JNI_FALSE;
973
974 int32_t value = (enabled == JNI_TRUE) ? 1 : 0;
975 status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0);
976 if (rc == NO_ERROR) {
977 return JNI_TRUE;
978 } else if (rc == PERMISSION_DENIED) {
979 return JNI_FALSE;
980 } else {
981 jniThrowRuntimeException(env, "enable shutter sound failed");
982 return JNI_FALSE;
983 }
984}
985
Wu-cheng Li4c2292e2011-07-22 02:37:11 +0800986static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz,
Wu-cheng Libb1e2752011-07-30 05:00:37 +0800987 jint type)
Wu-cheng Li4c2292e2011-07-22 02:37:11 +0800988{
Steve Block71f2cf12011-10-20 11:56:00 +0100989 ALOGV("startFaceDetection");
Wu-cheng Li4c2292e2011-07-22 02:37:11 +0800990 JNICameraContext* context;
991 sp<Camera> camera = get_native_camera(env, thiz, &context);
992 if (camera == 0) return;
993
994 status_t rc = camera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, type, 0);
995 if (rc == BAD_VALUE) {
996 char msg[64];
997 snprintf(msg, sizeof(msg), "invalid face detection type=%d", type);
998 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
999 } else if (rc != NO_ERROR) {
1000 jniThrowRuntimeException(env, "start face detection failed");
1001 }
1002}
1003
1004static void android_hardware_Camera_stopFaceDetection(JNIEnv *env, jobject thiz)
1005{
Steve Block71f2cf12011-10-20 11:56:00 +01001006 ALOGV("stopFaceDetection");
Wu-cheng Li4c2292e2011-07-22 02:37:11 +08001007 sp<Camera> camera = get_native_camera(env, thiz, NULL);
1008 if (camera == 0) return;
1009
1010 if (camera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0) != NO_ERROR) {
1011 jniThrowRuntimeException(env, "stop face detection failed");
1012 }
1013}
1014
Wu-cheng Li9d062cf2011-11-14 20:30:14 +08001015static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject thiz, jint enable)
1016{
Wu-cheng Li02097522011-11-30 11:06:04 +08001017 ALOGV("enableFocusMoveCallback");
Wu-cheng Li9d062cf2011-11-14 20:30:14 +08001018 sp<Camera> camera = get_native_camera(env, thiz, NULL);
1019 if (camera == 0) return;
1020
1021 if (camera->sendCommand(CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG, enable, 0) != NO_ERROR) {
1022 jniThrowRuntimeException(env, "enable focus move callback failed");
1023 }
1024}
1025
Yin-Chia Yeh6262db52019-09-09 13:07:25 -07001026static void android_hardware_Camera_setAudioRestriction(
Yin-Chia Yeh3eb79d62019-08-19 15:55:34 -07001027 JNIEnv *env, jobject thiz, jint mode)
1028{
1029 ALOGV("setAudioRestriction");
1030 sp<Camera> camera = get_native_camera(env, thiz, NULL);
1031 if (camera == 0) {
1032 jniThrowRuntimeException(env, "camera has been disconnected");
Yin-Chia Yeh6262db52019-09-09 13:07:25 -07001033 return;
Yin-Chia Yeh3eb79d62019-08-19 15:55:34 -07001034 }
1035
1036 int32_t ret = camera->setAudioRestriction(mode);
1037 if (ret < 0) {
1038 jniThrowRuntimeException(env, "Illegal argument or low-level eror");
Yin-Chia Yeh6262db52019-09-09 13:07:25 -07001039 return;
1040 }
1041}
1042
1043static int32_t android_hardware_Camera_getAudioRestriction(
1044 JNIEnv *env, jobject thiz)
1045{
1046 ALOGV("getAudioRestriction");
1047 sp<Camera> camera = get_native_camera(env, thiz, NULL);
1048 if (camera == 0) {
1049 jniThrowRuntimeException(env, "camera has been disconnected");
Yin-Chia Yeh3eb79d62019-08-19 15:55:34 -07001050 return -1;
1051 }
1052
Yin-Chia Yeh6262db52019-09-09 13:07:25 -07001053 int32_t ret = camera->getGlobalAudioRestriction();
1054 if (ret < 0) {
1055 jniThrowRuntimeException(env, "Illegal argument or low-level eror");
1056 return -1;
1057 }
Yin-Chia Yeh3eb79d62019-08-19 15:55:34 -07001058 return ret;
1059}
1060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061//-------------------------------------------------
1062
Daniel Micay76f6a862015-09-19 17:31:01 -04001063static const JNINativeMethod camMethods[] = {
Chih-Chung Change25cc652010-05-06 16:36:58 +08001064 { "getNumberOfCameras",
1065 "()I",
1066 (void *)android_hardware_Camera_getNumberOfCameras },
Eino-Ville Talvala4f8e5ce2012-10-08 18:16:35 -07001067 { "_getCameraInfo",
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +08001068 "(ILandroid/hardware/Camera$CameraInfo;)V",
1069 (void*)android_hardware_Camera_getCameraInfo },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 { "native_setup",
Zhijun He4c913802014-06-16 16:42:35 -07001071 "(Ljava/lang/Object;IILjava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 (void*)android_hardware_Camera_native_setup },
1073 { "native_release",
1074 "()V",
1075 (void*)android_hardware_Camera_release },
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001076 { "setPreviewSurface",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 "(Landroid/view/Surface;)V",
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001078 (void *)android_hardware_Camera_setPreviewSurface },
Jamie Gennisfd6f39e2010-12-20 12:15:00 -08001079 { "setPreviewTexture",
1080 "(Landroid/graphics/SurfaceTexture;)V",
1081 (void *)android_hardware_Camera_setPreviewTexture },
Eino-Ville Talvala7005b672013-04-02 15:46:38 -07001082 { "setPreviewCallbackSurface",
1083 "(Landroid/view/Surface;)V",
1084 (void *)android_hardware_Camera_setPreviewCallbackSurface },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 { "startPreview",
1086 "()V",
1087 (void *)android_hardware_Camera_startPreview },
Wu-cheng Li4c2292e2011-07-22 02:37:11 +08001088 { "_stopPreview",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 "()V",
1090 (void *)android_hardware_Camera_stopPreview },
1091 { "previewEnabled",
1092 "()Z",
1093 (void *)android_hardware_Camera_previewEnabled },
1094 { "setHasPreviewCallback",
1095 "(ZZ)V",
1096 (void *)android_hardware_Camera_setHasPreviewCallback },
James Donge00cab72011-02-17 16:38:06 -08001097 { "_addCallbackBuffer",
1098 "([BI)V",
Andrew Harp94927df2009-10-20 01:47:05 -04001099 (void *)android_hardware_Camera_addCallbackBuffer },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 { "native_autoFocus",
1101 "()V",
1102 (void *)android_hardware_Camera_autoFocus },
Chih-Chung Chang244f8c22009-09-15 14:51:56 +08001103 { "native_cancelAutoFocus",
1104 "()V",
1105 (void *)android_hardware_Camera_cancelAutoFocus },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 { "native_takePicture",
James Donge00cab72011-02-17 16:38:06 -08001107 "(I)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 (void *)android_hardware_Camera_takePicture },
1109 { "native_setParameters",
1110 "(Ljava/lang/String;)V",
1111 (void *)android_hardware_Camera_setParameters },
1112 { "native_getParameters",
1113 "()Ljava/lang/String;",
1114 (void *)android_hardware_Camera_getParameters },
1115 { "reconnect",
1116 "()V",
1117 (void*)android_hardware_Camera_reconnect },
1118 { "lock",
Wu-cheng Liffe1cf22009-09-10 16:49:17 +08001119 "()V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 (void*)android_hardware_Camera_lock },
1121 { "unlock",
Wu-cheng Liffe1cf22009-09-10 16:49:17 +08001122 "()V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 (void*)android_hardware_Camera_unlock },
Wu-cheng Li36f68b82009-09-28 16:14:58 -07001124 { "startSmoothZoom",
1125 "(I)V",
1126 (void *)android_hardware_Camera_startSmoothZoom },
1127 { "stopSmoothZoom",
1128 "()V",
1129 (void *)android_hardware_Camera_stopSmoothZoom },
Chih-Chung Changd1d77062010-01-22 17:49:48 -08001130 { "setDisplayOrientation",
1131 "(I)V",
1132 (void *)android_hardware_Camera_setDisplayOrientation },
Eino-Ville Talvala4f8e5ce2012-10-08 18:16:35 -07001133 { "_enableShutterSound",
Eino-Ville Talvala69fe5272012-09-07 12:26:40 -07001134 "(Z)Z",
1135 (void *)android_hardware_Camera_enableShutterSound },
Wu-cheng Li4c2292e2011-07-22 02:37:11 +08001136 { "_startFaceDetection",
1137 "(I)V",
1138 (void *)android_hardware_Camera_startFaceDetection },
1139 { "_stopFaceDetection",
1140 "()V",
1141 (void *)android_hardware_Camera_stopFaceDetection},
Wu-cheng Li9d062cf2011-11-14 20:30:14 +08001142 { "enableFocusMoveCallback",
1143 "(I)V",
1144 (void *)android_hardware_Camera_enableFocusMoveCallback},
Yin-Chia Yeh3eb79d62019-08-19 15:55:34 -07001145 { "setAudioRestriction",
Yin-Chia Yeh6262db52019-09-09 13:07:25 -07001146 "(I)V",
Yin-Chia Yeh3eb79d62019-08-19 15:55:34 -07001147 (void *)android_hardware_Camera_setAudioRestriction},
Yin-Chia Yeh6262db52019-09-09 13:07:25 -07001148 { "getAudioRestriction",
1149 "()I",
1150 (void *)android_hardware_Camera_getAudioRestriction},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151};
1152
1153struct field {
1154 const char *class_name;
1155 const char *field_name;
1156 const char *field_type;
1157 jfieldID *jfield;
1158};
1159
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001160static void find_fields(JNIEnv *env, field *fields, int count)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161{
1162 for (int i = 0; i < count; i++) {
1163 field *f = &fields[i];
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001164 jclass clazz = FindClassOrDie(env, f->class_name);
1165 jfieldID field = GetFieldIDOrDie(env, clazz, f->field_name, f->field_type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 *(f->jfield) = field;
1167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168}
1169
1170// Get all the required offsets in java class and register native functions
1171int register_android_hardware_Camera(JNIEnv *env)
1172{
1173 field fields_to_find[] = {
Ashok Bhat4838e332014-01-03 14:37:19 +00001174 { "android/hardware/Camera", "mNativeContext", "J", &fields.context },
Wu-cheng Li3fd5fa42010-09-15 16:06:20 -07001175 { "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing },
1176 { "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation },
Eino-Ville Talvalaf7c6c5a2012-09-19 11:46:11 -07001177 { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z",
1178 &fields.canDisableShutterSound },
Wu-cheng Lif0d6a482011-07-28 05:30:59 +08001179 { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect },
Igor Murashkin0601ab12014-09-18 15:17:20 -07001180 { "android/hardware/Camera$Face", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye},
1181 { "android/hardware/Camera$Face", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye},
1182 { "android/hardware/Camera$Face", "mouth", "Landroid/graphics/Point;", &fields.face_mouth},
Wu-cheng Lif0d6a482011-07-28 05:30:59 +08001183 { "android/hardware/Camera$Face", "score", "I", &fields.face_score },
Igor Murashkin0601ab12014-09-18 15:17:20 -07001184 { "android/hardware/Camera$Face", "id", "I", &fields.face_id},
Wu-cheng Li4c2292e2011-07-22 02:37:11 +08001185 { "android/graphics/Rect", "left", "I", &fields.rect_left },
1186 { "android/graphics/Rect", "top", "I", &fields.rect_top },
1187 { "android/graphics/Rect", "right", "I", &fields.rect_right },
1188 { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom },
Igor Murashkin0601ab12014-09-18 15:17:20 -07001189 { "android/graphics/Point", "x", "I", &fields.point_x},
1190 { "android/graphics/Point", "y", "I", &fields.point_y},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 };
1192
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001193 find_fields(env, fields_to_find, NELEM(fields_to_find));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001195 jclass clazz = FindClassOrDie(env, "android/hardware/Camera");
1196 fields.post_event = GetStaticMethodIDOrDie(env, clazz, "postEventFromNative",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001199 clazz = FindClassOrDie(env, "android/graphics/Rect");
1200 fields.rect_constructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
Wu-cheng Libb1e2752011-07-30 05:00:37 +08001201
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001202 clazz = FindClassOrDie(env, "android/hardware/Camera$Face");
1203 fields.face_constructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204
Igor Murashkin0601ab12014-09-18 15:17:20 -07001205 clazz = env->FindClass("android/graphics/Point");
1206 fields.point_constructor = env->GetMethodID(clazz, "<init>", "()V");
1207 if (fields.point_constructor == NULL) {
1208 ALOGE("Can't find android/graphics/Point()");
1209 return -1;
1210 }
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 // Register native functions
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001213 return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214}