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