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