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