/*
 * 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 "JHwRemoteBinder"
#include <android-base/logging.h>

#include "android_os_HwRemoteBinder.h"

#include "android_os_HwParcel.h"

#include <android/hidl/base/1.0/IBase.h>
#include <android/hidl/base/1.0/BpHwBase.h>
#include <android/hidl/base/1.0/BnHwBase.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/Status.h>
#include <hidl/HidlTransportSupport.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedLocalRef.h>

#include "core_jni_helpers.h"

using android::AndroidRuntime;

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

namespace android {

static struct fields_t {
    jclass proxy_class;
    jfieldID contextID;
    jmethodID constructID;
    jmethodID sendDeathNotice;
} gProxyOffsets;

static struct class_offsets_t
{
    jmethodID mGetName;
} gClassOffsets;

static JavaVM* jnienv_to_javavm(JNIEnv* env)
{
    JavaVM* vm;
    return env->GetJavaVM(&vm) >= 0 ? vm : NULL;
}

static JNIEnv* javavm_to_jnienv(JavaVM* vm)
{
    JNIEnv* env;
    return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
}

// ----------------------------------------------------------------------------
class HwBinderDeathRecipient : public hardware::IBinder::DeathRecipient
{
public:
    HwBinderDeathRecipient(JNIEnv* env, jobject object, jlong cookie, const sp<HwBinderDeathRecipientList>& list)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
          mObjectWeak(NULL), mCookie(cookie), mList(list)
    {
        // These objects manage their own lifetimes so are responsible for final bookkeeping.
        // The list holds a strong reference to this object.
        list->add(this);
    }

    void binderDied(const wp<hardware::IBinder>& who)
    {
        if (mObject != NULL) {
            JNIEnv* env = javavm_to_jnienv(mVM);

            env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, mObject, mCookie);
            if (env->ExceptionCheck()) {
                ALOGE("Uncaught exception returned from death notification.");
                env->ExceptionClear();
            }

            // Serialize with our containing HwBinderDeathRecipientList so that we can't
            // delete the global ref on mObject while the list is being iterated.
            sp<HwBinderDeathRecipientList> list = mList.promote();
            if (list != NULL) {
                AutoMutex _l(list->lock());

                // Demote from strong ref to weak after binderDied() has been delivered,
                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
                mObjectWeak = env->NewWeakGlobalRef(mObject);
                env->DeleteGlobalRef(mObject);
                mObject = NULL;
            }
        }
    }

    void clearReference()
    {
        sp<HwBinderDeathRecipientList> list = mList.promote();
        if (list != NULL) {
            list->remove(this);
        } else {
            ALOGE("clearReference() on JDR %p but DRL wp purged", this);
        }
    }

    bool matches(jobject obj) {
        bool result;
        JNIEnv* env = javavm_to_jnienv(mVM);

        if (mObject != NULL) {
            result = env->IsSameObject(obj, mObject);
        } else {
            jobject me = env->NewLocalRef(mObjectWeak);
            result = env->IsSameObject(obj, me);
            env->DeleteLocalRef(me);
        }
        return result;
    }

    void warnIfStillLive() {
        if (mObject != NULL) {
            // Okay, something is wrong -- we have a hard reference to a live death
            // recipient on the VM side, but the list is being torn down.
            JNIEnv* env = javavm_to_jnienv(mVM);
            ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
            ScopedLocalRef<jstring> nameRef(env,
                    (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
            ScopedUtfChars nameUtf(env, nameRef.get());
            if (nameUtf.c_str() != NULL) {
                ALOGW("BinderProxy is being destroyed but the application did not call "
                        "unlinkToDeath to unlink all of its death recipients beforehand.  "
                        "Releasing leaked death recipient: %s", nameUtf.c_str());
            } else {
                ALOGW("BinderProxy being destroyed; unable to get DR object name");
                env->ExceptionClear();
            }
        }
    }

protected:
    virtual ~HwBinderDeathRecipient()
    {
        JNIEnv* env = javavm_to_jnienv(mVM);
        if (mObject != NULL) {
            env->DeleteGlobalRef(mObject);
        } else {
            env->DeleteWeakGlobalRef(mObjectWeak);
        }
    }

private:
    JavaVM* const mVM;
    jobject mObject;
    jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied()
    jlong mCookie;
    wp<HwBinderDeathRecipientList> mList;
};
// ----------------------------------------------------------------------------

HwBinderDeathRecipientList::HwBinderDeathRecipientList() {
}

HwBinderDeathRecipientList::~HwBinderDeathRecipientList() {
    AutoMutex _l(mLock);

    for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
        deathRecipient->warnIfStillLive();
    }
}

void HwBinderDeathRecipientList::add(const sp<HwBinderDeathRecipient>& recipient) {
    AutoMutex _l(mLock);

    mList.push_back(recipient);
}

void HwBinderDeathRecipientList::remove(const sp<HwBinderDeathRecipient>& recipient) {
    AutoMutex _l(mLock);

    List< sp<HwBinderDeathRecipient> >::iterator iter;
    for (iter = mList.begin(); iter != mList.end(); iter++) {
        if (*iter == recipient) {
            mList.erase(iter);
            return;
        }
    }
}

sp<HwBinderDeathRecipient> HwBinderDeathRecipientList::find(jobject recipient) {
    AutoMutex _l(mLock);

    for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
        if (deathRecipient->matches(recipient)) {
            return deathRecipient;
        }
    }
    return NULL;
}

Mutex& HwBinderDeathRecipientList::lock() {
    return mLock;
}

// static
void JHwRemoteBinder::InitClass(JNIEnv *env) {
    jclass clazz = FindClassOrDie(env, CLASS_PATH);

    gProxyOffsets.proxy_class = MakeGlobalRefOrDie(env, clazz);
    gProxyOffsets.contextID =
        GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
    gProxyOffsets.constructID = GetMethodIDOrDie(env, clazz, "<init>", "()V");
    gProxyOffsets.sendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
            "(Landroid/os/IHwBinder$DeathRecipient;J)V");

    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
}

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

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

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

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

    return old;
}

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

// static
jobject JHwRemoteBinder::NewObject(
        JNIEnv *env, const sp<hardware::IBinder> &binder) {
    ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));

    // XXX Have to look up the constructor here because otherwise that static
    // class initializer isn't called and gProxyOffsets.constructID is undefined :(

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

    jobject obj = env->NewObject(clazz.get(), constructID);
    JHwRemoteBinder::GetNativeContext(env, obj)->setBinder(binder);

    return obj;
}

JHwRemoteBinder::JHwRemoteBinder(
        JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder)
    : mBinder(binder) {
    mDeathRecipientList = new HwBinderDeathRecipientList();
    jclass clazz = env->GetObjectClass(thiz);
    CHECK(clazz != NULL);

    mObject = env->NewWeakGlobalRef(thiz);
}

JHwRemoteBinder::~JHwRemoteBinder() {
    JNIEnv *env = AndroidRuntime::getJNIEnv();

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

sp<hardware::IBinder> JHwRemoteBinder::getBinder() const {
    return mBinder;
}

void JHwRemoteBinder::setBinder(const sp<hardware::IBinder> &binder) {
    mBinder = binder;
}

sp<HwBinderDeathRecipientList> JHwRemoteBinder::getDeathRecipientList() const {
    return mDeathRecipientList;
}

}  // namespace android

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

using namespace android;

static void releaseNativeContext(void *nativeContext) {
    sp<JHwRemoteBinder> binder = (JHwRemoteBinder *)nativeContext;

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

static jlong JHwRemoteBinder_native_init(JNIEnv *env) {
    JHwRemoteBinder::InitClass(env);

    return reinterpret_cast<jlong>(&releaseNativeContext);
}

static void JHwRemoteBinder_native_setup_empty(JNIEnv *env, jobject thiz) {
    sp<JHwRemoteBinder> context =
        new JHwRemoteBinder(env, thiz, NULL /* service */);

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

