/*
 * 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 "android_os_NativeHandle.h"

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

#include "core_jni_helpers.h"

using android::AndroidRuntime;
using android::hardware::hidl_handle;
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 != nullptr) {
        context->incStrong(nullptr /* id */);
    }

    if (old != nullptr) {
        old->decStrong(nullptr /* 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),
      mType(BlobType::GENERIC),
      mOwnsBuffer(true),
      mHandle(0) {
    if (size > 0) {
        mBuffer = calloc(size, 1);
    }
}

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

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

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

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

void JHwBlob::specializeBlobTo(BlobType type) {
    CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
    mType = type;
}

JHwBlob::BlobType JHwBlob::type() const {
    return mType;
}

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 {
    CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));

    size_t handle = 0;
    status_t err = parcel->writeBuffer(data(), size(), &handle);

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

    return writeSubBlobsToParcel(parcel, handle);
}

status_t JHwBlob::writeEmbeddedToParcel(
        hardware::Parcel *parcel,
        size_t parentHandle,
        size_t parentOffset) const {
    size_t handle = 0;
    status_t err = OK;

    switch (mType) {
        case BlobType::GENERIC: {
            err = parcel->writeEmbeddedBuffer(data(), size(), &handle, parentHandle, parentOffset);
            break;
        }
        case BlobType::NATIVE_HANDLE: {
            err = parcel->writeEmbeddedNativeHandle(
                    static_cast<const native_handle *>(data()), parentHandle, parentOffset);

            CHECK(mSubBlobs.empty());
            break;
        }
        default: { err = INVALID_OPERATION; }
    }

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

    return writeSubBlobsToParcel(parcel, handle);
}

status_t JHwBlob::writeSubBlobsToParcel(hardware::Parcel *parcel,
        size_t parentHandle) const {
    for (size_t i = 0; i < mSubBlobs.size(); ++i) {
        const BlobInfo &info = mSubBlobs[i];
        status_t err = info.mBlob->writeEmbeddedToParcel(parcel, parentHandle, 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 != nullptr) {
        parcel->decStrong(nullptr /* id */);
    }
}

static jlong JHwBlob_native_init(JNIEnv *env, jclass /*clazz*/) {
    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());
}

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

    return reinterpret_cast<jlong>(blob->data()) + offset;
}

#define DEFINE_BLOB_ARRAY_COPIER(Suffix,Type,NewType)                          \
static void JHwBlob_native_copyTo ## Suffix ## Array(                          \
        JNIEnv *env,                                                           \
        jobject thiz,                                                          \
        jlong offset,                                                          \
        Type ## Array array,                                                   \
        jint size) {                                                           \
    if (array == nullptr) {                                                    \
        jniThrowException(env, "java/lang/NullPointerException", nullptr);     \
        return;                                                                \
    }                                                                          \
                                                                               \
    if (env->GetArrayLength(array) < size) {                                   \
        signalExceptionForError(env, BAD_VALUE);                               \
        return;                                                                \
    }                                                                          \
                                                                               \
    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
                                                                               \
    if ((offset + size * sizeof(Type)) > blob->size()) {                       \
        signalExceptionForError(env, -ERANGE);                                 \
        return;                                                                \
    }                                                                          \
                                                                               \
    env->Set ## NewType ## ArrayRegion(                                        \
            array,                                                             \
            0 /* start */,                                                     \
            size,                                                              \
            reinterpret_cast<const Type *>(                                    \
                static_cast<const uint8_t *>(blob->data()) + offset));         \
}

DEFINE_BLOB_ARRAY_COPIER(Int8,jbyte,Byte)
DEFINE_BLOB_ARRAY_COPIER(Int16,jshort,Short)
DEFINE_BLOB_ARRAY_COPIER(Int32,jint,Int)
DEFINE_BLOB_ARRAY_COPIER(Int64,jlong,Long)
DEFINE_BLOB_ARRAY_COPIER(Float,jfloat,Float)
DEFINE_BLOB_ARRAY_COPIER(Double,jdouble,Double)

static void JHwBlob_native_copyToBoolArray(
        JNIEnv *env,
        jobject thiz,
        jlong offset,
        jbooleanArray array,
        jint size) {
    if (array == nullptr) {
        jniThrowException(env, "java/lang/NullPointerException", nullptr);
        return;
    }

    if (env->GetArrayLength(array) < size) {
        signalExceptionForError(env, BAD_VALUE);
        return;
    }

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

    if ((offset + size * sizeof(bool)) > blob->size()) {
        signalExceptionForError(env, -ERANGE);
        return;
    }

    const bool *src =
        reinterpret_cast<const bool *>(
                static_cast<const uint8_t *>(blob->data()) + offset);

    jboolean *dst = env->GetBooleanArrayElements(array, nullptr /* isCopy */);

    for (jint i = 0; i < size; ++i) {
        dst[i] = src[i];
    }

    env->ReleaseBooleanArrayElements(array, dst, 0 /* mode */);
    dst = nullptr;
}

