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