static void JHwRemoteBinder_native_transact(
        JNIEnv *env,
        jobject thiz,
        jint code,
        jobject requestObj,
        jobject replyObj,
        jint flags) {
    sp<hardware::IBinder> binder =
        JHwRemoteBinder::GetNativeContext(env, thiz)->getBinder();

    if (requestObj == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", NULL);
        return;
    }

    const hardware::Parcel *request =
        JHwParcel::GetNativeContext(env, requestObj)->getParcel();

    hardware::Parcel *reply =
        JHwParcel::GetNativeContext(env, replyObj)->getParcel();

    status_t err = binder->transact(code, *request, reply, flags);
    signalExceptionForError(env, err, true /* canThrowRemoteException */);
}

static jboolean JHwRemoteBinder_linkToDeath(JNIEnv* env, jobject thiz,
        jobject recipient, jlong cookie)
{
    if (recipient == NULL) {
        jniThrowNullPointerException(env, NULL);
        return JNI_FALSE;
    }

    sp<JHwRemoteBinder> context = JHwRemoteBinder::GetNativeContext(env, thiz);
    sp<hardware::IBinder> binder = context->getBinder();

    if (!binder->localBinder()) {
        HwBinderDeathRecipientList* list = (context->getDeathRecipientList()).get();
        sp<HwBinderDeathRecipient> jdr = new HwBinderDeathRecipient(env, recipient, cookie, list);
        status_t err = binder->linkToDeath(jdr, NULL, 0);
        if (err != NO_ERROR) {
            // Failure adding the death recipient, so clear its reference
            // now.
            jdr->clearReference();
            return JNI_FALSE;
        }
    }

    return JNI_TRUE;
}

