diff options
3 files changed, 203 insertions, 0 deletions
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index af1367c..c580083 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -173,6 +173,28 @@ public abstract class CameraMetadata<TKey> { } } + ArrayList<TKey> vendorKeys = CameraMetadataNative.getAllVendorKeys(keyClass); + + if (vendorKeys != null) { + for (TKey k : vendorKeys) { + String keyName; + if (k instanceof CaptureRequest.Key<?>) { + keyName = ((CaptureRequest.Key<?>) k).getName(); + } else if (k instanceof CaptureResult.Key<?>) { + keyName = ((CaptureResult.Key<?>) k).getName(); + } else if (k instanceof CameraCharacteristics.Key<?>) { + keyName = ((CameraCharacteristics.Key<?>) k).getName(); + } else { + continue; + } + + if (filterTags == null || Arrays.binarySearch(filterTags, + CameraMetadataNative.getTag(keyName)) >= 0) { + keyList.add(k); + } + } + } + return keyList; } diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 7e50fd9..12a2910 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -1078,6 +1078,7 @@ public class CameraMetadataNative implements Parcelable { private native synchronized void nativeWriteValues(int tag, byte[] src); private native synchronized void nativeDump() throws IOException; // dump to ALOGD + private static native ArrayList nativeGetAllVendorKeys(Class keyClass); private static native int nativeGetTagFromKey(String keyName) throws IllegalArgumentException; private static native int nativeGetTypeFromTag(int tag) @@ -1113,6 +1114,19 @@ public class CameraMetadataNative implements Parcelable { return nativeIsEmpty(); } + + /** + * Return a list containing keys of the given key class for all defined vendor tags. + * + * @hide + */ + public static <K> ArrayList<K> getAllVendorKeys(Class<K> keyClass) { + if (keyClass == null) { + throw new NullPointerException(); + } + return (ArrayList<K>) nativeGetAllVendorKeys(keyClass); + } + /** * Convert a key string into the equivalent native tag. * diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp index 7c8769d..fb22689 100644 --- a/core/jni/android_hardware_camera2_CameraMetadata.cpp +++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp @@ -23,7 +23,9 @@ #include <utils/Vector.h> #include <utils/SortedVector.h> #include <utils/KeyedVector.h> +#include <stdio.h> #include <string.h> +#include <vector> #include "jni.h" #include "JNIHelp.h" @@ -45,9 +47,30 @@ static const bool kIsDebug = false; // fully-qualified class name #define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative" +#define CHARACTERISTICS_KEY_CLASS_NAME "android/hardware/camera2/CameraCharacteristics$Key" +#define REQUEST_KEY_CLASS_NAME "android/hardware/camera2/CaptureRequest$Key" +#define RESULT_KEY_CLASS_NAME "android/hardware/camera2/CaptureResult$Key" using namespace android; +static struct metadata_java_key_offsets_t { + jclass mCharacteristicsKey; + jclass mResultKey; + jclass mRequestKey; + jmethodID mCharacteristicsConstr; + jmethodID mResultConstr; + jmethodID mRequestConstr; + jclass mByteArray; + jclass mInt32Array; + jclass mFloatArray; + jclass mInt64Array; + jclass mDoubleArray; + jclass mRationalArray; + jclass mArrayList; + jmethodID mArrayListConstr; + jmethodID mArrayListAdd; +} gMetadataOffsets; + struct fields_t { jfieldID metadata_ptr; }; @@ -141,6 +164,7 @@ struct Helpers { extern "C" { static void CameraMetadata_classInit(JNIEnv *env, jobject thiz); +static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType); static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName); static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag); static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz); @@ -510,6 +534,9 @@ static JNINativeMethod gCameraMetadataMethods[] = { { "nativeClassInit", "()V", (void *)CameraMetadata_classInit }, + { "nativeGetAllVendorKeys", + "(Ljava/lang/Class;)Ljava/util/ArrayList;", + (void *)CameraMetadata_getAllVendorKeys}, { "nativeGetTagFromKey", "(Ljava/lang/String;)I", (void *)CameraMetadata_getTagFromKey }, @@ -588,6 +615,44 @@ static int find_fields(JNIEnv *env, field *fields, int count) // Get all the required offsets in java class and register native functions int register_android_hardware_camera2_CameraMetadata(JNIEnv *env) { + + // Store global references to Key-related classes and methods used natively + jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME); + jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME); + jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME); + gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz); + gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz); + gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz); + gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env, + gMetadataOffsets.mCharacteristicsKey, "<init>", + "(Ljava/lang/String;Ljava/lang/Class;)V"); + gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env, + gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V"); + gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env, + gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V"); + + // Store global references for primitive array types used by Keys + jclass byteClazz = FindClassOrDie(env, "[B"); + jclass int32Clazz = FindClassOrDie(env, "[I"); + jclass floatClazz = FindClassOrDie(env, "[F"); + jclass int64Clazz = FindClassOrDie(env, "[J"); + jclass doubleClazz = FindClassOrDie(env, "[D"); + jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;"); + gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz); + gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz); + gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz); + gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz); + gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz); + gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz); + + // Store global references for ArrayList methods used + jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList"); + gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz); + gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList, + "<init>", "(I)V"); + gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList, + "add", "(Ljava/lang/Object;)Z"); + // Register native functions return RegisterMethodsOrDie(env, CAMERA_METADATA_CLASS_NAME, @@ -596,6 +661,7 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env) } extern "C" { + static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) { // XX: Why do this separately instead of doing it in the register function? ALOGV("%s", __FUNCTION__); @@ -612,6 +678,107 @@ static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) { env->FindClass(CAMERA_METADATA_CLASS_NAME); } +static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) { + + // Get all vendor tags + sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor(); + if (vTags.get() == nullptr) { + // No vendor tags. + return NULL; + } + + int count = vTags->getTagCount(); + if (count <= 0) { + // No vendor tags. + return NULL; + } + + std::vector<uint32_t> tagIds(count, /*initializer value*/0); + vTags->getTagArray(&tagIds[0]); + + // Which key class/constructor should we use? + jclass keyClazz; + jmethodID keyConstr; + if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) { + keyClazz = gMetadataOffsets.mCharacteristicsKey; + keyConstr = gMetadataOffsets.mCharacteristicsConstr; + } else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) { + keyClazz = gMetadataOffsets.mResultKey; + keyConstr = gMetadataOffsets.mResultConstr; + } else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) { + keyClazz = gMetadataOffsets.mRequestKey; + keyConstr = gMetadataOffsets.mRequestConstr; + } else { + jniThrowException(env, "java/lang/IllegalArgumentException", + "Invalid key class given as argument."); + return NULL; + } + + // Allocate arrayList to return + jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList, + gMetadataOffsets.mArrayListConstr, static_cast<jint>(count)); + if (env->ExceptionCheck()) { + return NULL; + } + + for (uint32_t id : tagIds) { + const char* section = vTags->getSectionName(id); + const char* tag = vTags->getTagName(id); + int type = vTags->getTagType(id); + + size_t totalLen = strlen(section) + strlen(tag) + 2; + std::vector<char> fullName(totalLen, 0); + snprintf(&fullName[0], totalLen, "%s.%s", section, tag); + + jstring name = env->NewStringUTF(&fullName[0]); + + if (env->ExceptionCheck()) { + return NULL; + } + + jclass valueClazz; + switch (type) { + case TYPE_BYTE: + valueClazz = gMetadataOffsets.mByteArray; + break; + case TYPE_INT32: + valueClazz = gMetadataOffsets.mInt32Array; + break; + case TYPE_FLOAT: + valueClazz = gMetadataOffsets.mFloatArray; + break; + case TYPE_INT64: + valueClazz = gMetadataOffsets.mInt64Array; + break; + case TYPE_DOUBLE: + valueClazz = gMetadataOffsets.mDoubleArray; + break; + case TYPE_RATIONAL: + valueClazz = gMetadataOffsets.mRationalArray; + break; + default: + jniThrowExceptionFmt(env, "java/lang/IllegalStateException", + "Invalid type %d given for key %s", type, &fullName[0]); + return NULL; + } + + jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz); + if (env->ExceptionCheck()) { + return NULL; + } + + env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key); + if (env->ExceptionCheck()) { + return NULL; + } + + env->DeleteLocalRef(name); + env->DeleteLocalRef(key); + } + + return arrayList; +} + static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) { ScopedUtfChars keyScoped(env, keyName); |