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 #undef ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION // TODO:remove this and fix code
18
19 // #define LOG_NDEBUG 0
20 #include <memory>
21 #define LOG_TAG "CameraMetadata-JNI"
22 #include <utils/Errors.h>
23 #include <utils/Log.h>
24 #include <utils/RefBase.h>
25 #include <utils/Vector.h>
26 #include <utils/SortedVector.h>
27 #include <utils/KeyedVector.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <vector>
31
32 #include "jni.h"
33 #include <nativehelper/JNIHelp.h>
34 #include "android_os_Parcel.h"
35 #include "core_jni_helpers.h"
36 #include "android_runtime/android_hardware_camera2_CameraMetadata.h"
37
38 #include <android/hardware/ICameraService.h>
39 #include <binder/IServiceManager.h>
40 #include <camera/CameraMetadata.h>
41 #include <camera_metadata_hidden.h>
42 #include <camera/VendorTagDescriptor.h>
43 #include <nativehelper/ScopedUtfChars.h>
44 #include <nativehelper/ScopedPrimitiveArray.h>
45
46 #include <sys/types.h> // for socketpair
47 #include <sys/socket.h> // for socketpair
48
49 // fully-qualified class name
50 #define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
51 #define CHARACTERISTICS_KEY_CLASS_NAME "android/hardware/camera2/CameraCharacteristics$Key"
52 #define REQUEST_KEY_CLASS_NAME "android/hardware/camera2/CaptureRequest$Key"
53 #define RESULT_KEY_CLASS_NAME "android/hardware/camera2/CaptureResult$Key"
54
55 using namespace android;
56
57 static struct metadata_java_key_offsets_t {
58 jclass mCharacteristicsKey;
59 jclass mResultKey;
60 jclass mRequestKey;
61 jmethodID mCharacteristicsConstr;
62 jmethodID mResultConstr;
63 jmethodID mRequestConstr;
64 jclass mByteArray;
65 jclass mInt32Array;
66 jclass mFloatArray;
67 jclass mInt64Array;
68 jclass mDoubleArray;
69 jclass mRationalArray;
70 jclass mArrayList;
71 jmethodID mArrayListConstr;
72 jmethodID mArrayListAdd;
73 } gMetadataOffsets;
74
75 struct fields_t {
76 jfieldID metadata_ptr;
77 };
78
79 static fields_t fields;
80
81 namespace android {
82
CameraMetadata_getNativeMetadata(JNIEnv * env,jobject thiz,CameraMetadata * metadata)83 status_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
84 /*out*/CameraMetadata* metadata) {
85 if (!thiz) {
86 ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
87 return BAD_VALUE;
88 }
89
90 if (!metadata) {
91 ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
92 return BAD_VALUE;
93 }
94 auto nativePtr = reinterpret_cast<std::shared_ptr<CameraMetadata> *>(
95 env->GetLongField(thiz, fields.metadata_ptr));
96 if (nativePtr == NULL) {
97 ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
98 return BAD_VALUE;
99 }
100 *metadata = *(nativePtr->get());
101 return OK;
102 }
103
104 } /*namespace android*/
105
106 namespace {
107 struct Helpers {
getTypeSize__anonc6fc29f90111::Helpers108 static size_t getTypeSize(uint8_t type) {
109 if (type >= NUM_TYPES) {
110 ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
111 return static_cast<size_t>(-1);
112 }
113
114 return camera_metadata_type_size[type];
115 }
116
updateAny__anonc6fc29f90111::Helpers117 static status_t updateAny(CameraMetadata *metadata,
118 uint32_t tag,
119 uint32_t type,
120 const void *data,
121 size_t dataBytes) {
122
123 if (type >= NUM_TYPES) {
124 ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
125 return INVALID_OPERATION;
126 }
127
128 size_t typeSize = getTypeSize(type);
129
130 if (dataBytes % typeSize != 0) {
131 ALOGE("%s: Expected dataBytes (%zu) to be divisible by typeSize "
132 "(%zu)", __FUNCTION__, dataBytes, typeSize);
133 return BAD_VALUE;
134 }
135
136 size_t dataCount = dataBytes / typeSize;
137
138 switch(type) {
139 #define METADATA_UPDATE(runtime_type, compile_type) \
140 case runtime_type: { \
141 const compile_type *dataPtr = \
142 static_cast<const compile_type*>(data); \
143 return metadata->update(tag, dataPtr, dataCount); \
144 } \
145
146 METADATA_UPDATE(TYPE_BYTE, uint8_t);
147 METADATA_UPDATE(TYPE_INT32, int32_t);
148 METADATA_UPDATE(TYPE_FLOAT, float);
149 METADATA_UPDATE(TYPE_INT64, int64_t);
150 METADATA_UPDATE(TYPE_DOUBLE, double);
151 METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);
152
153 default: {
154 // unreachable
155 ALOGE("%s: Unreachable", __FUNCTION__);
156 return INVALID_OPERATION;
157 }
158 }
159
160 #undef METADATA_UPDATE
161 }
162 };
163 } // namespace {}
164
165 extern "C" {
166
167 static void CameraMetadata_setVendorId(JNIEnv* env, jclass thiz, jlong ptr,
168 jlong vendorId);
169 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jclass thiz, jlong ptr,
170 jclass keyType);
171 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jclass thiz, jstring keyName,
172 jlong vendorId);
173 static jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jclass thiz, jlong ptr,
174 jstring keyName);
175 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jclass thiz, jint tag, jlong vendorId);
176 static jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jclass thiz, jlong ptr, jint tag);
177 static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jclass thiz);
178
CameraMetadata_getSharedPtr(jlong metadataLongPtr)179 static std::shared_ptr<CameraMetadata>* CameraMetadata_getSharedPtr(jlong metadataLongPtr) {
180 return reinterpret_cast<std::shared_ptr<CameraMetadata>* >(metadataLongPtr);
181 }
182
183 // Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
CameraMetadata_getPointerNoThrow(jlong ptr)184 static CameraMetadata* CameraMetadata_getPointerNoThrow(jlong ptr) {
185 auto metadata = CameraMetadata_getSharedPtr(ptr);
186 if (metadata == nullptr) {
187 return nullptr;
188 }
189 return metadata->get();
190 }
191
192 // Safe access to native pointer from object. Throws if not possible to access.
CameraMetadata_getPointerThrow(JNIEnv * env,jlong ptr,const char * argName="this")193 static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jlong ptr,
194 const char* argName = "this") {
195 CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(ptr);
196 if (metadata == nullptr) {
197 ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
198 __FUNCTION__);
199 jniThrowException(env, "java/lang/IllegalStateException",
200 "Metadata object was already closed");
201 return nullptr;
202 }
203
204 return metadata;
205 }
206
CameraMetadata_allocate(JNIEnv * env,jclass thiz)207 static jlong CameraMetadata_allocate(JNIEnv *env, jclass thiz) {
208 ALOGV("%s", __FUNCTION__);
209
210 return reinterpret_cast<jlong>(new std::shared_ptr<CameraMetadata>(new CameraMetadata()));
211 }
212
CameraMetadata_allocateCopy(JNIEnv * env,jclass thiz,jlong other)213 static jlong CameraMetadata_allocateCopy(JNIEnv *env, jclass thiz, jlong other) {
214 ALOGV("%s", __FUNCTION__);
215
216 CameraMetadata* otherMetadata =
217 CameraMetadata_getPointerThrow(env, other);
218 // In case of exception, return
219 if (otherMetadata == NULL) return NULL;
220
221 // Clone native metadata and return new pointer.
222 auto clonedMetadata = new CameraMetadata(*otherMetadata);
223 return reinterpret_cast<jlong>(new std::shared_ptr<CameraMetadata>(clonedMetadata));
224 }
225
226
CameraMetadata_isEmpty(JNIEnv * env,jclass thiz,jlong ptr)227 static jboolean CameraMetadata_isEmpty(JNIEnv *env, jclass thiz, jlong ptr) {
228 ALOGV("%s", __FUNCTION__);
229
230 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
231
232 if (metadata == NULL) {
233 ALOGW("%s: Returning early due to exception being thrown",
234 __FUNCTION__);
235 return JNI_TRUE; // actually throws java exc.
236 }
237
238 jboolean empty = metadata->isEmpty();
239
240 ALOGV("%s: Empty returned %d, entry count was %zu",
241 __FUNCTION__, empty, metadata->entryCount());
242
243 return empty;
244 }
245
CameraMetadata_getEntryCount(JNIEnv * env,jclass thiz,jlong ptr)246 static jint CameraMetadata_getEntryCount(JNIEnv *env, jclass thiz, jlong ptr) {
247 ALOGV("%s", __FUNCTION__);
248
249 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
250
251 if (metadata == NULL) return 0; // actually throws java exc.
252
253 return metadata->entryCount();
254 }
255
CameraMetadata_update(JNIEnv * env,jclass thiz,jlong dst,jlong src)256 static void CameraMetadata_update(JNIEnv *env, jclass thiz, jlong dst, jlong src) {
257 ALOGV("%s", __FUNCTION__);
258
259 CameraMetadata* metadataDst = CameraMetadata_getPointerThrow(env, dst);
260 CameraMetadata* metadataSrc = CameraMetadata_getPointerThrow(env, src);
261
262 if (((metadataDst == NULL) || (metadataDst->isEmpty())) ||
263 ((metadataSrc == NULL) || metadataSrc->isEmpty())) {
264 return;
265 }
266
267 auto metaBuffer = metadataSrc->getAndLock();
268 camera_metadata_ro_entry_t entry;
269 auto entryCount = get_camera_metadata_entry_count(metaBuffer);
270 for (size_t i = 0; i < entryCount; i++) {
271 auto stat = get_camera_metadata_ro_entry(metaBuffer, i, &entry);
272 if (stat != NO_ERROR) {
273 ALOGE("%s: Failed to retrieve source metadata!", __func__);
274 metadataSrc->unlock(metaBuffer);
275 return;
276 }
277 switch (entry.type) {
278 case TYPE_BYTE:
279 metadataDst->update(entry.tag, entry.data.u8, entry.count);
280 break;
281 case TYPE_INT32:
282 metadataDst->update(entry.tag, entry.data.i32, entry.count);
283 break;
284 case TYPE_FLOAT:
285 metadataDst->update(entry.tag, entry.data.f, entry.count);
286 break;
287 case TYPE_INT64:
288 metadataDst->update(entry.tag, entry.data.i64, entry.count);
289 break;
290 case TYPE_DOUBLE:
291 metadataDst->update(entry.tag, entry.data.d, entry.count);
292 break;
293 case TYPE_RATIONAL:
294 metadataDst->update(entry.tag, entry.data.r, entry.count);
295 break;
296 default:
297 ALOGE("%s: Unsupported tag type: %d!", __func__, entry.type);
298 }
299 }
300 metadataSrc->unlock(metaBuffer);
301 }
302
CameraMetadata_getBufferSize(JNIEnv * env,jclass thiz,jlong ptr)303 static jlong CameraMetadata_getBufferSize(JNIEnv *env, jclass thiz, jlong ptr) {
304 ALOGV("%s", __FUNCTION__);
305
306 CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr);
307
308 if (metadata == NULL) return 0;
309
310 return metadata->bufferSize();
311 }
312
313 // idempotent. calling more than once has no effect.
CameraMetadata_close(JNIEnv * env,jclass thiz,jlong ptr)314 static void CameraMetadata_close(JNIEnv *env, jclass thiz, jlong ptr) {
315 ALOGV("%s", __FUNCTION__);
316
317 auto metadata = CameraMetadata_getSharedPtr(ptr);
318 if (metadata != nullptr) {
319 delete metadata;
320 }
321 }
322
CameraMetadata_swap(JNIEnv * env,jclass thiz,jlong ptr,jlong other)323 static void CameraMetadata_swap(JNIEnv *env, jclass thiz, jlong ptr, jlong other) {
324 ALOGV("%s", __FUNCTION__);
325
326 auto metadata = CameraMetadata_getSharedPtr(ptr);
327 auto otherMetadata = CameraMetadata_getSharedPtr(other);
328
329 if (metadata == NULL) return;
330 if (otherMetadata == NULL) return;
331
332 // Need to swap shared pointers, not CameraMetadata, since the latter may be in use
333 // by an NDK client, and we don't want to swap their data out from under them.
334 metadata->swap(*otherMetadata);
335 }
336
CameraMetadata_readValues(JNIEnv * env,jclass thiz,jint tag,jlong ptr)337 static jbyteArray CameraMetadata_readValues(JNIEnv *env, jclass thiz, jint tag, jlong ptr) {
338 ALOGV("%s (tag = %d)", __FUNCTION__, tag);
339
340 const CameraMetadata *metadata = CameraMetadata_getPointerThrow(env, ptr);
341 if (metadata == NULL) return NULL;
342
343 const camera_metadata_t *metaBuffer = metadata->getAndLock();
344 int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
345 metadata->unlock(metaBuffer);
346 if (tagType == -1) {
347 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
348 "Tag (%d) did not have a type", tag);
349 return NULL;
350 }
351 size_t tagSize = Helpers::getTypeSize(tagType);
352
353 camera_metadata_ro_entry entry = metadata->find(tag);
354 if (entry.count == 0) {
355 if (!metadata->exists(tag)) {
356 ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
357 return NULL;
358 } else {
359 // OK: we will return a 0-sized array.
360 ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__, 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
nativeSetVendorId(JJ)602 { "nativeSetVendorId",
603 "(JJ)V",
604 (void *)CameraMetadata_setVendorId },
nativeGetTagFromKey(Ljava/lang/String;J)605 { "nativeGetTagFromKey",
606 "(Ljava/lang/String;J)I",
607 (void *)CameraMetadata_getTagFromKey },
nativeGetTypeFromTag(IJ)608 { "nativeGetTypeFromTag",
609 "(IJ)I",
610 (void *)CameraMetadata_getTypeFromTag },
nativeSetupGlobalVendorTagDescriptor()611 { "nativeSetupGlobalVendorTagDescriptor",
612 "()I",
613 (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
614 // instance methods
nativeAllocate()615 { "nativeAllocate",
616 "()J",
617 (void*)CameraMetadata_allocate },
nativeAllocateCopy(J)618 { "nativeAllocateCopy",
619 "(J)J",
620 (void *)CameraMetadata_allocateCopy },
nativeUpdate(JJ)621 { "nativeUpdate",
622 "(JJ)V",
623 (void*)CameraMetadata_update },
nativeIsEmpty(J)624 { "nativeIsEmpty",
625 "(J)Z",
626 (void*)CameraMetadata_isEmpty },
nativeGetEntryCount(J)627 { "nativeGetEntryCount",
628 "(J)I",
629 (void*)CameraMetadata_getEntryCount },
nativeGetBufferSize(J)630 { "nativeGetBufferSize",
631 "(J)J",
632 (void*)CameraMetadata_getBufferSize },
nativeClose(J)633 { "nativeClose",
634 "(J)V",
635 (void*)CameraMetadata_close },
nativeSwap(JJ)636 { "nativeSwap",
637 "(JJ)V",
638 (void *)CameraMetadata_swap },
nativeGetTagFromKeyLocal(JLjava/lang/String;)639 { "nativeGetTagFromKeyLocal",
640 "(JLjava/lang/String;)I",
641 (void *)CameraMetadata_getTagFromKeyLocal },
nativeGetTypeFromTagLocal(JI)642 { "nativeGetTypeFromTagLocal",
643 "(JI)I",
644 (void *)CameraMetadata_getTypeFromTagLocal },
nativeReadValues(IJ)645 { "nativeReadValues",
646 "(IJ)[B",
647 (void *)CameraMetadata_readValues },
nativeWriteValues(I[BJ)648 { "nativeWriteValues",
649 "(I[BJ)V",
650 (void *)CameraMetadata_writeValues },
nativeDump(J)651 { "nativeDump",
652 "(J)V",
653 (void *)CameraMetadata_dump },
nativeGetAllVendorKeys(JLjava/lang/Class;)654 { "nativeGetAllVendorKeys",
655 "(JLjava/lang/Class;)Ljava/util/ArrayList;",
656 (void *)CameraMetadata_getAllVendorKeys},
657 // Parcelable interface
nativeReadFromParcel(Landroid/os/Parcel;J)658 { "nativeReadFromParcel",
659 "(Landroid/os/Parcel;J)V",
660 (void *)CameraMetadata_readFromParcel },
nativeWriteToParcel(Landroid/os/Parcel;J)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