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