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