/*
**
** Copyright 2013, 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.
*/

// #define LOG_NDEBUG 0
#define LOG_TAG "CameraMetadata-JNI"
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#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"
#include "android_os_Parcel.h"
#include "core_jni_helpers.h"
#include "android_runtime/android_hardware_camera2_CameraMetadata.h"

#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.h>
#include <camera/ICameraService.h>
#include <camera/VendorTagDescriptor.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>

#include <sys/types.h> // for socketpair
#include <sys/socket.h> // for socketpair

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;
};

static fields_t fields;

namespace android {

status_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
        /*out*/CameraMetadata* metadata) {
    if (!thiz) {
        ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
        return BAD_VALUE;
    }

    if (!metadata) {
        ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
        return BAD_VALUE;
    }
    CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz,
            fields.metadata_ptr));
    if (nativePtr == NULL) {
        ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
        return BAD_VALUE;
    }
    *metadata = *nativePtr;
    return OK;
}

} /*namespace android*/

namespace {
struct Helpers {
    static size_t getTypeSize(uint8_t type) {
        if (type >= NUM_TYPES) {
            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
            return static_cast<size_t>(-1);
        }

        return camera_metadata_type_size[type];
    }

    static status_t updateAny(CameraMetadata *metadata,
                          uint32_t tag,
                          uint32_t type,
                          const void *data,
                          size_t dataBytes) {

        if (type >= NUM_TYPES) {
            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
            return INVALID_OPERATION;
        }

        size_t typeSize = getTypeSize(type);

        if (dataBytes % typeSize != 0) {
            ALOGE("%s: Expected dataBytes (%zu) to be divisible by typeSize "
                  "(%zu)", __FUNCTION__, dataBytes, typeSize);
            return BAD_VALUE;
        }

        size_t dataCount = dataBytes / typeSize;

        switch(type) {
#define METADATA_UPDATE(runtime_type, compile_type)                            \
            case runtime_type: {                                               \
                const compile_type *dataPtr =                                  \
                        static_cast<const compile_type*>(data);                \
                return metadata->update(tag, dataPtr, dataCount);              \
            }                                                                  \

            METADATA_UPDATE(TYPE_BYTE,     uint8_t);
            METADATA_UPDATE(TYPE_INT32,    int32_t);
            METADATA_UPDATE(TYPE_FLOAT,    float);
            METADATA_UPDATE(TYPE_INT64,    int64_t);
            METADATA_UPDATE(TYPE_DOUBLE,   double);
            METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);

            default: {
                // unreachable
                ALOGE("%s: Unreachable", __FUNCTION__);
                return INVALID_OPERATION;
            }
        }

#undef METADATA_UPDATE
    }
};
} // namespace {}

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);

// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {

    if (thiz == NULL) {
        return NULL;
    }

    return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
}

// Safe access to native pointer from object. Throws if not possible to access.
static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
                                                 const char* argName = "this") {

    if (thiz == NULL) {
        ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
              __FUNCTION__);
        jniThrowNullPointerException(env, argName);
        return NULL;
    }

    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
    if (metadata == NULL) {
        ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
              __FUNCTION__);
        jniThrowException(env, "java/lang/IllegalStateException",
                            "Metadata object was already closed");
        return NULL;
    }

    return metadata;
}

static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
    ALOGV("%s", __FUNCTION__);

    return reinterpret_cast<jlong>(new CameraMetadata());
}

static jlong CameraMetadata_allocateCopy(JNIEnv *env, jobject thiz,
        jobject other) {
    ALOGV("%s", __FUNCTION__);

    CameraMetadata* otherMetadata =
            CameraMetadata_getPointerThrow(env, other, "other");

    // In case of exception, return
    if (otherMetadata == NULL) return NULL;

    // Clone native metadata and return new pointer
    return reinterpret_cast<jlong>(new CameraMetadata(*otherMetadata));
}


static jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
    ALOGV("%s", __FUNCTION__);

    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);

    if (metadata == NULL) {
        ALOGW("%s: Returning early due to exception being thrown",
               __FUNCTION__);
        return JNI_TRUE; // actually throws java exc.
    }

    jboolean empty = metadata->isEmpty();

    ALOGV("%s: Empty returned %d, entry count was %zu",
          __FUNCTION__, empty, metadata->entryCount());

    return empty;
}

static jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
    ALOGV("%s", __FUNCTION__);

    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);

    if (metadata == NULL) return 0; // actually throws java exc.

    return metadata->entryCount();
}

// idempotent. calling more than once has no effect.
static void CameraMetadata_close(JNIEnv *env, jobject thiz) {
    ALOGV("%s", __FUNCTION__);

    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);

    if (metadata != NULL) {
        delete metadata;
        env->SetLongField(thiz, fields.metadata_ptr, 0);
    }

    LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
                        "Expected the native ptr to be 0 after #close");
}

static void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
    ALOGV("%s", __FUNCTION__);

    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);

    // order is important: we can't call another JNI method
    // if there is an exception pending
    if (metadata == NULL) return;

    CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");

    if (otherMetadata == NULL) return;

    metadata->swap(*otherMetadata);
}

static jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag) {
    ALOGV("%s (tag = %d)", __FUNCTION__, tag);

    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) return NULL;

    int tagType = get_camera_metadata_tag_type(tag);
    if (tagType == -1) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                             "Tag (%d) did not have a type", tag);
        return NULL;
    }
    size_t tagSize = Helpers::getTypeSize(tagType);

    camera_metadata_entry entry = metadata->find(tag);
    if (entry.count == 0) {
         if (!metadata->exists(tag)) {
             ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
             return NULL;
         } else {
             // OK: we will return a 0-sized array.
             ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__,
                   tag);
         }
    }

    jsize byteCount = entry.count * tagSize;
    jbyteArray byteArray = env->NewByteArray(byteCount);
    if (env->ExceptionCheck()) return NULL;

    // Copy into java array from native array
    ScopedByteArrayRW arrayWriter(env, byteArray);
    memcpy(arrayWriter.get(), entry.data.u8, byteCount);

    return byteArray;
}

static void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) {
    ALOGV("%s (tag = %d)", __FUNCTION__, tag);

    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) return;

    int tagType = get_camera_metadata_tag_type(tag);
    if (tagType == -1) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                             "Tag (%d) did not have a type", tag);
        return;
    }

    status_t res;

    if (src == NULL) {
        // If array is NULL, delete the entry
        if (metadata->exists(tag)) {
            res = metadata->erase(tag);
            ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
        } else {
            res = OK;
            ALOGV("%s: Don't need to erase", __FUNCTION__);
        }
    } else {
        // Copy from java array into native array
        ScopedByteArrayRO arrayReader(env, src);
        if (arrayReader.get() == NULL) return;

        res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
                                 tagType, arrayReader.get(), arrayReader.size());

        ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
    }

    if (res == OK) {
        return;
    } else if (res == BAD_VALUE) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                             "Src byte array was poorly formed");
    } else if (res == INVALID_OPERATION) {
        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                             "Internal error while trying to update metadata");
    } else {
        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                             "Unknown error (%d) while trying to update "
                            "metadata", res);
    }
}

struct DumpMetadataParams {
    int writeFd;
    const CameraMetadata* metadata;
};

static void* CameraMetadata_writeMetadataThread(void* arg) {
    DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);

    /*
     * Write the dumped data, and close the writing side FD.
     */
    p->metadata->dump(p->writeFd, /*verbosity*/2);

    if (close(p->writeFd) < 0) {
        ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
                __FUNCTION__, errno, strerror(errno));
    }

    return NULL;
}

