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