/*
 * Copyright (C) 2012 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_TAG "BluetoothServiceJni"
#include "com_android_bluetooth.h"
#include "hardware/bt_sock.h"
#include "utils/Log.h"
#include "utils/misc.h"
#include "cutils/properties.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"

#include <string.h>
#include <pthread.h>

#include <sys/stat.h>
#include <fcntl.h>

namespace android {
// OOB_LE_BD_ADDR_SIZE is 6 bytes addres + 1 byte address type
#define OOB_LE_BD_ADDR_SIZE 7
#define OOB_TK_SIZE 16
#define OOB_LE_SC_C_SIZE 16
#define OOB_LE_SC_R_SIZE 16

#define ADDITIONAL_NREFS 50
static jmethodID method_stateChangeCallback;
static jmethodID method_adapterPropertyChangedCallback;
static jmethodID method_devicePropertyChangedCallback;
static jmethodID method_deviceFoundCallback;
static jmethodID method_pinRequestCallback;
static jmethodID method_sspRequestCallback;
static jmethodID method_bondStateChangeCallback;
static jmethodID method_aclStateChangeCallback;
static jmethodID method_discoveryStateChangeCallback;
static jmethodID method_setWakeAlarm;
static jmethodID method_acquireWakeLock;
static jmethodID method_releaseWakeLock;
static jmethodID method_energyInfo;

static struct {
    jclass clazz;
    jmethodID constructor;
} android_bluetooth_UidTraffic;

static const bt_interface_t *sBluetoothInterface = NULL;
static const btsock_interface_t *sBluetoothSocketInterface = NULL;
static JNIEnv *callbackEnv = NULL;

static jobject sJniAdapterServiceObj;
static jobject sJniCallbacksObj;
static jfieldID sJniCallbacksField;


const bt_interface_t* getBluetoothInterface() {
    return sBluetoothInterface;
}

JNIEnv* getCallbackEnv() {
    return callbackEnv;
}

void checkAndClearExceptionFromCallback(JNIEnv* env,
                                               const char* methodName) {
    if (env->ExceptionCheck()) {
        ALOGE("An exception was thrown by callback '%s'.", methodName);
        LOGE_EX(env);
        env->ExceptionClear();
    }
}

static bool checkCallbackThread() {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    if (callbackEnv != env || callbackEnv == NULL) {
        ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
        return false;
    }
    return true;
}

static void adapter_state_change_callback(bt_state_t status) {
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }
    ALOGV("%s: Status is: %d", __FUNCTION__, status);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
}

static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
                        jobjectArray *props) {
    jbyteArray propVal;
    for (int i = 0; i < num_properties; i++) {
        propVal = callbackEnv->NewByteArray(properties[i].len);
        if (propVal == NULL) goto Fail;

        callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
                                             (jbyte*)properties[i].val);
        callbackEnv->SetObjectArrayElement(*props, i, propVal);
        // Delete reference to propVal
        callbackEnv->DeleteLocalRef(propVal);
        callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
    }
    return 0;
Fail:
    if (propVal) callbackEnv->DeleteLocalRef(propVal);
    ALOGE("Error while allocation of array in %s", __FUNCTION__);
    return -1;
}

static void adapter_properties_callback(bt_status_t status, int num_properties,
                                        bt_property_t *properties) {
    jobjectArray props;
    jintArray types;
    jbyteArray val;
    jclass mclass;

    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }

    ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);

    if (status != BT_STATUS_SUCCESS) {
        ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
        return;
    }

    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
    if (val == NULL) {
        ALOGE("%s: Error allocating byteArray", __FUNCTION__);
        return;
    }

    mclass = callbackEnv->GetObjectClass(val);

    /* (BT) Initialize the jobjectArray and jintArray here itself and send the
     initialized array pointers alone to get_properties */

    props = callbackEnv->NewObjectArray(num_properties, mclass,
                                             NULL);
    if (props == NULL) {
        ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
        return;
    }

    types = (jintArray)callbackEnv->NewIntArray(num_properties);

    if (types == NULL) {
        ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
        return;
    }
    // Delete the reference to val and mclass
    callbackEnv->DeleteLocalRef(mclass);
    callbackEnv->DeleteLocalRef(val);

    if (get_properties(num_properties, properties, &types, &props) < 0) {
        if (props) callbackEnv->DeleteLocalRef(props);
        if (types) callbackEnv->DeleteLocalRef(types);
        return;
    }

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
                                props);
    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(props);
    callbackEnv->DeleteLocalRef(types);
    return;

}

