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__anon33e199430111::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__anon33e199430111::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 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_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__,
360 tag);
361 }
362 }
363
364 jsize byteCount = entry.count * tagSize;
365 jbyteArray byteArray = env->NewByteArray(byteCount);
366 if (env->ExceptionCheck()) return NULL;
367
368 // Copy into java array from native array
369 ScopedByteArrayRW arrayWriter(env, byteArray);
370 memcpy(arrayWriter.get(), entry.data.u8, byteCount);
371
372 return byteArray;
373 }
374
CameraMetadata_writeValues(JNIEnv * env,jclass thiz,jint tag,jbyteArray src,jlong ptr)375 static void CameraMetadata_writeValues(JNIEnv *env, jclass thiz, jint tag, jbyteArray src,
376 jlong ptr) {
377 ALOGV("%s (tag = %d)", __FUNCTION__, tag);
378
379 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
380 if (metadata == NULL) return;
381
382 const camera_metadata_t *metaBuffer = metadata->getAndLock();
383 int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
384 metadata->unlock(metaBuffer);
385 if (tagType == -1) {
386 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
387 "Tag (%d) did not have a type", tag);
388 return;
389 }
390
391 status_t res;
392
393 if (src == NULL) {
394 // If array is NULL, delete the entry
395 if (metadata->exists(tag)) {
396 res = metadata->erase(tag);
397 ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
398 } else {
399 res = OK;
400 ALOGV("%s: Don't need to erase", __FUNCTION__);
401 }
402 } else {
403 // Copy from java array into native array
404 ScopedByteArrayRO arrayReader(env, src);
405 if (arrayReader.get() == NULL) return;
406
407 res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
408 tagType, arrayReader.get(), arrayReader.size());
409
410 ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
411 }
412
413 if (res == OK) {
414 return;
415 } else if (res == BAD_VALUE) {
416 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
417 "Src byte array was poorly formed");
418 } else if (res == INVALID_OPERATION) {
419 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
420 "Internal error while trying to update metadata");
421 } else {
422 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
423 "Unknown error (%d) while trying to update "
424 "metadata", res);
425 }
426 }
427
428 struct DumpMetadataParams {
429 int writeFd;
430 const CameraMetadata* metadata;
431 };
432
CameraMetadata_writeMetadataThread(void * arg)433 static void* CameraMetadata_writeMetadataThread(void* arg) {
434 DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);
435
436 /*
437 * Write the dumped data, and close the writing side FD.
438 */
439 p->metadata->dump(p->writeFd, /*verbosity*/2);
440
441 if (close(p->writeFd) < 0) {
442 ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
443 __FUNCTION__, errno, strerror(errno));
444 }
445
446 return NULL;
447 }
448
CameraMetadata_dump(JNIEnv * env,jclass thiz,jlong ptr)449 static void CameraMetadata_dump(JNIEnv *env, jclass thiz, jlong ptr) {
450 ALOGV("%s", __FUNCTION__);
451 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
452 if (metadata == NULL) {
453 return;
454 }
455
456 /*
457 * Create a socket pair for local streaming read/writes.
458 *
459 * The metadata will be dumped into the write side,
460 * and then read back out (and logged) via the read side.
461 */
462
463 int writeFd, readFd;
464 {
465
466 int sv[2];
467 if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
468 jniThrowExceptionFmt(env, "java/io/IOException",
469 "Failed to create socketpair (errno = %#x, message = '%s')",
470 errno, strerror(errno));
471 return;
472 }
473 writeFd = sv[0];
474 readFd = sv[1];
475 }
476
477 /*
478 * Create a thread for doing the writing.
479 *
480 * The reading and writing must be concurrent, otherwise
481 * the write will block forever once it exhausts the capped
482 * buffer size (from getsockopt).
483 */
484 pthread_t writeThread;
485 DumpMetadataParams params = {
486 writeFd,
487 metadata
488 };
489
490 {
491 int threadRet = pthread_create(&writeThread, /*attr*/NULL,
492 CameraMetadata_writeMetadataThread, (void*)¶ms);
493
494 if (threadRet != 0) {
495 close(writeFd);
496 close(readFd);
497
498 jniThrowExceptionFmt(env, "java/io/IOException",
499 "Failed to create thread for writing (errno = %#x, message = '%s')",
500 threadRet, strerror(threadRet));
501 return;
502 }
503 }
504
505 /*
506 * Read out a byte until stream is complete. Write completed lines
507 * to ALOG.
508 */
509 {
510 char out[] = {'\0', '\0'}; // large enough to append as a string
511 String8 logLine;
512
513 // Read one byte at a time! Very slow but avoids complicated \n scanning.
514 ssize_t res;
515 while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
516 if (out[0] == '\n') {
517 ALOGD("%s", logLine.c_str());
518 logLine.clear();
519 } else {
520 logLine.append(out);
521 }
522 }
523
524 if (res < 0) {
525 jniThrowExceptionFmt(env, "java/io/IOException",
526 "Failed to read from fd (errno = %#x, message = '%s')",
527 errno, strerror(errno));
528 //return;
529 } else if (!logLine.empty()) {
530 ALOGD("%s", logLine.c_str());
531 }
532
533 close(readFd);
534 }
535
536 int res;
537
538 // Join until thread finishes. Ensures params/metadata is valid until then.
539 if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
540 ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
541 __FUNCTION__, res, strerror(res));
542 }
543 }
544
CameraMetadata_readFromParcel(JNIEnv * env,jclass thiz,jobject parcel,jlong ptr)545 static void CameraMetadata_readFromParcel(JNIEnv *env, jclass thiz, jobject parcel, jlong ptr) {
546 ALOGV("%s", __FUNCTION__);
547 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
548 if (metadata == NULL) {
549 return;
550 }
551
552 Parcel* parcelNative = parcelForJavaObject(env, parcel);
553 if (parcelNative == NULL) {
554 jniThrowNullPointerException(env, "parcel");
555 return;
556 }
557
558 status_t err;
559 if ((err = metadata->readFromParcel(parcelNative)) != OK) {
560 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
561 "Failed to read from parcel (error code %d)", err);
562 return;
563 }
564
565 // Update vendor descriptor cache if necessary
566 auto vendorId = metadata->getVendorId();
567 if ((vendorId != CAMERA_METADATA_INVALID_VENDOR_ID) &&
568 !VendorTagDescriptorCache::isVendorCachePresent(vendorId)) {
569 ALOGW("%s: Tag vendor id missing or cache not initialized, trying to update!",
570 __FUNCTION__);
571 CameraMetadata_setupGlobalVendorTagDescriptor(env, thiz);
572 }
573 }
574
CameraMetadata_writeToParcel(JNIEnv * env,jclass thiz,jobject parcel,jlong ptr)575 static void CameraMetadata_writeToParcel(JNIEnv *env, jclass thiz, jobject parcel, jlong ptr) {
576 ALOGV("%s", __FUNCTION__);
577 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
578 if (metadata == NULL) {
579 return;
580 }
581
582 Parcel* parcelNative = parcelForJavaObject(env, parcel);
583 if (parcelNative == NULL) {
584 jniThrowNullPointerException(env, "parcel");
585 return;
586 }
587
588 status_t err;
589 if ((err = metadata->writeToParcel(parcelNative)) != OK) {
590 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
591 "Failed to write to parcel (error code %d)", err);
592 return;
593 }
594 }
595
596 } // extern "C"
597
598 //-------------------------------------------------
599
600 static const JNINativeMethod gCameraMetadataMethods[] = {
601 // static methods
602 { "nativeSetVendorId",
603 "(JJ)V",
604 (void *)CameraMetadata_setVendorId },
605 { "nativeGetTagFromKey",
606 "(Ljava/lang/String;J)I",
607 (void *)CameraMetadata_getTagFromKey },
608 { "nativeGetTypeFromTag",
609 "(IJ)I",
610 (void *)CameraMetadata_getTypeFromTag },
611 { "nativeSetupGlobalVendorTagDescriptor",
612 "()I",
613 (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
614 // instance methods
615 { "nativeAllocate",
616 "()J",
617 (void*)CameraMetadata_allocate },
618 { "nativeAllocateCopy",
619 "(J)J",
620 (void *)CameraMetadata_allocateCopy },
621 { "nativeUpdate",
622 "(JJ)V",
623 (void*)CameraMetadata_update },
624 { "nativeIsEmpty",
625 "(J)Z",
626 (void*)CameraMetadata_isEmpty },
627 { "nativeGetEntryCount",
628 "(J)I",
629 (void*)CameraMetadata_getEntryCount },
630 { "nativeGetBufferSize",
631 "(J)J",
632 (void*)CameraMetadata_getBufferSize },
633 { "nativeClose",
634 "(J)V",
635 (void*)CameraMetadata_close },
636 { "nativeSwap",
637 "(JJ)V",
638 (void *)CameraMetadata_swap },
639 { "nativeGetTagFromKeyLocal",
640 "(JLjava/lang/String;)I",
641 (void *)CameraMetadata_getTagFromKeyLocal },
642 { "nativeGetTypeFromTagLocal",
643 "(JI)I",
644 (void *)CameraMetadata_getTypeFromTagLocal },
645 { "nativeReadValues",
646 "(IJ)[B",
647 (void *)CameraMetadata_readValues },
648 { "nativeWriteValues",
649 "(I[BJ)V",
650 (void *)CameraMetadata_writeValues },
651 { "nativeDump",
652 "(J)V",
653 (void *)CameraMetadata_dump },
654 { "nativeGetAllVendorKeys",
655 "(JLjava/lang/Class;)Ljava/util/ArrayList;",
656 (void *)CameraMetadata_getAllVendorKeys},
657 // Parcelable interface
658 { "nativeReadFromParcel",
659 "(Landroid/os/Parcel;J)V",
660 (void *)CameraMetadata_readFromParcel },
661 { "nativeWriteToParcel",
662 "(Landroid/os/Parcel;J)V",
663 (void *)CameraMetadata_writeToParcel },
664 };
665
666 // Get all the required offsets in java class and register native functions
register_android_hardware_camera2_CameraMetadata(JNIEnv * env)667 int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
668 {
669
670 // Store global references to Key-related classes and methods used natively
671 jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME);
672 jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME);
673 jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME);
674 gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz);
675 gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz);
676 gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
677 gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
678 gMetadataOffsets.mCharacteristicsKey, "<init>",
679 "(Ljava/lang/String;Ljava/lang/Class;J)V");
680 gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
681 gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
682 gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
683 gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
684
685 // Store global references for primitive array types used by Keys
686 jclass byteClazz = FindClassOrDie(env, "[B");
687 jclass int32Clazz = FindClassOrDie(env, "[I");
688 jclass floatClazz = FindClassOrDie(env, "[F");
689 jclass int64Clazz = FindClassOrDie(env, "[J");
690 jclass doubleClazz = FindClassOrDie(env, "[D");
691 jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;");
692 gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz);
693 gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz);
694 gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz);
695 gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz);
696 gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz);
697 gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz);
698
699 // Store global references for ArrayList methods used
700 jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList");
701 gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz);
702 gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
703 "<init>", "(I)V");
704 gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
705 "add", "(Ljava/lang/Object;)Z");
706
707 jclass cameraMetadataClazz = FindClassOrDie(env, CAMERA_METADATA_CLASS_NAME);
708 fields.metadata_ptr = GetFieldIDOrDie(env, cameraMetadataClazz, "mMetadataPtr", "J");
709
710 // Register native functions
711 return RegisterMethodsOrDie(env,
712 CAMERA_METADATA_CLASS_NAME,
713 gCameraMetadataMethods,
714 NELEM(gCameraMetadataMethods));
715 }
716
717 extern "C" {
718
CameraMetadata_getTypeFromTagLocal(JNIEnv * env,jclass thiz,jlong ptr,jint tag)719 static jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jclass thiz, jlong ptr, jint tag) {
720 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(ptr);
721 metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
722 if (metadata) {
723 vendorId = metadata->getVendorId();
724 }
725
726 int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
727 if (tagType == -1) {
728 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
729 "Tag (%d) did not have a type", tag);
730 return -1;
731 }
732
733 return tagType;
734 }
735
CameraMetadata_getTagFromKeyLocal(JNIEnv * env,jclass thiz,jlong ptr,jstring keyName)736 static jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jclass thiz, jlong ptr,
737 jstring keyName) {
738 ScopedUtfChars keyScoped(env, keyName);
739 const char *key = keyScoped.c_str();
740 if (key == NULL) {
741 // exception thrown by ScopedUtfChars
742 return 0;
743 }
744 ALOGV("%s (key = '%s')", __FUNCTION__, key);
745
746 uint32_t tag = 0;
747 sp<VendorTagDescriptor> vTags;
748 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(ptr);
749 if (metadata) {
750 sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
751 if (cache.get()) {
752 auto vendorId = metadata->getVendorId();
753 cache->getVendorTagDescriptor(vendorId, &vTags);
754 }
755 }
756
757 status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
758 if (res != OK) {
759 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
760 "Could not find tag for key '%s')", key);
761 }
762 return tag;
763 }
764
CameraMetadata_getAllVendorKeys(JNIEnv * env,jclass thiz,jlong ptr,jclass keyType)765 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jclass thiz, jlong ptr,
766 jclass keyType) {
767 metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
768 // Get all vendor tags
769 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
770 if (vTags.get() == nullptr) {
771 sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
772 if (cache.get() == nullptr) {
773 // No vendor tags.
774 return nullptr;
775 }
776
777 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
778 if (metadata == NULL) return NULL;
779
780 vendorId = metadata->getVendorId();
781 cache->getVendorTagDescriptor(vendorId, &vTags);
782 if (vTags.get() == nullptr) {
783 return nullptr;
784 }
785 }
786
787 int count = vTags->getTagCount();
788 if (count <= 0) {
789 // No vendor tags.
790 return NULL;
791 }
792
793 std::vector<uint32_t> tagIds(count, /*initializer value*/0);
794 vTags->getTagArray(&tagIds[0]);
795
796 // Which key class/constructor should we use?
797 jclass keyClazz;
798 jmethodID keyConstr;
799 if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) {
800 keyClazz = gMetadataOffsets.mCharacteristicsKey;
801 keyConstr = gMetadataOffsets.mCharacteristicsConstr;
802 } else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) {
803 keyClazz = gMetadataOffsets.mResultKey;
804 keyConstr = gMetadataOffsets.mResultConstr;
805 } else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) {
806 keyClazz = gMetadataOffsets.mRequestKey;
807 keyConstr = gMetadataOffsets.mRequestConstr;
808 } else {
809 jniThrowException(env, "java/lang/IllegalArgumentException",
810 "Invalid key class given as argument.");
811 return NULL;
812 }
813
814 // Allocate arrayList to return
815 jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList,
816 gMetadataOffsets.mArrayListConstr, static_cast<jint>(count));
817 if (env->ExceptionCheck()) {
818 return NULL;
819 }
820
821 for (uint32_t id : tagIds) {
822 const char* section = vTags->getSectionName(id);
823 const char* tag = vTags->getTagName(id);
824 int type = vTags->getTagType(id);
825
826 size_t totalLen = strlen(section) + strlen(tag) + 2;
827 std::vector<char> fullName(totalLen, 0);
828 snprintf(&fullName[0], totalLen, "%s.%s", section, tag);
829
830 jstring name = env->NewStringUTF(&fullName[0]);
831
832 if (env->ExceptionCheck()) {
833 return NULL;
834 }
835
836 jclass valueClazz;
837 switch (type) {
838 case TYPE_BYTE:
839 valueClazz = gMetadataOffsets.mByteArray;
840 break;
841 case TYPE_INT32:
842 valueClazz = gMetadataOffsets.mInt32Array;
843 break;
844 case TYPE_FLOAT:
845 valueClazz = gMetadataOffsets.mFloatArray;
846 break;
847 case TYPE_INT64:
848 valueClazz = gMetadataOffsets.mInt64Array;
849 break;
850 case TYPE_DOUBLE:
851 valueClazz = gMetadataOffsets.mDoubleArray;
852 break;
853 case TYPE_RATIONAL:
854 valueClazz = gMetadataOffsets.mRationalArray;
855 break;
856 default:
857 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
858 "Invalid type %d given for key %s", type, &fullName[0]);
859 return NULL;
860 }
861
862 jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz, vendorId);
863 if (env->ExceptionCheck()) {
864 return NULL;
865 }
866
867 env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key);
868 if (env->ExceptionCheck()) {
869 return NULL;
870 }
871
872 env->DeleteLocalRef(name);
873 env->DeleteLocalRef(key);
874 }
875
876 return arrayList;
877 }
878
CameraMetadata_setVendorId(JNIEnv * env,jclass thiz,jlong ptr,jlong vendorId)879 static void CameraMetadata_setVendorId(JNIEnv *env, jclass thiz, jlong ptr,
880 jlong vendorId) {
881 ALOGV("%s", __FUNCTION__);
882
883 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
884
885 if (metadata == NULL) {
886 ALOGW("%s: Returning early due to exception being thrown",
887 __FUNCTION__);
888 return;
889 }
890 if (metadata->isEmpty()) {
891 std::unique_ptr<CameraMetadata> emptyBuffer = std::make_unique<CameraMetadata>(10);
892 metadata->swap(*emptyBuffer);
893 }
894
895 camera_metadata_t *meta = const_cast<camera_metadata_t *>(metadata->getAndLock());
896 set_camera_metadata_vendor_id(meta, vendorId);
897 metadata->unlock(meta);
898 }
899
CameraMetadata_getTagFromKey(JNIEnv * env,jclass thiz,jstring keyName,jlong vendorId)900 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jclass thiz, jstring keyName,
901 jlong vendorId) {
902 ScopedUtfChars keyScoped(env, keyName);
903 const char *key = keyScoped.c_str();
904 if (key == NULL) {
905 // exception thrown by ScopedUtfChars
906 return 0;
907 }
908 ALOGV("%s (key = '%s')", __FUNCTION__, key);
909
910 uint32_t tag = 0;
911 sp<VendorTagDescriptor> vTags =
912 VendorTagDescriptor::getGlobalVendorTagDescriptor();
913 if (vTags.get() == nullptr) {
914 sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
915 if (cache.get() != nullptr) {
916 cache->getVendorTagDescriptor(vendorId, &vTags);
917 }
918 }
919
920 status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
921 if (res != OK) {
922 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
923 "Could not find tag for key '%s')", key);
924 }
925 return tag;
926 }
927
CameraMetadata_getTypeFromTag(JNIEnv * env,jclass thiz,jint tag,jlong vendorId)928 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jclass thiz, jint tag, jlong vendorId) {
929 int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
930 if (tagType == -1) {
931 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
932 "Tag (%d) did not have a type", tag);
933 return -1;
934 }
935
936 return tagType;
937 }
938
CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv * env,jclass thiz)939 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jclass thiz) {
940 const String16 NAME("media.camera");
941 sp<hardware::ICameraService> cameraService;
942 status_t err = getService(NAME, /*out*/&cameraService);
943
944 if (err != OK) {
945 ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
946 strerror(-err), err);
947 return hardware::ICameraService::ERROR_DISCONNECTED;
948 }
949
950 sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
951 binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
952
953 if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
954 // No camera module available, not an error on devices with no cameras
955 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
956 return OK;
957 } else if (!res.isOk()) {
958 VendorTagDescriptor::clearGlobalVendorTagDescriptor();
959 ALOGE("%s: Failed to setup vendor tag descriptors: %s", __FUNCTION__,
960 res.toString8().c_str());
961 return res.serviceSpecificErrorCode();
962 }
963 if (0 < desc->getTagCount()) {
964 err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
965 } else {
966 sp<VendorTagDescriptorCache> cache = new VendorTagDescriptorCache();
967 binder::Status res = cameraService->getCameraVendorTagCache(/*out*/cache.get());
968 if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
969 // No camera module available, not an error on devices with no cameras
970 VendorTagDescriptorCache::clearGlobalVendorTagCache();
971 return OK;
972 } else if (!res.isOk()) {
973 VendorTagDescriptorCache::clearGlobalVendorTagCache();
974 ALOGE("%s: Failed to setup vendor tag cache: %s", __FUNCTION__,
975 res.toString8().c_str());
976 return res.serviceSpecificErrorCode();
977 }
978
979 err = VendorTagDescriptorCache::setAsGlobalVendorTagCache(cache);
980 }
981
982 if (err != OK) {
983 return hardware::ICameraService::ERROR_INVALID_OPERATION;
984 }
985 return OK;
986 }
987
988 } // extern "C"
989