/*
 * Copyright (C) 2016 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 "android_os_HwBlob"
#include <android-base/logging.h>

#include "android_os_HwBlob.h"

#include "android_os_HwParcel.h"

#include <JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/Status.h>
#include <nativehelper/ScopedLocalRef.h>

#include "core_jni_helpers.h"

using android::AndroidRuntime;
using android::hardware::hidl_string;

#define PACKAGE_PATH    "android/os"
#define CLASS_NAME      "HwBlob"
#define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME

namespace android {

static struct fields_t {
    jfieldID contextID;
    jmethodID constructID;

} gFields;

// static
void JHwBlob::InitClass(JNIEnv *env) {
    ScopedLocalRef<jclass> clazz(
            env, FindClassOrDie(env, CLASS_PATH));

    gFields.contextID =
        GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");

    gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V");
}

// static
sp<JHwBlob> JHwBlob::SetNativeContext(
        JNIEnv *env, jobject thiz, const sp<JHwBlob> &context) {
    sp<JHwBlob> old = (JHwBlob *)env->GetLongField(thiz, gFields.contextID);

    if (context != NULL) {
        context->incStrong(NULL /* id */);
    }

    if (old != NULL) {
        old->decStrong(NULL /* id */);
    }

    env->SetLongField(thiz, gFields.contextID, (long)context.get());

    return old;
}

// static
sp<JHwBlob> JHwBlob::GetNativeContext(JNIEnv *env, jobject thiz) {
    return (JHwBlob *)env->GetLongField(thiz, gFields.contextID);
}

JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size)
    : mBuffer(nullptr),
      mSize(size),
      mOwnsBuffer(true),
      mHandle(0) {
    jclass clazz = env->GetObjectClass(thiz);
    CHECK(clazz != NULL);

    mClass = (jclass)env->NewGlobalRef(clazz);
    mObject = env->NewWeakGlobalRef(thiz);

    if (size > 0) {
        mBuffer = malloc(size);
    }
}

JHwBlob::~JHwBlob() {
    if (mOwnsBuffer) {
        free(mBuffer);
        mBuffer = nullptr;
    }

    JNIEnv *env = AndroidRuntime::getJNIEnv();

    env->DeleteWeakGlobalRef(mObject);
    mObject = NULL;

    env->DeleteGlobalRef(mClass);
    mClass = NULL;
}

void JHwBlob::setTo(const void *ptr, size_t handle) {
    CHECK_EQ(mSize, 0u);
    CHECK(mBuffer == nullptr);

    mBuffer = const_cast<void *>(ptr);
    mSize = SIZE_MAX;  // XXX
    mOwnsBuffer = false;
    mHandle = handle;
}

status_t JHwBlob::getHandle(size_t *handle) const {
    if (mOwnsBuffer) {
        return INVALID_OPERATION;
    }

    *handle = mHandle;

    return OK;
}

status_t JHwBlob::read(size_t offset, void *data, size_t size) const {
    if (offset + size > mSize) {
        return -ERANGE;
    }

    memcpy(data, (const uint8_t *)mBuffer + offset, size);

    return OK;
}

status_t JHwBlob::write(size_t offset, const void *data, size_t size) {
    if (offset + size > mSize) {
        return -ERANGE;
    }

    memcpy((uint8_t *)mBuffer + offset, data, size);

    return OK;
}

status_t JHwBlob::getString(size_t offset, const hidl_string **s) const {
    if ((offset + sizeof(hidl_string)) > mSize) {
        return -ERANGE;
    }

    *s = reinterpret_cast<const hidl_string *>(
            (const uint8_t *)mBuffer + offset);

    return OK;
}

const void *JHwBlob::data() const {
    return mBuffer;
}

size_t JHwBlob::size() const {
    return mSize;
}

status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
    size_t index = mSubBlobs.add();
    BlobInfo *info = &mSubBlobs.editItemAt(index);

    info->mOffset = offset;
    info->mBlob = blob;

    const void *data = blob->data();

    return write(offset, &data, sizeof(data));
}