static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
                                              int num_properties, bt_property_t *properties) {
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }

    ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);

    if (status != BT_STATUS_SUCCESS) {
        ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
        return;
    }

    callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);

    jobjectArray props;
    jbyteArray addr;
    jintArray types;
    jbyteArray val;
    jclass mclass;

    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
    if (val == NULL) {
        ALOGE("%s: Error allocating byteArray", __FUNCTION__);
        return;
    }

    mclass = callbackEnv->GetObjectClass(val);

    /* Initialize the jobjectArray and jintArray here itself and send the
     initialized array pointers alone to get_properties */

    props = callbackEnv->NewObjectArray(num_properties, mclass,
                                             NULL);
    if (props == NULL) {
        ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
        return;
    }

    types = (jintArray)callbackEnv->NewIntArray(num_properties);

    if (types == NULL) {
        ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
        return;
    }
    // Delete the reference to val and mclass
    callbackEnv->DeleteLocalRef(mclass);
    callbackEnv->DeleteLocalRef(val);

    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (addr == NULL) goto Fail;
    if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);

    if (get_properties(num_properties, properties, &types, &props) < 0) {
        if (props) callbackEnv->DeleteLocalRef(props);
        if (types) callbackEnv->DeleteLocalRef(types);
        callbackEnv->PopLocalFrame(NULL);
        return;
    }

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
                                types, props);
    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(props);
    callbackEnv->DeleteLocalRef(types);
    callbackEnv->DeleteLocalRef(addr);
    callbackEnv->PopLocalFrame(NULL);
    return;

Fail:
    ALOGE("Error while allocation byte array in %s", __FUNCTION__);
}


static void device_found_callback(int num_properties, bt_property_t *properties) {
    jbyteArray addr = NULL;
    int addr_index;

    for (int i = 0; i < num_properties; i++) {
        if (properties[i].type == BT_PROPERTY_BDADDR) {
            addr = callbackEnv->NewByteArray(properties[i].len);
            if (addr) {
                callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
                                                (jbyte*)properties[i].val);
                addr_index = i;
            } else {
                ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
                return;
            }
        }
    }
    if (addr == NULL) {
        ALOGE("Address is NULL in %s", __FUNCTION__);
        return;
    }

    ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
        (const char *)properties[addr_index].val);

    remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
                                      num_properties, properties);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(addr);
}

static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
                                        bt_bond_state_t state) {
    jbyteArray addr;
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }
    if (!bd_addr) {
        ALOGE("Address is null in %s", __FUNCTION__);
        return;
    }
    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (addr == NULL) {
       ALOGE("Address allocation failed in %s", __FUNCTION__);
       return;
    }
    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
                                addr, (jint)state);
    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(addr);
}

static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
                                       bt_acl_state_t state)
{
    jbyteArray addr;
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }
    if (!bd_addr) {
        ALOGE("Address is null in %s", __FUNCTION__);
        return;
    }
    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (addr == NULL) {
       ALOGE("Address allocation failed in %s", __FUNCTION__);
       return;
    }
    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
                                addr, (jint)state);
    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(addr);
}

static void discovery_state_changed_callback(bt_discovery_state_t state) {
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }

    ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
                                (jint)state);

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
}

static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
        bool min_16_digits) {
    jbyteArray addr = NULL;
    jbyteArray devname = NULL;
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }
    if (!bd_addr) {
        ALOGE("Address is null in %s", __FUNCTION__);
        return;
    }

    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (addr == NULL) goto Fail;
    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);

    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
    if (devname == NULL) goto Fail;

    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod,
            min_16_digits);

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(addr);
    callbackEnv->DeleteLocalRef(devname);
    return;