static void CameraMetadata_dump(JNIEnv *env, jobject thiz) {
    ALOGV("%s", __FUNCTION__);
    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) {
        return;
    }

    /*
     * Create a socket pair for local streaming read/writes.
     *
     * The metadata will be dumped into the write side,
     * and then read back out (and logged) via the read side.
     */

    int writeFd, readFd;
    {

        int sv[2];
        if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
            jniThrowExceptionFmt(env, "java/io/IOException",
                    "Failed to create socketpair (errno = %#x, message = '%s')",
                    errno, strerror(errno));
            return;
        }
        writeFd = sv[0];
        readFd = sv[1];
    }

    /*
     * Create a thread for doing the writing.
     *
     * The reading and writing must be concurrent, otherwise
     * the write will block forever once it exhausts the capped
     * buffer size (from getsockopt).
     */
    pthread_t writeThread;
    DumpMetadataParams params = {
        writeFd,
        metadata
    };

    {
        int threadRet = pthread_create(&writeThread, /*attr*/NULL,
                CameraMetadata_writeMetadataThread, (void*)&params);

        if (threadRet != 0) {
            close(writeFd);

            jniThrowExceptionFmt(env, "java/io/IOException",
                    "Failed to create thread for writing (errno = %#x, message = '%s')",
                    threadRet, strerror(threadRet));
        }
    }

    /*
     * Read out a byte until stream is complete. Write completed lines
     * to ALOG.
     */
    {
        char out[] = {'\0', '\0'}; // large enough to append as a string
        String8 logLine;

        // Read one byte at a time! Very slow but avoids complicated \n scanning.
        ssize_t res;
        while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
            if (out[0] == '\n') {
                ALOGD("%s", logLine.string());
                logLine.clear();
            } else {
                logLine.append(out);
            }
        }

        if (res < 0) {
            jniThrowExceptionFmt(env, "java/io/IOException",
                    "Failed to read from fd (errno = %#x, message = '%s')",
                    errno, strerror(errno));
            //return;
        } else if (!logLine.isEmpty()) {
            ALOGD("%s", logLine.string());
        }
    }

    int res;

    // Join until thread finishes. Ensures params/metadata is valid until then.
    if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
        ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
                __FUNCTION__, res, strerror(res));
    }
}

static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
    ALOGV("%s", __FUNCTION__);
    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) {
        return;
    }

    Parcel* parcelNative = parcelForJavaObject(env, parcel);
    if (parcelNative == NULL) {
        jniThrowNullPointerException(env, "parcel");
        return;
    }

    status_t err;
    if ((err = metadata->readFromParcel(parcelNative)) != OK) {
        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                             "Failed to read from parcel (error code %d)", err);
        return;
    }
}

static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
    ALOGV("%s", __FUNCTION__);
    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) {
        return;
    }

    Parcel* parcelNative = parcelForJavaObject(env, parcel);
    if (parcelNative == NULL) {
        jniThrowNullPointerException(env, "parcel");
        return;
    }

    status_t err;
    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                                  "Failed to write to parcel (error code %d)", err);
        return;
    }
}

} // extern "C"

//-------------------------------------------------

