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