Fail:
    if (addr) callbackEnv->DeleteLocalRef(addr);
    if (devname) callbackEnv->DeleteLocalRef(devname);
    ALOGE("Error while allocating in: %s", __FUNCTION__);
}

static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
    jbyteArray addr = NULL;
    jbyteArray devname = NULL;
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }
    if (!bd_addr) {
        ALOGE("Address is null in %s", __FUNCTION__);
        return;
    }

    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    if (addr == NULL) goto Fail;
    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);

    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
    if (devname == NULL) goto Fail;
    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);

    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
                                (jint) pairing_variant, pass_key);

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(addr);
    callbackEnv->DeleteLocalRef(devname);
    return;

Fail:
    if (addr) callbackEnv->DeleteLocalRef(addr);
    if (devname) callbackEnv->DeleteLocalRef(devname);

    ALOGE("Error while allocating in: %s", __FUNCTION__);
}

static void callback_thread_event(bt_cb_thread_evt event) {
    JavaVM* vm = AndroidRuntime::getJavaVM();
    if (event  == ASSOCIATE_JVM) {
        JavaVMAttachArgs args;
        char name[] = "BT Service Callback Thread";
        args.version = JNI_VERSION_1_6;
        args.name = name;
        args.group = NULL;
        vm->AttachCurrentThread(&callbackEnv, &args);
        ALOGV("Callback thread attached: %p", callbackEnv);
    } else if (event == DISASSOCIATE_JVM) {
        if (!checkCallbackThread()) {
            ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
            return;
        }
        vm->DetachCurrentThread();
    }
}

static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {

}
static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {

    ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
}

static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info,
                                      bt_uid_traffic_t* uid_data)
{
    if (!checkCallbackThread()) {
       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
       return;
    }

    jsize len = 0;
    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
        len++;
    }

    jobjectArray array = callbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
    jsize i = 0;
    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
        jobject uidObj = callbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
                                                android_bluetooth_UidTraffic.constructor,
                                                (jint) data->app_uid, (jlong) data->rx_bytes,
                                                (jlong) data->tx_bytes);
        callbackEnv->SetObjectArrayElement(array, i++, uidObj);
        callbackEnv->DeleteLocalRef(uidObj);
    }

    callbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
        p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
        p_energy_info->idle_time, p_energy_info->energy_used, array);

    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    callbackEnv->DeleteLocalRef(array);
}

static bt_callbacks_t sBluetoothCallbacks = {
    sizeof(sBluetoothCallbacks),
    adapter_state_change_callback,
    adapter_properties_callback,
    remote_device_properties_callback,
    device_found_callback,
    discovery_state_changed_callback,
    pin_request_callback,
    ssp_request_callback,
    bond_state_changed_callback,
    acl_state_changed_callback,
    callback_thread_event,
    dut_mode_recv_callback,
    le_test_mode_recv_callback,
    energy_info_recv_callback
};

// The callback to call when the wake alarm fires.
static alarm_cb sAlarmCallback;

// The data to pass to the wake alarm callback.
static void *sAlarmCallbackData;

static JavaVMAttachArgs sAttachArgs = {
  .version = JNI_VERSION_1_6,
  .name = "bluetooth wake",
  .group = NULL
};

static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake,
        alarm_cb cb, void *data) {
    JNIEnv *env;
    JavaVM *vm = AndroidRuntime::getJavaVM();
    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);

    if (status != JNI_OK && status != JNI_EDETACHED) {
        ALOGE("%s unable to get environment for JNI call", __func__);
        return false;
    }

    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
        ALOGE("%s unable to attach thread to VM", __func__);
        return false;
    }

    sAlarmCallback = cb;
    sAlarmCallbackData = data;

    jboolean jshould_wake = should_wake ? JNI_TRUE : JNI_FALSE;
    jboolean ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_setWakeAlarm,
            (jlong)delay_millis, jshould_wake);
    if (!ret) {
        sAlarmCallback = NULL;
        sAlarmCallbackData = NULL;
    }

    if (status == JNI_EDETACHED) {
        vm->DetachCurrentThread();
    }

    return !!ret;
}

