Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "BluetoothServiceJni"
     18 #include "com_android_bluetooth.h"
     19 #include "hardware/bt_sock.h"
     20 #include "utils/Log.h"
     21 #include "utils/misc.h"
     22 #include "cutils/properties.h"
     23 #include "android_runtime/AndroidRuntime.h"
     24 
     25 #include <string.h>
     26 #include <pthread.h>
     27 
     28 #include <sys/stat.h>
     29 #include <fcntl.h>
     30 
     31 namespace android {
     32 
     33 #define ADDITIONAL_NREFS 50
     34 static jmethodID method_stateChangeCallback;
     35 static jmethodID method_adapterPropertyChangedCallback;
     36 static jmethodID method_devicePropertyChangedCallback;
     37 static jmethodID method_deviceFoundCallback;
     38 static jmethodID method_pinRequestCallback;
     39 static jmethodID method_sspRequestCallback;
     40 static jmethodID method_bondStateChangeCallback;
     41 static jmethodID method_aclStateChangeCallback;
     42 static jmethodID method_discoveryStateChangeCallback;
     43 
     44 static const bt_interface_t *sBluetoothInterface = NULL;
     45 static const btsock_interface_t *sBluetoothSocketInterface = NULL;
     46 static JNIEnv *callbackEnv = NULL;
     47 
     48 static jobject sJniCallbacksObj;
     49 static jfieldID sJniCallbacksField;
     50 
     51 
     52 const bt_interface_t* getBluetoothInterface() {
     53     return sBluetoothInterface;
     54 }
     55 
     56 JNIEnv* getCallbackEnv() {
     57     return callbackEnv;
     58 }
     59 
     60 void checkAndClearExceptionFromCallback(JNIEnv* env,
     61                                                const char* methodName) {
     62     if (env->ExceptionCheck()) {
     63         ALOGE("An exception was thrown by callback '%s'.", methodName);
     64         LOGE_EX(env);
     65         env->ExceptionClear();
     66     }
     67 }
     68 
     69 static bool checkCallbackThread() {
     70     JNIEnv* env = AndroidRuntime::getJNIEnv();
     71     if (callbackEnv != env || callbackEnv == NULL) {
     72         ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
     73         return false;
     74     }
     75     return true;
     76 }
     77 
     78 static void adapter_state_change_callback(bt_state_t status) {
     79     if (!checkCallbackThread()) {
     80        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
     81        return;
     82     }
     83     ALOGV("%s: Status is: %d", __FUNCTION__, status);
     84 
     85     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
     86 
     87     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
     88 }
     89 
     90 static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
     91                         jobjectArray *props) {
     92     jbyteArray propVal;
     93     for (int i = 0; i < num_properties; i++) {
     94         propVal = callbackEnv->NewByteArray(properties[i].len);
     95         if (propVal == NULL) goto Fail;
     96 
     97         callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
     98                                              (jbyte*)properties[i].val);
     99         callbackEnv->SetObjectArrayElement(*props, i, propVal);
    100         // Delete reference to propVal
    101         callbackEnv->DeleteLocalRef(propVal);
    102         callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
    103     }
    104     return 0;
    105 Fail:
    106     if (propVal) callbackEnv->DeleteLocalRef(propVal);
    107     ALOGE("Error while allocation of array in %s", __FUNCTION__);
    108     return -1;
    109 }
    110 
    111 static void adapter_properties_callback(bt_status_t status, int num_properties,
    112                                         bt_property_t *properties) {
    113     jobjectArray props;
    114     jintArray types;
    115     jbyteArray val;
    116     jclass mclass;
    117 
    118     if (!checkCallbackThread()) {
    119        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    120        return;
    121     }
    122 
    123     ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
    124 
    125     if (status != BT_STATUS_SUCCESS) {
    126         ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
    127         return;
    128     }
    129 
    130     val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
    131     if (val == NULL) {
    132         ALOGE("%s: Error allocating byteArray", __FUNCTION__);
    133         return;
    134     }
    135 
    136     mclass = callbackEnv->GetObjectClass(val);
    137 
    138     /* (BT) Initialize the jobjectArray and jintArray here itself and send the
    139      initialized array pointers alone to get_properties */
    140 
    141     props = callbackEnv->NewObjectArray(num_properties, mclass,
    142                                              NULL);
    143     if (props == NULL) {
    144         ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
    145         return;
    146     }
    147 
    148     types = (jintArray)callbackEnv->NewIntArray(num_properties);
    149 
    150     if (types == NULL) {
    151         ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
    152         return;
    153     }
    154     // Delete the reference to val and mclass
    155     callbackEnv->DeleteLocalRef(mclass);
    156     callbackEnv->DeleteLocalRef(val);
    157 
    158     if (get_properties(num_properties, properties, &types, &props) < 0) {
    159         if (props) callbackEnv->DeleteLocalRef(props);
    160         if (types) callbackEnv->DeleteLocalRef(types);
    161         return;
    162     }
    163 
    164     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
    165                                 props);
    166     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    167     callbackEnv->DeleteLocalRef(props);
    168     callbackEnv->DeleteLocalRef(types);
    169     return;
    170 
    171 }
    172 
    173 static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
    174                                               int num_properties, bt_property_t *properties) {
    175     if (!checkCallbackThread()) {
    176        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    177        return;
    178     }
    179 
    180     ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
    181 
    182     if (status != BT_STATUS_SUCCESS) {
    183         ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
    184         return;
    185     }
    186 
    187     callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
    188 
    189     jobjectArray props;
    190     jbyteArray addr;
    191     jintArray types;
    192     jbyteArray val;
    193     jclass mclass;
    194 
    195     val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
    196     if (val == NULL) {
    197         ALOGE("%s: Error allocating byteArray", __FUNCTION__);
    198         return;
    199     }
    200 
    201     mclass = callbackEnv->GetObjectClass(val);
    202 
    203     /* Initialize the jobjectArray and jintArray here itself and send the
    204      initialized array pointers alone to get_properties */
    205 
    206     props = callbackEnv->NewObjectArray(num_properties, mclass,
    207                                              NULL);
    208     if (props == NULL) {
    209         ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
    210         return;
    211     }
    212 
    213     types = (jintArray)callbackEnv->NewIntArray(num_properties);
    214 
    215     if (types == NULL) {
    216         ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
    217         return;
    218     }
    219     // Delete the reference to val and mclass
    220     callbackEnv->DeleteLocalRef(mclass);
    221     callbackEnv->DeleteLocalRef(val);
    222 
    223     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    224     if (addr == NULL) goto Fail;
    225     if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
    226 
    227     if (get_properties(num_properties, properties, &types, &props) < 0) {
    228         if (props) callbackEnv->DeleteLocalRef(props);
    229         if (types) callbackEnv->DeleteLocalRef(types);
    230         callbackEnv->PopLocalFrame(NULL);
    231         return;
    232     }
    233 
    234     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
    235                                 types, props);
    236     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    237     callbackEnv->DeleteLocalRef(props);
    238     callbackEnv->DeleteLocalRef(types);
    239     callbackEnv->DeleteLocalRef(addr);
    240     callbackEnv->PopLocalFrame(NULL);
    241     return;
    242 
    243 Fail:
    244     ALOGE("Error while allocation byte array in %s", __FUNCTION__);
    245 }
    246 
    247 
    248 static void device_found_callback(int num_properties, bt_property_t *properties) {
    249     jbyteArray addr = NULL;
    250     int addr_index;
    251 
    252     for (int i = 0; i < num_properties; i++) {
    253         if (properties[i].type == BT_PROPERTY_BDADDR) {
    254             addr = callbackEnv->NewByteArray(properties[i].len);
    255             if (addr) {
    256                 callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
    257                                                 (jbyte*)properties[i].val);
    258                 addr_index = i;
    259             } else {
    260                 ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
    261                 return;
    262             }
    263         }
    264     }
    265     if (addr == NULL) {
    266         ALOGE("Address is NULL in %s", __FUNCTION__);
    267         return;
    268     }
    269 
    270     ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
    271         (const char *)properties[addr_index].val);
    272 
    273     remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
    274                                       num_properties, properties);
    275 
    276     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
    277     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    278     callbackEnv->DeleteLocalRef(addr);
    279 }
    280 
    281 static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
    282                                         bt_bond_state_t state) {
    283     jbyteArray addr;
    284     int i;
    285     if (!checkCallbackThread()) {
    286        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    287        return;
    288     }
    289     if (!bd_addr) {
    290         ALOGE("Address is null in %s", __FUNCTION__);
    291         return;
    292     }
    293     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    294     if (addr == NULL) {
    295        ALOGE("Address allocation failed in %s", __FUNCTION__);
    296        return;
    297     }
    298     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
    299 
    300     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
    301                                 addr, (jint)state);
    302     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    303     callbackEnv->DeleteLocalRef(addr);
    304 }
    305 
    306 static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
    307                                        bt_acl_state_t state)
    308 {
    309     jbyteArray addr;
    310     int i;
    311     if (!checkCallbackThread()) {
    312        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    313        return;
    314     }
    315     if (!bd_addr) {
    316         ALOGE("Address is null in %s", __FUNCTION__);
    317         return;
    318     }
    319     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    320     if (addr == NULL) {
    321        ALOGE("Address allocation failed in %s", __FUNCTION__);
    322        return;
    323     }
    324     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
    325 
    326     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
    327                                 addr, (jint)state);
    328     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    329     callbackEnv->DeleteLocalRef(addr);
    330 }
    331 
    332 static void discovery_state_changed_callback(bt_discovery_state_t state) {
    333     jbyteArray addr;
    334     if (!checkCallbackThread()) {
    335        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    336        return;
    337     }
    338 
    339     ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
    340 
    341     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
    342                                 (jint)state);
    343 
    344     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    345 }
    346 
    347 static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) {
    348     jbyteArray addr, devname;
    349     if (!checkCallbackThread()) {
    350        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    351        return;
    352     }
    353     if (!bd_addr) {
    354         ALOGE("Address is null in %s", __FUNCTION__);
    355         return;
    356     }
    357 
    358     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    359     if (addr == NULL) goto Fail;
    360     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
    361 
    362     devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
    363     if (devname == NULL) goto Fail;
    364 
    365     callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
    366 
    367     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod);
    368 
    369     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    370     callbackEnv->DeleteLocalRef(addr);
    371     callbackEnv->DeleteLocalRef(devname);
    372     return;
    373 
    374 Fail:
    375     if (addr) callbackEnv->DeleteLocalRef(addr);
    376     if (devname) callbackEnv->DeleteLocalRef(devname);
    377     ALOGE("Error while allocating in: %s", __FUNCTION__);
    378 }
    379 
    380 static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
    381                                  bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
    382     jbyteArray addr, devname;
    383     if (!checkCallbackThread()) {
    384        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    385        return;
    386     }
    387     if (!bd_addr) {
    388         ALOGE("Address is null in %s", __FUNCTION__);
    389         return;
    390     }
    391 
    392     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
    393     if (addr == NULL) goto Fail;
    394     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
    395 
    396     devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
    397     if (devname == NULL) goto Fail;
    398     callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
    399 
    400     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
    401                                 (jint) pairing_variant, pass_key);
    402 
    403     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
    404     callbackEnv->DeleteLocalRef(addr);
    405     callbackEnv->DeleteLocalRef(devname);
    406     return;
    407 
    408 Fail:
    409     if (addr) callbackEnv->DeleteLocalRef(addr);
    410     if (devname) callbackEnv->DeleteLocalRef(devname);
    411 
    412     ALOGE("Error while allocating in: %s", __FUNCTION__);
    413 }
    414 
    415 static void callback_thread_event(bt_cb_thread_evt event) {
    416     JavaVM* vm = AndroidRuntime::getJavaVM();
    417     if (event  == ASSOCIATE_JVM) {
    418         JavaVMAttachArgs args;
    419         char name[] = "BT Service Callback Thread";
    420         args.version = JNI_VERSION_1_6;
    421         args.name = name;
    422         args.group = NULL;
    423         vm->AttachCurrentThread(&callbackEnv, &args);
    424         ALOGV("Callback thread attached: %p", callbackEnv);
    425     } else if (event == DISASSOCIATE_JVM) {
    426         if (!checkCallbackThread()) {
    427             ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
    428             return;
    429         }
    430         vm->DetachCurrentThread();
    431     }
    432 }
    433 
    434 static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {
    435 
    436 }
    437 static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {
    438 
    439     ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
    440 }
    441 bt_callbacks_t sBluetoothCallbacks = {
    442     sizeof(sBluetoothCallbacks),
    443     adapter_state_change_callback,
    444     adapter_properties_callback,
    445     remote_device_properties_callback,
    446     device_found_callback,
    447     discovery_state_changed_callback,
    448     pin_request_callback,
    449     ssp_request_callback,
    450     bond_state_changed_callback,
    451     acl_state_changed_callback,
    452     callback_thread_event,
    453     dut_mode_recv_callback,
    454 
    455     le_test_mode_recv_callback
    456 };
    457 
    458 static void classInitNative(JNIEnv* env, jclass clazz) {
    459     int err;
    460     hw_module_t* module;
    461 
    462     jclass jniCallbackClass =
    463         env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
    464     sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
    465         "Lcom/android/bluetooth/btservice/JniCallbacks;");
    466 
    467     method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
    468 
    469     method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
    470                                                              "adapterPropertyChangedCallback",
    471                                                              "([I[[B)V");
    472     method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
    473                                                            "discoveryStateChangeCallback", "(I)V");
    474 
    475     method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
    476                                                             "devicePropertyChangedCallback",
    477                                                             "([B[I[[B)V");
    478     method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
    479     method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
    480                                                  "([B[BI)V");
    481     method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
    482                                                  "([B[BIII)V");
    483 
    484     method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
    485                                                      "bondStateChangeCallback", "(I[BI)V");
    486 
    487     method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
    488                                                     "aclStateChangeCallback", "(I[BI)V");
    489     char value[PROPERTY_VALUE_MAX];
    490     property_get("bluetooth.mock_stack", value, "");
    491 
    492     const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
    493 
    494     err = hw_get_module(id, (hw_module_t const**)&module);
    495 
    496     if (err == 0) {
    497         hw_device_t* abstraction;
    498         err = module->methods->open(module, id, &abstraction);
    499         if (err == 0) {
    500             bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
    501             sBluetoothInterface = btStack->get_bluetooth_interface();
    502         } else {
    503            ALOGE("Error while opening Bluetooth library");
    504         }
    505     } else {
    506         ALOGE("No Bluetooth Library found");
    507     }
    508 }
    509 
    510 static bool initNative(JNIEnv* env, jobject obj) {
    511     ALOGV("%s:",__FUNCTION__);
    512 
    513     sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
    514 
    515     if (sBluetoothInterface) {
    516         int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
    517         if (ret != BT_STATUS_SUCCESS) {
    518             ALOGE("Error while setting the callbacks \n");
    519             sBluetoothInterface = NULL;
    520             return JNI_FALSE;
    521         }
    522         if ( (sBluetoothSocketInterface = (btsock_interface_t *)
    523                   sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
    524                 ALOGE("Error getting socket interface");
    525         }
    526         return JNI_TRUE;
    527     }
    528     return JNI_FALSE;
    529 }
    530 
    531 static bool cleanupNative(JNIEnv *env, jobject obj) {
    532     ALOGV("%s:",__FUNCTION__);
    533 
    534     jboolean result = JNI_FALSE;
    535     if (!sBluetoothInterface) return result;
    536 
    537     sBluetoothInterface->cleanup();
    538     ALOGI("%s: return from cleanup",__FUNCTION__);
    539 
    540     env->DeleteGlobalRef(sJniCallbacksObj);
    541     return JNI_TRUE;
    542 }
    543 
    544 static jboolean enableNative(JNIEnv* env, jobject obj) {
    545     ALOGV("%s:",__FUNCTION__);
    546 
    547     jboolean result = JNI_FALSE;
    548     if (!sBluetoothInterface) return result;
    549 
    550     int ret = sBluetoothInterface->enable();
    551     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    552     return result;
    553 }
    554 
    555 static jboolean disableNative(JNIEnv* env, jobject obj) {
    556     ALOGV("%s:",__FUNCTION__);
    557 
    558     jboolean result = JNI_FALSE;
    559     if (!sBluetoothInterface) return result;
    560 
    561     int ret = sBluetoothInterface->disable();
    562     /* Retrun JNI_FALSE only when BTIF explicitly reports
    563        BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
    564        case which indicates that stack had not been enabled.
    565     */
    566     result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
    567     return result;
    568 }
    569 
    570 static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
    571     ALOGV("%s:",__FUNCTION__);
    572 
    573     jboolean result = JNI_FALSE;
    574     if (!sBluetoothInterface) return result;
    575 
    576     int ret = sBluetoothInterface->start_discovery();
    577     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    578     return result;
    579 }
    580 
    581 static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
    582     ALOGV("%s:",__FUNCTION__);
    583 
    584     jboolean result = JNI_FALSE;
    585     if (!sBluetoothInterface) return result;
    586 
    587     int ret = sBluetoothInterface->cancel_discovery();
    588     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    589     return result;
    590 }
    591 
    592 static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
    593     ALOGV("%s:",__FUNCTION__);
    594 
    595     jbyte *addr;
    596     jboolean result = JNI_FALSE;
    597 
    598     if (!sBluetoothInterface) return result;
    599 
    600     addr = env->GetByteArrayElements(address, NULL);
    601     if (addr == NULL) {
    602         jniThrowIOException(env, EINVAL);
    603         return result;
    604     }
    605 
    606     int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
    607     env->ReleaseByteArrayElements(address, addr, 0);
    608     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    609 
    610     return result;
    611 }
    612 
    613 static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
    614     ALOGV("%s:",__FUNCTION__);
    615 
    616     jbyte *addr;
    617     jboolean result;
    618     if (!sBluetoothInterface) return JNI_FALSE;
    619 
    620     addr = env->GetByteArrayElements(address, NULL);
    621     if (addr == NULL) {
    622         jniThrowIOException(env, EINVAL);
    623         return JNI_FALSE;
    624     }
    625 
    626     int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
    627     env->ReleaseByteArrayElements(address, addr, 0);
    628     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    629 
    630     return result;
    631 }
    632 
    633 static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
    634     ALOGV("%s:",__FUNCTION__);
    635 
    636     jbyte *addr;
    637     jboolean result;
    638     if (!sBluetoothInterface) return JNI_FALSE;
    639 
    640     addr = env->GetByteArrayElements(address, NULL);
    641     if (addr == NULL) {
    642         jniThrowIOException(env, EINVAL);
    643         return JNI_FALSE;
    644     }
    645 
    646     int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
    647     env->ReleaseByteArrayElements(address, addr, 0);
    648     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    649 
    650     return result;
    651 }
    652 
    653 static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
    654                                jint len, jbyteArray pinArray) {
    655     ALOGV("%s:",__FUNCTION__);
    656 
    657     jbyte *addr, *pinPtr = NULL;
    658     jboolean result = JNI_FALSE;
    659     if (!sBluetoothInterface) return result;
    660 
    661     addr = env->GetByteArrayElements(address, NULL);
    662     if (addr == NULL) {
    663         jniThrowIOException(env, EINVAL);
    664         return result;
    665     }
    666 
    667     if (accept) {
    668         pinPtr = env->GetByteArrayElements(pinArray, NULL);
    669         if (pinPtr == NULL) {
    670            jniThrowIOException(env, EINVAL);
    671            env->ReleaseByteArrayElements(address, addr, 0);
    672            return result;
    673         }
    674     }
    675 
    676     int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
    677                                               (bt_pin_code_t *) pinPtr);
    678     env->ReleaseByteArrayElements(address, addr, 0);
    679     env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
    680     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    681 
    682     return result;
    683 }
    684 
    685 static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
    686                                jint type, jboolean accept, jint passkey) {
    687     ALOGV("%s:",__FUNCTION__);
    688 
    689     jbyte *addr;
    690     jboolean result = JNI_FALSE;
    691     if (!sBluetoothInterface) return result;
    692 
    693     addr = env->GetByteArrayElements(address, NULL);
    694     if (addr == NULL) {
    695         jniThrowIOException(env, EINVAL);
    696         return result;
    697     }
    698 
    699     int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
    700          (bt_ssp_variant_t) type, accept, passkey);
    701     env->ReleaseByteArrayElements(address, addr, 0);
    702     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    703 
    704     return result;
    705 }
    706 
    707 static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
    708     ALOGV("%s:",__FUNCTION__);
    709 
    710     jbyte *val;
    711     jboolean result = JNI_FALSE;
    712     if (!sBluetoothInterface) return result;
    713 
    714     val = env->GetByteArrayElements(value, NULL);
    715     bt_property_t prop;
    716     prop.type = (bt_property_type_t) type;
    717     prop.len = env->GetArrayLength(value);
    718     prop.val = val;
    719 
    720     int ret = sBluetoothInterface->set_adapter_property(&prop);
    721     env->ReleaseByteArrayElements(value, val, 0);
    722     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    723 
    724     return result;
    725 }
    726 
    727 static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
    728     ALOGV("%s:",__FUNCTION__);
    729 
    730     jboolean result = JNI_FALSE;
    731     if (!sBluetoothInterface) return result;
    732 
    733     int ret = sBluetoothInterface->get_adapter_properties();
    734     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    735 
    736     return result;
    737 }
    738 
    739 static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
    740     ALOGV("%s:",__FUNCTION__);
    741 
    742     jboolean result = JNI_FALSE;
    743     if (!sBluetoothInterface) return result;
    744 
    745     int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
    746     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    747 
    748     return result;
    749 }
    750 
    751 static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
    752     ALOGV("%s:",__FUNCTION__);
    753 
    754     jbyte *addr = NULL;
    755     jboolean result = JNI_FALSE;
    756     if (!sBluetoothInterface) return result;
    757 
    758     addr = env->GetByteArrayElements(address, NULL);
    759     if (addr == NULL) {
    760         jniThrowIOException(env, EINVAL);
    761         return result;
    762     }
    763 
    764     int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
    765                                                               (bt_property_type_t) type);
    766     env->ReleaseByteArrayElements(address, addr, 0);
    767     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    768 
    769     return result;
    770 }
    771 
    772 static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
    773                                         jint type, jbyteArray value) {
    774     ALOGV("%s:",__FUNCTION__);
    775 
    776     jbyte *val, *addr;
    777     jboolean result = JNI_FALSE;
    778     if (!sBluetoothInterface) return result;
    779 
    780     val = env->GetByteArrayElements(value, NULL);
    781     if (val == NULL) {
    782         jniThrowIOException(env, EINVAL);
    783         return result;
    784     }
    785 
    786     addr = env->GetByteArrayElements(address, NULL);
    787     if (addr == NULL) {
    788         env->ReleaseByteArrayElements(value, val, 0);
    789         jniThrowIOException(env, EINVAL);
    790         return result;
    791     }
    792 
    793 
    794     bt_property_t prop;
    795     prop.type = (bt_property_type_t) type;
    796     prop.len = env->GetArrayLength(value);
    797     prop.val = val;
    798 
    799     int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
    800     env->ReleaseByteArrayElements(value, val, 0);
    801     env->ReleaseByteArrayElements(address, addr, 0);
    802 
    803     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    804 
    805     return result;
    806 }
    807 
    808 static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
    809     ALOGV("%s:",__FUNCTION__);
    810 
    811     jbyte *addr = NULL;
    812     jboolean result = JNI_FALSE;
    813     if (!sBluetoothInterface) return result;
    814 
    815     addr = env->GetByteArrayElements(address, NULL);
    816     if (addr == NULL) {
    817         jniThrowIOException(env, EINVAL);
    818         return result;
    819     }
    820 
    821     int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
    822     env->ReleaseByteArrayElements(address, addr, 0);
    823     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
    824     return result;
    825 }
    826 
    827 static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
    828                                    jbyteArray uuidObj, jint channel, jint flag) {
    829     jbyte *addr = NULL, *uuid = NULL;
    830     int socket_fd;
    831     bt_status_t status;
    832 
    833     if (!sBluetoothSocketInterface) return -1;
    834 
    835     addr = env->GetByteArrayElements(address, NULL);
    836     if (!addr) {
    837         ALOGE("failed to get Bluetooth device address");
    838         goto Fail;
    839     }
    840 
    841     uuid = env->GetByteArrayElements(uuidObj, NULL);
    842     if (!uuid) {
    843         ALOGE("failed to get uuid");
    844         goto Fail;
    845     }
    846 
    847     if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
    848                        (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
    849         ALOGE("Socket connection failed: %d", status);
    850         goto Fail;
    851     }
    852 
    853 
    854     if (socket_fd < 0) {
    855         ALOGE("Fail to creat file descriptor on socket fd");
    856         goto Fail;
    857     }
    858     env->ReleaseByteArrayElements(address, addr, 0);
    859     env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    860     return socket_fd;
    861 
    862 Fail:
    863     if (addr) env->ReleaseByteArrayElements(address, addr, 0);
    864     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    865 
    866     return -1;
    867 }
    868 
    869 static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
    870                                      jstring name_str, jbyteArray uuidObj, jint channel, jint flag) {
    871     const char *service_name;
    872     jbyte *uuid = NULL;
    873     int socket_fd;
    874     bt_status_t status;
    875 
    876     if (!sBluetoothSocketInterface) return -1;
    877 
    878     service_name = env->GetStringUTFChars(name_str, NULL);
    879 
    880     uuid = env->GetByteArrayElements(uuidObj, NULL);
    881     if (!uuid) {
    882         ALOGE("failed to get uuid");
    883         goto Fail;
    884     }
    885     ALOGE("SOCK FLAG = %x ***********************",flag);
    886     if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
    887                        (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
    888         ALOGE("Socket listen failed: %d", status);
    889         goto Fail;
    890     }
    891 
    892     if (socket_fd < 0) {
    893         ALOGE("Fail to creat file descriptor on socket fd");
    894         goto Fail;
    895     }
    896     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
    897     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    898     return socket_fd;
    899 
    900 Fail:
    901     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
    902     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
    903 
    904     return -1;
    905 }
    906 
    907 static JNINativeMethod sMethods[] = {
    908     /* name, signature, funcPtr */
    909     {"classInitNative", "()V", (void *) classInitNative},
    910     {"initNative", "()Z", (void *) initNative},
    911     {"cleanupNative", "()V", (void*) cleanupNative},
    912     {"enableNative", "()Z",  (void*) enableNative},
    913     {"disableNative", "()Z",  (void*) disableNative},
    914     {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
    915     {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
    916     {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
    917     {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
    918     {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
    919     {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
    920     {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
    921     {"createBondNative", "([B)Z", (void*) createBondNative},
    922     {"removeBondNative", "([B)Z", (void*) removeBondNative},
    923     {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
    924     {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
    925     {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
    926     {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
    927     {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
    928     {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
    929      (void*) createSocketChannelNative}
    930 };
    931 
    932 int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
    933 {
    934     return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
    935                                     sMethods, NELEM(sMethods));
    936 }
    937 
    938 } /* namespace android */
    939 
    940 
    941 /*
    942  * JNI Initialization
    943  */
    944 jint JNI_OnLoad(JavaVM *jvm, void *reserved)
    945 {
    946     JNIEnv *e;
    947     int status;
    948 
    949     ALOGV("Bluetooth Adapter Service : loading JNI\n");
    950 
    951     // Check JNI version
    952     if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
    953         ALOGE("JNI version mismatch error");
    954         return JNI_ERR;
    955     }
    956 
    957     if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
    958         ALOGE("jni adapter service registration failure, status: %d", status);
    959         return JNI_ERR;
    960     }
    961 
    962     if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
    963         ALOGE("jni hfp registration failure, status: %d", status);
    964         return JNI_ERR;
    965     }
    966 
    967     if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
    968         ALOGE("jni a2dp registration failure: %d", status);
    969         return JNI_ERR;
    970     }
    971 
    972     if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
    973         ALOGE("jni avrcp registration failure: %d", status);
    974         return JNI_ERR;
    975     }
    976 
    977     if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
    978         ALOGE("jni hid registration failure: %d", status);
    979         return JNI_ERR;
    980     }
    981 
    982     if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
    983         ALOGE("jni hdp registration failure: %d", status);
    984         return JNI_ERR;
    985     }
    986 
    987     if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
    988         ALOGE("jni pan registration failure: %d", status);
    989         return JNI_ERR;
    990     }
    991 
    992     if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
    993         ALOGE("jni gatt registration failure: %d", status);
    994         return JNI_ERR;
    995     }
    996     return JNI_VERSION_1_6;
    997 }
    998