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