/*
**
** 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 <android/hardware/ICameraService.h>
#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.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 const 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<hardware::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 hardware::ICameraService::ERROR_DISCONNECTED;
    }

    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
    binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());

    if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
        // No camera module available, not an error on devices with no cameras
        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
        return OK;
    } else if (!res.isOk()) {
        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
        ALOGE("%s: Failed to setup vendor tag descriptors: %s",
                __FUNCTION__, res.toString8().string());
        return res.serviceSpecificErrorCode();
    }

    err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);

    if (err != OK) {
        return hardware::ICameraService::ERROR_INVALID_OPERATION;
    }
    return OK;
}

} // extern "C"
