blob: 331210967e242d8172e1c3c5b3ed9cb5a8547a4d [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
Igor Murashkinb519cc52013-07-02 11:23:44 -070019// #define LOG_NNDEBUG 0
Igor Murashkin70725502013-06-25 20:27:06 +000020#define LOG_TAG "CameraMetadata-JNI"
Ruben Brunk32ef3ae2014-02-21 17:40:51 -080021#include <utils/Errors.h>
Igor Murashkin70725502013-06-25 20:27:06 +000022#include <utils/Log.h>
Ruben Brunk85c43882014-02-21 17:40:51 -080023#include <utils/RefBase.h>
Ruben Brunk32ef3ae2014-02-21 17:40:51 -080024#include <utils/Vector.h>
25#include <utils/SortedVector.h>
26#include <utils/KeyedVector.h>
Ruben Brunk85c43882014-02-21 17:40:51 -080027#include <string.h>
Igor Murashkin70725502013-06-25 20:27:06 +000028
29#include "jni.h"
30#include "JNIHelp.h"
31#include "android_os_Parcel.h"
32#include "android_runtime/AndroidRuntime.h"
Ruben Brunkf967a542014-04-28 16:31:11 -070033#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
Igor Murashkin70725502013-06-25 20:27:06 +000034
Ruben Brunk85c43882014-02-21 17:40:51 -080035#include <binder/IServiceManager.h>
Igor Murashkin70725502013-06-25 20:27:06 +000036#include <camera/CameraMetadata.h>
Ruben Brunk85c43882014-02-21 17:40:51 -080037#include <camera/ICameraService.h>
38#include <camera/VendorTagDescriptor.h>
Igor Murashkinb519cc52013-07-02 11:23:44 -070039#include <nativehelper/ScopedUtfChars.h>
40#include <nativehelper/ScopedPrimitiveArray.h>
41
42#if defined(LOG_NNDEBUG)
43#if !LOG_NNDEBUG
44#define ALOGVV ALOGV
45#endif
46#else
47#define ALOGVV(...)
48#endif
Igor Murashkin70725502013-06-25 20:27:06 +000049
50// fully-qualified class name
Eino-Ville Talvala70c22072013-08-27 12:09:04 -070051#define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
Igor Murashkin70725502013-06-25 20:27:06 +000052
53using namespace android;
54
55struct fields_t {
56 jfieldID metadata_ptr;
57};
58
59static fields_t fields;
60
Ruben Brunkf967a542014-04-28 16:31:11 -070061namespace android {
62
63status_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
64 /*out*/CameraMetadata* metadata) {
65 if (!thiz) {
66 ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
67 return BAD_VALUE;
68 }
69
70 if (!metadata) {
71 ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
72 return BAD_VALUE;
73 }
74 CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz,
75 fields.metadata_ptr));
76 if (nativePtr == NULL) {
77 ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
78 return BAD_VALUE;
79 }
80 *metadata = *nativePtr;
81 return OK;
82}
83
84} /*namespace android*/
85
Igor Murashkinb519cc52013-07-02 11:23:44 -070086namespace {
87struct Helpers {
88 static size_t getTypeSize(uint8_t type) {
89 if (type >= NUM_TYPES) {
90 ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
91 return static_cast<size_t>(-1);
92 }
93
94 return camera_metadata_type_size[type];
95 }
96
97 static status_t updateAny(CameraMetadata *metadata,
98 uint32_t tag,
99 uint32_t type,
100 const void *data,
101 size_t dataBytes) {
102
103 if (type >= NUM_TYPES) {
104 ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
105 return INVALID_OPERATION;
106 }
107
108 size_t typeSize = getTypeSize(type);
109
110 if (dataBytes % typeSize != 0) {
111 ALOGE("%s: Expected dataBytes (%ud) to be divisible by typeSize "
112 "(%ud)", __FUNCTION__, dataBytes, typeSize);
113 return BAD_VALUE;
114 }
115
116 size_t dataCount = dataBytes / typeSize;
117
118 switch(type) {
119#define METADATA_UPDATE(runtime_type, compile_type) \
120 case runtime_type: { \
121 const compile_type *dataPtr = \
122 static_cast<const compile_type*>(data); \
123 return metadata->update(tag, dataPtr, dataCount); \
124 } \
125
126 METADATA_UPDATE(TYPE_BYTE, uint8_t);
127 METADATA_UPDATE(TYPE_INT32, int32_t);
128 METADATA_UPDATE(TYPE_FLOAT, float);
129 METADATA_UPDATE(TYPE_INT64, int64_t);
130 METADATA_UPDATE(TYPE_DOUBLE, double);
131 METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);
132
133 default: {
134 // unreachable
135 ALOGE("%s: Unreachable", __FUNCTION__);
136 return INVALID_OPERATION;
137 }
138 }
139
140#undef METADATA_UPDATE
141 }
142};
143} // namespace {}
144
Igor Murashkin70725502013-06-25 20:27:06 +0000145extern "C" {
146
147static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
Igor Murashkinb519cc52013-07-02 11:23:44 -0700148static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
149static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
Ruben Brunk85c43882014-02-21 17:40:51 -0800150static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
Igor Murashkin70725502013-06-25 20:27:06 +0000151
152// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
153static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
154
155 if (thiz == NULL) {
156 return NULL;
157 }
158
159 return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
160}
161
162// Safe access to native pointer from object. Throws if not possible to access.
163static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
164 const char* argName = "this") {
165
166 if (thiz == NULL) {
167 ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
168 __FUNCTION__);
169 jniThrowNullPointerException(env, argName);
170 return NULL;
171 }
172
173 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
174 if (metadata == NULL) {
175 ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
176 __FUNCTION__);
177 jniThrowException(env, "java/lang/IllegalStateException",
178 "Metadata object was already closed");
179 return NULL;
180 }
181
182 return metadata;
183}
184
185static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
186 ALOGV("%s", __FUNCTION__);
187
188 return reinterpret_cast<jlong>(new CameraMetadata());
189}
190
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700191static jlong CameraMetadata_allocateCopy(JNIEnv *env, jobject thiz,
192 jobject other) {
193 ALOGV("%s", __FUNCTION__);
194
195 CameraMetadata* otherMetadata =
196 CameraMetadata_getPointerThrow(env, other, "other");
197
198 // In case of exception, return
199 if (otherMetadata == NULL) return NULL;
200
201 // Clone native metadata and return new pointer
202 return reinterpret_cast<jlong>(new CameraMetadata(*otherMetadata));
203}
204
205
Igor Murashkin70725502013-06-25 20:27:06 +0000206static jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
207 ALOGV("%s", __FUNCTION__);
208
209 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
210
211 if (metadata == NULL) {
212 ALOGW("%s: Returning early due to exception being thrown",
213 __FUNCTION__);
214 return JNI_TRUE; // actually throws java exc.
215 }
216
217 jboolean empty = metadata->isEmpty();
218
219 ALOGV("%s: Empty returned %d, entry count was %d",
220 __FUNCTION__, empty, metadata->entryCount());
221
222 return empty;
223}
224
225static jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
226 ALOGV("%s", __FUNCTION__);
227
228 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
229
230 if (metadata == NULL) return 0; // actually throws java exc.
231
232 return metadata->entryCount();
233}
234
235// idempotent. calling more than once has no effect.
236static void CameraMetadata_close(JNIEnv *env, jobject thiz) {
237 ALOGV("%s", __FUNCTION__);
238
239 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
240
241 if (metadata != NULL) {
242 delete metadata;
243 env->SetLongField(thiz, fields.metadata_ptr, 0);
244 }
245
246 LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
247 "Expected the native ptr to be 0 after #close");
248}
249
250static void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
251 ALOGV("%s", __FUNCTION__);
252
253 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
254
255 // order is important: we can't call another JNI method
256 // if there is an exception pending
257 if (metadata == NULL) return;
258
259 CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
260
261 if (otherMetadata == NULL) return;
262
263 metadata->swap(*otherMetadata);
264}
265
Igor Murashkinb519cc52013-07-02 11:23:44 -0700266static jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag) {
267 ALOGV("%s (tag = %d)", __FUNCTION__, tag);
268
269 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
270 if (metadata == NULL) return NULL;
271
272 int tagType = get_camera_metadata_tag_type(tag);
273 if (tagType == -1) {
274 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
275 "Tag (%d) did not have a type", tag);
276 return NULL;
277 }
278 size_t tagSize = Helpers::getTypeSize(tagType);
279
280 camera_metadata_entry entry = metadata->find(tag);
281 if (entry.count == 0) {
282 if (!metadata->exists(tag)) {
283 ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
284 return NULL;
285 } else {
286 // OK: we will return a 0-sized array.
287 ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__,
288 tag);
289 }
290 }
291
292 jsize byteCount = entry.count * tagSize;
293 jbyteArray byteArray = env->NewByteArray(byteCount);
294 if (env->ExceptionCheck()) return NULL;
295
296 // Copy into java array from native array
297 ScopedByteArrayRW arrayWriter(env, byteArray);
298 memcpy(arrayWriter.get(), entry.data.u8, byteCount);
299
300 return byteArray;
301}
302
303static void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) {
304 ALOGV("%s (tag = %d)", __FUNCTION__, tag);
305
306 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
307 if (metadata == NULL) return;
308
309 int tagType = get_camera_metadata_tag_type(tag);
310 if (tagType == -1) {
311 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
312 "Tag (%d) did not have a type", tag);
313 return;
314 }
315 size_t tagSize = Helpers::getTypeSize(tagType);
316
317 status_t res;
318
319 if (src == NULL) {
320 // If array is NULL, delete the entry
Igor Murashkin3710db82013-07-18 20:11:17 -0700321 if (metadata->exists(tag)) {
322 res = metadata->erase(tag);
323 ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
324 } else {
325 res = OK;
326 ALOGV("%s: Don't need to erase", __FUNCTION__);
327 }
Igor Murashkinb519cc52013-07-02 11:23:44 -0700328 } else {
329 // Copy from java array into native array
330 ScopedByteArrayRO arrayReader(env, src);
331 if (arrayReader.get() == NULL) return;
332
333 res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
334 tagType, arrayReader.get(), arrayReader.size());
Igor Murashkin3710db82013-07-18 20:11:17 -0700335
336 ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
Igor Murashkinb519cc52013-07-02 11:23:44 -0700337 }
338
339 if (res == OK) {
340 return;
341 } else if (res == BAD_VALUE) {
342 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
343 "Src byte array was poorly formed");
344 } else if (res == INVALID_OPERATION) {
345 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
346 "Internal error while trying to update metadata");
347 } else {
348 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
349 "Unknown error (%d) while trying to update "
350 "metadata", res);
351 }
352}
353
Igor Murashkin70725502013-06-25 20:27:06 +0000354static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
355 ALOGV("%s", __FUNCTION__);
356 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
357 if (metadata == NULL) {
358 return;
359 }
360
361 Parcel* parcelNative = parcelForJavaObject(env, parcel);
362 if (parcelNative == NULL) {
363 jniThrowNullPointerException(env, "parcel");
364 return;
365 }
366
367 status_t err;
368 if ((err = metadata->readFromParcel(parcelNative)) != OK) {
369 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
370 "Failed to read from parcel (error code %d)", err);
371 return;
372 }
373}
374
375static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
376 ALOGV("%s", __FUNCTION__);
377 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
378 if (metadata == NULL) {
379 return;
380 }
381
382 Parcel* parcelNative = parcelForJavaObject(env, parcel);
383 if (parcelNative == NULL) {
384 jniThrowNullPointerException(env, "parcel");
385 return;
386 }
387
388 status_t err;
389 if ((err = metadata->writeToParcel(parcelNative)) != OK) {
390 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
391 "Failed to write to parcel (error code %d)", err);
392 return;
393 }
394}
395
396} // extern "C"
397
398//-------------------------------------------------
399
400static JNINativeMethod gCameraMetadataMethods[] = {
Igor Murashkinb519cc52013-07-02 11:23:44 -0700401// static methods
Igor Murashkin70725502013-06-25 20:27:06 +0000402 { "nativeClassInit",
403 "()V",
404 (void *)CameraMetadata_classInit },
Igor Murashkinb519cc52013-07-02 11:23:44 -0700405 { "nativeGetTagFromKey",
406 "(Ljava/lang/String;)I",
407 (void *)CameraMetadata_getTagFromKey },
408 { "nativeGetTypeFromTag",
409 "(I)I",
410 (void *)CameraMetadata_getTypeFromTag },
Ruben Brunk85c43882014-02-21 17:40:51 -0800411 { "nativeSetupGlobalVendorTagDescriptor",
412 "()I",
413 (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
Igor Murashkinb519cc52013-07-02 11:23:44 -0700414// instance methods
Igor Murashkin70725502013-06-25 20:27:06 +0000415 { "nativeAllocate",
416 "()J",
417 (void*)CameraMetadata_allocate },
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700418 { "nativeAllocateCopy",
419 "(L" CAMERA_METADATA_CLASS_NAME ";)J",
420 (void *)CameraMetadata_allocateCopy },
Igor Murashkin70725502013-06-25 20:27:06 +0000421 { "nativeIsEmpty",
422 "()Z",
423 (void*)CameraMetadata_isEmpty },
424 { "nativeGetEntryCount",
425 "()I",
426 (void*)CameraMetadata_getEntryCount },
427 { "nativeClose",
428 "()V",
429 (void*)CameraMetadata_close },
430 { "nativeSwap",
431 "(L" CAMERA_METADATA_CLASS_NAME ";)V",
432 (void *)CameraMetadata_swap },
Igor Murashkinb519cc52013-07-02 11:23:44 -0700433 { "nativeReadValues",
434 "(I)[B",
435 (void *)CameraMetadata_readValues },
436 { "nativeWriteValues",
437 "(I[B)V",
438 (void *)CameraMetadata_writeValues },
439// Parcelable interface
Igor Murashkin70725502013-06-25 20:27:06 +0000440 { "nativeReadFromParcel",
441 "(Landroid/os/Parcel;)V",
442 (void *)CameraMetadata_readFromParcel },
443 { "nativeWriteToParcel",
444 "(Landroid/os/Parcel;)V",
445 (void *)CameraMetadata_writeToParcel },
446};
447
448struct field {
449 const char *class_name;
450 const char *field_name;
451 const char *field_type;
452 jfieldID *jfield;
453};
454
455static int find_fields(JNIEnv *env, field *fields, int count)
456{
457 for (int i = 0; i < count; i++) {
458 field *f = &fields[i];
459 jclass clazz = env->FindClass(f->class_name);
460 if (clazz == NULL) {
461 ALOGE("Can't find %s", f->class_name);
462 return -1;
463 }
464
465 jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
466 if (field == NULL) {
467 ALOGE("Can't find %s.%s", f->class_name, f->field_name);
468 return -1;
469 }
470
471 *(f->jfield) = field;
472 }
473
474 return 0;
475}
476
477// Get all the required offsets in java class and register native functions
Eino-Ville Talvala2f1a2e42013-07-25 17:12:05 -0700478int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
Igor Murashkin70725502013-06-25 20:27:06 +0000479{
480 // Register native functions
481 return AndroidRuntime::registerNativeMethods(env,
482 CAMERA_METADATA_CLASS_NAME,
483 gCameraMetadataMethods,
484 NELEM(gCameraMetadataMethods));
485}
486
487extern "C" {
488static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
489 // XX: Why do this separately instead of doing it in the register function?
490 ALOGV("%s", __FUNCTION__);
491
492 field fields_to_find[] = {
493 { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
494 };
495
496 // Do this here instead of in register_native_methods,
497 // since otherwise it will fail to find the fields.
498 if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
499 return;
500
501 jclass clazz = env->FindClass(CAMERA_METADATA_CLASS_NAME);
502}
Igor Murashkinb519cc52013-07-02 11:23:44 -0700503
504static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
505
506 ScopedUtfChars keyScoped(env, keyName);
507 const char *key = keyScoped.c_str();
508 if (key == NULL) {
509 // exception thrown by ScopedUtfChars
510 return 0;
511 }
512 size_t keyLength = strlen(key);
513
514 ALOGV("%s (key = '%s')", __FUNCTION__, key);
515
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800516 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
517
Igor Murashkin3c40a042014-04-22 15:05:50 -0700518 SortedVector<String8> vendorSections;
519 size_t vendorSectionCount = 0;
520
521 if (vTags != 0) {
522 vendorSections = vTags->getAllSectionNames();
523 vendorSectionCount = vendorSections.size();
524 }
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800525
Igor Murashkinb519cc52013-07-02 11:23:44 -0700526 // First, find the section by the longest string match
527 const char *section = NULL;
528 size_t sectionIndex = 0;
529 size_t sectionLength = 0;
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800530 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
531 for (size_t i = 0; i < totalSectionCount; ++i) {
532
533 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
534 vendorSections[i - ANDROID_SECTION_COUNT].string();
Igor Murashkinb519cc52013-07-02 11:23:44 -0700535 ALOGVV("%s: Trying to match against section '%s'",
536 __FUNCTION__, str);
537 if (strstr(key, str) == key) { // key begins with the section name
538 size_t strLength = strlen(str);
539
540 ALOGVV("%s: Key begins with section name", __FUNCTION__);
541
542 // section name is the longest we've found so far
543 if (section == NULL || sectionLength < strLength) {
544 section = str;
545 sectionIndex = i;
546 sectionLength = strLength;
547
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800548 ALOGVV("%s: Found new best section (%s)", __FUNCTION__, section);
Igor Murashkinb519cc52013-07-02 11:23:44 -0700549 }
550 }
551 }
552
Igor Murashkinb519cc52013-07-02 11:23:44 -0700553 // TODO: Make above get_camera_metadata_section_from_name ?
554
555 if (section == NULL) {
556 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
557 "Could not find section name for key '%s')", key);
558 return 0;
559 } else {
560 ALOGV("%s: Found matched section '%s' (%d)",
561 __FUNCTION__, section, sectionIndex);
562 }
563
564 // Get the tag name component of the key
565 const char *keyTagName = key + sectionLength + 1; // x.y.z -> z
566 if (sectionLength + 1 >= keyLength) {
567 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
568 "Key length too short for key '%s')", key);
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800569 return 0;
Igor Murashkinb519cc52013-07-02 11:23:44 -0700570 }
571
572 // Match rest of name against the tag names in that section only
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800573 uint32_t tag = 0;
574 if (sectionIndex < ANDROID_SECTION_COUNT) {
575 // Match built-in tags (typically android.*)
576 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
577 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
578 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
Igor Murashkinb519cc52013-07-02 11:23:44 -0700579
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800580 for (tag = tagBegin; tag < tagEnd; ++tag) {
581 const char *tagName = get_camera_metadata_tag_name(tag);
Igor Murashkinb519cc52013-07-02 11:23:44 -0700582
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800583 if (strcmp(keyTagName, tagName) == 0) {
584 ALOGV("%s: Found matched tag '%s' (%d)",
585 __FUNCTION__, tagName, tag);
586 break;
587 }
588 }
589
590 if (tag == tagEnd) {
591 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
592 "Could not find tag name for key '%s')", key);
593 return 0;
594 }
Igor Murashkin3c40a042014-04-22 15:05:50 -0700595 } else if (vTags != 0) {
Ruben Brunk32ef3ae2014-02-21 17:40:51 -0800596 // Match vendor tags (typically com.*)
597 const String8 sectionName(section);
598 const String8 tagName(keyTagName);
599
600 status_t res = OK;
601 if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) {
602 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
603 "%s: No vendor tag matches key '%s'", __FUNCTION__, key);
604 return 0;
Igor Murashkinb519cc52013-07-02 11:23:44 -0700605 }
606 }
607
Igor Murashkinb519cc52013-07-02 11:23:44 -0700608 // TODO: Make above get_camera_metadata_tag_from_name ?
609
Igor Murashkinb519cc52013-07-02 11:23:44 -0700610 return tag;
611}
612
613static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
614 int tagType = get_camera_metadata_tag_type(tag);
615 if (tagType == -1) {
616 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
617 "Tag (%d) did not have a type", tag);
618 return -1;
619 }
620
621 return tagType;
622}
623
Ruben Brunk85c43882014-02-21 17:40:51 -0800624static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
625 const String16 NAME("media.camera");
626 sp<ICameraService> cameraService;
627 status_t err = getService(NAME, /*out*/&cameraService);
628
629 if (err != OK) {
630 ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
631 strerror(-err), err);
632 return err;
633 }
634
635 sp<VendorTagDescriptor> desc;
636 err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
637
Igor Murashkin5614cbe2014-03-17 14:00:55 -0700638 if (err == -EOPNOTSUPP) {
639 ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
640 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
641
642 return OK;
643 } else if (err != OK) {
644 ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
645 __FUNCTION__, strerror(-err), err);
Ruben Brunk85c43882014-02-21 17:40:51 -0800646 return err;
647 }
648
649 err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
650
651 return err;
652}
653
Igor Murashkin70725502013-06-25 20:27:06 +0000654} // extern "C"