static jboolean JHwRemoteBinder_unlinkToDeath(JNIEnv* env, jobject thiz,
                                                 jobject recipient)
{
    jboolean res = JNI_FALSE;
    if (recipient == NULL) {
        jniThrowNullPointerException(env, NULL);
        return res;
    }

    sp<JHwRemoteBinder> context = JHwRemoteBinder::GetNativeContext(env, thiz);
    sp<hardware::IBinder> binder = context->getBinder();

    if (!binder->localBinder()) {
        status_t err = NAME_NOT_FOUND;

        // If we find the matching recipient, proceed to unlink using that
        HwBinderDeathRecipientList* list = (context->getDeathRecipientList()).get();
        sp<HwBinderDeathRecipient> origJDR = list->find(recipient);
        if (origJDR != NULL) {
            wp<hardware::IBinder::DeathRecipient> dr;
            err = binder->unlinkToDeath(origJDR, NULL, 0, &dr);
            if (err == NO_ERROR && dr != NULL) {
                sp<hardware::IBinder::DeathRecipient> sdr = dr.promote();
                HwBinderDeathRecipient* jdr = static_cast<HwBinderDeathRecipient*>(sdr.get());
                if (jdr != NULL) {
                    jdr->clearReference();
                }
            }
        }

        if (err == NO_ERROR || err == DEAD_OBJECT) {
            res = JNI_TRUE;
        } else {
            jniThrowException(env, "java/util/NoSuchElementException",
                              "Death link does not exist");
        }
    }

    return res;
}

static sp<hidl::base::V1_0::IBase> toIBase(JNIEnv* env, jclass hwRemoteBinderClazz, jobject jbinder)
{
    if (jbinder == nullptr) {
        return nullptr;
    }
    if (!env->IsInstanceOf(jbinder, hwRemoteBinderClazz)) {
        return nullptr;
    }
    sp<JHwRemoteBinder> context = JHwRemoteBinder::GetNativeContext(env, jbinder);
    sp<hardware::IBinder> cbinder = context->getBinder();
    return hardware::fromBinder<hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase,
                                hidl::base::V1_0::BnHwBase>(cbinder);
}

// equals iff other is also a non-null android.os.HwRemoteBinder object
// and getBinder() returns the same object.
// In particular, if other is an android.os.HwBinder object (for stubs) then
// it returns false.
static jboolean JHwRemoteBinder_equals(JNIEnv* env, jobject thiz, jobject other)
{
    if (env->IsSameObject(thiz, other)) {
        return true;
    }
    if (other == NULL) {
        return false;
    }

    ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));

    return hardware::interfacesEqual(toIBase(env, clazz.get(), thiz), toIBase(env, clazz.get(), other));
}

static jint JHwRemoteBinder_hashCode(JNIEnv* env, jobject thiz) {
    jlong longHash = reinterpret_cast<jlong>(
            JHwRemoteBinder::GetNativeContext(env, thiz)->getBinder().get());
    return static_cast<jint>(longHash ^ (longHash >> 32)); // See Long.hashCode()
}

static JNINativeMethod gMethods[] = {
    { "native_init", "()J", (void *)JHwRemoteBinder_native_init },

    { "native_setup_empty", "()V",
        (void *)JHwRemoteBinder_native_setup_empty },

    { "transact",
        "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
        (void *)JHwRemoteBinder_native_transact },

    {"linkToDeath",
        "(Landroid/os/IHwBinder$DeathRecipient;J)Z",
        (void*)JHwRemoteBinder_linkToDeath},

    {"unlinkToDeath",
        "(Landroid/os/IHwBinder$DeathRecipient;)Z",
        (void*)JHwRemoteBinder_unlinkToDeath},

    {"equals", "(Ljava/lang/Object;)Z",
        (void*)JHwRemoteBinder_equals},

    {"hashCode", "()I", (void*)JHwRemoteBinder_hashCode},
};

namespace android {

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

}  // namespace android