static int acquire_wake_lock_callout(const char *lock_name) {
    JNIEnv *env;
    JavaVM *vm = AndroidRuntime::getJavaVM();
    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
    if (status != JNI_OK && status != JNI_EDETACHED) {
        ALOGE("%s unable to get environment for JNI call", __func__);
        return BT_STATUS_JNI_ENVIRONMENT_ERROR;
    }
    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
        ALOGE("%s unable to attach thread to VM", __func__);
        return BT_STATUS_JNI_THREAD_ATTACH_ERROR;
    }

    jint ret = BT_STATUS_SUCCESS;
    jstring lock_name_jni = env->NewStringUTF(lock_name);
    if (lock_name_jni) {
        bool acquired = env->CallBooleanMethod(sJniAdapterServiceObj,
                            method_acquireWakeLock, lock_name_jni);
        if (!acquired) ret = BT_STATUS_WAKELOCK_ERROR;
        env->DeleteLocalRef(lock_name_jni);
    } else {
        ALOGE("%s unable to allocate string: %s", __func__, lock_name);
        ret = BT_STATUS_NOMEM;
    }

    if (status == JNI_EDETACHED) {
        vm->DetachCurrentThread();
    }

    return ret;
}

static int release_wake_lock_callout(const char *lock_name) {
    JNIEnv *env;
    JavaVM *vm = AndroidRuntime::getJavaVM();
    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
    if (status != JNI_OK && status != JNI_EDETACHED) {
        ALOGE("%s unable to get environment for JNI call", __func__);
        return BT_STATUS_JNI_ENVIRONMENT_ERROR;
    }
    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
        ALOGE("%s unable to attach thread to VM", __func__);
        return BT_STATUS_JNI_THREAD_ATTACH_ERROR;
    }

    jint ret = BT_STATUS_SUCCESS;
    jstring lock_name_jni = env->NewStringUTF(lock_name);
    if (lock_name_jni) {
        bool released = env->CallBooleanMethod(sJniAdapterServiceObj,
                            method_releaseWakeLock, lock_name_jni);
        if (!released) ret = BT_STATUS_WAKELOCK_ERROR;
        env->DeleteLocalRef(lock_name_jni);
    } else {
        ALOGE("%s unable to allocate string: %s", __func__, lock_name);
        ret = BT_STATUS_NOMEM;
    }

    if (status == JNI_EDETACHED) {
        vm->DetachCurrentThread();
    }

    return ret;
}

// Called by Java code when alarm is fired. A wake lock is held by the caller
// over the duration of this callback.
static void alarmFiredNative(JNIEnv *env, jobject obj) {
    if (sAlarmCallback) {
        sAlarmCallback(sAlarmCallbackData);
    } else {
        ALOGE("%s() - Alarm fired with callback not set!", __FUNCTION__);
    }
}

static bt_os_callouts_t sBluetoothOsCallouts = {
    sizeof(sBluetoothOsCallouts),
    set_wake_alarm_callout,
    acquire_wake_lock_callout,
    release_wake_lock_callout,
};



static void classInitNative(JNIEnv* env, jclass clazz) {
    int err;
    hw_module_t* module;


    jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
    android_bluetooth_UidTraffic.constructor = env->GetMethodID(jniUidTrafficClass,
                                                                "<init>", "(IJJ)V");

    jclass jniCallbackClass =
        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
        "Lcom/android/bluetooth/btservice/JniCallbacks;");

    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");

    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
                                                             "adapterPropertyChangedCallback",
                                                             "([I[[B)V");
    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
                                                           "discoveryStateChangeCallback", "(I)V");

    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
                                                            "devicePropertyChangedCallback",
                                                            "([B[I[[B)V");
    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
                                                 "([B[BIZ)V");
    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
                                                 "([B[BIII)V");

    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
                                                     "bondStateChangeCallback", "(I[BI)V");

    method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
                                                    "aclStateChangeCallback", "(I[BI)V");

    method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
    method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
    method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
    method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");

    char value[PROPERTY_VALUE_MAX];
    property_get("bluetooth.mock_stack", value, "");

    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);

    err = hw_get_module(id, (hw_module_t const**)&module);

    if (err == 0) {
        hw_device_t* abstraction;
        err = module->methods->open(module, id, &abstraction);
        if (err == 0) {
            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
            sBluetoothInterface = btStack->get_bluetooth_interface();
        } else {
           ALOGE("Error while opening Bluetooth library");
        }
    } else {
        ALOGE("No Bluetooth Library found");
    }
}

