Merge "Camera: Initial support for vendor tag caches" into oc-dev

This commit is contained in:
TreeHugger Robot
2017-04-06 14:02:06 +00:00
committed by Android (Google) Code Review
9 changed files with 337 additions and 48 deletions

View File

@@ -62,6 +62,15 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
public static final class Key<T> {
private final CameraMetadataNative.Key<T> mKey;
/**
* Visible for testing and vendor extensions only.
*
* @hide
*/
public Key(String name, Class<T> type, long vendorId) {
mKey = new CameraMetadataNative.Key<T>(name, type, vendorId);
}
/**
* Visible for testing and vendor extensions only.
*
@@ -98,6 +107,15 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
return mKey.getName();
}
/**
* Return vendor tag id.
*
* @hide
*/
public long getVendorId() {
return mKey.getVendorId();
}
/**
* {@inheritDoc}
*/
@@ -159,6 +177,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
*/
public CameraCharacteristics(CameraMetadataNative properties) {
mProperties = CameraMetadataNative.move(properties);
setNativeInstance(mProperties);
}
/**
@@ -227,7 +246,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
}
mKeys = Collections.unmodifiableList(
getKeysStatic(getClass(), getKeyClass(), this, filterTags));
getKeys(getClass(), getKeyClass(), this, filterTags));
return mKeys;
}
@@ -320,7 +339,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
"metadataClass must be a subclass of CameraMetadata");
}
List<TKey> staticKeyList = CameraCharacteristics.<TKey>getKeysStatic(
List<TKey> staticKeyList = getKeys(
metadataClass, keyClass, /*instance*/null, filterTags);
return Collections.unmodifiableList(staticKeyList);
}

View File