status_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const {
    size_t handle;
    status_t err = parcel->writeBuffer(data(), size(), &handle);

    if (err != OK) {
        return err;
    }

    for (size_t i = 0; i < mSubBlobs.size(); ++i) {
        const BlobInfo &info = mSubBlobs[i];

        err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);

        if (err != OK) {
            return err;
        }
    }

    return OK;
}

status_t JHwBlob::writeEmbeddedToParcel(
        hardware::Parcel *parcel,
        size_t parentHandle,
        size_t parentOffset) const {
    size_t handle;
    status_t err = parcel->writeEmbeddedBuffer(
            data(), size(), &handle, parentHandle, parentOffset);

    if (err != OK) {
        return err;
    }

    for (size_t i = 0; i < mSubBlobs.size(); ++i) {
        const BlobInfo &info = mSubBlobs[i];

        err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);

        if (err != OK) {
            return err;
        }
    }

    return OK;
}

// static
jobject JHwBlob::NewObject(JNIEnv *env, const void *ptr, size_t handle) {
    jobject obj = JHwBlob::NewObject(env, 0 /* size */);
    JHwBlob::GetNativeContext(env, obj)->setTo(ptr, handle);

    return obj;
}

// static
jobject JHwBlob::NewObject(JNIEnv *env, size_t size) {
    ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));

    jmethodID constructID =
        GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V");

    // XXX Again cannot refer to gFields.constructID because InitClass may
    // not have been called yet.

    return env->NewObject(clazz.get(), constructID, size);
}

}  // namespace android

////////////////////////////////////////////////////////////////////////////////

using namespace android;

static void releaseNativeContext(void *nativeContext) {
    sp<JHwBlob> parcel = (JHwBlob *)nativeContext;

    if (parcel != NULL) {
        parcel->decStrong(NULL /* id */);
    }
}

static jlong JHwBlob_native_init(JNIEnv *env) {
    JHwBlob::InitClass(env);

    return reinterpret_cast<jlong>(&releaseNativeContext);
}

static void JHwBlob_native_setup(
        JNIEnv *env, jobject thiz, jint size) {
    sp<JHwBlob> context = new JHwBlob(env, thiz, size);

    JHwBlob::SetNativeContext(env, thiz, context);
}

#define DEFINE_BLOB_GETTER(Suffix,Type)                                        \
static Type JHwBlob_native_get ## Suffix(                                      \
        JNIEnv *env, jobject thiz, jlong offset) {                             \
    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
                                                                               \
    Type x;                                                                    \
    status_t err = blob->read(offset, &x, sizeof(x));                          \
                                                                               \
    if (err != OK) {                                                           \
        signalExceptionForError(env, err);                                     \
        return 0;                                                              \
    }                                                                          \
                                                                               \
    return x;                                                                  \
}

DEFINE_BLOB_GETTER(Int8,jbyte)
DEFINE_BLOB_GETTER(Int16,jshort)
DEFINE_BLOB_GETTER(Int32,jint)
DEFINE_BLOB_GETTER(Int64,jlong)
DEFINE_BLOB_GETTER(Float,jfloat)
DEFINE_BLOB_GETTER(Double,jdouble)

static jboolean JHwBlob_native_getBool(
        JNIEnv *env, jobject thiz, jlong offset) {
    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);

    bool x;
    status_t err = blob->read(offset, &x, sizeof(x));

    if (err != OK) {
        signalExceptionForError(env, err);
        return 0;
    }

    return (jboolean)x;
}

static jstring JHwBlob_native_getString(
        JNIEnv *env, jobject thiz, jlong offset) {
    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);

    const hidl_string *s;
    status_t err = blob->getString(offset, &s);

    if (err != OK) {
        signalExceptionForError(env, err);
        return nullptr;
    }

    return env->NewStringUTF(s->c_str());
}