static bool initNative(JNIEnv* env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    android_bluetooth_UidTraffic.clazz = (jclass) env->NewGlobalRef(
            env->FindClass("android/bluetooth/UidTraffic"));

    sJniAdapterServiceObj = env->NewGlobalRef(obj);
    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

    if (sBluetoothInterface) {
        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
        if (ret != BT_STATUS_SUCCESS) {
            ALOGE("Error while setting the callbacks: %d\n", ret);
            sBluetoothInterface = NULL;
            return JNI_FALSE;
        }
        ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);
        if (ret != BT_STATUS_SUCCESS) {
            ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
            sBluetoothInterface->cleanup();
            sBluetoothInterface = NULL;
            return JNI_FALSE;
        }

        if ( (sBluetoothSocketInterface = (btsock_interface_t *)
                  sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
                ALOGE("Error getting socket interface");
        }

        return JNI_TRUE;
    }
    return JNI_FALSE;
}

static bool cleanupNative(JNIEnv *env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    sBluetoothInterface->cleanup();
    ALOGI("%s: return from cleanup",__FUNCTION__);

    env->DeleteGlobalRef(sJniCallbacksObj);
    env->DeleteGlobalRef(sJniAdapterServiceObj);
    env->DeleteGlobalRef(android_bluetooth_UidTraffic.clazz);
    android_bluetooth_UidTraffic.clazz = NULL;
    return JNI_TRUE;
}

static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;
    int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
    result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE;
    return result;
}

static jboolean disableNative(JNIEnv* env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    int ret = sBluetoothInterface->disable();
    /* Retrun JNI_FALSE only when BTIF explicitly reports
       BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
       case which indicates that stack had not been enabled.
    */
    result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
    return result;
}

static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    int ret = sBluetoothInterface->start_discovery();
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    return result;
}

static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    int ret = sBluetoothInterface->cancel_discovery();
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    return result;
}

static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr;
    jboolean result = JNI_FALSE;

    if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);
    env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jbyteArray callByteArrayGetter(JNIEnv* env, jobject object,
                                      const char* className,
                                      const char* methodName) {
    jclass myClass = env->FindClass(className);
    jmethodID myMethod = env->GetMethodID(myClass, methodName, "()[B");
    return (jbyteArray) env->CallObjectMethod(object, myMethod);
}

