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