Skip to content

Commit c620eb7

Browse files
committed
Make vendor keys visible in Camera2 java APIs.
- Add vendor keys to getKeys() calls for CameraCharacteristics, CaptureRequest, and CaptureResult. - Vendors can specify whether custom keys show up by listing visible keys in the REQUEST_AVAILABLE_RESULT_KEYS field. - Vendor key types are always treated as a primitive (or Rational) array type corresponding to one of the valid types for a camera metadata entry. Bug: 22067625 Change-Id: I6e7dd3db7a8bf533c2ec15ff69ca38824134e971
1 parent eec3d9e commit c620eb7

3 files changed

Lines changed: 203 additions & 0 deletions

File tree

core/java/android/hardware/camera2/CameraMetadata.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,28 @@ static <TKey> ArrayList<TKey> getKeysStatic(
173173
}
174174
}
175175

176+
ArrayList<TKey> vendorKeys = CameraMetadataNative.getAllVendorKeys(keyClass);
177+
178+
if (vendorKeys != null) {
179+
for (TKey k : vendorKeys) {
180+
String keyName;
181+
if (k instanceof CaptureRequest.Key<?>) {
182+
keyName = ((CaptureRequest.Key<?>) k).getName();
183+
} else if (k instanceof CaptureResult.Key<?>) {
184+
keyName = ((CaptureResult.Key<?>) k).getName();
185+
} else if (k instanceof CameraCharacteristics.Key<?>) {
186+
keyName = ((CameraCharacteristics.Key<?>) k).getName();
187+
} else {
188+
continue;
189+
}
190+
191+
if (filterTags == null || Arrays.binarySearch(filterTags,
192+
CameraMetadataNative.getTag(keyName)) >= 0) {
193+
keyList.add(k);
194+
}
195+
}
196+
}
197+
176198
return keyList;
177199
}
178200

core/java/android/hardware/camera2/impl/CameraMetadataNative.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,7 @@ private native synchronized void nativeSwap(CameraMetadataNative other)
10781078
private native synchronized void nativeWriteValues(int tag, byte[] src);
10791079
private native synchronized void nativeDump() throws IOException; // dump to ALOGD
10801080

1081+
private static native ArrayList nativeGetAllVendorKeys(Class keyClass);
10811082
private static native int nativeGetTagFromKey(String keyName)
10821083
throws IllegalArgumentException;
10831084
private static native int nativeGetTypeFromTag(int tag)
@@ -1113,6 +1114,19 @@ public boolean isEmpty() {
11131114
return nativeIsEmpty();
11141115
}
11151116