static jboolean createBondOutOfBandNative(JNIEnv* env, jobject obj, jbyteArray address,
                jint transport, jobject oobData) {
    jbyte *addr;
    jboolean result = JNI_FALSE;
    bt_out_of_band_data_t oob_data;

    memset(&oob_data, 0, sizeof(oob_data));

    if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    jbyte* leBtDeviceAddressBytes = NULL;
    jbyte* smTKBytes = NULL;
    jbyte* leScCBytes = NULL;
    jbyte* leScRBytes = NULL;
    jbyteArray leBtDeviceAddress = NULL;
    jbyteArray smTK = NULL;
    jbyteArray leScC = NULL;
    jbyteArray leScR = NULL;

    leBtDeviceAddress = callByteArrayGetter(env, oobData, "android/bluetooth/OobData", "getLeBluetoothDeviceAddress");
    if (leBtDeviceAddress != NULL) {
        leBtDeviceAddressBytes = env->GetByteArrayElements(leBtDeviceAddress, NULL);
        int len = env->GetArrayLength(leBtDeviceAddress);
        if (len != OOB_LE_BD_ADDR_SIZE) {
            ALOGI("%s: wrong length of leBtDeviceAddress, should be empty or %d bytes.", __func__, OOB_LE_BD_ADDR_SIZE);
            jniThrowIOException(env, EINVAL);
            goto done;
        }
        memcpy(oob_data.le_bt_dev_addr, leBtDeviceAddressBytes, len);
    }

    smTK = callByteArrayGetter(env, oobData, "android/bluetooth/OobData", "getSecurityManagerTk");
    if (smTK != NULL) {
        smTKBytes = env->GetByteArrayElements(smTK, NULL);
        int len = env->GetArrayLength(smTK);
        if (len != OOB_TK_SIZE) {
            ALOGI("%s: wrong length of smTK, should be empty or %d bytes.", __func__, OOB_TK_SIZE);
            jniThrowIOException(env, EINVAL);
            goto done;
        }
        memcpy(oob_data.sm_tk, smTKBytes, len);
    }

    leScC = callByteArrayGetter(env, oobData, "android/bluetooth/OobData",
                                           "getLeSecureConnectionsConfirmation");
    if (leScC != NULL) {
        leScCBytes = env->GetByteArrayElements(leScC, NULL);
        int len = env->GetArrayLength(leScC);
        if (len != OOB_LE_SC_C_SIZE) {
            ALOGI("%s: wrong length of LE SC Confirmation, should be empty or %d bytes.",
                    __func__, OOB_LE_SC_C_SIZE);
            jniThrowIOException(env, EINVAL);
            goto done;
        }
        memcpy(oob_data.le_sc_c, leScCBytes, len);
    }

    leScR = callByteArrayGetter(env, oobData, "android/bluetooth/OobData",
                                           "getLeSecureConnectionsRandom");
    if (leScR != NULL) {
        leScRBytes = env->GetByteArrayElements(leScR, NULL);
        int len = env->GetArrayLength(leScR);
        if (len != OOB_LE_SC_R_SIZE) {
            ALOGI("%s: wrong length of LE SC Random, should be empty or %d bytes.",
                  __func__, OOB_LE_SC_R_SIZE);
            jniThrowIOException(env, EINVAL);
            goto done;
        }
        memcpy(oob_data.le_sc_r, leScRBytes, len);
    }

    if (sBluetoothInterface->create_bond_out_of_band((bt_bdaddr_t *)addr, transport, &oob_data)
        == BT_STATUS_SUCCESS)
        result = JNI_TRUE;

done:
    env->ReleaseByteArrayElements(address, addr, 0);

    if (leBtDeviceAddress != NULL)
        env->ReleaseByteArrayElements(leBtDeviceAddress, leBtDeviceAddressBytes, 0);

    if (smTK != NULL)
        env->ReleaseByteArrayElements(smTK, smTKBytes, 0);

    if (leScC != NULL)
        env->ReleaseByteArrayElements(leScC, leScCBytes, 0);

    if (leScR != NULL)
        env->ReleaseByteArrayElements(leScR, leScRBytes, 0);

    return result;
}

static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr;
    jboolean result;
    if (!sBluetoothInterface) return JNI_FALSE;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return JNI_FALSE;
    }

    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
    env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr;
    jboolean result;
    if (!sBluetoothInterface) return JNI_FALSE;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return JNI_FALSE;
    }

    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
    env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static int getConnectionStateNative(JNIEnv* env, jobject obj, jbyteArray address) {
    ALOGV("%s:",__FUNCTION__);
    if (!sBluetoothInterface) return JNI_FALSE;

    jbyte *addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return JNI_FALSE;
    }

    int ret = sBluetoothInterface->get_connection_state((bt_bdaddr_t *)addr);
    env->ReleaseByteArrayElements(address, addr, 0);

    return ret;
}

