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