com_android_bluetooth_btservice_AdapterService.cpp revision c030f08f419d596c4aa216c9cca9867e7b5486f0
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "BluetoothServiceJni" 18#include "com_android_bluetooth.h" 19#include "hardware/bt_sock.h" 20#include "utils/Log.h" 21#include "utils/misc.h" 22#include "cutils/properties.h" 23#include "android_runtime/AndroidRuntime.h" 24#include "android_runtime/Log.h" 25 26#include <string.h> 27#include <pthread.h> 28 29#include <sys/stat.h> 30#include <fcntl.h> 31 32namespace android { 33 34#define ADDITIONAL_NREFS 50 35static jmethodID method_stateChangeCallback; 36static jmethodID method_adapterPropertyChangedCallback; 37static jmethodID method_devicePropertyChangedCallback; 38static jmethodID method_deviceFoundCallback; 39static jmethodID method_pinRequestCallback; 40static jmethodID method_sspRequestCallback; 41static jmethodID method_bondStateChangeCallback; 42static jmethodID method_aclStateChangeCallback; 43static jmethodID method_discoveryStateChangeCallback; 44static jmethodID method_setWakeAlarm; 45static jmethodID method_acquireWakeLock; 46static jmethodID method_releaseWakeLock; 47 48static const bt_interface_t *sBluetoothInterface = NULL; 49static const btsock_interface_t *sBluetoothSocketInterface = NULL; 50static JNIEnv *callbackEnv = NULL; 51 52static jobject sJniAdapterServiceObj; 53static jobject sJniCallbacksObj; 54static jfieldID sJniCallbacksField; 55 56 57const bt_interface_t* getBluetoothInterface() { 58 return sBluetoothInterface; 59} 60 61JNIEnv* getCallbackEnv() { 62 return callbackEnv; 63} 64 65void checkAndClearExceptionFromCallback(JNIEnv* env, 66 const char* methodName) { 67 if (env->ExceptionCheck()) { 68 ALOGE("An exception was thrown by callback '%s'.", methodName); 69 LOGE_EX(env); 70 env->ExceptionClear(); 71 } 72} 73 74static bool checkCallbackThread() { 75 JNIEnv* env = AndroidRuntime::getJNIEnv(); 76 if (callbackEnv != env || callbackEnv == NULL) { 77 ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv); 78 return false; 79 } 80 return true; 81} 82 83static void adapter_state_change_callback(bt_state_t status) { 84 if (!checkCallbackThread()) { 85 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 86 return; 87 } 88 ALOGV("%s: Status is: %d", __FUNCTION__, status); 89 90 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status); 91 92 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 93} 94 95static int get_properties(int num_properties, bt_property_t *properties, jintArray *types, 96 jobjectArray *props) { 97 jbyteArray propVal; 98 for (int i = 0; i < num_properties; i++) { 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 // Delete reference to propVal 106 callbackEnv->DeleteLocalRef(propVal); 107 callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type); 108 } 109 return 0; 110Fail: 111 if (propVal) callbackEnv->DeleteLocalRef(propVal); 112 ALOGE("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 jbyteArray val; 121 jclass mclass; 122 123 if (!checkCallbackThread()) { 124 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 125 return; 126 } 127 128 ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties); 129 130 if (status != BT_STATUS_SUCCESS) { 131 ALOGE("%s: Status %d is incorrect", __FUNCTION__, status); 132 return; 133 } 134 135 val = (jbyteArray) callbackEnv->NewByteArray(num_properties); 136 if (val == NULL) { 137 ALOGE("%s: Error allocating byteArray", __FUNCTION__); 138 return; 139 } 140 141 mclass = callbackEnv->GetObjectClass(val); 142 143 /* (BT) Initialize the jobjectArray and jintArray here itself and send the 144 initialized array pointers alone to get_properties */ 145 146 props = callbackEnv->NewObjectArray(num_properties, mclass, 147 NULL); 148 if (props == NULL) { 149 ALOGE("%s: Error allocating object Array for properties", __FUNCTION__); 150 return; 151 } 152 153 types = (jintArray)callbackEnv->NewIntArray(num_properties); 154 155 if (types == NULL) { 156 ALOGE("%s: Error allocating int Array for values", __FUNCTION__); 157 return; 158 } 159 // Delete the reference to val and mclass 160 callbackEnv->DeleteLocalRef(mclass); 161 callbackEnv->DeleteLocalRef(val); 162 163 if (get_properties(num_properties, properties, &types, &props) < 0) { 164 if (props) callbackEnv->DeleteLocalRef(props); 165 if (types) callbackEnv->DeleteLocalRef(types); 166 return; 167 } 168 169 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types, 170 props); 171 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 172 callbackEnv->DeleteLocalRef(props); 173 callbackEnv->DeleteLocalRef(types); 174 return; 175 176} 177 178static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr, 179 int num_properties, bt_property_t *properties) { 180 if (!checkCallbackThread()) { 181 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 182 return; 183 } 184 185 ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties); 186 187 if (status != BT_STATUS_SUCCESS) { 188 ALOGE("%s: Status %d is incorrect", __FUNCTION__, status); 189 return; 190 } 191 192 callbackEnv->PushLocalFrame(ADDITIONAL_NREFS); 193 194 jobjectArray props; 195 jbyteArray addr; 196 jintArray types; 197 jbyteArray val; 198 jclass mclass; 199 200 val = (jbyteArray) callbackEnv->NewByteArray(num_properties); 201 if (val == NULL) { 202 ALOGE("%s: Error allocating byteArray", __FUNCTION__); 203 return; 204 } 205 206 mclass = callbackEnv->GetObjectClass(val); 207 208 /* Initialize the jobjectArray and jintArray here itself and send the 209 initialized array pointers alone to get_properties */ 210 211 props = callbackEnv->NewObjectArray(num_properties, mclass, 212 NULL); 213 if (props == NULL) { 214 ALOGE("%s: Error allocating object Array for properties", __FUNCTION__); 215 return; 216 } 217 218 types = (jintArray)callbackEnv->NewIntArray(num_properties); 219 220 if (types == NULL) { 221 ALOGE("%s: Error allocating int Array for values", __FUNCTION__); 222 return; 223 } 224 // Delete the reference to val and mclass 225 callbackEnv->DeleteLocalRef(mclass); 226 callbackEnv->DeleteLocalRef(val); 227 228 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 229 if (addr == NULL) goto Fail; 230 if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr); 231 232 if (get_properties(num_properties, properties, &types, &props) < 0) { 233 if (props) callbackEnv->DeleteLocalRef(props); 234 if (types) callbackEnv->DeleteLocalRef(types); 235 callbackEnv->PopLocalFrame(NULL); 236 return; 237 } 238 239 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr, 240 types, props); 241 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 242 callbackEnv->DeleteLocalRef(props); 243 callbackEnv->DeleteLocalRef(types); 244 callbackEnv->DeleteLocalRef(addr); 245 callbackEnv->PopLocalFrame(NULL); 246 return; 247 248Fail: 249 ALOGE("Error while allocation byte array in %s", __FUNCTION__); 250} 251 252 253static void device_found_callback(int num_properties, bt_property_t *properties) { 254 jbyteArray addr = NULL; 255 int addr_index; 256 257 for (int i = 0; i < num_properties; i++) { 258 if (properties[i].type == BT_PROPERTY_BDADDR) { 259 addr = callbackEnv->NewByteArray(properties[i].len); 260 if (addr) { 261 callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len, 262 (jbyte*)properties[i].val); 263 addr_index = i; 264 } else { 265 ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__); 266 return; 267 } 268 } 269 } 270 if (addr == NULL) { 271 ALOGE("Address is NULL in %s", __FUNCTION__); 272 return; 273 } 274 275 ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties, 276 (const char *)properties[addr_index].val); 277 278 remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val, 279 num_properties, properties); 280 281 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr); 282 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 283 callbackEnv->DeleteLocalRef(addr); 284} 285 286static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr, 287 bt_bond_state_t state) { 288 jbyteArray addr; 289 int i; 290 if (!checkCallbackThread()) { 291 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 292 return; 293 } 294 if (!bd_addr) { 295 ALOGE("Address is null in %s", __FUNCTION__); 296 return; 297 } 298 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 299 if (addr == NULL) { 300 ALOGE("Address allocation failed in %s", __FUNCTION__); 301 return; 302 } 303 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr); 304 305 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status, 306 addr, (jint)state); 307 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 308 callbackEnv->DeleteLocalRef(addr); 309} 310 311static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr, 312 bt_acl_state_t state) 313{ 314 jbyteArray addr; 315 int i; 316 if (!checkCallbackThread()) { 317 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 318 return; 319 } 320 if (!bd_addr) { 321 ALOGE("Address is null in %s", __FUNCTION__); 322 return; 323 } 324 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 325 if (addr == NULL) { 326 ALOGE("Address allocation failed in %s", __FUNCTION__); 327 return; 328 } 329 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr); 330 331 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status, 332 addr, (jint)state); 333 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 334 callbackEnv->DeleteLocalRef(addr); 335} 336 337static void discovery_state_changed_callback(bt_discovery_state_t state) { 338 jbyteArray addr; 339 if (!checkCallbackThread()) { 340 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 341 return; 342 } 343 344 ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state); 345 346 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback, 347 (jint)state); 348 349 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 350} 351 352static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) { 353 jbyteArray addr, devname; 354 if (!checkCallbackThread()) { 355 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 356 return; 357 } 358 if (!bd_addr) { 359 ALOGE("Address is null in %s", __FUNCTION__); 360 return; 361 } 362 363 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 364 if (addr == NULL) goto Fail; 365 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr); 366 367 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t)); 368 if (devname == NULL) goto Fail; 369 370 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname); 371 372 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod); 373 374 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 375 callbackEnv->DeleteLocalRef(addr); 376 callbackEnv->DeleteLocalRef(devname); 377 return; 378 379Fail: 380 if (addr) callbackEnv->DeleteLocalRef(addr); 381 if (devname) callbackEnv->DeleteLocalRef(devname); 382 ALOGE("Error while allocating in: %s", __FUNCTION__); 383} 384 385static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod, 386 bt_ssp_variant_t pairing_variant, uint32_t pass_key) { 387 jbyteArray addr, devname; 388 if (!checkCallbackThread()) { 389 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 390 return; 391 } 392 if (!bd_addr) { 393 ALOGE("Address is null in %s", __FUNCTION__); 394 return; 395 } 396 397 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 398 if (addr == NULL) goto Fail; 399 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr); 400 401 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t)); 402 if (devname == NULL) goto Fail; 403 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname); 404 405 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod, 406 (jint) pairing_variant, pass_key); 407 408 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__); 409 callbackEnv->DeleteLocalRef(addr); 410 callbackEnv->DeleteLocalRef(devname); 411 return; 412 413Fail: 414 if (addr) callbackEnv->DeleteLocalRef(addr); 415 if (devname) callbackEnv->DeleteLocalRef(devname); 416 417 ALOGE("Error while allocating in: %s", __FUNCTION__); 418} 419 420static void callback_thread_event(bt_cb_thread_evt event) { 421 JavaVM* vm = AndroidRuntime::getJavaVM(); 422 if (event == ASSOCIATE_JVM) { 423 JavaVMAttachArgs args; 424 char name[] = "BT Service Callback Thread"; 425 args.version = JNI_VERSION_1_6; 426 args.name = name; 427 args.group = NULL; 428 vm->AttachCurrentThread(&callbackEnv, &args); 429 ALOGV("Callback thread attached: %p", callbackEnv); 430 } else if (event == DISASSOCIATE_JVM) { 431 if (!checkCallbackThread()) { 432 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); 433 return; 434 } 435 vm->DetachCurrentThread(); 436 } 437} 438 439static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) { 440 441} 442static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) { 443 444 ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count); 445} 446static bt_callbacks_t sBluetoothCallbacks = { 447 sizeof(sBluetoothCallbacks), 448 adapter_state_change_callback, 449 adapter_properties_callback, 450 remote_device_properties_callback, 451 device_found_callback, 452 discovery_state_changed_callback, 453 pin_request_callback, 454 ssp_request_callback, 455 bond_state_changed_callback, 456 acl_state_changed_callback, 457 callback_thread_event, 458 dut_mode_recv_callback, 459 460 le_test_mode_recv_callback 461}; 462 463// The callback to call when the wake alarm fires. 464static alarm_cb sAlarmCallback; 465 466// The data to pass to the wake alarm callback. 467static void *sAlarmCallbackData; 468 469static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake, alarm_cb cb, void *data) { 470 JNIEnv *env; 471 JavaVM *vm = AndroidRuntime::getJavaVM(); 472 jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6); 473 474 if (status != JNI_OK && status != JNI_EDETACHED) { 475 ALOGE("%s unable to get environment for JNI call", __func__); 476 return false; 477 } 478 479 if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, NULL) != 0) { 480 ALOGE("%s unable to attach thread to VM", __func__); 481 return false; 482 } 483 484 jboolean jshould_wake = should_wake ? JNI_TRUE : JNI_FALSE; 485 jboolean ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_setWakeAlarm, (jlong)delay_millis, jshould_wake); 486 if (ret) { 487 sAlarmCallback = cb; 488 sAlarmCallbackData = data; 489 } 490 491 if (status == JNI_EDETACHED) { 492 vm->DetachCurrentThread(); 493 } 494 495 return !!ret; 496} 497 498static int acquire_wake_lock_callout(const char *lock_name) { 499 JNIEnv *env; 500 JavaVM *vm = AndroidRuntime::getJavaVM(); 501 jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6); 502 503 if (status != JNI_OK && status != JNI_EDETACHED) { 504 ALOGE("%s unable to get environment for JNI call", __func__); 505 return BT_STATUS_FAIL; 506 } 507 508 if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, NULL) != 0) { 509 ALOGE("%s unable to attach thread to VM", __func__); 510 return BT_STATUS_FAIL; 511 } 512 513 jboolean ret = JNI_FALSE; 514 jstring lock_name_jni = env->NewStringUTF(lock_name); 515 if (lock_name_jni) { 516 ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_acquireWakeLock, lock_name_jni); 517 env->DeleteLocalRef(lock_name_jni); 518 } else { 519 ALOGE("%s unable to allocate string: %s", __func__, lock_name); 520 } 521 522 if (status == JNI_EDETACHED) { 523 vm->DetachCurrentThread(); 524 } 525 526 return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 527} 528 529static int release_wake_lock_callout(const char *lock_name) { 530 JNIEnv *env; 531 JavaVM *vm = AndroidRuntime::getJavaVM(); 532 jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6); 533 534 if (status != JNI_OK && status != JNI_EDETACHED) { 535 ALOGE("%s unable to get environment for JNI call", __func__); 536 return BT_STATUS_FAIL; 537 } 538 539 if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, NULL) != 0) { 540 ALOGE("%s unable to attach thread to VM", __func__); 541 return BT_STATUS_FAIL; 542 } 543 544 jboolean ret = JNI_FALSE; 545 jstring lock_name_jni = env->NewStringUTF(lock_name); 546 if (lock_name_jni) { 547 ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_releaseWakeLock, lock_name_jni); 548 env->DeleteLocalRef(lock_name_jni); 549 } else { 550 ALOGE("%s unable to allocate string: %s", __func__, lock_name); 551 } 552 553 if (status == JNI_EDETACHED) { 554 vm->DetachCurrentThread(); 555 } 556 557 return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 558} 559 560// Called by Java code when alarm is fired. A wake lock is held by the caller 561// over the duration of this callback. 562static void alarmFiredNative(JNIEnv *env, jobject obj) { 563 sAlarmCallback(sAlarmCallbackData); 564} 565 566static bt_os_callouts_t sBluetoothOsCallouts = { 567 sizeof(sBluetoothOsCallouts), 568 set_wake_alarm_callout, 569 acquire_wake_lock_callout, 570 release_wake_lock_callout, 571}; 572 573static void classInitNative(JNIEnv* env, jclass clazz) { 574 int err; 575 hw_module_t* module; 576 577 jclass jniCallbackClass = 578 env->FindClass("com/android/bluetooth/btservice/JniCallbacks"); 579 sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks", 580 "Lcom/android/bluetooth/btservice/JniCallbacks;"); 581 582 method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V"); 583 584 method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass, 585 "adapterPropertyChangedCallback", 586 "([I[[B)V"); 587 method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass, 588 "discoveryStateChangeCallback", "(I)V"); 589 590 method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass, 591 "devicePropertyChangedCallback", 592 "([B[I[[B)V"); 593 method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V"); 594 method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback", 595 "([B[BI)V"); 596 method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback", 597 "([B[BIII)V"); 598 599 method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass, 600 "bondStateChangeCallback", "(I[BI)V"); 601 602 method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass, 603 "aclStateChangeCallback", "(I[BI)V"); 604 605 method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z"); 606 method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z"); 607 method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z"); 608 609 char value[PROPERTY_VALUE_MAX]; 610 property_get("bluetooth.mock_stack", value, ""); 611 612 const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID); 613 614 err = hw_get_module(id, (hw_module_t const**)&module); 615 616 if (err == 0) { 617 hw_device_t* abstraction; 618 err = module->methods->open(module, id, &abstraction); 619 if (err == 0) { 620 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction; 621 sBluetoothInterface = btStack->get_bluetooth_interface(); 622 } else { 623 ALOGE("Error while opening Bluetooth library"); 624 } 625 } else { 626 ALOGE("No Bluetooth Library found"); 627 } 628} 629 630static bool initNative(JNIEnv* env, jobject obj) { 631 ALOGV("%s:",__FUNCTION__); 632 633 sJniAdapterServiceObj = env->NewGlobalRef(obj); 634 sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField)); 635 636 if (sBluetoothInterface) { 637 int ret = sBluetoothInterface->init(&sBluetoothCallbacks); 638 if (ret != BT_STATUS_SUCCESS) { 639 ALOGE("Error while setting the callbacks: %d\n", ret); 640 sBluetoothInterface = NULL; 641 return JNI_FALSE; 642 } 643 ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts); 644 if (ret != BT_STATUS_SUCCESS) { 645 ALOGE("Error while setting Bluetooth callouts: %d\n", ret); 646 sBluetoothInterface->cleanup(); 647 sBluetoothInterface = NULL; 648 return JNI_FALSE; 649 } 650 651 if ( (sBluetoothSocketInterface = (btsock_interface_t *) 652 sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) { 653 ALOGE("Error getting socket interface"); 654 } 655 return JNI_TRUE; 656 } 657 return JNI_FALSE; 658} 659 660static bool cleanupNative(JNIEnv *env, jobject obj) { 661 ALOGV("%s:",__FUNCTION__); 662 663 jboolean result = JNI_FALSE; 664 if (!sBluetoothInterface) return result; 665 666 sBluetoothInterface->cleanup(); 667 ALOGI("%s: return from cleanup",__FUNCTION__); 668 669 env->DeleteGlobalRef(sJniCallbacksObj); 670 env->DeleteGlobalRef(sJniAdapterServiceObj); 671 return JNI_TRUE; 672} 673 674static jboolean enableNative(JNIEnv* env, jobject obj) { 675 ALOGV("%s:",__FUNCTION__); 676 677 jboolean result = JNI_FALSE; 678 if (!sBluetoothInterface) return result; 679 680 int ret = sBluetoothInterface->enable(); 681 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 682 return result; 683} 684 685static jboolean disableNative(JNIEnv* env, jobject obj) { 686 ALOGV("%s:",__FUNCTION__); 687 688 jboolean result = JNI_FALSE; 689 if (!sBluetoothInterface) return result; 690 691 int ret = sBluetoothInterface->disable(); 692 /* Retrun JNI_FALSE only when BTIF explicitly reports 693 BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY 694 case which indicates that stack had not been enabled. 695 */ 696 result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE; 697 return result; 698} 699 700static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) { 701 ALOGV("%s:",__FUNCTION__); 702 703 jboolean result = JNI_FALSE; 704 if (!sBluetoothInterface) return result; 705 706 int ret = sBluetoothInterface->start_discovery(); 707 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 708 return result; 709} 710 711static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) { 712 ALOGV("%s:",__FUNCTION__); 713 714 jboolean result = JNI_FALSE; 715 if (!sBluetoothInterface) return result; 716 717 int ret = sBluetoothInterface->cancel_discovery(); 718 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 719 return result; 720} 721 722static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 723 ALOGV("%s:",__FUNCTION__); 724 725 jbyte *addr; 726 jboolean result = JNI_FALSE; 727 728 if (!sBluetoothInterface) return result; 729 730 addr = env->GetByteArrayElements(address, NULL); 731 if (addr == NULL) { 732 jniThrowIOException(env, EINVAL); 733 return result; 734 } 735 736 int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr); 737 env->ReleaseByteArrayElements(address, addr, 0); 738 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 739 740 return result; 741} 742 743static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 744 ALOGV("%s:",__FUNCTION__); 745 746 jbyte *addr; 747 jboolean result; 748 if (!sBluetoothInterface) return JNI_FALSE; 749 750 addr = env->GetByteArrayElements(address, NULL); 751 if (addr == NULL) { 752 jniThrowIOException(env, EINVAL); 753 return JNI_FALSE; 754 } 755 756 int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr); 757 env->ReleaseByteArrayElements(address, addr, 0); 758 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 759 760 return result; 761} 762 763static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) { 764 ALOGV("%s:",__FUNCTION__); 765 766 jbyte *addr; 767 jboolean result; 768 if (!sBluetoothInterface) return JNI_FALSE; 769 770 addr = env->GetByteArrayElements(address, NULL); 771 if (addr == NULL) { 772 jniThrowIOException(env, EINVAL); 773 return JNI_FALSE; 774 } 775 776 int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr); 777 env->ReleaseByteArrayElements(address, addr, 0); 778 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 779 780 return result; 781} 782 783static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept, 784 jint len, jbyteArray pinArray) { 785 ALOGV("%s:",__FUNCTION__); 786 787 jbyte *addr, *pinPtr = NULL; 788 jboolean result = JNI_FALSE; 789 if (!sBluetoothInterface) return result; 790 791 addr = env->GetByteArrayElements(address, NULL); 792 if (addr == NULL) { 793 jniThrowIOException(env, EINVAL); 794 return result; 795 } 796 797 if (accept) { 798 pinPtr = env->GetByteArrayElements(pinArray, NULL); 799 if (pinPtr == NULL) { 800 jniThrowIOException(env, EINVAL); 801 env->ReleaseByteArrayElements(address, addr, 0); 802 return result; 803 } 804 } 805 806 int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len, 807 (bt_pin_code_t *) pinPtr); 808 env->ReleaseByteArrayElements(address, addr, 0); 809 env->ReleaseByteArrayElements(pinArray, pinPtr, 0); 810 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 811 812 return result; 813} 814 815static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address, 816 jint type, jboolean accept, jint passkey) { 817 ALOGV("%s:",__FUNCTION__); 818 819 jbyte *addr; 820 jboolean result = JNI_FALSE; 821 if (!sBluetoothInterface) return result; 822 823 addr = env->GetByteArrayElements(address, NULL); 824 if (addr == NULL) { 825 jniThrowIOException(env, EINVAL); 826 return result; 827 } 828 829 int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr, 830 (bt_ssp_variant_t) type, accept, passkey); 831 env->ReleaseByteArrayElements(address, addr, 0); 832 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 833 834 return result; 835} 836 837static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) { 838 ALOGV("%s:",__FUNCTION__); 839 840 jbyte *val; 841 jboolean result = JNI_FALSE; 842 if (!sBluetoothInterface) return result; 843 844 val = env->GetByteArrayElements(value, NULL); 845 bt_property_t prop; 846 prop.type = (bt_property_type_t) type; 847 prop.len = env->GetArrayLength(value); 848 prop.val = val; 849 850 int ret = sBluetoothInterface->set_adapter_property(&prop); 851 env->ReleaseByteArrayElements(value, val, 0); 852 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 853 854 return result; 855} 856 857static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) { 858 ALOGV("%s:",__FUNCTION__); 859 860 jboolean result = JNI_FALSE; 861 if (!sBluetoothInterface) return result; 862 863 int ret = sBluetoothInterface->get_adapter_properties(); 864 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 865 866 return result; 867} 868 869static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) { 870 ALOGV("%s:",__FUNCTION__); 871 872 jboolean result = JNI_FALSE; 873 if (!sBluetoothInterface) return result; 874 875 int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type); 876 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 877 878 return result; 879} 880 881static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) { 882 ALOGV("%s:",__FUNCTION__); 883 884 jbyte *addr = NULL; 885 jboolean result = JNI_FALSE; 886 if (!sBluetoothInterface) return result; 887 888 addr = env->GetByteArrayElements(address, NULL); 889 if (addr == NULL) { 890 jniThrowIOException(env, EINVAL); 891 return result; 892 } 893 894 int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr, 895 (bt_property_type_t) type); 896 env->ReleaseByteArrayElements(address, addr, 0); 897 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 898 899 return result; 900} 901 902static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, 903 jint type, jbyteArray value) { 904 ALOGV("%s:",__FUNCTION__); 905 906 jbyte *val, *addr; 907 jboolean result = JNI_FALSE; 908 if (!sBluetoothInterface) return result; 909 910 val = env->GetByteArrayElements(value, NULL); 911 if (val == NULL) { 912 jniThrowIOException(env, EINVAL); 913 return result; 914 } 915 916 addr = env->GetByteArrayElements(address, NULL); 917 if (addr == NULL) { 918 env->ReleaseByteArrayElements(value, val, 0); 919 jniThrowIOException(env, EINVAL); 920 return result; 921 } 922 923 924 bt_property_t prop; 925 prop.type = (bt_property_type_t) type; 926 prop.len = env->GetArrayLength(value); 927 prop.val = val; 928 929 int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop); 930 env->ReleaseByteArrayElements(value, val, 0); 931 env->ReleaseByteArrayElements(address, addr, 0); 932 933 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 934 935 return result; 936} 937 938static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) { 939 ALOGV("%s:",__FUNCTION__); 940 941 jbyte *addr = NULL; 942 jboolean result = JNI_FALSE; 943 if (!sBluetoothInterface) return result; 944 945 addr = env->GetByteArrayElements(address, NULL); 946 if (addr == NULL) { 947 jniThrowIOException(env, EINVAL); 948 return result; 949 } 950 951 int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr); 952 env->ReleaseByteArrayElements(address, addr, 0); 953 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 954 return result; 955} 956 957static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type, 958 jbyteArray uuidObj, jint channel, jint flag) { 959 jbyte *addr = NULL, *uuid = NULL; 960 int socket_fd; 961 bt_status_t status; 962 963 if (!sBluetoothSocketInterface) return -1; 964 965 addr = env->GetByteArrayElements(address, NULL); 966 if (!addr) { 967 ALOGE("failed to get Bluetooth device address"); 968 goto Fail; 969 } 970 971 uuid = env->GetByteArrayElements(uuidObj, NULL); 972 if (!uuid) { 973 ALOGE("failed to get uuid"); 974 goto Fail; 975 } 976 977 if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type, 978 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 979 ALOGE("Socket connection failed: %d", status); 980 goto Fail; 981 } 982 983 984 if (socket_fd < 0) { 985 ALOGE("Fail to creat file descriptor on socket fd"); 986 goto Fail; 987 } 988 env->ReleaseByteArrayElements(address, addr, 0); 989 env->ReleaseByteArrayElements(uuidObj, uuid, 0); 990 return socket_fd; 991 992Fail: 993 if (addr) env->ReleaseByteArrayElements(address, addr, 0); 994 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 995 996 return -1; 997} 998 999static int createSocketChannelNative(JNIEnv *env, jobject object, jint type, 1000 jstring name_str, jbyteArray uuidObj, jint channel, jint flag) { 1001 const char *service_name; 1002 jbyte *uuid = NULL; 1003 int socket_fd; 1004 bt_status_t status; 1005 1006 if (!sBluetoothSocketInterface) return -1; 1007 1008 ALOGV("%s: SOCK FLAG = %x", __FUNCTION__, flag); 1009 1010 service_name = env->GetStringUTFChars(name_str, NULL); 1011 1012 uuid = env->GetByteArrayElements(uuidObj, NULL); 1013 if (!uuid) { 1014 ALOGE("failed to get uuid"); 1015 goto Fail; 1016 } 1017 if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name, 1018 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) { 1019 ALOGE("Socket listen failed: %d", status); 1020 goto Fail; 1021 } 1022 1023 if (socket_fd < 0) { 1024 ALOGE("Fail to creat file descriptor on socket fd"); 1025 goto Fail; 1026 } 1027 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 1028 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 1029 return socket_fd; 1030 1031Fail: 1032 if (service_name) env->ReleaseStringUTFChars(name_str, service_name); 1033 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0); 1034 1035 return -1; 1036} 1037 1038static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) { 1039 ALOGV("%s:",__FUNCTION__); 1040 1041 jboolean result = JNI_FALSE; 1042 1043 if (!sBluetoothInterface) return result; 1044 1045 int ret = sBluetoothInterface->config_hci_snoop_log(enable); 1046 1047 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 1048 1049 return result; 1050} 1051 1052static JNINativeMethod sMethods[] = { 1053 /* name, signature, funcPtr */ 1054 {"classInitNative", "()V", (void *) classInitNative}, 1055 {"initNative", "()Z", (void *) initNative}, 1056 {"cleanupNative", "()V", (void*) cleanupNative}, 1057 {"enableNative", "()Z", (void*) enableNative}, 1058 {"disableNative", "()Z", (void*) disableNative}, 1059 {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative}, 1060 {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative}, 1061 {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative}, 1062 {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative}, 1063 {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative}, 1064 {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative}, 1065 {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative}, 1066 {"createBondNative", "([B)Z", (void*) createBondNative}, 1067 {"removeBondNative", "([B)Z", (void*) removeBondNative}, 1068 {"cancelBondNative", "([B)Z", (void*) cancelBondNative}, 1069 {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative}, 1070 {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative}, 1071 {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative}, 1072 {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative}, 1073 {"createSocketChannelNative", "(ILjava/lang/String;[BII)I", 1074 (void*) createSocketChannelNative}, 1075 {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative}, 1076 {"alarmFiredNative", "()V", (void *) alarmFiredNative}, 1077}; 1078 1079int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) 1080{ 1081 return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService", 1082 sMethods, NELEM(sMethods)); 1083} 1084 1085} /* namespace android */ 1086 1087 1088/* 1089 * JNI Initialization 1090 */ 1091jint JNI_OnLoad(JavaVM *jvm, void *reserved) 1092{ 1093 JNIEnv *e; 1094 int status; 1095 1096 ALOGV("Bluetooth Adapter Service : loading JNI\n"); 1097 1098 // Check JNI version 1099 if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) { 1100 ALOGE("JNI version mismatch error"); 1101 return JNI_ERR; 1102 } 1103 1104 if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) { 1105 ALOGE("jni adapter service registration failure, status: %d", status); 1106 return JNI_ERR; 1107 } 1108 1109 if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) { 1110 ALOGE("jni hfp registration failure, status: %d", status); 1111 return JNI_ERR; 1112 } 1113 1114 if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) { 1115 ALOGE("jni hfp client registration failure, status: %d", status); 1116 return JNI_ERR; 1117 } 1118 1119 if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) { 1120 ALOGE("jni a2dp source registration failure: %d", status); 1121 return JNI_ERR; 1122 } 1123 1124 if ((status = android::register_com_android_bluetooth_a2dp_sink(e)) < 0) { 1125 ALOGE("jni a2dp sink registration failure: %d", status); 1126 return JNI_ERR; 1127 } 1128 1129 if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) { 1130 ALOGE("jni avrcp registration failure: %d", status); 1131 return JNI_ERR; 1132 } 1133 1134 if ((status = android::register_com_android_bluetooth_hid(e)) < 0) { 1135 ALOGE("jni hid registration failure: %d", status); 1136 return JNI_ERR; 1137 } 1138 1139 if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) { 1140 ALOGE("jni hdp registration failure: %d", status); 1141 return JNI_ERR; 1142 } 1143 1144 if ((status = android::register_com_android_bluetooth_pan(e)) < 0) { 1145 ALOGE("jni pan registration failure: %d", status); 1146 return JNI_ERR; 1147 } 1148 1149 if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) { 1150 ALOGE("jni gatt registration failure: %d", status); 1151 return JNI_ERR; 1152 } 1153 return JNI_VERSION_1_6; 1154} 1155