1 /* 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_NNDEBUG 0 20 #define LOG_TAG "CameraMetadata-JNI" 21 #include <utils/Errors.h> 22 #include <utils/Log.h> 23 #include <utils/RefBase.h> 24 #include <utils/Vector.h> 25 #include <utils/SortedVector.h> 26 #include <utils/KeyedVector.h> 27 #include <string.h> 28 29 #include "jni.h" 30 #include "JNIHelp.h" 31 #include "android_os_Parcel.h" 32 #include "android_runtime/AndroidRuntime.h" 33 #include "android_runtime/android_hardware_camera2_CameraMetadata.h" 34 35 #include <binder/IServiceManager.h> 36 #include <camera/CameraMetadata.h> 37 #include <camera/ICameraService.h> 38 #include <camera/VendorTagDescriptor.h> 39 #include <nativehelper/ScopedUtfChars.h> 40 #include <nativehelper/ScopedPrimitiveArray.h> 41 42 #include <sys/types.h> // for socketpair 43 #include <sys/socket.h> // for socketpair 44 45 #if defined(LOG_NNDEBUG) 46 #if !LOG_NNDEBUG 47 #define ALOGVV ALOGV 48 #endif 49 #else 50 #define ALOGVV(...) 51 #endif 52 53 // fully-qualified class name 54 #define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative" 55 56 using namespace android; 57 58 struct fields_t { 59 jfieldID metadata_ptr; 60 }; 61 62 static fields_t fields; 63 64 namespace android { 65 66 status_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz, 67 /*out*/CameraMetadata* metadata) { 68 if (!thiz) { 69 ALOGE("%s: Invalid java metadata object.", __FUNCTION__); 70 return BAD_VALUE; 71 } 72 73 if (!metadata) { 74 ALOGE("%s: Invalid output metadata object.", __FUNCTION__); 75 return BAD_VALUE; 76 } 77 CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, 78 fields.metadata_ptr)); 79 if (nativePtr == NULL) { 80 ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__); 81 return BAD_VALUE; 82 } 83 *metadata = *nativePtr; 84 return OK; 85 } 86 87 } /*namespace android*/ 88 89 namespace { 90 struct Helpers { 91 static size_t getTypeSize(uint8_t type) { 92 if (type >= NUM_TYPES) { 93 ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type); 94 return static_cast<size_t>(-1); 95 } 96 97 return camera_metadata_type_size[type]; 98 } 99 100 static status_t updateAny(CameraMetadata *metadata, 101 uint32_t tag, 102 uint32_t type, 103 const void *data, 104 size_t dataBytes) { 105 106 if (type >= NUM_TYPES) { 107 ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type); 108 return INVALID_OPERATION; 109 } 110 111 size_t typeSize = getTypeSize(type); 112 113 if (dataBytes % typeSize != 0) { 114 ALOGE("%s: Expected dataBytes (%ud) to be divisible by typeSize " 115 "(%ud)", __FUNCTION__, dataBytes, typeSize); 116 return BAD_VALUE; 117 } 118 119 size_t dataCount = dataBytes / typeSize; 120 121 switch(type) { 122 #define METADATA_UPDATE(runtime_type, compile_type) \ 123 case runtime_type: { \ 124 const compile_type *dataPtr = \ 125 static_cast<const compile_type*>(data); \ 126 return metadata->update(tag, dataPtr, dataCount); \ 127 } \ 128 129 METADATA_UPDATE(TYPE_BYTE, uint8_t); 130 METADATA_UPDATE(TYPE_INT32, int32_t); 131 METADATA_UPDATE(TYPE_FLOAT, float); 132 METADATA_UPDATE(TYPE_INT64, int64_t); 133 METADATA_UPDATE(TYPE_DOUBLE, double); 134 METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t); 135 136 default: { 137 // unreachable 138 ALOGE("%s: Unreachable", __FUNCTION__); 139 return INVALID_OPERATION; 140 } 141 } 142 143 #undef METADATA_UPDATE 144 } 145 }; 146 } // namespace {} 147 148 extern "C" { 149 150 static void CameraMetadata_classInit(JNIEnv *env, jobject thiz); 151 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName); 152 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag); 153 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz); 154 155 // Less safe access to native pointer. Does NOT throw any Java exceptions if NULL. 156 static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) { 157 158 if (thiz == NULL) { 159 return NULL; 160 } 161 162 return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr)); 163 } 164 165 // Safe access to native pointer from object. Throws if not possible to access. 166 static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz, 167 const char* argName = "this") { 168 169 if (thiz == NULL) { 170 ALOGV("%s: Throwing java.lang.NullPointerException for null reference", 171 __FUNCTION__); 172 jniThrowNullPointerException(env, argName); 173 return NULL; 174 } 175 176 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz); 177 if (metadata == NULL) { 178 ALOGV("%s: Throwing java.lang.IllegalStateException for closed object", 179 __FUNCTION__); 180 jniThrowException(env, "java/lang/IllegalStateException", 181 "Metadata object was already closed"); 182 return NULL; 183 } 184 185 return metadata; 186 } 187 188 static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) { 189 ALOGV("%s", __FUNCTION__); 190 191 return reinterpret_cast<jlong>(new CameraMetadata()); 192 } 193 194 static jlong CameraMetadata_allocateCopy(JNIEnv *env, jobject thiz, 195 jobject other) { 196 ALOGV("%s", __FUNCTION__); 197 198 CameraMetadata* otherMetadata = 199 CameraMetadata_getPointerThrow(env, other, "other"); 200 201 // In case of exception, return 202 if (otherMetadata == NULL) return NULL; 203 204 // Clone native metadata and return new pointer 205 return reinterpret_cast<jlong>(new CameraMetadata(*otherMetadata)); 206 } 207 208 209 static jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) { 210 ALOGV("%s", __FUNCTION__); 211 212 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 213 214 if (metadata == NULL) { 215 ALOGW("%s: Returning early due to exception being thrown", 216 __FUNCTION__); 217 return JNI_TRUE; // actually throws java exc. 218 } 219 220 jboolean empty = metadata->isEmpty(); 221 222 ALOGV("%s: Empty returned %d, entry count was %d", 223 __FUNCTION__, empty, metadata->entryCount()); 224 225 return empty; 226 } 227 228 static jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) { 229 ALOGV("%s", __FUNCTION__); 230 231 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 232 233 if (metadata == NULL) return 0; // actually throws java exc. 234 235 return metadata->entryCount(); 236 } 237 238 // idempotent. calling more than once has no effect. 239 static void CameraMetadata_close(JNIEnv *env, jobject thiz) { 240 ALOGV("%s", __FUNCTION__); 241 242 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz); 243 244 if (metadata != NULL) { 245 delete metadata; 246 env->SetLongField(thiz, fields.metadata_ptr, 0); 247 } 248 249 LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL, 250 "Expected the native ptr to be 0 after #close"); 251 } 252 253 static void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) { 254 ALOGV("%s", __FUNCTION__); 255 256 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 257 258 // order is important: we can't call another JNI method 259 // if there is an exception pending 260 if (metadata == NULL) return; 261 262 CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other"); 263 264 if (otherMetadata == NULL) return; 265 266 metadata->swap(*otherMetadata); 267 } 268 269 static jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag) { 270 ALOGV("%s (tag = %d)", __FUNCTION__, tag); 271 272 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 273 if (metadata == NULL) return NULL; 274 275 int tagType = get_camera_metadata_tag_type(tag); 276 if (tagType == -1) { 277 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 278 "Tag (%d) did not have a type", tag); 279 return NULL; 280 } 281 size_t tagSize = Helpers::getTypeSize(tagType); 282 283 camera_metadata_entry entry = metadata->find(tag); 284 if (entry.count == 0) { 285 if (!metadata->exists(tag)) { 286 ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag); 287 return NULL; 288 } else { 289 // OK: we will return a 0-sized array. 290 ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__, 291 tag); 292 } 293 } 294 295 jsize byteCount = entry.count * tagSize; 296 jbyteArray byteArray = env->NewByteArray(byteCount); 297 if (env->ExceptionCheck()) return NULL; 298 299 // Copy into java array from native array 300 ScopedByteArrayRW arrayWriter(env, byteArray); 301 memcpy(arrayWriter.get(), entry.data.u8, byteCount); 302 303 return byteArray; 304 } 305 306 static void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) { 307 ALOGV("%s (tag = %d)", __FUNCTION__, tag); 308 309 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 310 if (metadata == NULL) return; 311 312 int tagType = get_camera_metadata_tag_type(tag); 313 if (tagType == -1) { 314 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 315 "Tag (%d) did not have a type", tag); 316 return; 317 } 318 size_t tagSize = Helpers::getTypeSize(tagType); 319 320 status_t res; 321 322 if (src == NULL) { 323 // If array is NULL, delete the entry 324 if (metadata->exists(tag)) { 325 res = metadata->erase(tag); 326 ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res); 327 } else { 328 res = OK; 329 ALOGV("%s: Don't need to erase", __FUNCTION__); 330 } 331 } else { 332 // Copy from java array into native array 333 ScopedByteArrayRO arrayReader(env, src); 334 if (arrayReader.get() == NULL) return; 335 336 res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag), 337 tagType, arrayReader.get(), arrayReader.size()); 338 339 ALOGV("%s: Update values (res = %d)", __FUNCTION__, res); 340 } 341 342 if (res == OK) { 343 return; 344 } else if (res == BAD_VALUE) { 345 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 346 "Src byte array was poorly formed"); 347 } else if (res == INVALID_OPERATION) { 348 jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 349 "Internal error while trying to update metadata"); 350 } else { 351 jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 352 "Unknown error (%d) while trying to update " 353 "metadata", res); 354 } 355 } 356 357 struct DumpMetadataParams { 358 int writeFd; 359 const CameraMetadata* metadata; 360 }; 361 362 static void* CameraMetadata_writeMetadataThread(void* arg) { 363 DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg); 364 365 /* 366 * Write the dumped data, and close the writing side FD. 367 */ 368 p->metadata->dump(p->writeFd, /*verbosity*/2); 369 370 if (close(p->writeFd) < 0) { 371 ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')", 372 __FUNCTION__, errno, strerror(errno)); 373 } 374 375 return NULL; 376 } 377 378 static void CameraMetadata_dump(JNIEnv *env, jobject thiz) { 379 ALOGV("%s", __FUNCTION__); 380 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 381 if (metadata == NULL) { 382 return; 383 } 384 385 /* 386 * Create a socket pair for local streaming read/writes. 387 * 388 * The metadata will be dumped into the write side, 389 * and then read back out (and logged) via the read side. 390 */ 391 392 int writeFd, readFd; 393 { 394 395 int sv[2]; 396 if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) { 397 jniThrowExceptionFmt(env, "java/io/IOException", 398 "Failed to create socketpair (errno = %#x, message = '%s')", 399 errno, strerror(errno)); 400 return; 401 } 402 writeFd = sv[0]; 403 readFd = sv[1]; 404 } 405 406 /* 407 * Create a thread for doing the writing. 408 * 409 * The reading and writing must be concurrent, otherwise 410 * the write will block forever once it exhausts the capped 411 * buffer size (from getsockopt). 412 */ 413 pthread_t writeThread; 414 DumpMetadataParams params = { 415 writeFd, 416 metadata 417 }; 418 419 { 420 int threadRet = pthread_create(&writeThread, /*attr*/NULL, 421 CameraMetadata_writeMetadataThread, (void*)¶ms); 422 423 if (threadRet != 0) { 424 close(writeFd); 425 426 jniThrowExceptionFmt(env, "java/io/IOException", 427 "Failed to create thread for writing (errno = %#x, message = '%s')", 428 threadRet, strerror(threadRet)); 429 } 430 } 431 432 /* 433 * Read out a byte until stream is complete. Write completed lines 434 * to ALOG. 435 */ 436 { 437 char out[] = {'\0', '\0'}; // large enough to append as a string 438 String8 logLine; 439 440 // Read one byte at a time! Very slow but avoids complicated \n scanning. 441 ssize_t res; 442 while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) { 443 if (out[0] == '\n') { 444 ALOGD("%s", logLine.string()); 445 logLine.clear(); 446 } else { 447 logLine.append(out); 448 } 449 } 450 451 if (res < 0) { 452 jniThrowExceptionFmt(env, "java/io/IOException", 453 "Failed to read from fd (errno = %#x, message = '%s')", 454 errno, strerror(errno)); 455 //return; 456 } else if (!logLine.isEmpty()) { 457 ALOGD("%s", logLine.string()); 458 } 459 } 460 461 int res; 462 463 // Join until thread finishes. Ensures params/metadata is valid until then. 464 if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) { 465 ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')", 466 __FUNCTION__, res, strerror(res)); 467 } 468 } 469 470 static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) { 471 ALOGV("%s", __FUNCTION__); 472 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 473 if (metadata == NULL) { 474 return; 475 } 476 477 Parcel* parcelNative = parcelForJavaObject(env, parcel); 478 if (parcelNative == NULL) { 479 jniThrowNullPointerException(env, "parcel"); 480 return; 481 } 482 483 status_t err; 484 if ((err = metadata->readFromParcel(parcelNative)) != OK) { 485 jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 486 "Failed to read from parcel (error code %d)", err); 487 return; 488 } 489 } 490 491 static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) { 492 ALOGV("%s", __FUNCTION__); 493 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz); 494 if (metadata == NULL) { 495 return; 496 } 497 498 Parcel* parcelNative = parcelForJavaObject(env, parcel); 499 if (parcelNative == NULL) { 500 jniThrowNullPointerException(env, "parcel"); 501 return; 502 } 503 504 status_t err; 505 if ((err = metadata->writeToParcel(parcelNative)) != OK) { 506 jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 507 "Failed to write to parcel (error code %d)", err); 508 return; 509 } 510 } 511 512 } // extern "C" 513 514 //------------------------------------------------- 515 516 static JNINativeMethod gCameraMetadataMethods[] = { 517 // static methods 518 { "nativeClassInit", 519 "()V", 520 (void *)CameraMetadata_classInit }, 521 { "nativeGetTagFromKey", 522 "(Ljava/lang/String;)I", 523 (void *)CameraMetadata_getTagFromKey }, 524 { "nativeGetTypeFromTag", 525 "(I)I", 526 (void *)CameraMetadata_getTypeFromTag }, 527 { "nativeSetupGlobalVendorTagDescriptor", 528 "()I", 529 (void*)CameraMetadata_setupGlobalVendorTagDescriptor }, 530 // instance methods 531 { "nativeAllocate", 532 "()J", 533 (void*)CameraMetadata_allocate }, 534 { "nativeAllocateCopy", 535 "(L" CAMERA_METADATA_CLASS_NAME ";)J", 536 (void *)CameraMetadata_allocateCopy }, 537 { "nativeIsEmpty", 538 "()Z", 539 (void*)CameraMetadata_isEmpty }, 540 { "nativeGetEntryCount", 541 "()I", 542 (void*)CameraMetadata_getEntryCount }, 543 { "nativeClose", 544 "()V", 545 (void*)CameraMetadata_close }, 546 { "nativeSwap", 547 "(L" CAMERA_METADATA_CLASS_NAME ";)V", 548 (void *)CameraMetadata_swap }, 549 { "nativeReadValues", 550 "(I)[B", 551 (void *)CameraMetadata_readValues }, 552 { "nativeWriteValues", 553 "(I[B)V", 554 (void *)CameraMetadata_writeValues }, 555 { "nativeDump", 556 "()V", 557 (void *)CameraMetadata_dump }, 558 // Parcelable interface 559 { "nativeReadFromParcel", 560 "(Landroid/os/Parcel;)V", 561 (void *)CameraMetadata_readFromParcel }, 562 { "nativeWriteToParcel", 563 "(Landroid/os/Parcel;)V", 564 (void *)CameraMetadata_writeToParcel }, 565 }; 566 567 struct field { 568 const char *class_name; 569 const char *field_name; 570 const char *field_type; 571 jfieldID *jfield; 572 }; 573 574 static int find_fields(JNIEnv *env, field *fields, int count) 575 { 576 for (int i = 0; i < count; i++) { 577 field *f = &fields[i]; 578 jclass clazz = env->FindClass(f->class_name); 579 if (clazz == NULL) { 580 ALOGE("Can't find %s", f->class_name); 581 return -1; 582 } 583 584 jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type); 585 if (field == NULL) { 586 ALOGE("Can't find %s.%s", f->class_name, f->field_name); 587 return -1; 588 } 589 590 *(f->jfield) = field; 591 } 592 593 return 0; 594 } 595 596 // Get all the required offsets in java class and register native functions 597 int register_android_hardware_camera2_CameraMetadata(JNIEnv *env) 598 { 599 // Register native functions 600 return AndroidRuntime::registerNativeMethods(env, 601 CAMERA_METADATA_CLASS_NAME, 602 gCameraMetadataMethods, 603 NELEM(gCameraMetadataMethods)); 604 } 605 606 extern "C" { 607 static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) { 608 // XX: Why do this separately instead of doing it in the register function? 609 ALOGV("%s", __FUNCTION__); 610 611 field fields_to_find[] = { 612 { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr }, 613 }; 614 615 // Do this here instead of in register_native_methods, 616 // since otherwise it will fail to find the fields. 617 if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0) 618 return; 619 620 jclass clazz = env->FindClass(CAMERA_METADATA_CLASS_NAME); 621 } 622 623 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) { 624 625 ScopedUtfChars keyScoped(env, keyName); 626 const char *key = keyScoped.c_str(); 627 if (key == NULL) { 628 // exception thrown by ScopedUtfChars 629 return 0; 630 } 631 size_t keyLength = strlen(key); 632 633 ALOGV("%s (key = '%s')", __FUNCTION__, key); 634 635 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor(); 636 637 SortedVector<String8> vendorSections; 638 size_t vendorSectionCount = 0; 639 640 if (vTags != NULL) { 641 vendorSections = vTags->getAllSectionNames(); 642 vendorSectionCount = vendorSections.size(); 643 } 644 645 // First, find the section by the longest string match 646 const char *section = NULL; 647 size_t sectionIndex = 0; 648 size_t sectionLength = 0; 649 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount; 650 for (size_t i = 0; i < totalSectionCount; ++i) { 651 652 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] : 653 vendorSections[i - ANDROID_SECTION_COUNT].string(); 654 ALOGVV("%s: Trying to match against section '%s'", 655 __FUNCTION__, str); 656 if (strstr(key, str) == key) { // key begins with the section name 657 size_t strLength = strlen(str); 658 659 ALOGVV("%s: Key begins with section name", __FUNCTION__); 660 661 // section name is the longest we've found so far 662 if (section == NULL || sectionLength < strLength) { 663 section = str; 664 sectionIndex = i; 665 sectionLength = strLength; 666 667 ALOGVV("%s: Found new best section (%s)", __FUNCTION__, section); 668 } 669 } 670 } 671 672 // TODO: Make above get_camera_metadata_section_from_name ? 673 674 if (section == NULL) { 675 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 676 "Could not find section name for key '%s')", key); 677 return 0; 678 } else { 679 ALOGV("%s: Found matched section '%s' (%d)", 680 __FUNCTION__, section, sectionIndex); 681 } 682 683 // Get the tag name component of the key 684 const char *keyTagName = key + sectionLength + 1; // x.y.z -> z 685 if (sectionLength + 1 >= keyLength) { 686 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 687 "Key length too short for key '%s')", key); 688 return 0; 689 } 690 691 // Match rest of name against the tag names in that section only 692 uint32_t tag = 0; 693 if (sectionIndex < ANDROID_SECTION_COUNT) { 694 // Match built-in tags (typically android.*) 695 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd) 696 tagBegin = camera_metadata_section_bounds[sectionIndex][0]; 697 tagEnd = camera_metadata_section_bounds[sectionIndex][1]; 698 699 for (tag = tagBegin; tag < tagEnd; ++tag) { 700 const char *tagName = get_camera_metadata_tag_name(tag); 701 702 if (strcmp(keyTagName, tagName) == 0) { 703 ALOGV("%s: Found matched tag '%s' (%d)", 704 __FUNCTION__, tagName, tag); 705 break; 706 } 707 } 708 709 if (tag == tagEnd) { 710 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 711 "Could not find tag name for key '%s')", key); 712 return 0; 713 } 714 } else if (vTags != NULL) { 715 // Match vendor tags (typically com.*) 716 const String8 sectionName(section); 717 const String8 tagName(keyTagName); 718 719 status_t res = OK; 720 if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) { 721 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 722 "%s: No vendor tag matches key '%s'", __FUNCTION__, key); 723 return 0; 724 } 725 } 726 727 // TODO: Make above get_camera_metadata_tag_from_name ? 728 729 return tag; 730 } 731 732 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) { 733 int tagType = get_camera_metadata_tag_type(tag); 734 if (tagType == -1) { 735 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 736 "Tag (%d) did not have a type", tag); 737 return -1; 738 } 739 740 return tagType; 741 } 742 743 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) { 744 const String16 NAME("media.camera"); 745 sp<ICameraService> cameraService; 746 status_t err = getService(NAME, /*out*/&cameraService); 747 748 if (err != OK) { 749 ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__, 750 strerror(-err), err); 751 return err; 752 } 753 754 sp<VendorTagDescriptor> desc; 755 err = cameraService->getCameraVendorTagDescriptor(/*out*/desc); 756 757 if (err == -EOPNOTSUPP) { 758 ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__); 759 VendorTagDescriptor::clearGlobalVendorTagDescriptor(); 760 761 return OK; 762 } else if (err != OK) { 763 ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)", 764 __FUNCTION__, strerror(-err), err); 765 return err; 766 } 767 768 err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc); 769 770 return err; 771 } 772 773 } // extern "C" 774