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