static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
                               jint len, jbyteArray pinArray) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr, *pinPtr = NULL;
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    if (accept) {
        pinPtr = env->GetByteArrayElements(pinArray, NULL);
        if (pinPtr == NULL) {
           jniThrowIOException(env, EINVAL);
           env->ReleaseByteArrayElements(address, addr, 0);
           return result;
        }
    }

    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
                                              (bt_pin_code_t *) pinPtr);
    env->ReleaseByteArrayElements(address, addr, 0);
    env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
                               jint type, jboolean accept, jint passkey) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr;
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
         (bt_ssp_variant_t) type, accept, passkey);
    env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *val;
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    val = env->GetByteArrayElements(value, NULL);
    bt_property_t prop;
    prop.type = (bt_property_type_t) type;
    prop.len = env->GetArrayLength(value);
    prop.val = val;

    int ret = sBluetoothInterface->set_adapter_property(&prop);
    env->ReleaseByteArrayElements(value, val, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    int ret = sBluetoothInterface->get_adapter_properties();
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr = NULL;
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
                                                              (bt_property_type_t) type);
    env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
                                        jint type, jbyteArray value) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *val, *addr;
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    val = env->GetByteArrayElements(value, NULL);
    if (val == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        env->ReleaseByteArrayElements(value, val, 0);
        jniThrowIOException(env, EINVAL);
        return result;
    }


    bt_property_t prop;
    prop.type = (bt_property_type_t) type;
    prop.len = env->GetArrayLength(value);
    prop.val = val;

    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
    env->ReleaseByteArrayElements(value, val, 0);
    env->ReleaseByteArrayElements(address, addr, 0);

    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
    ALOGV("%s:",__FUNCTION__);

    jbyte *addr = NULL;
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;

    addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return result;
    }

    int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
    env->ReleaseByteArrayElements(address, addr, 0);
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    return result;
}

static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
                                   jbyteArray uuidObj, jint channel, jint flag, jint callingUid) {
    jbyte *addr = NULL, *uuid = NULL;
    int socket_fd;
    bt_status_t status;

    if (!sBluetoothSocketInterface) return -1;

    addr = env->GetByteArrayElements(address, NULL);
    if (!addr) {
        ALOGE("failed to get Bluetooth device address");
        goto Fail;
    }

    if(uuidObj != NULL) {
        uuid = env->GetByteArrayElements(uuidObj, NULL);
        if (!uuid) {
            ALOGE("failed to get uuid");
            goto Fail;
        }
    }

    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
            != BT_STATUS_SUCCESS) {
        ALOGE("Socket connection failed: %d", status);
        goto Fail;
    }


    if (socket_fd < 0) {
        ALOGE("Fail to create file descriptor on socket fd");
        goto Fail;
    }
    env->ReleaseByteArrayElements(address, addr, 0);
    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    return socket_fd;

Fail:
    if (addr) env->ReleaseByteArrayElements(address, addr, 0);
    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);

    return -1;
}

static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
                                     jstring name_str, jbyteArray uuidObj,
                                     jint channel, jint flag, jint callingUid) {
    const char *service_name = NULL;
    jbyte *uuid = NULL;
    int socket_fd;
    bt_status_t status;

    if (!sBluetoothSocketInterface) return -1;

    ALOGV("%s: SOCK FLAG = %x", __FUNCTION__, flag);

    if(name_str != NULL) {
        service_name = env->GetStringUTFChars(name_str, NULL);
    }

    if(uuidObj != NULL) {
        uuid = env->GetByteArrayElements(uuidObj, NULL);
        if (!uuid) {
            ALOGE("failed to get uuid");
            goto Fail;
        }
    }
    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
            != BT_STATUS_SUCCESS) {
        ALOGE("Socket listen failed: %d", status);
        goto Fail;
    }

    if (socket_fd < 0) {
        ALOGE("Fail to creat file descriptor on socket fd");
        goto Fail;
    }
    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    return socket_fd;

Fail:
    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    return -1;
}

static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) {
    ALOGV("%s:",__FUNCTION__);

    jboolean result = JNI_FALSE;

    if (!sBluetoothInterface) return result;

    int ret = sBluetoothInterface->config_hci_snoop_log(enable);

    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

    return result;
}

static int readEnergyInfo()
{
    ALOGV("%s:",__FUNCTION__);
    jboolean result = JNI_FALSE;
    if (!sBluetoothInterface) return result;
    int ret = sBluetoothInterface->read_energy_info();
    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    return result;
}

