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