com_android_bluetooth_btservice_AdapterService.cpp revision edb14a4944d66ca9255b2ab9b384c583b626fd94
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 env->DeleteGlobalRef(sJniCallbacksObj); 500 return JNI_TRUE; 501} 502 503static jboolean enableNative(JNIEnv* env, jobject obj) { 504 LOGV("%s:",__FUNCTION__); 505 506 jboolean result = JNI_FALSE; 507 if (!sBluetoothInterface) return result; 508 509 int ret = sBluetoothInterface->enable(); 510 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 511 return result; 512} 513 514static jboolean disableNative(JNIEnv* env, jobject obj) { 515 LOGV("%s:",__FUNCTION__); 516 517 jboolean result = JNI_FALSE; 518 if (!sBluetoothInterface) return result; 519 520 int ret = sBluetoothInterface->disable(); 521 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 522 return result; 523} 524 525static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) { 526 LOGV("%s:",__FUNCTION__); 527 528 jboolean result = JNI_FALSE; 529 if (!sBluetoothInterface) return result; 530 531 int ret = sBluetoothInterface->start_discovery(); 532 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 533 return result; 534} 535 536static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) { 537 LOGV("%s:",__FUNCTION__); 538 539 jboolean result = JNI_FALSE; 540 if (!sBluetoothInterface) return result; 541 542 int ret = sBluetoothInterface->cancel_discovery(); 543 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 544 return result; 545} 546 547static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 548 LOGV("%s:",__FUNCTION__); 549 550 jbyte *addr; 551 jboolean result = JNI_FALSE; 552 553 if (!sBluetoothInterface) return result; 554 555 addr = env->GetByteArrayElements(address, NULL); 556 if (addr == NULL) { 557 jniThrowIOException(env, EINVAL); 558 return result; 559 } 560 561 int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr); 562 env->ReleaseByteArrayElements(address, addr, NULL); 563 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 564 565 return result; 566} 567 568static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 569 LOGV("%s:",__FUNCTION__); 570 571 jbyte *addr; 572 jboolean result; 573 if (!sBluetoothInterface) return JNI_FALSE; 574 575 addr = env->GetByteArrayElements(address, NULL); 576 if (addr == NULL) { 577 jniThrowIOException(env, EINVAL); 578 return JNI_FALSE; 579 } 580 581 int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr); 582 env->ReleaseByteArrayElements(address, addr, NULL); 583 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 584 585 return result; 586} 587 588static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 589 LOGV("%s:",__FUNCTION__); 590 591 jbyte *addr; 592 jboolean result; 593 if (!sBluetoothInterface) return JNI_FALSE; 594 595 addr = env->GetByteArrayElements(address, NULL); 596 if (addr == NULL) { 597 jniThrowIOException(env, EINVAL); 598 return JNI_FALSE; 599 } 600 601 int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr); 602 env->ReleaseByteArrayElements(address, addr, NULL); 603 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 604 605 return result; 606} 607 608static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept, 609 jint len, jbyteArray pinArray) { 610 LOGV("%s:",__FUNCTION__); 611 612 jbyte *addr, *pinPtr = NULL; 613 jboolean result = JNI_FALSE; 614 if (!sBluetoothInterface) return result; 615 616 addr = env->GetByteArrayElements(address, NULL); 617 if (addr == NULL) { 618 jniThrowIOException(env, EINVAL); 619 return result; 620 } 621 622 if (accept) { 623 pinPtr = env->GetByteArrayElements(pinArray, NULL); 624 if (pinPtr == NULL) { 625 jniThrowIOException(env, EINVAL); 626 env->ReleaseByteArrayElements(address, addr, NULL); 627 return result; 628 } 629 } 630 631 int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len, 632 (bt_pin_code_t *) pinPtr); 633 env->ReleaseByteArrayElements(address, addr, NULL); 634 env->ReleaseByteArrayElements(pinArray, pinPtr, NULL); 635 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 636 637 return result; 638} 639 640static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address, 641 jint type, jboolean accept, jint passkey) { 642 LOGV("%s:",__FUNCTION__); 643 644 jbyte *addr; 645 jboolean result = JNI_FALSE; 646 if (!sBluetoothInterface) return result; 647 648 addr = env->GetByteArrayElements(address, NULL); 649 if (addr == NULL) { 650 jniThrowIOException(env, EINVAL); 651 return result; 652 } 653 654 int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr, 655 (bt_ssp_variant_t) type, accept, passkey); 656 env->ReleaseByteArrayElements(address, addr, NULL); 657 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 658 659 return result; 660} 661 662static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) { 663 LOGV("%s:",__FUNCTION__); 664 665 jbyte *val; 666 jboolean result = JNI_FALSE; 667 if (!sBluetoothInterface) return result; 668 669 val = env->GetByteArrayElements(value, NULL); 670 bt_property_t prop; 671 prop.type = (bt_property_type_t) type; 672 prop.len = env->GetArrayLength(value); 673 prop.val = val; 674 675 int ret = sBluetoothInterface->set_adapter_property(&prop); 676 env->ReleaseByteArrayElements(value, val, NULL); 677 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 678 679 return result; 680} 681 682static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) { 683 LOGV("%s:",__FUNCTION__); 684 685 jboolean result = JNI_FALSE; 686 if (!sBluetoothInterface) return result; 687 688 int ret = sBluetoothInterface->get_adapter_properties(); 689 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 690 691 return result; 692} 693 694static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) { 695 LOGV("%s:",__FUNCTION__); 696 697 jboolean result = JNI_FALSE; 698 if (!sBluetoothInterface) return result; 699 700 int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type); 701 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 702 703 return result; 704} 705 706static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) { 707 LOGV("%s:",__FUNCTION__); 708 709 jbyte *addr = NULL; 710 jboolean result = JNI_FALSE; 711 if (!sBluetoothInterface) return result; 712 713 addr = env->GetByteArrayElements(address, NULL); 714 if (addr == NULL) { 715 jniThrowIOException(env, EINVAL); 716 return result; 717 } 718 719 int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr, 720 (bt_property_type_t) type); 721 env->ReleaseByteArrayElements(address, addr, NULL); 722 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 723 724 return result; 725} 726 727static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, 728 jint type, jbyteArray value) { 729 LOGV("%s:",__FUNCTION__); 730 731 jbyte *val, *addr; 732 jboolean result = JNI_FALSE; 733 if (!sBluetoothInterface) return result; 734 735 val = env->GetByteArrayElements(value, NULL); 736 if (val == NULL) { 737 jniThrowIOException(env, EINVAL); 738 return result; 739 } 740 741 addr = env->GetByteArrayElements(address, NULL); 742 if (addr == NULL) { 743 env->ReleaseByteArrayElements(value, val, NULL); 744 jniThrowIOException(env, EINVAL); 745 return result; 746 } 747 748 749 bt_property_t prop; 750 prop.type = (bt_property_type_t) type; 751 prop.len = env->GetArrayLength(value); 752 prop.val = val; 753 754 int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop); 755 env->ReleaseByteArrayElements(value, val, NULL); 756 env->ReleaseByteArrayElements(address, addr, NULL); 757 758 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 759 760 return result; 761} 762 763static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) { 764 LOGV("%s:",__FUNCTION__); 765 766 jbyte *addr = NULL; 767 jboolean result = JNI_FALSE; 768 if (!sBluetoothInterface) return result; 769 770 addr = env->GetByteArrayElements(address, NULL); 771 if (addr == NULL) { 772 jniThrowIOException(env, EINVAL); 773 return result; 774 } 775 776 int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr); 777 env->ReleaseByteArrayElements(address, addr, NULL); 778 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 779 return result; 780} 781 782static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type, 783 jbyteArray uuidObj, jint channel, jint flag) { 784 jbyte *addr = NULL, *uuid = NULL; 785 int socket_fd; 786 bt_status_t status; 787 788 if (!sBluetoothSocketInterface) return NULL; 789 790 addr = env->GetByteArrayElements(address, NULL); 791 if (!addr) { 792 LOGE("failed to get Bluetooth device address"); 793 goto Fail; 794 } 795 796 uuid = env->GetByteArrayElements(uuidObj, NULL); 797 if (!uuid) { 798 LOGE("failed to get uuid"); 799 goto Fail; 800 } 801 802 if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type, 803 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 804 LOGE("Socket connection failed: %d", status); 805 goto Fail; 806 } 807 808 809 if (socket_fd < 0) { 810 LOGE("Fail to creat file descriptor on socket fd"); 811 goto Fail; 812 } 813 env->ReleaseByteArrayElements(address, addr, 0); 814 env->ReleaseByteArrayElements(uuidObj, uuid, 0); 815 return socket_fd; 816 817Fail: 818 if (addr) env->ReleaseByteArrayElements(address, addr, 0); 819 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 820 821 return -1; 822} 823 824static int createSocketChannelNative(JNIEnv *env, jobject object, jint type, 825 jstring name_str, jbyteArray uuidObj, jint channel, jint flag) { 826 const char *service_name; 827 jbyte *uuid = NULL; 828 int socket_fd; 829 bt_status_t status; 830 831 if (!sBluetoothSocketInterface) return NULL; 832 833 service_name = env->GetStringUTFChars(name_str, NULL); 834 835 uuid = env->GetByteArrayElements(uuidObj, NULL); 836 if (!uuid) { 837 LOGE("failed to get uuid"); 838 goto Fail; 839 } 840 841 if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name, 842 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 843 LOGE("Socket listen failed: %d", status); 844 goto Fail; 845 } 846 847 if (socket_fd < 0) { 848 LOGE("Fail to creat file descriptor on socket fd"); 849 goto Fail; 850 } 851 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 852 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 853 return socket_fd; 854 855Fail: 856 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 857 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 858 859 return -1; 860} 861 862static JNINativeMethod sMethods[] = { 863 /* name, signature, funcPtr */ 864 {"classInitNative", "()V", (void *) classInitNative}, 865 {"initNative", "()Z", (void *) initNative}, 866 {"cleanupNative", "()V", (void*) cleanupNative}, 867 {"enableNative", "()Z", (void*) enableNative}, 868 {"disableNative", "()Z", (void*) disableNative}, 869 {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative}, 870 {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative}, 871 {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative}, 872 {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative}, 873 {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative}, 874 {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative}, 875 {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative}, 876 {"createBondNative", "([B)Z", (void*) createBondNative}, 877 {"removeBondNative", "([B)Z", (void*) removeBondNative}, 878 {"cancelBondNative", "([B)Z", (void*) cancelBondNative}, 879 {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative}, 880 {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative}, 881 {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative}, 882 {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative}, 883 {"createSocketChannelNative", "(ILjava/lang/String;[BII)I", 884 (void*) createSocketChannelNative}, 885}; 886 887int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) 888{ 889 return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService", 890 sMethods, NELEM(sMethods)); 891} 892 893} /* namespace android */ 894 895 896/* 897 * JNI Initialization 898 */ 899jint JNI_OnLoad(JavaVM *jvm, void *reserved) 900{ 901 JNIEnv *e; 902 int status; 903 904 LOGV("Bluetooth Adapter Service : loading JNI\n"); 905 906 // Check JNI version 907 if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) { 908 LOGE("JNI version mismatch error"); 909 return JNI_ERR; 910 } 911 912 if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) { 913 LOGE("jni adapter service registration failure, status: %d", status); 914 return JNI_ERR; 915 } 916 917 if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) { 918 LOGE("jni hfp registration failure, status: %d", status); 919 return JNI_ERR; 920 } 921 922 if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) { 923 LOGE("jni a2dp registration failure: %d", status); 924 return JNI_ERR; 925 } 926 927 if ((status = android::register_com_android_bluetooth_hid(e)) < 0) { 928 LOGE("jni hid registration failure: %d", status); 929 return JNI_ERR; 930 } 931 932 if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) { 933 LOGE("jni hdp registration failure: %d", status); 934 return JNI_ERR; 935 } 936 937 return JNI_VERSION_1_6; 938} 939