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