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