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