#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_putNativeHandle(JNIEnv *env, jobject thiz,
        jlong offset, jobject jHandle) {
    std::unique_ptr<native_handle_t, int(*)(native_handle_t*)> nativeHandle(
            JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */),
            native_handle_delete);

    size_t size = 0;
    if (nativeHandle != nullptr) {
        size = sizeof(native_handle_t) + nativeHandle->numFds * sizeof(int)
               + nativeHandle->numInts * sizeof(int);
    }

    ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
    sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
    subBlob->specializeBlobTo(JHwBlob::BlobType::NATIVE_HANDLE);
    subBlob->write(0 /* offset */, nativeHandle.get(), size);

    hidl_handle cppHandle;
    cppHandle.setTo(static_cast<native_handle_t *>(subBlob->data()), false /* shouldOwn */);

    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
    blob->write(offset, &cppHandle, sizeof(cppHandle));
    blob->putBlob(offset + hidl_handle::kOffsetOfNativeHandle, subBlob);
}

#define DEFINE_BLOB_ARRAY_PUTTER(Suffix,Type,NewType)                          \
static void JHwBlob_native_put ## Suffix ## Array(                             \
        JNIEnv *env, jobject thiz, jlong offset, Type ## Array array) {        \
    Scoped ## NewType ## ArrayRO autoArray(env, array);                        \
                                                                               \
    if (array == nullptr) {                                                    \
        /* NullpointerException already pending */                             \
        return;                                                                \
    }                                                                          \
                                                                               \
    sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
                                                                               \
    status_t err = blob->write(                                                \
            offset, autoArray.get(), autoArray.size() * sizeof(Type));         \
                                                                               \
    if (err != OK) {                                                           \
        signalExceptionForError(env, err);                                     \
    }                                                                          \
}

DEFINE_BLOB_ARRAY_PUTTER(Int8,jbyte,Byte)
DEFINE_BLOB_ARRAY_PUTTER(Int16,jshort,Short)
DEFINE_BLOB_ARRAY_PUTTER(Int32,jint,Int)
DEFINE_BLOB_ARRAY_PUTTER(Int64,jlong,Long)
DEFINE_BLOB_ARRAY_PUTTER(Float,jfloat,Float)
DEFINE_BLOB_ARRAY_PUTTER(Double,jdouble,Double)

static void JHwBlob_native_putBoolArray(
        JNIEnv *env, jobject thiz, jlong offset, jbooleanArray array) {
    ScopedBooleanArrayRO autoArray(env, array);

    if (array == nullptr) {
        /* NullpointerException already pending */
        return;
    }

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

    if ((offset + autoArray.size() * sizeof(bool)) > blob->size()) {
        signalExceptionForError(env, -ERANGE);
        return;
    }

    const jboolean *src = autoArray.get();

    bool *dst = reinterpret_cast<bool *>(
            static_cast<uint8_t *>(blob->data()) + offset);

    for (size_t i = 0; i < autoArray.size(); ++i) {
        dst[i] = src[i];
    }
}

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 },
    { "getFieldHandle", "(J)J", (void*) JHwBlob_native_getFieldHandle},

    { "copyToBoolArray", "(J[ZI)V", (void *)JHwBlob_native_copyToBoolArray },
    { "copyToInt8Array", "(J[BI)V", (void *)JHwBlob_native_copyToInt8Array },
    { "copyToInt16Array", "(J[SI)V", (void *)JHwBlob_native_copyToInt16Array },
    { "copyToInt32Array", "(J[II)V", (void *)JHwBlob_native_copyToInt32Array },
    { "copyToInt64Array", "(J[JI)V", (void *)JHwBlob_native_copyToInt64Array },
    { "copyToFloatArray", "(J[FI)V", (void *)JHwBlob_native_copyToFloatArray },
    { "copyToDoubleArray", "(J[DI)V", (void *)JHwBlob_native_copyToDoubleArray },

    { "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 },
    { "putNativeHandle", "(JL" PACKAGE_PATH "/NativeHandle;)V",
        (void*)JHwBlob_native_putNativeHandle },

    { "putBoolArray", "(J[Z)V", (void *)JHwBlob_native_putBoolArray },
    { "putInt8Array", "(J[B)V", (void *)JHwBlob_native_putInt8Array },
    { "putInt16Array", "(J[S)V", (void *)JHwBlob_native_putInt16Array },
    { "putInt32Array", "(J[I)V", (void *)JHwBlob_native_putInt32Array },
    { "putInt64Array", "(J[J)V", (void *)JHwBlob_native_putInt64Array },
    { "putFloatArray", "(J[F)V", (void *)JHwBlob_native_putFloatArray },
    { "putDoubleArray", "(J[D)V", (void *)JHwBlob_native_putDoubleArray },

    { "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