@@ -52,6 +52,7 @@ public abstract class CameraMetadata<TKey> {
private static final String TAG = "CameraMetadataAb";
private static final boolean DEBUG = false;
private CameraMetadataNative mNativeInstance = null;
/**
* Set a camera metadata field to a value. The field definitions can be
@@ -86,6 +87,13 @@ public abstract class CameraMetadata<TKey> {
*/
protected abstract <T> T getProtected(TKey key);
/**
* @hide
*/
protected void setNativeInstance(CameraMetadataNative nativeInstance) {
mNativeInstance = nativeInstance;
}
/**
* @hide
*/
@@ -108,7 +116,7 @@ public abstract class CameraMetadata<TKey> {
public List<TKey> getKeys() {
Class<CameraMetadata<TKey>> thisClass = (Class<CameraMetadata<TKey>>) getClass();
return Collections.unmodifiableList(
getKeysStatic(thisClass, getKeyClass(), this, /*filterTags*/null));
getKeys(thisClass, getKeyClass(), this, /*filterTags*/null));
}
/**
@@ -126,7 +134,7 @@ public abstract class CameraMetadata<TKey> {
* </p>
*/
/*package*/ @SuppressWarnings("unchecked")
static <TKey> ArrayList<TKey> getKeysStatic(
<TKey> ArrayList<TKey> getKeys(
Class<?> type, Class<TKey> keyClass,
CameraMetadata<TKey> instance,
int[] filterTags) {
@@ -173,23 +181,31 @@ public abstract class CameraMetadata<TKey> {
}
}
ArrayList<TKey> vendorKeys = CameraMetadataNative.getAllVendorKeys(keyClass);
if (null == mNativeInstance) {
return keyList;
}
ArrayList<TKey> vendorKeys = mNativeInstance.getAllVendorKeys(keyClass);
if (vendorKeys != null) {
for (TKey k : vendorKeys) {
String keyName;
long vendorId;
if (k instanceof CaptureRequest.Key<?>) {
keyName = ((CaptureRequest.Key<?>) k).getName();
vendorId = ((CaptureRequest.Key<?>) k).getVendorId();
} else if (k instanceof CaptureResult.Key<?>) {
keyName = ((CaptureResult.Key<?>) k).getName();
vendorId = ((CaptureResult.Key<?>) k).getVendorId();
} else if (k instanceof CameraCharacteristics.Key<?>) {
keyName = ((CameraCharacteristics.Key<?>) k).getName();
vendorId = ((CameraCharacteristics.Key<?>) k).getVendorId();
} else {
continue;
}
if (filterTags == null || Arrays.binarySearch(filterTags,
CameraMetadataNative.getTag(keyName)) >= 0) {
CameraMetadataNative.getTag(keyName, vendorId)) >= 0) {
keyList.add(k);
}
}

View File

@@ -96,6 +96,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
public final static class Key<T> {
private final CameraMetadataNative.Key<T> mKey;
/**
* Visible for testing and vendor extensions only.
*
* @hide
*/
public Key(String name, Class<T> type, long vendorId) {
mKey = new CameraMetadataNative.Key<T>(name, type, vendorId);
}
/**
* Visible for testing and vendor extensions only.
*
@@ -132,6 +141,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
return mKey.getName();
}
/**
* Return vendor tag id.
*
* @hide
*/
public long getVendorId() {
return mKey.getVendorId();
}
/**
* {@inheritDoc}
*/
@@ -199,6 +217,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
*/
private CaptureRequest() {
mSettings = new CameraMetadataNative();
setNativeInstance(mSettings);
mSurfaceSet = new HashSet<Surface>();
mIsReprocess = false;
mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE;
@@ -212,6 +231,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
@SuppressWarnings("unchecked")
private CaptureRequest(CaptureRequest source) {
mSettings = new CameraMetadataNative(source.mSettings);
setNativeInstance(mSettings);
mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone();
mIsReprocess = source.mIsReprocess;
mIsPartOfCHSRequestList = source.mIsPartOfCHSRequestList;
@@ -242,6 +262,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
private CaptureRequest(CameraMetadataNative settings, boolean isReprocess,
int reprocessableSessionId) {
mSettings = CameraMetadataNative.move(settings);
setNativeInstance(mSettings);
mSurfaceSet = new HashSet<Surface>();
mIsReprocess = isReprocess;
if (isReprocess) {
@@ -441,6 +462,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
*/
private void readFromParcel(Parcel in) {
mSettings.readFromParcel(in);
setNativeInstance(mSettings);
mSurfaceSet.clear();

View File

@@ -73,6 +73,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
public final static class Key<T> {
private final CameraMetadataNative.Key<T> mKey;
/**
* Visible for testing and vendor extensions only.
*
* @hide
*/
public Key(String name, Class<T> type, long vendorId) {
mKey = new CameraMetadataNative.Key<T>(name, type, vendorId);
}
/**
* Visible for testing and vendor extensions only.
*
@@ -109,6 +118,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
return mKey.getName();
}
/**
* Return vendor tag id.
*
* @hide
*/
public long getVendorId() {
return mKey.getVendorId();
}
/**
* {@inheritDoc}
*/
@@ -186,6 +204,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
if (mResults.isEmpty()) {
throw new AssertionError("Results must not be empty");
}
setNativeInstance(mResults);
mRequest = parent;
mSequenceId = extras.getRequestId();
mFrameNumber = extras.getFrameNumber();
@@ -215,6 +234,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
throw new AssertionError("Results must not be empty");
}
setNativeInstance(mResults);
mRequest = null;
mSequenceId = sequenceId;
mFrameNumber = -1;

View File

@@ -79,10 +79,28 @@ public class CameraMetadataNative implements Parcelable {
public static class Key<T> {
private boolean mHasTag;
private int mTag;
private long mVendorId = Long.MAX_VALUE;
private final Class<T> mType;
private final TypeReference<T> mTypeReference;
private final String mName;
private final int mHash;
/**
* @hide
*/
public Key(String name, Class<T> type, long vendorId) {
if (name == null) {
throw new NullPointerException("Key needs a valid name");
} else if (type == null) {
throw new NullPointerException("Type needs to be non-null");
}
mName = name;
mType = type;
mVendorId = vendorId;
mTypeReference = TypeReference.createSpecializedTypeReference(type);
mHash = mName.hashCode() ^ mTypeReference.hashCode();
}
/**
* Visible for testing only.
*
@@ -194,7 +212,7 @@ public class CameraMetadataNative implements Parcelable {
*/
public final int getTag() {
if (!mHasTag) {
mTag = CameraMetadataNative.getTag(mName);
mTag = CameraMetadataNative.getTag(mName, mVendorId);
mHasTag = true;
}
return mTag;
@@ -211,6 +229,15 @@ public class CameraMetadataNative implements Parcelable {
return mType;
}
/**
* Get the vendor tag provider id.
*
* @hide
*/
public final long getVendorId() {
return mVendorId;
}
/**
* Get the type reference backing the type {@code T} for this key.
*
@@ -463,13 +490,14 @@ public class CameraMetadataNative implements Parcelable {
}
private <T> T getBase(Key<T> key) {
int tag = key.getTag();
int tag = nativeGetTagFromKeyLocal(key.getName());
byte[] values = readValues(tag);
if (values == null) {
return null;
}
Marshaler<T> marshaler = getMarshalerForKey(key);
int nativeType = nativeGetTypeFromTagLocal(tag);
Marshaler<T> marshaler = getMarshalerForKey(key, nativeType);
ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder());
return marshaler.unmarshal(buffer);
}
@@ -947,15 +975,15 @@ public class CameraMetadataNative implements Parcelable {
}
private <T> void setBase(Key<T> key, T value) {
int tag = key.getTag();
int tag = nativeGetTagFromKeyLocal(key.getName());
if (value == null) {
// Erase the entry
writeValues(tag, /*src*/null);
return;
} // else update the entry to a new value
Marshaler<T> marshaler = getMarshalerForKey(key);
int nativeType = nativeGetTypeFromTagLocal(tag);
Marshaler<T> marshaler = getMarshalerForKey(key, nativeType);
int size = marshaler.calculateMarshalSize(value);
// TODO: Optimization. Cache the byte[] and reuse if the size is big enough.
@@ -1092,10 +1120,14 @@ 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)
private native synchronized ArrayList nativeGetAllVendorKeys(Class keyClass);
private native synchronized int nativeGetTagFromKeyLocal(String keyName)
throws IllegalArgumentException;
private static native int nativeGetTypeFromTag(int tag)
private native synchronized int nativeGetTypeFromTagLocal(int tag)
throws IllegalArgumentException;
private static native int nativeGetTagFromKey(String keyName, long vendorId)
throws IllegalArgumentException;
private static native int nativeGetTypeFromTag(int tag, long vendorId)
throws IllegalArgumentException;
/**
@@ -1133,7 +1165,7 @@ public class CameraMetadataNative implements Parcelable {
*
* @hide
*/
public static <K> ArrayList<K> getAllVendorKeys(Class<K> keyClass) {
public <K> ArrayList<K> getAllVendorKeys(Class<K> keyClass) {
if (keyClass == null) {
throw new NullPointerException();
}
@@ -1149,19 +1181,32 @@ public class CameraMetadataNative implements Parcelable {
* @hide
*/
public static int getTag(String key) {
return nativeGetTagFromKey(key);
return nativeGetTagFromKey(key, Long.MAX_VALUE);
}
/**
* Convert a key string into the equivalent native tag.
*
* @throws IllegalArgumentException if the key was not recognized
* @throws NullPointerException if the key was null
*
* @hide
*/
public static int getTag(String key, long vendorId) {
return nativeGetTagFromKey(key, vendorId);
}
/**
* Get the underlying native type for a tag.
*
* @param tag An integer tag, see e.g. {@link #getTag}
* @param vendorId A vendor tag provider id
* @return An int enum for the metadata type, see e.g. {@link #TYPE_BYTE}
*
* @hide
*/
public static int getNativeType(int tag) {
return nativeGetTypeFromTag(tag);
public static int getNativeType(int tag, long vendorId) {
return nativeGetTypeFromTag(tag, vendorId);
}
/**
@@ -1226,9 +1271,9 @@ public class CameraMetadataNative implements Parcelable {
* @throws UnsupportedOperationException
* if the native/managed type combination for {@code key} is not supported
*/
private static <T> Marshaler<T> getMarshalerForKey(Key<T> key) {
private static <T> Marshaler<T> getMarshalerForKey(Key<T> key, int nativeType) {
return MarshalRegistry.getMarshaler(key.getTypeReference(),
getNativeType(key.getTag()));
nativeType);
}
@SuppressWarnings({ "unchecked", "rawtypes" })

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.camera2.params;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
/**
* A class for describing the vendor tag cache declared by a camera HAL module.
* Generally only used by the native side of
* android.hardware.camera2.impl.CameraMetadataNative
*
* @hide
*/
public final class VendorTagDescriptorCache implements Parcelable {
private VendorTagDescriptorCache(Parcel source) {
}
public static final Parcelable.Creator<VendorTagDescriptorCache> CREATOR =
new Parcelable.Creator<VendorTagDescriptorCache>() {
@Override
public VendorTagDescriptorCache createFromParcel(Parcel source) {
try {
VendorTagDescriptorCache vendorDescriptorCache = new VendorTagDescriptorCache(source);
return vendorDescriptorCache;
} catch (Exception e) {
Log.e(TAG, "Exception creating VendorTagDescriptorCache from parcel", e);
return null;
}
}
@Override
public VendorTagDescriptorCache[] newArray(int size) {
return new VendorTagDescriptorCache[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
if (dest == null) {
throw new IllegalArgumentException("dest must not be null");
}
}
private static final String TAG = "VendorTagDescriptorCache";
}

View File

@@ -208,6 +208,7 @@ LOCAL_C_INCLUDES += \
$(TOP)/system/core/include \
$(TOP)/system/core/libappfuse/include \
$(TOP)/system/media/camera/include \
$(TOP)/system/media/private/camera/include \
$(TOP)/system/netd/include \
external/giflib \
external/pdfium/public \

View File

@@ -36,6 +36,7 @@
#include <android/hardware/ICameraService.h>
#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.h>
#include <camera_metadata_hidden.h>
#include <camera/VendorTagDescriptor.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>
@@ -162,8 +163,10 @@ struct Helpers {
extern "C" {
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_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName, jlong vendorId);
static jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jobject thiz, jstring keyName);
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag, jlong vendorId);
static jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jobject thiz, jint tag);
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
@@ -286,7 +289,9 @@ static jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag)
CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
if (metadata == NULL) return NULL;
int tagType = get_camera_metadata_tag_type(tag);
const camera_metadata_t *metaBuffer = metadata->getAndLock();
int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
metadata->unlock(metaBuffer);
if (tagType == -1) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Tag (%d) did not have a type", tag);
@@ -323,7 +328,9 @@ static void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyt
CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
if (metadata == NULL) return;
int tagType = get_camera_metadata_tag_type(tag);
const camera_metadata_t *metaBuffer = metadata->getAndLock();
int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
metadata->unlock(metaBuffer);
if (tagType == -1) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Tag (%d) did not have a type", tag);
@@ -528,14 +535,11 @@ static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parc
static const JNINativeMethod gCameraMetadataMethods[] = {
// static methods
{ "nativeGetAllVendorKeys",
"(Ljava/lang/Class;)Ljava/util/ArrayList;",
(void *)CameraMetadata_getAllVendorKeys},
{ "nativeGetTagFromKey",
"(Ljava/lang/String;)I",
"(Ljava/lang/String;J)I",
(void *)CameraMetadata_getTagFromKey },
{ "nativeGetTypeFromTag",
"(I)I",
"(IJ)I",
(void *)CameraMetadata_getTypeFromTag },
{ "nativeSetupGlobalVendorTagDescriptor",
"()I",
@@ -559,6 +563,12 @@ static const JNINativeMethod gCameraMetadataMethods[] = {
{ "nativeSwap",
"(L" CAMERA_METADATA_CLASS_NAME ";)V",
(void *)CameraMetadata_swap },
{ "nativeGetTagFromKeyLocal",
"(Ljava/lang/String;)I",
(void *)CameraMetadata_getTagFromKeyLocal },
{ "nativeGetTypeFromTagLocal",
"(I)I",
(void *)CameraMetadata_getTypeFromTagLocal },
{ "nativeReadValues",
"(I)[B",
(void *)CameraMetadata_readValues },
@@ -568,6 +578,9 @@ static const JNINativeMethod gCameraMetadataMethods[] = {
{ "nativeDump",
"()V",
(void *)CameraMetadata_dump },
{ "nativeGetAllVendorKeys",
"(Ljava/lang/Class;)Ljava/util/ArrayList;",
(void *)CameraMetadata_getAllVendorKeys},
// Parcelable interface
{ "nativeReadFromParcel",
"(Landroid/os/Parcel;)V",
@@ -590,11 +603,11 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
gMetadataOffsets.mCharacteristicsKey, "<init>",
"(Ljava/lang/String;Ljava/lang/Class;)V");
"(Ljava/lang/String;Ljava/lang/Class;J)V");
gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
// Store global references for primitive array types used by Keys
jclass byteClazz = FindClassOrDie(env, "[B");
@@ -630,13 +643,76 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
extern "C" {
static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
static jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jobject thiz, jint tag) {
CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
if (metadata) {
const camera_metadata_t *metaBuffer = metadata->getAndLock();
vendorId = get_camera_metadata_vendor_id(metaBuffer);
metadata->unlock(metaBuffer);
}
int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
if (tagType == -1) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Tag (%d) did not have a type", tag);
return -1;
}
return tagType;
}
static jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jobject thiz, jstring keyName) {
ScopedUtfChars keyScoped(env, keyName);
const char *key = keyScoped.c_str();
if (key == NULL) {
// exception thrown by ScopedUtfChars
return 0;
}
ALOGV("%s (key = '%s')", __FUNCTION__, key);
uint32_t tag = 0;
sp<VendorTagDescriptor> vTags;
CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
if (metadata) {
sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
if (cache.get()) {
const camera_metadata_t *metaBuffer = metadata->getAndLock();
metadata_vendor_id_t vendorId = get_camera_metadata_vendor_id(metaBuffer);
metadata->unlock(metaBuffer);
cache->getVendorTagDescriptor(vendorId, &vTags);
}
}
status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
if (res != OK) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Could not find tag for key '%s')", key);
}
return tag;
}
static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
// Get all vendor tags
sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
if (vTags.get() == nullptr) {
// No vendor tags.
return NULL;
sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
if (cache.get() == nullptr) {
// No vendor tags.
return nullptr;
}
CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
if (metadata == NULL) return NULL;
const camera_metadata_t *metaBuffer = metadata->getAndLock();
vendorId = get_camera_metadata_vendor_id(metaBuffer);
cache->getVendorTagDescriptor(vendorId, &vTags);
metadata->unlock(metaBuffer);
if (vTags.get() == nullptr) {
return nullptr;
}
}
int count = vTags->getTagCount();
@@ -714,7 +790,7 @@ static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass
return NULL;
}
jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz);
jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz, vendorId);
if (env->ExceptionCheck()) {
return NULL;
}
@@ -731,8 +807,8 @@ static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass
return arrayList;
}
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName,
jlong vendorId) {
ScopedUtfChars keyScoped(env, keyName);
const char *key = keyScoped.c_str();
if (key == NULL) {
@@ -744,6 +820,13 @@ static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyN
uint32_t tag = 0;
sp<VendorTagDescriptor> vTags =
VendorTagDescriptor::getGlobalVendorTagDescriptor();
if (vTags.get() == nullptr) {
sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
if (cache.get() != nullptr) {
cache->getVendorTagDescriptor(vendorId, &vTags);
}
}
status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
if (res != OK) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
@@ -752,8 +835,8 @@ static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyN
return tag;
}
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
int tagType = get_camera_metadata_tag_type(tag);
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag, jlong vendorId) {
int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
if (tagType == -1) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Tag (%d) did not have a type", tag);
@@ -787,8 +870,24 @@ static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject t
__FUNCTION__, res.toString8().string());
return res.serviceSpecificErrorCode();
}
if (0 < desc->getTagCount()) {
err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
} else {
sp<VendorTagDescriptorCache> cache = new VendorTagDescriptorCache();
binder::Status res = cameraService->getCameraVendorTagCache(/*out*/cache.get());
if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
// No camera module available, not an error on devices with no cameras
VendorTagDescriptorCache::clearGlobalVendorTagCache();
return OK;
} else if (!res.isOk()) {
VendorTagDescriptorCache::clearGlobalVendorTagCache();
ALOGE("%s: Failed to setup vendor tag cache: %s",
__FUNCTION__, res.toString8().string());
return res.serviceSpecificErrorCode();
}
err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
err = VendorTagDescriptorCache::setAsGlobalVendorTagCache(cache);
}
if (err != OK) {
return hardware::ICameraService::ERROR_INVALID_OPERATION;

View File

@@ -154,18 +154,18 @@ public class CameraMetadataTest extends junit.framework.TestCase {
@SmallTest
public void testGetTypeFromTag() {
assertEquals(TYPE_BYTE,
CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE));
CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE, Long.MAX_VALUE));
assertEquals(TYPE_RATIONAL,
CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM));
CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM, Long.MAX_VALUE));
assertEquals(TYPE_FLOAT,
CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_GAINS));
CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_GAINS, Long.MAX_VALUE));
assertEquals(TYPE_BYTE,
CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE));
CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE, Long.MAX_VALUE));
assertEquals(TYPE_INT32,
CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION));
CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, Long.MAX_VALUE));
try {
CameraMetadataNative.getNativeType(0xDEADF00D);
CameraMetadataNative.getNativeType(0xDEADF00D, Long.MAX_VALUE);
fail("No type should exist for invalid tag 0xDEADF00D");
} catch(IllegalArgumentException e) {
}