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