com_android_bluetooth_btservice_AdapterService.cpp revision 6654f5c903de510a70f9e72cd5ad7837b615d93f
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 22 23static jmethodID method_stateChangeCallback; 24static jmethodID method_adapterPropertyChangedCallback; 25static jmethodID method_devicePropertyChangedCallback; 26static jmethodID method_deviceFoundCallback; 27static jmethodID method_pinRequestCallback; 28static jmethodID method_sspRequestCallback; 29static jmethodID method_bondStateChangeCallback; 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 LOGE("%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 LOGE("%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 LOGE("%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 LOGE("%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 LOGE("%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 LOGE("%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 discovery_state_changed_callback(bt_discovery_state_t state) { 306 jbyteArray addr; 307 if (!checkCallbackThread()) { 308 LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 309 return; 310 } 311 312 LOGV("%s: DiscoveryState:%d ", __FUNCTION__, state); 313 314 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback, 315 (jint)state); 316 317 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 318} 319 320static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) { 321 jbyteArray addr, devname; 322 if (!checkCallbackThread()) { 323 LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 324 return; 325 } 326 if (!bd_addr) { 327 LOGE("Address is null in %s", __FUNCTION__); 328 return; 329 } 330 331 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 332 if (addr == NULL) goto Fail; 333 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr); 334 335 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t)); 336 if (devname == NULL) goto Fail; 337 338 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname); 339 340 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod); 341 342 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 343 callbackEnv->DeleteLocalRef(addr); 344 callbackEnv->DeleteLocalRef(devname); 345 return; 346 347Fail: 348 if (addr) callbackEnv->DeleteLocalRef(addr); 349 if (devname) callbackEnv->DeleteLocalRef(devname); 350 LOGE("Error while allocating in: %s", __FUNCTION__); 351} 352 353static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod, 354 bt_ssp_variant_t pairing_variant, uint32_t pass_key) { 355 jbyteArray addr, devname; 356 if (!checkCallbackThread()) { 357 LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 358 return; 359 } 360 if (!bd_addr) { 361 LOGE("Address is null in %s", __FUNCTION__); 362 return; 363 } 364 365 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 366 if (addr == NULL) goto Fail; 367 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr); 368 369 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t)); 370 if (devname == NULL) goto Fail; 371 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname); 372 373 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod, 374 (jint) pairing_variant, pass_key); 375 376 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 377 callbackEnv->DeleteLocalRef(addr); 378 callbackEnv->DeleteLocalRef(devname); 379 return; 380 381Fail: 382 if (addr) callbackEnv->DeleteLocalRef(addr); 383 if (devname) callbackEnv->DeleteLocalRef(devname); 384 385 LOGE("Error while allocating in: %s", __FUNCTION__); 386} 387 388static void callback_thread_event(bt_cb_thread_evt event) { 389 JavaVM* vm = AndroidRuntime::getJavaVM(); 390 if (event == ASSOCIATE_JVM) { 391 JavaVMAttachArgs args; 392 char name[] = "BT Service Callback Thread"; 393 //TODO(BT) 394 //args.version = nat->envVer; 395 args.name = name; 396 args.group = NULL; 397 vm->AttachCurrentThread(&callbackEnv, &args); 398 LOGV("Callback thread attached: %p", callbackEnv); 399 } else if (event == DISASSOCIATE_JVM) { 400 if (!checkCallbackThread()) { 401 LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 402 return; 403 } 404 vm->DetachCurrentThread(); 405 } 406} 407 408bt_callbacks_t sBluetoothCallbacks = { 409 sizeof(sBluetoothCallbacks), 410 adapter_state_change_callback, 411 adapter_properties_callback, 412 remote_device_properties_callback, 413 device_found_callback, 414 discovery_state_changed_callback, 415 pin_request_callback, 416 ssp_request_callback, 417 bond_state_changed_callback, 418 callback_thread_event, 419}; 420 421static void classInitNative(JNIEnv* env, jclass clazz) { 422 int err; 423 hw_module_t* module; 424 425 jclass jniCallbackClass = 426 env->FindClass("com/android/bluetooth/btservice/JniCallbacks"); 427 sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks", 428 "Lcom/android/bluetooth/btservice/JniCallbacks;"); 429 430 method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V"); 431 432 method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass, 433 "adapterPropertyChangedCallback", 434 "([I[[B)V"); 435 method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass, 436 "discoveryStateChangeCallback", "(I)V"); 437 438 method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass, 439 "devicePropertyChangedCallback", 440 "([B[I[[B)V"); 441 method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V"); 442 method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback", 443 "([B[BI)V"); 444 method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback", 445 "([B[BIII)V"); 446 447 method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass, 448 "bondStateChangeCallback", "(I[BI)V"); 449 450 char value[PROPERTY_VALUE_MAX]; 451 property_get("bluetooth.mock_stack", value, ""); 452 453 const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID); 454 455 err = hw_get_module(id, (hw_module_t const**)&module); 456 457 if (err == 0) { 458 hw_device_t* abstraction; 459 err = module->methods->open(module, id, &abstraction); 460 if (err == 0) { 461 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction; 462 sBluetoothInterface = btStack->get_bluetooth_interface(); 463 } else { 464 LOGE("Error while opening Bluetooth library"); 465 } 466 } else { 467 LOGE("No Bluetooth Library found"); 468 } 469} 470 471static bool initNative(JNIEnv* env, jobject obj) { 472 LOGV("%s:",__FUNCTION__); 473 474 sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField)); 475 476 if (sBluetoothInterface) { 477 int ret = sBluetoothInterface->init(&sBluetoothCallbacks); 478 if (ret != BT_STATUS_SUCCESS) { 479 LOGE("Error while setting the callbacks \n"); 480 sBluetoothInterface = NULL; 481 return JNI_FALSE; 482 } 483 if ( (sBluetoothSocketInterface = (btsock_interface_t *) 484 sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) { 485 LOGE("Error getting socket interface"); 486 } 487 return JNI_TRUE; 488 } 489 return JNI_FALSE; 490} 491 492static bool cleanupNative(JNIEnv *env, jobject obj) { 493 LOGV("%s:",__FUNCTION__); 494 495 jboolean result = JNI_FALSE; 496 if (!sBluetoothInterface) return result; 497 498 sBluetoothInterface->cleanup(); 499 LOGV("%s: return from cleanup",__FUNCTION__); 500 501 env->DeleteGlobalRef(sJniCallbacksObj); 502 return JNI_TRUE; 503} 504 505static jboolean enableNative(JNIEnv* env, jobject obj) { 506 LOGV("%s:",__FUNCTION__); 507 508 jboolean result = JNI_FALSE; 509 if (!sBluetoothInterface) return result; 510 511 int ret = sBluetoothInterface->enable(); 512 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 513 return result; 514} 515 516static jboolean disableNative(JNIEnv* env, jobject obj) { 517 LOGV("%s:",__FUNCTION__); 518 519 jboolean result = JNI_FALSE; 520 if (!sBluetoothInterface) return result; 521 522 int ret = sBluetoothInterface->disable(); 523 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 524 return result; 525} 526 527static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) { 528 LOGV("%s:",__FUNCTION__); 529 530 jboolean result = JNI_FALSE; 531 if (!sBluetoothInterface) return result; 532 533 int ret = sBluetoothInterface->start_discovery(); 534 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 535 return result; 536} 537 538static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) { 539 LOGV("%s:",__FUNCTION__); 540 541 jboolean result = JNI_FALSE; 542 if (!sBluetoothInterface) return result; 543 544 int ret = sBluetoothInterface->cancel_discovery(); 545 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 546 return result; 547} 548 549static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 550 LOGV("%s:",__FUNCTION__); 551 552 jbyte *addr; 553 jboolean result = JNI_FALSE; 554 555 if (!sBluetoothInterface) return result; 556 557 addr = env->GetByteArrayElements(address, NULL); 558 if (addr == NULL) { 559 jniThrowIOException(env, EINVAL); 560 return result; 561 } 562 563 int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr); 564 env->ReleaseByteArrayElements(address, addr, NULL); 565 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 566 567 return result; 568} 569 570static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 571 LOGV("%s:",__FUNCTION__); 572 573 jbyte *addr; 574 jboolean result; 575 if (!sBluetoothInterface) return JNI_FALSE; 576 577 addr = env->GetByteArrayElements(address, NULL); 578 if (addr == NULL) { 579 jniThrowIOException(env, EINVAL); 580 return JNI_FALSE; 581 } 582 583 int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr); 584 env->ReleaseByteArrayElements(address, addr, NULL); 585 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 586 587 return result; 588} 589 590static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 591 LOGV("%s:",__FUNCTION__); 592 593 jbyte *addr; 594 jboolean result; 595 if (!sBluetoothInterface) return JNI_FALSE; 596 597 addr = env->GetByteArrayElements(address, NULL); 598 if (addr == NULL) { 599 jniThrowIOException(env, EINVAL); 600 return JNI_FALSE; 601 } 602 603 int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr); 604 env->ReleaseByteArrayElements(address, addr, NULL); 605 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 606 607 return result; 608} 609 610static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept, 611 jint len, jbyteArray pinArray) { 612 LOGV("%s:",__FUNCTION__); 613 614 jbyte *addr, *pinPtr = NULL; 615 jboolean result = JNI_FALSE; 616 if (!sBluetoothInterface) return result; 617 618 addr = env->GetByteArrayElements(address, NULL); 619 if (addr == NULL) { 620 jniThrowIOException(env, EINVAL); 621 return result; 622 } 623 624 if (accept) { 625 pinPtr = env->GetByteArrayElements(pinArray, NULL); 626 if (pinPtr == NULL) { 627 jniThrowIOException(env, EINVAL); 628 env->ReleaseByteArrayElements(address, addr, NULL); 629 return result; 630 } 631 } 632 633 int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len, 634 (bt_pin_code_t *) pinPtr); 635 env->ReleaseByteArrayElements(address, addr, NULL); 636 env->ReleaseByteArrayElements(pinArray, pinPtr, NULL); 637 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 638 639 return result; 640} 641 642static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address, 643 jint type, jboolean accept, jint passkey) { 644 LOGV("%s:",__FUNCTION__); 645 646 jbyte *addr; 647 jboolean result = JNI_FALSE; 648 if (!sBluetoothInterface) return result; 649 650 addr = env->GetByteArrayElements(address, NULL); 651 if (addr == NULL) { 652 jniThrowIOException(env, EINVAL); 653 return result; 654 } 655 656 int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr, 657 (bt_ssp_variant_t) type, accept, passkey); 658 env->ReleaseByteArrayElements(address, addr, NULL); 659 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 660 661 return result; 662} 663 664static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) { 665 LOGV("%s:",__FUNCTION__); 666 667 jbyte *val; 668 jboolean result = JNI_FALSE; 669 if (!sBluetoothInterface) return result; 670 671 val = env->GetByteArrayElements(value, NULL); 672 bt_property_t prop; 673 prop.type = (bt_property_type_t) type; 674 prop.len = env->GetArrayLength(value); 675 prop.val = val; 676 677 int ret = sBluetoothInterface->set_adapter_property(&prop); 678 env->ReleaseByteArrayElements(value, val, NULL); 679 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 680 681 return result; 682} 683 684static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) { 685 LOGV("%s:",__FUNCTION__); 686 687 jboolean result = JNI_FALSE; 688 if (!sBluetoothInterface) return result; 689 690 int ret = sBluetoothInterface->get_adapter_properties(); 691 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 692 693 return result; 694} 695 696static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) { 697 LOGV("%s:",__FUNCTION__); 698 699 jboolean result = JNI_FALSE; 700 if (!sBluetoothInterface) return result; 701 702 int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type); 703 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 704 705 return result; 706} 707 708static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) { 709 LOGV("%s:",__FUNCTION__); 710 711 jbyte *addr = NULL; 712 jboolean result = JNI_FALSE; 713 if (!sBluetoothInterface) return result; 714 715 addr = env->GetByteArrayElements(address, NULL); 716 if (addr == NULL) { 717 jniThrowIOException(env, EINVAL); 718 return result; 719 } 720 721 int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr, 722 (bt_property_type_t) type); 723 env->ReleaseByteArrayElements(address, addr, NULL); 724 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 725 726 return result; 727} 728 729static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, 730 jint type, jbyteArray value) { 731 LOGV("%s:",__FUNCTION__); 732 733 jbyte *val, *addr; 734 jboolean result = JNI_FALSE; 735 if (!sBluetoothInterface) return result; 736 737 val = env->GetByteArrayElements(value, NULL); 738 if (val == NULL) { 739 jniThrowIOException(env, EINVAL); 740 return result; 741 } 742 743 addr = env->GetByteArrayElements(address, NULL); 744 if (addr == NULL) { 745 env->ReleaseByteArrayElements(value, val, NULL); 746 jniThrowIOException(env, EINVAL); 747 return result; 748 } 749 750 751 bt_property_t prop; 752 prop.type = (bt_property_type_t) type; 753 prop.len = env->GetArrayLength(value); 754 prop.val = val; 755 756 int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop); 757 env->ReleaseByteArrayElements(value, val, NULL); 758 env->ReleaseByteArrayElements(address, addr, NULL); 759 760 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 761 762 return result; 763} 764 765static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) { 766 LOGV("%s:",__FUNCTION__); 767 768 jbyte *addr = NULL; 769 jboolean result = JNI_FALSE; 770 if (!sBluetoothInterface) return result; 771 772 addr = env->GetByteArrayElements(address, NULL); 773 if (addr == NULL) { 774 jniThrowIOException(env, EINVAL); 775 return result; 776 } 777 778 int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr); 779 env->ReleaseByteArrayElements(address, addr, NULL); 780 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 781 return result; 782} 783 784static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type, 785 jbyteArray uuidObj, jint channel, jint flag) { 786 jbyte *addr = NULL, *uuid = NULL; 787 int socket_fd; 788 bt_status_t status; 789 790 if (!sBluetoothSocketInterface) return NULL; 791 792 addr = env->GetByteArrayElements(address, NULL); 793 if (!addr) { 794 LOGE("failed to get Bluetooth device address"); 795 goto Fail; 796 } 797 798 uuid = env->GetByteArrayElements(uuidObj, NULL); 799 if (!uuid) { 800 LOGE("failed to get uuid"); 801 goto Fail; 802 } 803 804 if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type, 805 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 806 LOGE("Socket connection failed: %d", status); 807 goto Fail; 808 } 809 810 811 if (socket_fd < 0) { 812 LOGE("Fail to creat file descriptor on socket fd"); 813 goto Fail; 814 } 815 env->ReleaseByteArrayElements(address, addr, 0); 816 env->ReleaseByteArrayElements(uuidObj, uuid, 0); 817 return socket_fd; 818 819Fail: 820 if (addr) env->ReleaseByteArrayElements(address, addr, 0); 821 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 822 823 return -1; 824} 825 826static int createSocketChannelNative(JNIEnv *env, jobject object, jint type, 827 jstring name_str, jbyteArray uuidObj, jint channel, jint flag) { 828 const char *service_name; 829 jbyte *uuid = NULL; 830 int socket_fd; 831 bt_status_t status; 832 833 if (!sBluetoothSocketInterface) return NULL; 834 835 service_name = env->GetStringUTFChars(name_str, NULL); 836 837 uuid = env->GetByteArrayElements(uuidObj, NULL); 838 if (!uuid) { 839 LOGE("failed to get uuid"); 840 goto Fail; 841 } 842 LOGE("SOCK FLAG = %x ***********************",flag); 843 if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name, 844 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 845 LOGE("Socket listen failed: %d", status); 846 goto Fail; 847 } 848 849 if (socket_fd < 0) { 850 LOGE("Fail to creat file descriptor on socket fd"); 851 goto Fail; 852 } 853 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 854 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 855 return socket_fd; 856 857Fail: 858 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 859 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 860 861 return -1; 862} 863 864static JNINativeMethod sMethods[] = { 865 /* name, signature, funcPtr */ 866 {"classInitNative", "()V", (void *) classInitNative}, 867 {"initNative", "()Z", (void *) initNative}, 868 {"cleanupNative", "()V", (void*) cleanupNative}, 869 {"enableNative", "()Z", (void*) enableNative}, 870 {"disableNative", "()Z", (void*) disableNative}, 871 {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative}, 872 {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative}, 873 {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative}, 874 {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative}, 875 {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative}, 876 {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative}, 877 {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative}, 878 {"createBondNative", "([B)Z", (void*) createBondNative}, 879 {"removeBondNative", "([B)Z", (void*) removeBondNative}, 880 {"cancelBondNative", "([B)Z", (void*) cancelBondNative}, 881 {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative}, 882 {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative}, 883 {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative}, 884 {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative}, 885 {"createSocketChannelNative", "(ILjava/lang/String;[BII)I", 886 (void*) createSocketChannelNative}, 887}; 888 889int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) 890{ 891 return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService", 892 sMethods, NELEM(sMethods)); 893} 894 895} /* namespace android */ 896 897 898/* 899 * JNI Initialization 900 */ 901jint JNI_OnLoad(JavaVM *jvm, void *reserved) 902{ 903 JNIEnv *e; 904 int status; 905 906 LOGV("Bluetooth Adapter Service : loading JNI\n"); 907 908 // Check JNI version 909 if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) { 910 LOGE("JNI version mismatch error"); 911 return JNI_ERR; 912 } 913 914 if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) { 915 LOGE("jni adapter service registration failure, status: %d", status); 916 return JNI_ERR; 917 } 918 919 if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) { 920 LOGE("jni hfp registration failure, status: %d", status); 921 return JNI_ERR; 922 } 923 924 if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) { 925 LOGE("jni a2dp registration failure: %d", status); 926 return JNI_ERR; 927 } 928 929 if ((status = android::register_com_android_bluetooth_hid(e)) < 0) { 930 LOGE("jni hid registration failure: %d", status); 931 return JNI_ERR; 932 } 933 934 if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) { 935 LOGE("jni hdp registration failure: %d", status); 936 return JNI_ERR; 937 } 938 939 if ((status = android::register_com_android_bluetooth_pan(e)) < 0) { 940 LOGE("jni pan registration failure: %d", status); 941 return JNI_ERR; 942 } 943 944 return JNI_VERSION_1_6; 945} 946