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 #include <memory>
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 <stdio.h>
28 #include <string.h>
29 #include <vector>
30
31 #include "jni.h"
32 #include <nativehelper/JNIHelp.h>
33 #include "android_os_Parcel.h"
34 #include "core_jni_helpers.h"
35 #include "android_runtime/android_hardware_camera2_CameraMetadata.h"
36
37 #include <android/hardware/ICameraService.h>
38 #include <binder/IServiceManager.h>
39 #include <camera/CameraMetadata.h>
40 #include <camera_metadata_hidden.h>
41 #include <camera/VendorTagDescriptor.h>
42 #include <nativehelper/ScopedUtfChars.h>
43 #include <nativehelper/ScopedPrimitiveArray.h>
44
45 #include <sys/types.h> // for socketpair
46 #include <sys/socket.h> // for socketpair
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
CameraMetadata_getNativeMetadata(JNIEnv * env,jobject thiz,CameraMetadata * metadata)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 auto nativePtr = reinterpret_cast<std::shared_ptr<CameraMetadata> *>(
94 env->GetLongField(thiz, 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->get());
100 return OK;
101 }
102
103 } /*namespace android*/
104
105 namespace {
106 struct Helpers {
getTypeSize__anon4ed3cf790111::Helpers107 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
updateAny__anon4ed3cf790111::Helpers116 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_setVendorId(JNIEnv* env, jclass thiz, jlong ptr,
167 jlong vendorId);
168 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jclass thiz, jlong ptr,
169 jclass keyType);
170 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jclass thiz, jstring keyName,
171 jlong vendorId);
172 static jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jclass thiz, jlong ptr,
173 jstring keyName);
174 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jclass thiz, jint tag, jlong vendorId);
175 static jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jclass thiz, jlong ptr, jint tag);
176 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jclass thiz);
177
CameraMetadata_getSharedPtr(jlong metadataLongPtr)178 static std::shared_ptr<CameraMetadata>* CameraMetadata_getSharedPtr(jlong metadataLongPtr) {
179 return reinterpret_cast<std::shared_ptr<CameraMetadata>* >(metadataLongPtr);
180 }
181
182 // Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
CameraMetadata_getPointerNoThrow(jlong ptr)183 static CameraMetadata* CameraMetadata_getPointerNoThrow(jlong ptr) {
184 auto metadata = CameraMetadata_getSharedPtr(ptr);
185 if (metadata == nullptr) {
186 return nullptr;
187 }
188 return metadata->get();
189 }
190
191 // Safe access to native pointer from object. Throws if not possible to access.
CameraMetadata_getPointerThrow(JNIEnv * env,jlong ptr,const char * argName="this")192 static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jlong ptr,
193 const char* argName = "this") {
194 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(ptr);
195 if (metadata == nullptr) {
196 ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
197 __FUNCTION__);
198 jniThrowException(env, "java/lang/IllegalStateException",
199 "Metadata object was already closed");
200 return nullptr;
201 }
202
203 return metadata;
204 }
205
CameraMetadata_allocate(JNIEnv * env,jclass thiz)206 static jlong CameraMetadata_allocate(JNIEnv *env, jclass thiz) {
207 ALOGV("%s", __FUNCTION__);
208
209 return reinterpret_cast<jlong>(new std::shared_ptr<CameraMetadata>(new CameraMetadata()));
210 }
211
CameraMetadata_allocateCopy(JNIEnv * env,jclass thiz,jlong other)212 static jlong CameraMetadata_allocateCopy(JNIEnv *env, jclass thiz, jlong other) {
213 ALOGV("%s", __FUNCTION__);
214
215 CameraMetadata* otherMetadata =
216 CameraMetadata_getPointerThrow(env, other);
217 // In case of exception, return
218 if (otherMetadata == NULL) return NULL;
219
220 // Clone native metadata and return new pointer.
221 auto clonedMetadata = new CameraMetadata(*otherMetadata);
222 return reinterpret_cast<jlong>(new std::shared_ptr<CameraMetadata>(clonedMetadata));
223 }
224
225
CameraMetadata_isEmpty(JNIEnv * env,jclass thiz,jlong ptr)226 static jboolean CameraMetadata_isEmpty(JNIEnv *env, jclass thiz, jlong ptr) {
227 ALOGV("%s", __FUNCTION__);
228
229 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
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
CameraMetadata_getEntryCount(JNIEnv * env,jclass thiz,jlong ptr)245 static jint CameraMetadata_getEntryCount(JNIEnv *env, jclass thiz, jlong ptr) {
246 ALOGV("%s", __FUNCTION__);
247
248 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
249
250 if (metadata == NULL) return 0; // actually throws java exc.
251
252 return metadata->entryCount();
253 }
254
CameraMetadata_update(JNIEnv * env,jclass thiz,jlong dst,jlong src)255 static void CameraMetadata_update(JNIEnv *env, jclass thiz, jlong dst, jlong src) {
256 ALOGV("%s", __FUNCTION__);
257
258 CameraMetadata* metadataDst = CameraMetadata_getPointerThrow(env, dst);
259 CameraMetadata* metadataSrc = CameraMetadata_getPointerThrow(env, src);
260
261 if (((metadataDst == NULL) || (metadataDst->isEmpty())) ||
262 ((metadataSrc == NULL) || metadataSrc->isEmpty())) {
263 return;
264 }
265
266 auto metaBuffer = metadataSrc->getAndLock();
267 camera_metadata_ro_entry_t entry;
268 auto entryCount = get_camera_metadata_entry_count(metaBuffer);
269 for (size_t i = 0; i < entryCount; i++) {
270 auto stat = get_camera_metadata_ro_entry(metaBuffer, i, &entry);
271 if (stat != NO_ERROR) {
272 ALOGE("%s: Failed to retrieve source metadata!", __func__);
273 metadataSrc->unlock(metaBuffer);
274 return;
275 }
276 switch (entry.type) {
277 case TYPE_BYTE:
278 metadataDst->update(entry.tag, entry.data.u8, entry.count);
279 break;
280 case TYPE_INT32:
281 metadataDst->update(entry.tag, entry.data.i32, entry.count);
282 break;
283 case TYPE_FLOAT:
284 metadataDst->update(entry.tag, entry.data.f, entry.count);
285 break;
286 case TYPE_INT64:
287 metadataDst->update(entry.tag, entry.data.i64, entry.count);
288 break;
289 case TYPE_DOUBLE:
290 metadataDst->update(entry.tag, entry.data.d, entry.count);
291 break;
292 case TYPE_RATIONAL:
293 metadataDst->update(entry.tag, entry.data.r, entry.count);
294 break;
295 default:
296 ALOGE("%s: Unsupported tag type: %d!", __func__, entry.type);
297 }
298 }
299 metadataSrc->unlock(metaBuffer);
300 }
301
CameraMetadata_getBufferSize(JNIEnv * env,jclass thiz,jlong ptr)302 static jlong CameraMetadata_getBufferSize(JNIEnv *env, jclass thiz, jlong ptr) {
303 ALOGV("%s", __FUNCTION__);
304
305 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
306
307 if (metadata == NULL) return 0;
308
309 return metadata->bufferSize();
310 }
311
312 // idempotent. calling more than once has no effect.
CameraMetadata_close(JNIEnv * env,jclass thiz,jlong ptr)313 static void CameraMetadata_close(JNIEnv *env, jclass thiz, jlong ptr) {
314 ALOGV("%s", __FUNCTION__);
315
316 auto metadata = CameraMetadata_getSharedPtr(ptr);
317 if (metadata != nullptr) {
318 delete metadata;
319 }
320 }
321
CameraMetadata_swap(JNIEnv * env,jclass thiz,jlong ptr,jlong other)322 static void CameraMetadata_swap(JNIEnv *env, jclass thiz, jlong ptr, jlong other) {
323 ALOGV("%s", __FUNCTION__);
324
325 auto metadata = CameraMetadata_getSharedPtr(ptr);
326 auto otherMetadata = CameraMetadata_getSharedPtr(other);
327
328 if (metadata == NULL) return;
329 if (otherMetadata == NULL) return;
330
331 // Need to swap shared pointers, not CameraMetadata, since the latter may be in use
332 // by an NDK client, and we don't want to swap their data out from under them.
333 metadata->swap(*otherMetadata);
334 }
335
CameraMetadata_readValues(JNIEnv * env,jclass thiz,jint tag,jlong ptr)336 static jbyteArray CameraMetadata_readValues(JNIEnv *env, jclass thiz, jint tag, jlong ptr) {
337 ALOGV("%s (tag = %d)", __FUNCTION__, tag);
338
339 const CameraMetadata *metadata = CameraMetadata_getPointerThrow(env, ptr);
340 if (metadata == NULL) return NULL;
341
342 const camera_metadata_t *metaBuffer = metadata->getAndLock();
343 int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
344 metadata->unlock(metaBuffer);
345 if (tagType == -1) {
346 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
347 "Tag (%d) did not have a type", tag);
348 return NULL;
349 }
350 size_t tagSize = Helpers::getTypeSize(tagType);
351
352 camera_metadata_ro_entry entry = metadata->find(tag);
353 if (entry.count == 0) {
354 if (!metadata->exists(tag)) {
355 ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
356 return NULL;
357 } else {
358 // OK: we will return a 0-sized array.
359 ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__, tag);
360 }
361 }
362
363 jsize byteCount = entry.count * tagSize;
364 jbyteArray byteArray = env->NewByteArray(byteCount);
365 if (env->ExceptionCheck()) return NULL;
366
367 // Copy into java array from native array
368 ScopedByteArrayRW arrayWriter(env, byteArray);
369 memcpy(arrayWriter.get(), entry.data.u8, byteCount);
370
371 return byteArray;
372 }
373
CameraMetadata_writeValues(JNIEnv * env,jclass thiz,jint tag,jbyteArray src,jlong ptr)374 static void CameraMetadata_writeValues(JNIEnv *env, jclass thiz, jint tag, jbyteArray src,
375 jlong ptr) {
376 ALOGV("%s (tag = %d)", __FUNCTION__, tag);
377
378 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
379 if (metadata == NULL) return;
380
381 const camera_metadata_t *metaBuffer = metadata->getAndLock();
382 int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
383 metadata->unlock(metaBuffer);
384 if (tagType == -1) {
385 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
386 "Tag (%d) did not have a type", tag);
387 return;
388 }
389
390 status_t res;
391
392 if (src == NULL) {
393 // If array is NULL, delete the entry
394 if (metadata->exists(tag)) {
395 res = metadata->erase(tag);
396 ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
397 } else {
398 res = OK;
399 ALOGV("%s: Don't need to erase", __FUNCTION__);
400 }
401 } else {
402 // Copy from java array into native array
403 ScopedByteArrayRO arrayReader(env, src);
404 if (arrayReader.get() == NULL) return;
405
406 res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
407 tagType, arrayReader.get(), arrayReader.size());
408
409 ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
410 }
411
412 if (res == OK) {
413 return;
414 } else if (res == BAD_VALUE) {
415 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
416 "Src byte array was poorly formed");
417 } else if (res == INVALID_OPERATION) {
418 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
419 "Internal error while trying to update metadata");
420 } else {
421 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
422 "Unknown error (%d) while trying to update "
423 "metadata", res);
424 }
425 }
426
427 struct DumpMetadataParams {
428 int writeFd;
429 const CameraMetadata* metadata;
430 };
431
CameraMetadata_writeMetadataThread(void * arg)432 static void* CameraMetadata_writeMetadataThread(void* arg) {
433 DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);
434
435 /*
436 * Write the dumped data, and close the writing side FD.
437 */
438 p->metadata->dump(p->writeFd, /*verbosity*/2);
439
440 if (close(p->writeFd) < 0) {
441 ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
442 __FUNCTION__, errno, strerror(errno));
443 }
444
445 return NULL;
446 }
447
CameraMetadata_dump(JNIEnv * env,jclass thiz,jlong ptr)448 static void CameraMetadata_dump(JNIEnv *env, jclass thiz, jlong ptr) {
449 ALOGV("%s", __FUNCTION__);
450 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
451 if (metadata == NULL) {
452 return;
453 }
454
455 /*
456 * Create a socket pair for local streaming read/writes.
457 *
458 * The metadata will be dumped into the write side,
459 * and then read back out (and logged) via the read side.
460 */
461
462 int writeFd, readFd;
463 {
464
465 int sv[2];
466 if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
467 jniThrowExceptionFmt(env, "java/io/IOException",
468 "Failed to create socketpair (errno = %#x, message = '%s')",
469 errno, strerror(errno));
470 return;
471 }
472 writeFd = sv[0];
473 readFd = sv[1];
474 }
475
476 /*
477 * Create a thread for doing the writing.
478 *
479 * The reading and writing must be concurrent, otherwise
480 * the write will block forever once it exhausts the capped
481 * buffer size (from getsockopt).
482 */
483 pthread_t writeThread;
484 DumpMetadataParams params = {
485 writeFd,
486 metadata
487 };
488
489 {
490 int threadRet = pthread_create(&writeThread, /*attr*/NULL,
491 CameraMetadata_writeMetadataThread, (void*)¶ms);
492
493 if (threadRet != 0) {
494 close(writeFd);
495 close(readFd);
496
497 jniThrowExceptionFmt(env, "java/io/IOException",
498 "Failed to create thread for writing (errno = %#x, message = '%s')",
499 threadRet, strerror(threadRet));
500 return;
501 }
502 }
503
504 /*
505 * Read out a byte until stream is complete. Write completed lines
506 * to ALOG.
507 */
508 {
509 char out[] = {'\0', '\0'}; // large enough to append as a string
510 String8 logLine;
511
512 // Read one byte at a time! Very slow but avoids complicated \n scanning.
513 ssize_t res;
514 while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
515 if (out[0] == '\n') {
516 ALOGD("%s", logLine.c_str());
517 logLine.clear();
518 } else {
519 logLine.append(out);
520 }
521 }
522
523 if (res < 0) {
524 jniThrowExceptionFmt(env, "java/io/IOException",
525 "Failed to read from fd (errno = %#x, message = '%s')",
526 errno, strerror(errno));
527 //return;
528 } else if (!logLine.empty()) {
529 ALOGD("%s", logLine.c_str());
530 }
531
532 close(readFd);
533 }
534
535 int res;
536
537 // Join until thread finishes. Ensures params/metadata is valid until then.
538 if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
539 ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
540 __FUNCTION__, res, strerror(res));
541 }
542 }
543
CameraMetadata_readFromParcel(JNIEnv * env,jclass thiz,jobject parcel,jlong ptr)544 static void CameraMetadata_readFromParcel(JNIEnv *env, jclass thiz, jobject parcel, jlong ptr) {
545 ALOGV("%s", __FUNCTION__);
546 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
547 if (metadata == NULL) {
548 return;
549 }
550
551 Parcel* parcelNative = parcelForJavaObject(env, parcel);
552 if (parcelNative == NULL) {
553 jniThrowNullPointerException(env, "parcel");
554 return;
555 }
556
557 status_t err;
558 if ((err = metadata->readFromParcel(parcelNative)) != OK) {
559 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
560 "Failed to read from parcel (error code %d)", err);
561 return;
562 }
563
564 // Update vendor descriptor cache if necessary
565 auto vendorId = metadata->getVendorId();
566 if ((vendorId != CAMERA_METADATA_INVALID_VENDOR_ID) &&
567 !VendorTagDescriptorCache::isVendorCachePresent(vendorId)) {
568 ALOGW("%s: Tag vendor id missing or cache not initialized, trying to update!",
569 __FUNCTION__);
570 CameraMetadata_setupGlobalVendorTagDescriptor(env, thiz);
571 }
572 }
573
CameraMetadata_writeToParcel(JNIEnv * env,jclass thiz,jobject parcel,jlong ptr)574 static void CameraMetadata_writeToParcel(JNIEnv *env, jclass thiz, jobject parcel, jlong ptr) {
575 ALOGV("%s", __FUNCTION__);
576 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
577 if (metadata == NULL) {
578 return;
579 }
580
581 Parcel* parcelNative = parcelForJavaObject(env, parcel);
582 if (parcelNative == NULL) {
583 jniThrowNullPointerException(env, "parcel");
584 return;
585 }
586
587 status_t err;
588 if ((err = metadata->writeToParcel(parcelNative)) != OK) {
589 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
590 "Failed to write to parcel (error code %d)", err);
591 return;
592 }
593 }
594
595 } // extern "C"
596
597 //-------------------------------------------------
598
599 static const JNINativeMethod gCameraMetadataMethods[] = {
600 // static methods
601 { "nativeSetVendorId",
602 "(JJ)V",
603 (void *)CameraMetadata_setVendorId },
604 { "nativeGetTagFromKey",
605 "(Ljava/lang/String;J)I",
606 (void *)CameraMetadata_getTagFromKey },
607 { "nativeGetTypeFromTag",
608 "(IJ)I",
609 (void *)CameraMetadata_getTypeFromTag },
610 { "nativeSetupGlobalVendorTagDescriptor",
611 "()I",
612 (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
613 // instance methods
614 { "nativeAllocate",
615 "()J",
616 (void*)CameraMetadata_allocate },
617 { "nativeAllocateCopy",
618 "(J)J",
619 (void *)CameraMetadata_allocateCopy },
620 { "nativeUpdate",
621 "(JJ)V",
622 (void*)CameraMetadata_update },
623 { "nativeIsEmpty",
624 "(J)Z",
625 (void*)CameraMetadata_isEmpty },
626 { "nativeGetEntryCount",
627 "(J)I",
628 (void*)CameraMetadata_getEntryCount },
629 { "nativeGetBufferSize",
630 "(J)J",
631 (void*)CameraMetadata_getBufferSize },
632 { "nativeClose",
633 "(J)V",
634 (void*)CameraMetadata_close },
635 { "nativeSwap",
636 "(JJ)V",
637 (void *)CameraMetadata_swap },
638 { "nativeGetTagFromKeyLocal",
639 "(JLjava/lang/String;)I",
640 (void *)CameraMetadata_getTagFromKeyLocal },
641 { "nativeGetTypeFromTagLocal",
642 "(JI)I",
643 (void *)CameraMetadata_getTypeFromTagLocal },
644 { "nativeReadValues",
645 "(IJ)[B",
646 (void *)CameraMetadata_readValues },
647 { "nativeWriteValues",
648 "(I[BJ)V",
649 (void *)CameraMetadata_writeValues },
650 { "nativeDump",
651 "(J)V",
652 (void *)CameraMetadata_dump },
653 { "nativeGetAllVendorKeys",
654 "(JLjava/lang/Class;)Ljava/util/ArrayList;",
655 (void *)CameraMetadata_getAllVendorKeys},
656 // Parcelable interface
657 { "nativeReadFromParcel",
658 "(Landroid/os/Parcel;J)V",
659 (void *)CameraMetadata_readFromParcel },
660 { "nativeWriteToParcel",
661 "(Landroid/os/Parcel;J)V",
662 (void *)CameraMetadata_writeToParcel },
663 };
664
665 // Get all the required offsets in java class and register native functions
register_android_hardware_camera2_CameraMetadata(JNIEnv * env)666 int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
667 {
668
669 // Store global references to Key-related classes and methods used natively
670 jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME);
671 jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME);
672 jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME);
673 gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz);
674 gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz);
675 gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
676 gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
677 gMetadataOffsets.mCharacteristicsKey, "<init>",
678 "(Ljava/lang/String;Ljava/lang/Class;J)V");
679 gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
680 gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
681 gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
682 gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
683
684 // Store global references for primitive array types used by Keys
685 jclass byteClazz = FindClassOrDie(env, "[B");
686 jclass int32Clazz = FindClassOrDie(env, "[I");
687 jclass floatClazz = FindClassOrDie(env, "[F");
688 jclass int64Clazz = FindClassOrDie(env, "[J");
689 jclass doubleClazz = FindClassOrDie(env, "[D");
690 jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;");
691 gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz);
692 gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz);
693 gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz);
694 gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz);
695 gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz);
696 gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz);
697
698 // Store global references for ArrayList methods used
699 jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList");
700 gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz);
701 gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
702 "<init>", "(I)V");
703 gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
704 "add", "(Ljava/lang/Object;)Z");
705
706 jclass cameraMetadataClazz = FindClassOrDie(env, CAMERA_METADATA_CLASS_NAME);
707 fields.metadata_ptr = GetFieldIDOrDie(env, cameraMetadataClazz, "mMetadataPtr", "J");
708
709 // Register native functions
710 return RegisterMethodsOrDie(env,
711 CAMERA_METADATA_CLASS_NAME,
712 gCameraMetadataMethods,
713 NELEM(gCameraMetadataMethods));
714 }
715
716 extern "C" {
717
CameraMetadata_getTypeFromTagLocal(JNIEnv * env,jclass thiz,jlong ptr,jint tag)718 static jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jclass thiz, jlong ptr, jint tag) {
719 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(ptr);
720 metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
721 if (metadata) {
722 vendorId = metadata->getVendorId();
723 }
724
725 int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
726 if (tagType == -1) {
727 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
728 "Tag (%d) did not have a type", tag);
729 return -1;
730 }
731
732 return tagType;
733 }
734
CameraMetadata_getTagFromKeyLocal(JNIEnv * env,jclass thiz,jlong ptr,jstring keyName)735 static jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jclass thiz, jlong ptr,
736 jstring keyName) {
737 ScopedUtfChars keyScoped(env, keyName);
738 const char *key = keyScoped.c_str();
739 if (key == NULL) {
740 // exception thrown by ScopedUtfChars
741 return 0;
742 }
743 ALOGV("%s (key = '%s')", __FUNCTION__, key);
744
745 uint32_t tag = 0;
746 sp<VendorTagDescriptor> vTags;
747 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(ptr);
748 if (metadata) {
749 sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
750 if (cache.get()) {
751 auto vendorId = metadata->getVendorId();
752 cache->getVendorTagDescriptor(vendorId, &vTags);
753 }
754 }
755
756 status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
757 if (res != OK) {
758 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
759 "Could not find tag for key '%s')", key);
760 }
761 return tag;
762 }
763
CameraMetadata_getAllVendorKeys(JNIEnv * env,jclass thiz,jlong ptr,jclass keyType)764 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jclass thiz, jlong ptr,
765 jclass keyType) {
766 metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
767 // Get all vendor tags
768 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
769 if (vTags.get() == nullptr) {
770 sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
771 if (cache.get() == nullptr) {
772 // No vendor tags.
773 return nullptr;
774 }
775
776 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
777 if (metadata == NULL) return NULL;
778
779 vendorId = metadata->getVendorId();
780 cache->getVendorTagDescriptor(vendorId, &vTags);
781 if (vTags.get() == nullptr) {
782 return nullptr;
783 }
784 }
785
786 int count = vTags->getTagCount();
787 if (count <= 0) {
788 // No vendor tags.
789 return NULL;
790 }
791
792 std::vector<uint32_t> tagIds(count, /*initializer value*/0);
793 vTags->getTagArray(&tagIds[0]);
794
795 // Which key class/constructor should we use?
796 jclass keyClazz;
797 jmethodID keyConstr;
798 if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) {
799 keyClazz = gMetadataOffsets.mCharacteristicsKey;
800 keyConstr = gMetadataOffsets.mCharacteristicsConstr;
801 } else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) {
802 keyClazz = gMetadataOffsets.mResultKey;
803 keyConstr = gMetadataOffsets.mResultConstr;
804 } else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) {
805 keyClazz = gMetadataOffsets.mRequestKey;
806 keyConstr = gMetadataOffsets.mRequestConstr;
807 } else {
808 jniThrowException(env, "java/lang/IllegalArgumentException",
809 "Invalid key class given as argument.");
810 return NULL;
811 }
812
813 // Allocate arrayList to return
814 jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList,
815 gMetadataOffsets.mArrayListConstr, static_cast<jint>(count));
816 if (env->ExceptionCheck()) {
817 return NULL;
818 }
819
820 for (uint32_t id : tagIds) {
821 const char* section = vTags->getSectionName(id);
822 const char* tag = vTags->getTagName(id);
823 int type = vTags->getTagType(id);
824
825 size_t totalLen = strlen(section) + strlen(tag) + 2;
826 std::vector<char> fullName(totalLen, 0);
827 snprintf(&fullName[0], totalLen, "%s.%s", section, tag);
828
829 jstring name = env->NewStringUTF(&fullName[0]);
830
831 if (env->ExceptionCheck()) {
832 return NULL;
833 }
834
835 jclass valueClazz;
836 switch (type) {
837 case TYPE_BYTE:
838 valueClazz = gMetadataOffsets.mByteArray;
839 break;
840 case TYPE_INT32:
841 valueClazz = gMetadataOffsets.mInt32Array;
842 break;
843 case TYPE_FLOAT:
844 valueClazz = gMetadataOffsets.mFloatArray;
845 break;
846 case TYPE_INT64:
847 valueClazz = gMetadataOffsets.mInt64Array;
848 break;
849 case TYPE_DOUBLE:
850 valueClazz = gMetadataOffsets.mDoubleArray;
851 break;
852 case TYPE_RATIONAL:
853 valueClazz = gMetadataOffsets.mRationalArray;
854 break;
855 default:
856 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
857 "Invalid type %d given for key %s", type, &fullName[0]);
858 return NULL;
859 }
860
861 jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz, vendorId);
862 if (env->ExceptionCheck()) {
863 return NULL;
864 }
865
866 env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key);
867 if (env->ExceptionCheck()) {
868 return NULL;
869 }
870
871 env->DeleteLocalRef(name);
872 env->DeleteLocalRef(key);
873 }
874
875 return arrayList;
876 }
877
CameraMetadata_setVendorId(JNIEnv * env,jclass thiz,jlong ptr,jlong vendorId)878 static void CameraMetadata_setVendorId(JNIEnv *env, jclass thiz, jlong ptr,
879 jlong vendorId) {
880 ALOGV("%s", __FUNCTION__);
881
882 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
883
884 if (metadata == NULL) {
885 ALOGW("%s: Returning early due to exception being thrown",
886 __FUNCTION__);
887 return;
888 }
889 if (metadata->isEmpty()) {
890 std::unique_ptr<CameraMetadata> emptyBuffer = std::make_unique<CameraMetadata>(10);
891 metadata->swap(*emptyBuffer);
892 }
893
894 camera_metadata_t *meta = const_cast<camera_metadata_t *>(metadata->getAndLock());
895 set_camera_metadata_vendor_id(meta, vendorId);
896 metadata->unlock(meta);
897 }
898
CameraMetadata_getTagFromKey(JNIEnv * env,jclass thiz,jstring keyName,jlong vendorId)899 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jclass thiz, jstring keyName,
900 jlong vendorId) {
901 ScopedUtfChars keyScoped(env, keyName);
902 const char *key = keyScoped.c_str();
903 if (key == NULL) {
904 // exception thrown by ScopedUtfChars
905 return 0;
906 }
907 ALOGV("%s (key = '%s')", __FUNCTION__, key);
908
909 uint32_t tag = 0;
910 sp<VendorTagDescriptor> vTags =
911 VendorTagDescriptor::getGlobalVendorTagDescriptor();
912 if (vTags.get() == nullptr) {
913 sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
914 if (cache.get() != nullptr) {
915 cache->getVendorTagDescriptor(vendorId, &vTags);
916 }
917 }
918
919 status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
920 if (res != OK) {
921 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
922 "Could not find tag for key '%s')", key);
923 }
924 return tag;
925 }
926
CameraMetadata_getTypeFromTag(JNIEnv * env,jclass thiz,jint tag,jlong vendorId)927 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jclass thiz, jint tag, jlong vendorId) {
928 int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
929 if (tagType == -1) {
930 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
931 "Tag (%d) did not have a type", tag);
932 return -1;
933 }
934
935 return tagType;
936 }
937
CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv * env,jclass thiz)938 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jclass thiz) {
939 const String16 NAME("media.camera");
940 sp<hardware::ICameraService> cameraService;
941 status_t err = getService(NAME, /*out*/&cameraService);
942
943 if (err != OK) {
944 ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
945 strerror(-err), err);
946 return hardware::ICameraService::ERROR_DISCONNECTED;
947 }
948
949 sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
950 binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
951
952 if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
953 // No camera module available, not an error on devices with no cameras
954 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
955 return OK;
956 } else if (!res.isOk()) {
957 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
958 ALOGE("%s: Failed to setup vendor tag descriptors: %s", __FUNCTION__,
959 res.toString8().c_str());
960 return res.serviceSpecificErrorCode();
961 }
962 if (0 < desc->getTagCount()) {
963 err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
964 } else {
965 sp<VendorTagDescriptorCache> cache = new VendorTagDescriptorCache();
966 binder::Status res = cameraService->getCameraVendorTagCache(/*out*/cache.get());
967 if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
968 // No camera module available, not an error on devices with no cameras
969 VendorTagDescriptorCache::clearGlobalVendorTagCache();
970 return OK;
971 } else if (!res.isOk()) {
972 VendorTagDescriptorCache::clearGlobalVendorTagCache();
973 ALOGE("%s: Failed to setup vendor tag cache: %s", __FUNCTION__,
974 res.toString8().c_str());
975 return res.serviceSpecificErrorCode();
976 }
977
978 err = VendorTagDescriptorCache::setAsGlobalVendorTagCache(cache);
979 }
980
981 if (err != OK) {
982 return hardware::ICameraService::ERROR_INVALID_OPERATION;
983 }
984 return OK;
985 }
986
987 } // extern "C"
988