#define DEFINE_BLOB_PUTTER(Suffix,Type)                                        \
static void JHwBlob_native_put ## Suffix(                                      \
        JNIEnv *env, jobject thiz, jlong offset, Type x) {                     \
                                                                               \
    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
                                                                               \
    status_t err = blob->write(offset, &x, sizeof(x));                         \
                                                                               \
    if (err != OK) {                                                           \
        signalExceptionForError(env, err);                                     \
    }                                                                          \
}

DEFINE_BLOB_PUTTER(Int8,jbyte)
DEFINE_BLOB_PUTTER(Int16,jshort)
DEFINE_BLOB_PUTTER(Int32,jint)
DEFINE_BLOB_PUTTER(Int64,jlong)
DEFINE_BLOB_PUTTER(Float,jfloat)
DEFINE_BLOB_PUTTER(Double,jdouble)

static void JHwBlob_native_putBool(
        JNIEnv *env, jobject thiz, jlong offset, jboolean x) {

    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);

    bool b = (bool)x;
    status_t err = blob->write(offset, &b, sizeof(b));

    if (err != OK) {
        signalExceptionForError(env, err);
    }
}

static void JHwBlob_native_putString(
        JNIEnv *env, jobject thiz, jlong offset, jstring stringObj) {
    if (stringObj == nullptr) {
        jniThrowException(env, "java/lang/NullPointerException", nullptr);
        return;
    }

    const char *s = env->GetStringUTFChars(stringObj, nullptr);

    if (s == nullptr) {
        return;
    }

    size_t size = strlen(s) + 1;
    ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
    sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
    subBlob->write(0 /* offset */, s, size);

    env->ReleaseStringUTFChars(stringObj, s);
    s = nullptr;

    hidl_string tmp;
    tmp.setToExternal(static_cast<const char *>(subBlob->data()), size - 1);

    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
    blob->write(offset, &tmp, sizeof(tmp));
    blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
}

static void JHwBlob_native_putBlob(
        JNIEnv *env, jobject thiz, jlong offset, jobject blobObj) {
    if (blobObj == nullptr) {
        jniThrowException(env, "java/lang/NullPointerException", nullptr);
        return;
    }

    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
    sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, blobObj);

    blob->putBlob(offset, subBlob);
}

static jlong JHwBlob_native_handle(JNIEnv *env, jobject thiz) {
    size_t handle;
    status_t err = JHwBlob::GetNativeContext(env, thiz)->getHandle(&handle);

    if (err != OK) {
        signalExceptionForError(env, err);
        return 0;
    }

    return handle;
}

static JNINativeMethod gMethods[] = {
    { "native_init", "()J", (void *)JHwBlob_native_init },
    { "native_setup", "(I)V", (void *)JHwBlob_native_setup },

    { "getBool", "(J)Z", (void *)JHwBlob_native_getBool },
    { "getInt8", "(J)B", (void *)JHwBlob_native_getInt8 },
    { "getInt16", "(J)S", (void *)JHwBlob_native_getInt16 },
    { "getInt32", "(J)I", (void *)JHwBlob_native_getInt32 },
    { "getInt64", "(J)J", (void *)JHwBlob_native_getInt64 },
    { "getFloat", "(J)F", (void *)JHwBlob_native_getFloat },
    { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble },
    { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString },

    { "putBool", "(JZ)V", (void *)JHwBlob_native_putBool },
    { "putInt8", "(JB)V", (void *)JHwBlob_native_putInt8 },
    { "putInt16", "(JS)V", (void *)JHwBlob_native_putInt16 },
    { "putInt32", "(JI)V", (void *)JHwBlob_native_putInt32 },
    { "putInt64", "(JJ)V", (void *)JHwBlob_native_putInt64 },
    { "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat },
    { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
    { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },

    { "putBlob", "(JL" PACKAGE_PATH "/HwBlob;)V",
        (void *)JHwBlob_native_putBlob },

    { "handle", "()J", (void *)JHwBlob_native_handle },
};

namespace android {

int register_android_os_HwBlob(JNIEnv *env) {
    return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
}

}  // namespace android