1117+
1118+
/**
1119+
* Return a list containing keys of the given key class for all defined vendor tags.
1120+
*
1121+
* @hide
1122+
*/
1123+
public static <K> ArrayList<K> getAllVendorKeys(Class<K> keyClass) {
1124+
if (keyClass == null) {
1125+
throw new NullPointerException();
1126+
}
1127+
return (ArrayList<K>) nativeGetAllVendorKeys(keyClass);
1128+
}
1129+
11161130
/**
11171131
* Convert a key string into the equivalent native tag.
11181132
*

core/jni/android_hardware_camera2_CameraMetadata.cpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
#include <utils/Vector.h>
2424
#include <utils/SortedVector.h>
2525
#include <utils/KeyedVector.h>
26+
#include <stdio.h>
2627
#include <string.h>
28+
#include <vector>
2729

2830
#include "jni.h"
2931
#include "JNIHelp.h"
@@ -45,9 +47,30 @@ static const bool kIsDebug = false;
4547

4648
// fully-qualified class name
4749
#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"
4853

4954
using namespace android;
5055

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+
5174
struct fields_t {
5275
jfieldID metadata_ptr;
5376
};
@@ -141,6 +164,7 @@ struct Helpers {
141164
extern "C" {
142165

143166
static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
167+
static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType);
144168
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
145169
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
146170
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
@@ -510,6 +534,9 @@ static JNINativeMethod gCameraMetadataMethods[] = {
510534
{ "nativeClassInit",
511535
"()V",
512536
(void *)CameraMetadata_classInit },
537+
{ "nativeGetAllVendorKeys",
538+
"(Ljava/lang/Class;)Ljava/util/ArrayList;",
539+
(void *)CameraMetadata_getAllVendorKeys},
513540
{ "nativeGetTagFromKey",
514541
"(Ljava/lang/String;)I",
515542
(void *)CameraMetadata_getTagFromKey },
@@ -588,6 +615,44 @@ static int find_fields(JNIEnv *env, field *fields, int count)
588615
// Get all the required offsets in java class and register native functions
589616
int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
590617
{
618+
619+
// Store global references to Key-related classes and methods used natively
620+
jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME);
621+
jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME);
622+
jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME);
623+
gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz);
624+
gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz);
625+
gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
626+
gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
627+
gMetadataOffsets.mCharacteristicsKey, "<init>",
628+
"(Ljava/lang/String;Ljava/lang/Class;)V");
629+
gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
630+
gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
631+
gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
632+
gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
633+
634+
// Store global references for primitive array types used by Keys
635+
jclass byteClazz = FindClassOrDie(env, "[B");
636+
jclass int32Clazz = FindClassOrDie(env, "[I");
637+
jclass floatClazz = FindClassOrDie(env, "[F");
638+
jclass int64Clazz = FindClassOrDie(env, "[J");
639+
jclass doubleClazz = FindClassOrDie(env, "[D");
640+
jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;");
641+
gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz);
642+
gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz);
643+
gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz);
644+
gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz);
645+
gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz);
646+
gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz);
647+
648+
// Store global references for ArrayList methods used
649+
jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList");
650+
gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz);
651+
gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
652+
"<init>", "(I)V");
653+
gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
654+
"add", "(Ljava/lang/Object;)Z");
655+
591656
// Register native functions
592657
return RegisterMethodsOrDie(env,
593658
CAMERA_METADATA_CLASS_NAME,
@@ -596,6 +661,7 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
596661
}
597662

598663
extern "C" {
664+
599665
static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
600666
// XX: Why do this separately instead of doing it in the register function?
601667
ALOGV("%s", __FUNCTION__);
@@ -612,6 +678,107 @@ static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
612678
env->FindClass(CAMERA_METADATA_CLASS_NAME);
613679
}
614680

681+
static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
682+
683+
// Get all vendor tags
684+
sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
685+
if (vTags.get() == nullptr) {
686+
// No vendor tags.
687+
return NULL;
688+
}
689+
690+
int count = vTags->getTagCount();
691+
if (count <= 0) {
692+
// No vendor tags.
693+
return NULL;
694+
}
695+
696+
std::vector<uint32_t> tagIds(count, /*initializer value*/0);
697+
vTags->getTagArray(&tagIds[0]);
698+
699+
// Which key class/constructor should we use?
700+
jclass keyClazz;
701+
jmethodID keyConstr;
702+
if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) {
703+
keyClazz = gMetadataOffsets.mCharacteristicsKey;
704+
keyConstr = gMetadataOffsets.mCharacteristicsConstr;
705+
} else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) {
706+
keyClazz = gMetadataOffsets.mResultKey;
707+
keyConstr = gMetadataOffsets.mResultConstr;
708+
} else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) {
709+
keyClazz = gMetadataOffsets.mRequestKey;
710+
keyConstr = gMetadataOffsets.mRequestConstr;
711+
} else {
712+
jniThrowException(env, "java/lang/IllegalArgumentException",
713+
"Invalid key class given as argument.");
714+
return NULL;
715+
}
716+
717+
// Allocate arrayList to return
718+
jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList,
719+
gMetadataOffsets.mArrayListConstr, static_cast<jint>(count));
720+
if (env->ExceptionCheck()) {
721+
return NULL;
722+
}
723+
724+
for (uint32_t id : tagIds) {
725+
const char* section = vTags->getSectionName(id);
726+
const char* tag = vTags->getTagName(id);
727+
int type = vTags->getTagType(id);
728+
729+
size_t totalLen = strlen(section) + strlen(tag) + 2;
730+
std::vector<char> fullName(totalLen, 0);
731+
snprintf(&fullName[0], totalLen, "%s.%s", section, tag);
732+
733+
jstring name = env->NewStringUTF(&fullName[0]);
734+
735+
if (env->ExceptionCheck()) {
736+
return NULL;
737+
}
738+
739+
jclass valueClazz;
740+
switch (type) {
741+
case TYPE_BYTE:
742+
valueClazz = gMetadataOffsets.mByteArray;
743+
break;
744+
case TYPE_INT32:
745+
valueClazz = gMetadataOffsets.mInt32Array;
746+
break;
747+
case TYPE_FLOAT:
748+
valueClazz = gMetadataOffsets.mFloatArray;
749+
break;
750+
case TYPE_INT64:
751+
valueClazz = gMetadataOffsets.mInt64Array;
752+
break;
753+
case TYPE_DOUBLE:
754+
valueClazz = gMetadataOffsets.mDoubleArray;
755+
break;
756+
case TYPE_RATIONAL:
757+
valueClazz = gMetadataOffsets.mRationalArray;
758+
break;
759+
default:
760+
jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
761+
"Invalid type %d given for key %s", type, &fullName[0]);
762+
return NULL;
763+
}
764+
765+
jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz);
766+
if (env->ExceptionCheck()) {
767+
return NULL;
768+
}
769+
770+
env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key);
771+
if (env->ExceptionCheck()) {
772+
return NULL;
773+
}
774+
775+
env->DeleteLocalRef(name);
776+
env->DeleteLocalRef(key);
777+
}
778+
779+
return arrayList;
780+
}
781+
615782
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
616783

617784
ScopedUtfChars keyScoped(env, keyName);

0 commit comments

Comments
 (0)