xref: /aosp_15_r20/frameworks/base/core/jni/android_hardware_camera2_CameraMetadata.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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*)&params);
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