static void dumpNative(JNIEnv *env, jobject obj, jobject fdObj,
                       jobjectArray argArray)
{
    ALOGV("%s()", __FUNCTION__);
    if (!sBluetoothInterface) return;

    int fd = jniGetFDFromFileDescriptor(env, fdObj);
    if (fd < 0) return;

    int numArgs = env->GetArrayLength(argArray);

    jstring *argObjs = new jstring[numArgs];
    const char **args = nullptr;
    if (numArgs > 0)
      args = new const char*[numArgs];

    for (int i = 0; i < numArgs; i++) {
      argObjs[i] = (jstring) env->GetObjectArrayElement(argArray, i);
      args[i] = env->GetStringUTFChars(argObjs[i], NULL);
    }

    sBluetoothInterface->dump(fd, args);

    for (int i = 0; i < numArgs; i++) {
      env->ReleaseStringUTFChars(argObjs[i], args[i]);
    }

    delete[] args;
    delete[] argObjs;
}

static jboolean factoryResetNative(JNIEnv *env, jobject obj) {
    ALOGV("%s:", __FUNCTION__);
    if (!sBluetoothInterface) return JNI_FALSE;
    int ret = sBluetoothInterface->config_clear();
    return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

static void interopDatabaseClearNative(JNIEnv *env, jobject obj) {
    ALOGV("%s()", __FUNCTION__);
    if (!sBluetoothInterface) return;
    sBluetoothInterface->interop_database_clear();
}

static void interopDatabaseAddNative(JNIEnv *env, jobject obj, int feature,
                                      jbyteArray address, int length) {
    ALOGV("%s()", __FUNCTION__);
    if (!sBluetoothInterface) return;

    jbyte *addr = env->GetByteArrayElements(address, NULL);
    if (addr == NULL) {
        jniThrowIOException(env, EINVAL);
        return;
    }

    sBluetoothInterface->interop_database_add(feature, (bt_bdaddr_t *)addr, length);
    env->ReleaseByteArrayElements(address, addr, 0);
}

static JNINativeMethod sMethods[] = {
    /* name, signature, funcPtr */
    {"classInitNative", "()V", (void *) classInitNative},
    {"initNative", "()Z", (void *) initNative},
    {"cleanupNative", "()V", (void*) cleanupNative},
    {"enableNative", "(Z)Z",  (void*) enableNative},
    {"disableNative", "()Z",  (void*) disableNative},
    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
    {"createBondNative", "([BI)Z", (void*) createBondNative},
    {"createBondOutOfBandNative", "([BILandroid/bluetooth/OobData;)Z", (void*) createBondOutOfBandNative},
    {"removeBondNative", "([B)Z", (void*) removeBondNative},
    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
    {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
    {"connectSocketNative", "([BI[BIII)I", (void*) connectSocketNative},
    {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I",
     (void*) createSocketChannelNative},
    {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},
    {"alarmFiredNative", "()V", (void *) alarmFiredNative},
    {"readEnergyInfo", "()I", (void*) readEnergyInfo},
    {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V", (void*) dumpNative},
    {"factoryResetNative", "()Z", (void*)factoryResetNative},
    {"interopDatabaseClearNative", "()V", (void*) interopDatabaseClearNative},
    {"interopDatabaseAddNative", "(I[BI)V", (void*) interopDatabaseAddNative}
};

int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
                                    sMethods, NELEM(sMethods));
}

} /* namespace android */


/*
 * JNI Initialization
 */
jint JNI_OnLoad(JavaVM *jvm, void *reserved)
{
    JNIEnv *e;
    int status;

    ALOGV("Bluetooth Adapter Service : loading JNI\n");

    // Check JNI version
    if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
        ALOGE("JNI version mismatch error");
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
        ALOGE("jni adapter service registration failure, status: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
        ALOGE("jni hfp registration failure, status: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) {
        ALOGE("jni hfp client registration failure, status: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
        ALOGE("jni a2dp source registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_a2dp_sink(e)) < 0) {
        ALOGE("jni a2dp sink registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
        ALOGE("jni avrcp target registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_avrcp_controller(e)) < 0) {
        ALOGE("jni avrcp controller registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
        ALOGE("jni hid registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
        ALOGE("jni hdp registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
        ALOGE("jni pan registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
        ALOGE("jni gatt registration failure: %d", status);
        return JNI_ERR;
    }

    if ((status = android::register_com_android_bluetooth_sdp(e)) < 0) {
        ALOGE("jni sdp registration failure: %d", status);
        return JNI_ERR;
    }

    return JNI_VERSION_1_6;
}
