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