static JNINativeMethod gCameraMetadataMethods[] = {
// static methods
  { "nativeClassInit",
    "()V",
    (void *)CameraMetadata_classInit },
  { "nativeGetAllVendorKeys",
    "(Ljava/lang/Class;)Ljava/util/ArrayList;",
    (void *)CameraMetadata_getAllVendorKeys},
  { "nativeGetTagFromKey",
    "(Ljava/lang/String;)I",
    (void *)CameraMetadata_getTagFromKey },
  { "nativeGetTypeFromTag",
    "(I)I",
    (void *)CameraMetadata_getTypeFromTag },
  { "nativeSetupGlobalVendorTagDescriptor",
    "()I",
    (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
// instance methods
  { "nativeAllocate",
    "()J",
    (void*)CameraMetadata_allocate },
  { "nativeAllocateCopy",
    "(L" CAMERA_METADATA_CLASS_NAME ";)J",
    (void *)CameraMetadata_allocateCopy },
  { "nativeIsEmpty",
    "()Z",
    (void*)CameraMetadata_isEmpty },
  { "nativeGetEntryCount",
    "()I",
    (void*)CameraMetadata_getEntryCount },
  { "nativeClose",
    "()V",
    (void*)CameraMetadata_close },
  { "nativeSwap",
    "(L" CAMERA_METADATA_CLASS_NAME ";)V",
    (void *)CameraMetadata_swap },
  { "nativeReadValues",
    "(I)[B",
    (void *)CameraMetadata_readValues },
  { "nativeWriteValues",
    "(I[B)V",
    (void *)CameraMetadata_writeValues },
  { "nativeDump",
    "()V",
    (void *)CameraMetadata_dump },
// Parcelable interface
  { "nativeReadFromParcel",
    "(Landroid/os/Parcel;)V",
    (void *)CameraMetadata_readFromParcel },
  { "nativeWriteToParcel",
    "(Landroid/os/Parcel;)V",
    (void *)CameraMetadata_writeToParcel },
};

struct field {
    const char *class_name;
    const char *field_name;
    const char *field_type;
    jfieldID   *jfield;
};

static int find_fields(JNIEnv *env, field *fields, int count)
{
    for (int i = 0; i < count; i++) {
        field *f = &fields[i];
        jclass clazz = env->FindClass(f->class_name);
        if (clazz == NULL) {
            ALOGE("Can't find %s", f->class_name);
            return -1;
        }

        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
        if (field == NULL) {
            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
            return -1;
        }

        *(f->jfield) = field;
    }

    return 0;
}

// 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,
            gCameraMetadataMethods,
            NELEM(gCameraMetadataMethods));
}

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__);

    field fields_to_find[] = {
        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
    };

    // Do this here instead of in register_native_methods,
    // since otherwise it will fail to find the fields.
    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
        return;

    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);
    const char *key = keyScoped.c_str();
    if (key == NULL) {
        // exception thrown by ScopedUtfChars
        return 0;
    }
    size_t keyLength = strlen(key);

    ALOGV("%s (key = '%s')", __FUNCTION__, key);

    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();

    SortedVector<String8> vendorSections;
    size_t vendorSectionCount = 0;

    if (vTags != NULL) {
        vendorSections = vTags->getAllSectionNames();
        vendorSectionCount = vendorSections.size();
    }

    // First, find the section by the longest string match
    const char *section = NULL;
    size_t sectionIndex = 0;
    size_t sectionLength = 0;
    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
    for (size_t i = 0; i < totalSectionCount; ++i) {

        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
                vendorSections[i - ANDROID_SECTION_COUNT].string();
        if (kIsDebug) {
            ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
        }
        if (strstr(key, str) == key) { // key begins with the section name
            size_t strLength = strlen(str);

            if (kIsDebug) {
                ALOGV("%s: Key begins with section name", __FUNCTION__);
            }

            // section name is the longest we've found so far
            if (section == NULL || sectionLength < strLength) {
                section = str;
                sectionIndex = i;
                sectionLength = strLength;

                if (kIsDebug) {
                    ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
                }
            }
        }
    }

    // TODO: Make above get_camera_metadata_section_from_name ?

    if (section == NULL) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                             "Could not find section name for key '%s')", key);
        return 0;
    } else {
        ALOGV("%s: Found matched section '%s' (%zu)",
              __FUNCTION__, section, sectionIndex);
    }

    // Get the tag name component of the key
    const char *keyTagName = key + sectionLength + 1; // x.y.z -> z
    if (sectionLength + 1 >= keyLength) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                             "Key length too short for key '%s')", key);
        return 0;
    }

    // Match rest of name against the tag names in that section only
    uint32_t tag = 0;
    if (sectionIndex < ANDROID_SECTION_COUNT) {
        // Match built-in tags (typically android.*)
        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
        tagEnd = camera_metadata_section_bounds[sectionIndex][1];

        for (tag = tagBegin; tag < tagEnd; ++tag) {
            const char *tagName = get_camera_metadata_tag_name(tag);

            if (strcmp(keyTagName, tagName) == 0) {
                ALOGV("%s: Found matched tag '%s' (%d)",
                      __FUNCTION__, tagName, tag);
                break;
            }
        }

        if (tag == tagEnd) {
            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                                 "Could not find tag name for key '%s')", key);
            return 0;
        }
    } else if (vTags != NULL) {
        // Match vendor tags (typically com.*)
        const String8 sectionName(section);
        const String8 tagName(keyTagName);

        status_t res = OK;
        if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) {
            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                    "%s: No vendor tag matches key '%s'", __FUNCTION__, key);
            return 0;
        }
    }

    // TODO: Make above get_camera_metadata_tag_from_name ?

    return tag;
}

static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
    int tagType = get_camera_metadata_tag_type(tag);
    if (tagType == -1) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                             "Tag (%d) did not have a type", tag);
        return -1;
    }

    return tagType;
}

static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
    const String16 NAME("media.camera");
    sp<ICameraService> cameraService;
    status_t err = getService(NAME, /*out*/&cameraService);

    if (err != OK) {
        ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
                strerror(-err), err);
        return err;
    }

    sp<VendorTagDescriptor> desc;
    err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);

    if (err == -EOPNOTSUPP) {
        ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
        VendorTagDescriptor::clearGlobalVendorTagDescriptor();

        return OK;
    } else if (err != OK) {
        ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
                __FUNCTION__, strerror(-err), err);
        return err;
    }

    err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);

    return err;
}

} // extern "C"
