com_android_bluetooth_btservice_AdapterService.cpp revision ede67c26e7b2564ea35db6d9b3027a269c150e13
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 //TODO(BT) 432 //args.version = nat->envVer; 433 args.name = name; 434 args.group = NULL; 435 vm->AttachCurrentThread(&callbackEnv, &args); 436 ALOGV("Callback thread attached: %p", callbackEnv); 437 } else if (event == DISASSOCIATE_JVM) { 438 if (!checkCallbackThread()) { 439 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 440 return; 441 } 442 vm->DetachCurrentThread(); 443 } 444} 445 446bt_callbacks_t sBluetoothCallbacks = { 447 sizeof(sBluetoothCallbacks), 448 adapter_state_change_callback, 449 adapter_properties_callback, 450 remote_device_properties_callback, 451 device_found_callback, 452 discovery_state_changed_callback, 453 pin_request_callback, 454 ssp_request_callback, 455 bond_state_changed_callback, 456 acl_state_changed_callback, 457 callback_thread_event, 458}; 459 460static void classInitNative(JNIEnv* env, jclass clazz) { 461 int err; 462 hw_module_t* module; 463 464 jclass jniCallbackClass = 465 env->FindClass("com/android/bluetooth/btservice/JniCallbacks"); 466 sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks", 467 "Lcom/android/bluetooth/btservice/JniCallbacks;"); 468 469 method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V"); 470 471 method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass, 472 "adapterPropertyChangedCallback", 473 "([I[[B)V"); 474 method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass, 475 "discoveryStateChangeCallback", "(I)V"); 476 477 method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass, 478 "devicePropertyChangedCallback", 479 "([B[I[[B)V"); 480 method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V"); 481 method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback", 482 "([B[BI)V"); 483 method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback", 484 "([B[BIII)V"); 485 486 method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass, 487 "bondStateChangeCallback", "(I[BI)V"); 488 489 method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass, 490 "aclStateChangeCallback", "(I[BI)V"); 491 char value[PROPERTY_VALUE_MAX]; 492 property_get("bluetooth.mock_stack", value, ""); 493 494 const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID); 495 496 err = hw_get_module(id, (hw_module_t const**)&module); 497 498 if (err == 0) { 499 hw_device_t* abstraction; 500 err = module->methods->open(module, id, &abstraction); 501 if (err == 0) { 502 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction; 503 sBluetoothInterface = btStack->get_bluetooth_interface(); 504 } else { 505 ALOGE("Error while opening Bluetooth library"); 506 } 507 } else { 508 ALOGE("No Bluetooth Library found"); 509 } 510} 511 512static bool initNative(JNIEnv* env, jobject obj) { 513 ALOGV("%s:",__FUNCTION__); 514 515 sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField)); 516 517 if (sBluetoothInterface) { 518 int ret = sBluetoothInterface->init(&sBluetoothCallbacks); 519 if (ret != BT_STATUS_SUCCESS) { 520 ALOGE("Error while setting the callbacks \n"); 521 sBluetoothInterface = NULL; 522 return JNI_FALSE; 523 } 524 if ( (sBluetoothSocketInterface = (btsock_interface_t *) 525 sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) { 526 ALOGE("Error getting socket interface"); 527 } 528 return JNI_TRUE; 529 } 530 return JNI_FALSE; 531} 532 533static bool cleanupNative(JNIEnv *env, jobject obj) { 534 ALOGV("%s:",__FUNCTION__); 535 536 jboolean result = JNI_FALSE; 537 if (!sBluetoothInterface) return result; 538 539 sBluetoothInterface->cleanup(); 540 ALOGI("%s: return from cleanup",__FUNCTION__); 541 542 env->DeleteGlobalRef(sJniCallbacksObj); 543 return JNI_TRUE; 544} 545 546static jboolean enableNative(JNIEnv* env, jobject obj) { 547 ALOGV("%s:",__FUNCTION__); 548 549 jboolean result = JNI_FALSE; 550 if (!sBluetoothInterface) return result; 551 552 int ret = sBluetoothInterface->enable(); 553 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 554 return result; 555} 556 557static jboolean disableNative(JNIEnv* env, jobject obj) { 558 ALOGV("%s:",__FUNCTION__); 559 560 jboolean result = JNI_FALSE; 561 if (!sBluetoothInterface) return result; 562 563 int ret = sBluetoothInterface->disable(); 564 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 565 return result; 566} 567 568static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) { 569 ALOGV("%s:",__FUNCTION__); 570 571 jboolean result = JNI_FALSE; 572 if (!sBluetoothInterface) return result; 573 574 int ret = sBluetoothInterface->start_discovery(); 575 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 576 return result; 577} 578 579static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) { 580 ALOGV("%s:",__FUNCTION__); 581 582 jboolean result = JNI_FALSE; 583 if (!sBluetoothInterface) return result; 584 585 int ret = sBluetoothInterface->cancel_discovery(); 586 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 587 return result; 588} 589 590static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 591 ALOGV("%s:",__FUNCTION__); 592 593 jbyte *addr; 594 jboolean result = JNI_FALSE; 595 596 if (!sBluetoothInterface) return result; 597 598 addr = env->GetByteArrayElements(address, NULL); 599 if (addr == NULL) { 600 jniThrowIOException(env, EINVAL); 601 return result; 602 } 603 604 int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr); 605 env->ReleaseByteArrayElements(address, addr, NULL); 606 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 607 608 return result; 609} 610 611static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 612 ALOGV("%s:",__FUNCTION__); 613 614 jbyte *addr; 615 jboolean result; 616 if (!sBluetoothInterface) return JNI_FALSE; 617 618 addr = env->GetByteArrayElements(address, NULL); 619 if (addr == NULL) { 620 jniThrowIOException(env, EINVAL); 621 return JNI_FALSE; 622 } 623 624 int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr); 625 env->ReleaseByteArrayElements(address, addr, NULL); 626 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 627 628 return result; 629} 630 631static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 632 ALOGV("%s:",__FUNCTION__); 633 634 jbyte *addr; 635 jboolean result; 636 if (!sBluetoothInterface) return JNI_FALSE; 637 638 addr = env->GetByteArrayElements(address, NULL); 639 if (addr == NULL) { 640 jniThrowIOException(env, EINVAL); 641 return JNI_FALSE; 642 } 643 644 int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr); 645 env->ReleaseByteArrayElements(address, addr, NULL); 646 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 647 648 return result; 649} 650 651static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept, 652 jint len, jbyteArray pinArray) { 653 ALOGV("%s:",__FUNCTION__); 654 655 jbyte *addr, *pinPtr = NULL; 656 jboolean result = JNI_FALSE; 657 if (!sBluetoothInterface) return result; 658 659 addr = env->GetByteArrayElements(address, NULL); 660 if (addr == NULL) { 661 jniThrowIOException(env, EINVAL); 662 return result; 663 } 664 665 if (accept) { 666 pinPtr = env->GetByteArrayElements(pinArray, NULL); 667 if (pinPtr == NULL) { 668 jniThrowIOException(env, EINVAL); 669 env->ReleaseByteArrayElements(address, addr, NULL); 670 return result; 671 } 672 } 673 674 int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len, 675 (bt_pin_code_t *) pinPtr); 676 env->ReleaseByteArrayElements(address, addr, NULL); 677 env->ReleaseByteArrayElements(pinArray, pinPtr, NULL); 678 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 679 680 return result; 681} 682 683static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address, 684 jint type, jboolean accept, jint passkey) { 685 ALOGV("%s:",__FUNCTION__); 686 687 jbyte *addr; 688 jboolean result = JNI_FALSE; 689 if (!sBluetoothInterface) return result; 690 691 addr = env->GetByteArrayElements(address, NULL); 692 if (addr == NULL) { 693 jniThrowIOException(env, EINVAL); 694 return result; 695 } 696 697 int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr, 698 (bt_ssp_variant_t) type, accept, passkey); 699 env->ReleaseByteArrayElements(address, addr, NULL); 700 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 701 702 return result; 703} 704 705static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) { 706 ALOGV("%s:",__FUNCTION__); 707 708 jbyte *val; 709 jboolean result = JNI_FALSE; 710 if (!sBluetoothInterface) return result; 711 712 val = env->GetByteArrayElements(value, NULL); 713 bt_property_t prop; 714 prop.type = (bt_property_type_t) type; 715 prop.len = env->GetArrayLength(value); 716 prop.val = val; 717 718 int ret = sBluetoothInterface->set_adapter_property(&prop); 719 env->ReleaseByteArrayElements(value, val, NULL); 720 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 721 722 return result; 723} 724 725static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) { 726 ALOGV("%s:",__FUNCTION__); 727 728 jboolean result = JNI_FALSE; 729 if (!sBluetoothInterface) return result; 730 731 int ret = sBluetoothInterface->get_adapter_properties(); 732 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 733 734 return result; 735} 736 737static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) { 738 ALOGV("%s:",__FUNCTION__); 739 740 jboolean result = JNI_FALSE; 741 if (!sBluetoothInterface) return result; 742 743 int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type); 744 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 745 746 return result; 747} 748 749static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) { 750 ALOGV("%s:",__FUNCTION__); 751 752 jbyte *addr = NULL; 753 jboolean result = JNI_FALSE; 754 if (!sBluetoothInterface) return result; 755 756 addr = env->GetByteArrayElements(address, NULL); 757 if (addr == NULL) { 758 jniThrowIOException(env, EINVAL); 759 return result; 760 } 761 762 int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr, 763 (bt_property_type_t) type); 764 env->ReleaseByteArrayElements(address, addr, NULL); 765 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 766 767 return result; 768} 769 770static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, 771 jint type, jbyteArray value) { 772 ALOGV("%s:",__FUNCTION__); 773 774 jbyte *val, *addr; 775 jboolean result = JNI_FALSE; 776 if (!sBluetoothInterface) return result; 777 778 val = env->GetByteArrayElements(value, NULL); 779 if (val == NULL) { 780 jniThrowIOException(env, EINVAL); 781 return result; 782 } 783 784 addr = env->GetByteArrayElements(address, NULL); 785 if (addr == NULL) { 786 env->ReleaseByteArrayElements(value, val, NULL); 787 jniThrowIOException(env, EINVAL); 788 return result; 789 } 790 791 792 bt_property_t prop; 793 prop.type = (bt_property_type_t) type; 794 prop.len = env->GetArrayLength(value); 795 prop.val = val; 796 797 int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop); 798 env->ReleaseByteArrayElements(value, val, NULL); 799 env->ReleaseByteArrayElements(address, addr, NULL); 800 801 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 802 803 return result; 804} 805 806static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) { 807 ALOGV("%s:",__FUNCTION__); 808 809 jbyte *addr = NULL; 810 jboolean result = JNI_FALSE; 811 if (!sBluetoothInterface) return result; 812 813 addr = env->GetByteArrayElements(address, NULL); 814 if (addr == NULL) { 815 jniThrowIOException(env, EINVAL); 816 return result; 817 } 818 819 int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr); 820 env->ReleaseByteArrayElements(address, addr, NULL); 821 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 822 return result; 823} 824 825static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type, 826 jbyteArray uuidObj, jint channel, jint flag) { 827 jbyte *addr = NULL, *uuid = NULL; 828 int socket_fd; 829 bt_status_t status; 830 831 if (!sBluetoothSocketInterface) return NULL; 832 833 addr = env->GetByteArrayElements(address, NULL); 834 if (!addr) { 835 ALOGE("failed to get Bluetooth device address"); 836 goto Fail; 837 } 838 839 uuid = env->GetByteArrayElements(uuidObj, NULL); 840 if (!uuid) { 841 ALOGE("failed to get uuid"); 842 goto Fail; 843 } 844 845 if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type, 846 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 847 ALOGE("Socket connection failed: %d", status); 848 goto Fail; 849 } 850 851 852 if (socket_fd < 0) { 853 ALOGE("Fail to creat file descriptor on socket fd"); 854 goto Fail; 855 } 856 env->ReleaseByteArrayElements(address, addr, 0); 857 env->ReleaseByteArrayElements(uuidObj, uuid, 0); 858 return socket_fd; 859 860Fail: 861 if (addr) env->ReleaseByteArrayElements(address, addr, 0); 862 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 863 864 return -1; 865} 866 867static int createSocketChannelNative(JNIEnv *env, jobject object, jint type, 868 jstring name_str, jbyteArray uuidObj, jint channel, jint flag) { 869 const char *service_name; 870 jbyte *uuid = NULL; 871 int socket_fd; 872 bt_status_t status; 873 874 if (!sBluetoothSocketInterface) return NULL; 875 876 service_name = env->GetStringUTFChars(name_str, NULL); 877 878 uuid = env->GetByteArrayElements(uuidObj, NULL); 879 if (!uuid) { 880 ALOGE("failed to get uuid"); 881 goto Fail; 882 } 883 ALOGE("SOCK FLAG = %x ***********************",flag); 884 if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name, 885 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 886 ALOGE("Socket listen failed: %d", status); 887 goto Fail; 888 } 889 890 if (socket_fd < 0) { 891 ALOGE("Fail to creat file descriptor on socket fd"); 892 goto Fail; 893 } 894 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 895 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 896 return socket_fd; 897 898Fail: 899 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 900 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 901 902 return -1; 903} 904 905static JNINativeMethod sMethods[] = { 906 /* name, signature, funcPtr */ 907 {"classInitNative", "()V", (void *) classInitNative}, 908 {"initNative", "()Z", (void *) initNative}, 909 {"cleanupNative", "()V", (void*) cleanupNative}, 910 {"enableNative", "()Z", (void*) enableNative}, 911 {"disableNative", "()Z", (void*) disableNative}, 912 {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative}, 913 {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative}, 914 {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative}, 915 {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative}, 916 {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative}, 917 {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative}, 918 {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative}, 919 {"createBondNative", "([B)Z", (void*) createBondNative}, 920 {"removeBondNative", "([B)Z", (void*) removeBondNative}, 921 {"cancelBondNative", "([B)Z", (void*) cancelBondNative}, 922 {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative}, 923 {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative}, 924 {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative}, 925 {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative}, 926 {"createSocketChannelNative", "(ILjava/lang/String;[BII)I", 927 (void*) createSocketChannelNative}, 928}; 929 930int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) 931{ 932 return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService", 933 sMethods, NELEM(sMethods)); 934} 935 936} /* namespace android */ 937 938 939/* 940 * JNI Initialization 941 */ 942jint JNI_OnLoad(JavaVM *jvm, void *reserved) 943{ 944 JNIEnv *e; 945 int status; 946 947 ALOGV("Bluetooth Adapter Service : loading JNI\n"); 948 949 // Check JNI version 950 if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) { 951 ALOGE("JNI version mismatch error"); 952 return JNI_ERR; 953 } 954 955 if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) { 956 ALOGE("jni adapter service registration failure, status: %d", status); 957 return JNI_ERR; 958 } 959 960 if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) { 961 ALOGE("jni hfp registration failure, status: %d", status); 962 return JNI_ERR; 963 } 964 965 if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) { 966 ALOGE("jni a2dp registration failure: %d", status); 967 return JNI_ERR; 968 } 969 970 if ((status = android::register_com_android_bluetooth_hid(e)) < 0) { 971 ALOGE("jni hid registration failure: %d", status); 972 return JNI_ERR; 973 } 974 975 if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) { 976 ALOGE("jni hdp registration failure: %d", status); 977 return JNI_ERR; 978 } 979 980 if ((status = android::register_com_android_bluetooth_pan(e)) < 0) { 981 ALOGE("jni pan registration failure: %d", status); 982 return JNI_ERR; 983 } 984 985 return JNI_VERSION_1_6; 986} 987