blob: fa363f38cbb01903178b26383875aad9d9cffab5 [file] [log] [blame]
Igor Murashkin70725502013-06-25 20:27:06 +00001/*
2**
3** Copyright 2013, 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 "CameraMetadata-JNI"
20#include <utils/Log.h>
21
22#include "jni.h"
23#include "JNIHelp.h"
24#include "android_os_Parcel.h"
25#include "android_runtime/AndroidRuntime.h"
26
27#include <camera/CameraMetadata.h>
28
29// fully-qualified class name
30#define CAMERA_METADATA_CLASS_NAME "android/hardware/photography/CameraMetadata"
31
32using namespace android;
33
34struct fields_t {
35 jfieldID metadata_ptr;
36};
37
38static fields_t fields;
39
40extern "C" {
41
42static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
43
44// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
45static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
46
47 if (thiz == NULL) {
48 return NULL;
49 }
50
51 return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
52}
53
54// Safe access to native pointer from object. Throws if not possible to access.
55static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
56 const char* argName = "this") {
57
58 if (thiz == NULL) {
59 ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
60 __FUNCTION__);
61 jniThrowNullPointerException(env, argName);
62 return NULL;
63 }
64
65 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
66 if (metadata == NULL) {
67 ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
68 __FUNCTION__);
69 jniThrowException(env, "java/lang/IllegalStateException",
70 "Metadata object was already closed");
71 return NULL;
72 }
73
74 return metadata;
75}
76
77static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
78 ALOGV("%s", __FUNCTION__);
79
80 return reinterpret_cast<jlong>(new CameraMetadata());
81}
82
83static jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
84 ALOGV("%s", __FUNCTION__);
85
86 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
87
88 if (metadata == NULL) {
89 ALOGW("%s: Returning early due to exception being thrown",
90 __FUNCTION__);
91 return JNI_TRUE; // actually throws java exc.
92 }
93
94 jboolean empty = metadata->isEmpty();
95
96 ALOGV("%s: Empty returned %d, entry count was %d",
97 __FUNCTION__, empty, metadata->entryCount());
98
99 return empty;
100}
101
102static jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
103 ALOGV("%s", __FUNCTION__);
104
105 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
106
107 if (metadata == NULL) return 0; // actually throws java exc.
108
109 return metadata->entryCount();
110}
111
112// idempotent. calling more than once has no effect.
113static void CameraMetadata_close(JNIEnv *env, jobject thiz) {
114 ALOGV("%s", __FUNCTION__);
115
116 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
117
118 if (metadata != NULL) {
119 delete metadata;
120 env->SetLongField(thiz, fields.metadata_ptr, 0);
121 }
122
123 LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
124 "Expected the native ptr to be 0 after #close");
125}
126
127static void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
128 ALOGV("%s", __FUNCTION__);
129
130 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
131
132 // order is important: we can't call another JNI method
133 // if there is an exception pending
134 if (metadata == NULL) return;
135
136 CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
137
138 if (otherMetadata == NULL) return;
139
140 metadata->swap(*otherMetadata);
141}
142
143static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
144 ALOGV("%s", __FUNCTION__);
145 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
146 if (metadata == NULL) {
147 return;
148 }
149
150 Parcel* parcelNative = parcelForJavaObject(env, parcel);
151 if (parcelNative == NULL) {
152 jniThrowNullPointerException(env, "parcel");
153 return;
154 }
155
156 status_t err;
157 if ((err = metadata->readFromParcel(parcelNative)) != OK) {
158 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
159 "Failed to read from parcel (error code %d)", err);
160 return;
161 }
162}
163
164static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
165 ALOGV("%s", __FUNCTION__);
166 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
167 if (metadata == NULL) {
168 return;
169 }
170
171 Parcel* parcelNative = parcelForJavaObject(env, parcel);
172 if (parcelNative == NULL) {
173 jniThrowNullPointerException(env, "parcel");
174 return;
175 }
176
177 status_t err;
178 if ((err = metadata->writeToParcel(parcelNative)) != OK) {
179 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
180 "Failed to write to parcel (error code %d)", err);
181 return;
182 }
183}
184
185} // extern "C"
186
187//-------------------------------------------------
188
189static JNINativeMethod gCameraMetadataMethods[] = {
190 { "nativeClassInit",
191 "()V",
192 (void *)CameraMetadata_classInit },
193 { "nativeAllocate",
194 "()J",
195 (void*)CameraMetadata_allocate },
196 { "nativeIsEmpty",
197 "()Z",
198 (void*)CameraMetadata_isEmpty },
199 { "nativeGetEntryCount",
200 "()I",
201 (void*)CameraMetadata_getEntryCount },
202 { "nativeClose",
203 "()V",
204 (void*)CameraMetadata_close },
205 { "nativeSwap",
206 "(L" CAMERA_METADATA_CLASS_NAME ";)V",
207 (void *)CameraMetadata_swap },
208 { "nativeReadFromParcel",
209 "(Landroid/os/Parcel;)V",
210 (void *)CameraMetadata_readFromParcel },
211 { "nativeWriteToParcel",
212 "(Landroid/os/Parcel;)V",
213 (void *)CameraMetadata_writeToParcel },
214};
215
216struct field {
217 const char *class_name;
218 const char *field_name;
219 const char *field_type;
220 jfieldID *jfield;
221};
222
223static int find_fields(JNIEnv *env, field *fields, int count)
224{
225 for (int i = 0; i < count; i++) {
226 field *f = &fields[i];
227 jclass clazz = env->FindClass(f->class_name);
228 if (clazz == NULL) {
229 ALOGE("Can't find %s", f->class_name);
230 return -1;
231 }
232
233 jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
234 if (field == NULL) {
235 ALOGE("Can't find %s.%s", f->class_name, f->field_name);
236 return -1;
237 }
238
239 *(f->jfield) = field;
240 }
241
242 return 0;
243}
244
245// Get all the required offsets in java class and register native functions
246int register_android_hardware_photography_CameraMetadata(JNIEnv *env)
247{
248 // Register native functions
249 return AndroidRuntime::registerNativeMethods(env,
250 CAMERA_METADATA_CLASS_NAME,
251 gCameraMetadataMethods,
252 NELEM(gCameraMetadataMethods));
253}
254
255extern "C" {
256static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
257 // XX: Why do this separately instead of doing it in the register function?
258 ALOGV("%s", __FUNCTION__);
259
260 field fields_to_find[] = {
261 { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
262 };
263
264 // Do this here instead of in register_native_methods,
265 // since otherwise it will fail to find the fields.
266 if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
267 return;
268
269 jclass clazz = env->FindClass(CAMERA_METADATA_CLASS_NAME);
270}
271} // extern "C"