1 /* 2 ** Copyright 2006, 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 DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter" 18 #define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device" 19 #define DBUS_INPUT_IFACE BLUEZ_DBUS_BASE_IFC ".Input" 20 #define DBUS_NETWORK_IFACE BLUEZ_DBUS_BASE_IFC ".Network" 21 #define DBUS_NETWORKSERVER_IFACE BLUEZ_DBUS_BASE_IFC ".NetworkServer" 22 #define DBUS_HEALTH_MANAGER_PATH "/org/bluez" 23 #define DBUS_HEALTH_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".HealthManager" 24 #define DBUS_HEALTH_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".HealthDevice" 25 #define DBUS_HEALTH_CHANNEL_IFACE BLUEZ_DBUS_BASE_IFC ".HealthChannel" 26 27 #define LOG_TAG "BluetoothService.cpp" 28 29 #include "android_bluetooth_common.h" 30 #include "android_runtime/AndroidRuntime.h" 31 #include "android_util_Binder.h" 32 #include "JNIHelp.h" 33 #include "jni.h" 34 #include "utils/Log.h" 35 #include "utils/misc.h" 36 37 #include <ctype.h> 38 #include <stdio.h> 39 #include <string.h> 40 #include <stdlib.h> 41 #include <errno.h> 42 #include <unistd.h> 43 44 #include <sys/socket.h> 45 #include <sys/ioctl.h> 46 #include <fcntl.h> 47 48 #ifdef HAVE_BLUETOOTH 49 #include <dbus/dbus.h> 50 #include <bluedroid/bluetooth.h> 51 #endif 52 53 #include <cutils/properties.h> 54 55 namespace android { 56 57 #define BLUETOOTH_CLASS_ERROR 0xFF000000 58 #define PROPERTIES_NREFS 10 59 60 #ifdef HAVE_BLUETOOTH 61 // We initialize these variables when we load class 62 // android.server.BluetoothService 63 static jfieldID field_mNativeData; 64 static jfieldID field_mEventLoop; 65 66 typedef struct { 67 JNIEnv *env; 68 DBusConnection *conn; 69 const char *adapter; // dbus object name of the local adapter 70 } native_data_t; 71 72 extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *, 73 jobject); 74 extern DBusHandlerResult agent_event_filter(DBusConnection *conn, 75 DBusMessage *msg, 76 void *data); 77 void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *nat); 78 void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat); 79 void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat); 80 void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *nat); 81 void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *nat); 82 void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *nat); 83 84 85 /** Get native data stored in the opaque (Java code maintained) pointer mNativeData 86 * Perform quick sanity check, if there are any problems return NULL 87 */ 88 static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { 89 native_data_t *nat = 90 (native_data_t *)(env->GetIntField(object, field_mNativeData)); 91 if (nat == NULL || nat->conn == NULL) { 92 LOGE("Uninitialized native data\n"); 93 return NULL; 94 } 95 return nat; 96 } 97 #endif 98 99 static void classInitNative(JNIEnv* env, jclass clazz) { 100 LOGV("%s", __FUNCTION__); 101 #ifdef HAVE_BLUETOOTH 102 field_mNativeData = get_field(env, clazz, "mNativeData", "I"); 103 field_mEventLoop = get_field(env, clazz, "mEventLoop", 104 "Landroid/server/BluetoothEventLoop;"); 105 #endif 106 } 107 108 /* Returns true on success (even if adapter is present but disabled). 109 * Return false if dbus is down, or another serious error (out of memory) 110 */ 111 static bool initializeNativeDataNative(JNIEnv* env, jobject object) { 112 LOGV("%s", __FUNCTION__); 113 #ifdef HAVE_BLUETOOTH 114 native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); 115 if (NULL == nat) { 116 LOGE("%s: out of memory!", __FUNCTION__); 117 return false; 118 } 119 nat->env = env; 120 121 env->SetIntField(object, field_mNativeData, (jint)nat); 122 DBusError err; 123 dbus_error_init(&err); 124 dbus_threads_init_default(); 125 nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); 126 if (dbus_error_is_set(&err)) { 127 LOGE("Could not get onto the system bus: %s", err.message); 128 dbus_error_free(&err); 129 return false; 130 } 131 dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); 132 #endif /*HAVE_BLUETOOTH*/ 133 return true; 134 } 135 136 static const char *get_adapter_path(JNIEnv* env, jobject object) { 137 #ifdef HAVE_BLUETOOTH 138 event_loop_native_data_t *event_nat = 139 get_EventLoop_native_data(env, env->GetObjectField(object, 140 field_mEventLoop)); 141 if (event_nat == NULL) 142 return NULL; 143 return event_nat->adapter; 144 #else 145 return NULL; 146 #endif 147 } 148 149 // This function is called when the adapter is enabled. 150 static jboolean setupNativeDataNative(JNIEnv* env, jobject object) { 151 LOGV("%s", __FUNCTION__); 152 #ifdef HAVE_BLUETOOTH 153 native_data_t *nat = 154 (native_data_t *)env->GetIntField(object, field_mNativeData); 155 event_loop_native_data_t *event_nat = 156 get_EventLoop_native_data(env, env->GetObjectField(object, 157 field_mEventLoop)); 158 // Register agent for remote devices. 159 const char *device_agent_path = "/android/bluetooth/remote_device_agent"; 160 static const DBusObjectPathVTable agent_vtable = { 161 NULL, agent_event_filter, NULL, NULL, NULL, NULL }; 162 163 if (!dbus_connection_register_object_path(nat->conn, device_agent_path, 164 &agent_vtable, event_nat)) { 165 LOGE("%s: Can't register object path %s for remote device agent!", 166 __FUNCTION__, device_agent_path); 167 return JNI_FALSE; 168 } 169 #endif /*HAVE_BLUETOOTH*/ 170 return JNI_TRUE; 171 } 172 173 static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) { 174 LOGV("%s", __FUNCTION__); 175 #ifdef HAVE_BLUETOOTH 176 native_data_t *nat = 177 (native_data_t *)env->GetIntField(object, field_mNativeData); 178 if (nat != NULL) { 179 const char *device_agent_path = 180 "/android/bluetooth/remote_device_agent"; 181 dbus_connection_unregister_object_path (nat->conn, device_agent_path); 182 } 183 #endif /*HAVE_BLUETOOTH*/ 184 return JNI_TRUE; 185 } 186 187 static void cleanupNativeDataNative(JNIEnv* env, jobject object) { 188 LOGV("%s", __FUNCTION__); 189 #ifdef HAVE_BLUETOOTH 190 native_data_t *nat = 191 (native_data_t *)env->GetIntField(object, field_mNativeData); 192 if (nat) { 193 free(nat); 194 nat = NULL; 195 } 196 #endif 197 } 198 199 static jstring getAdapterPathNative(JNIEnv *env, jobject object) { 200 LOGV("%s", __FUNCTION__); 201 #ifdef HAVE_BLUETOOTH 202 native_data_t *nat = get_native_data(env, object); 203 if (nat) { 204 return (env->NewStringUTF(get_adapter_path(env, object))); 205 } 206 #endif 207 return NULL; 208 } 209 210 211 static jboolean startDiscoveryNative(JNIEnv *env, jobject object) { 212 LOGV("%s", __FUNCTION__); 213 #ifdef HAVE_BLUETOOTH 214 DBusMessage *msg = NULL; 215 DBusMessage *reply = NULL; 216 DBusError err; 217 const char *name; 218 jboolean ret = JNI_FALSE; 219 220 native_data_t *nat = get_native_data(env, object); 221 if (nat == NULL) { 222 goto done; 223 } 224 225 dbus_error_init(&err); 226 227 /* Compose the command */ 228 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, 229 get_adapter_path(env, object), 230 DBUS_ADAPTER_IFACE, "StartDiscovery"); 231 232 if (msg == NULL) { 233 if (dbus_error_is_set(&err)) { 234 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 235 } 236 goto done; 237 } 238 239 /* Send the command. */ 240 reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); 241 if (dbus_error_is_set(&err)) { 242 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 243 ret = JNI_FALSE; 244 goto done; 245 } 246 247 ret = JNI_TRUE; 248 done: 249 if (reply) dbus_message_unref(reply); 250 if (msg) dbus_message_unref(msg); 251 return ret; 252 #else 253 return JNI_FALSE; 254 #endif 255 } 256 257 static jboolean stopDiscoveryNative(JNIEnv *env, jobject object) { 258 LOGV("%s", __FUNCTION__); 259 #ifdef HAVE_BLUETOOTH 260 DBusMessage *msg = NULL; 261 DBusMessage *reply = NULL; 262 DBusError err; 263 const char *name; 264 native_data_t *nat; 265 jboolean ret = JNI_FALSE; 266 267 dbus_error_init(&err); 268 269 nat = get_native_data(env, object); 270 if (nat == NULL) { 271 goto done; 272 } 273 274 /* Compose the command */ 275 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, 276 get_adapter_path(env, object), 277 DBUS_ADAPTER_IFACE, "StopDiscovery"); 278 if (msg == NULL) { 279 if (dbus_error_is_set(&err)) 280 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 281 goto done; 282 } 283 284 /* Send the command. */ 285 reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); 286 if (dbus_error_is_set(&err)) { 287 if(strncmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized", 288 strlen(BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized")) == 0) { 289 // hcid sends this if there is no active discovery to cancel 290 LOGV("%s: There was no active discovery to cancel", __FUNCTION__); 291 dbus_error_free(&err); 292 } else { 293 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 294 } 295 goto done; 296 } 297 298 ret = JNI_TRUE; 299 done: 300 if (msg) dbus_message_unref(msg); 301 if (reply) dbus_message_unref(reply); 302 return ret; 303 #else 304 return JNI_FALSE; 305 #endif 306 } 307 308 static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) { 309 LOGV("%s", __FUNCTION__); 310 #ifdef HAVE_BLUETOOTH 311 native_data_t *nat = get_native_data(env, object); 312 DBusError err; 313 jbyte *hash, *randomizer; 314 jbyteArray byteArray = NULL; 315 int hash_len, r_len; 316 if (nat) { 317 DBusMessage *reply = dbus_func_args(env, nat->conn, 318 get_adapter_path(env, object), 319 DBUS_ADAPTER_IFACE, "ReadLocalOutOfBandData", 320 DBUS_TYPE_INVALID); 321 if (!reply) return NULL; 322 323 dbus_error_init(&err); 324 if (dbus_message_get_args(reply, &err, 325 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hash_len, 326 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &r_len, 327 DBUS_TYPE_INVALID)) { 328 if (hash_len == 16 && r_len == 16) { 329 byteArray = env->NewByteArray(32); 330 if (byteArray) { 331 env->SetByteArrayRegion(byteArray, 0, 16, hash); 332 env->SetByteArrayRegion(byteArray, 16, 16, randomizer); 333 } 334 } else { 335 LOGE("readAdapterOutOfBandDataNative: Hash len = %d, R len = %d", 336 hash_len, r_len); 337 } 338 } else { 339 LOG_AND_FREE_DBUS_ERROR(&err); 340 } 341 dbus_message_unref(reply); 342 return byteArray; 343 } 344 #endif 345 return NULL; 346 } 347 348 static jboolean createPairedDeviceNative(JNIEnv *env, jobject object, 349 jstring address, jint timeout_ms) { 350 LOGV("%s", __FUNCTION__); 351 #ifdef HAVE_BLUETOOTH 352 native_data_t *nat = get_native_data(env, object); 353 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 354 struct event_loop_native_data_t *eventLoopNat = 355 get_EventLoop_native_data(env, eventLoop); 356 357 if (nat && eventLoopNat) { 358 const char *c_address = env->GetStringUTFChars(address, NULL); 359 LOGV("... address = %s", c_address); 360 char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); 361 const char *capabilities = "DisplayYesNo"; 362 const char *agent_path = "/android/bluetooth/remote_device_agent"; 363 364 strlcpy(context_address, c_address, BTADDR_SIZE); // for callback 365 bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, 366 onCreatePairedDeviceResult, // callback 367 context_address, 368 eventLoopNat, 369 get_adapter_path(env, object), 370 DBUS_ADAPTER_IFACE, 371 "CreatePairedDevice", 372 DBUS_TYPE_STRING, &c_address, 373 DBUS_TYPE_OBJECT_PATH, &agent_path, 374 DBUS_TYPE_STRING, &capabilities, 375 DBUS_TYPE_INVALID); 376 env->ReleaseStringUTFChars(address, c_address); 377 return ret ? JNI_TRUE : JNI_FALSE; 378 379 } 380 #endif 381 return JNI_FALSE; 382 } 383 384 static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object, 385 jstring address, jint timeout_ms) { 386 LOGV("%s", __FUNCTION__); 387 #ifdef HAVE_BLUETOOTH 388 native_data_t *nat = get_native_data(env, object); 389 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 390 struct event_loop_native_data_t *eventLoopNat = 391 get_EventLoop_native_data(env, eventLoop); 392 393 if (nat && eventLoopNat) { 394 const char *c_address = env->GetStringUTFChars(address, NULL); 395 LOGV("... address = %s", c_address); 396 char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); 397 const char *capabilities = "DisplayYesNo"; 398 const char *agent_path = "/android/bluetooth/remote_device_agent"; 399 400 strlcpy(context_address, c_address, BTADDR_SIZE); // for callback 401 bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, 402 onCreatePairedDeviceResult, // callback 403 context_address, 404 eventLoopNat, 405 get_adapter_path(env, object), 406 DBUS_ADAPTER_IFACE, 407 "CreatePairedDeviceOutOfBand", 408 DBUS_TYPE_STRING, &c_address, 409 DBUS_TYPE_OBJECT_PATH, &agent_path, 410 DBUS_TYPE_STRING, &capabilities, 411 DBUS_TYPE_INVALID); 412 env->ReleaseStringUTFChars(address, c_address); 413 return ret ? JNI_TRUE : JNI_FALSE; 414 } 415 #endif 416 return JNI_FALSE; 417 } 418 419 static jint getDeviceServiceChannelNative(JNIEnv *env, jobject object, 420 jstring path, 421 jstring pattern, jint attr_id) { 422 #ifdef HAVE_BLUETOOTH 423 LOGV("%s", __FUNCTION__); 424 native_data_t *nat = get_native_data(env, object); 425 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 426 struct event_loop_native_data_t *eventLoopNat = 427 get_EventLoop_native_data(env, eventLoop); 428 if (nat && eventLoopNat) { 429 const char *c_pattern = env->GetStringUTFChars(pattern, NULL); 430 const char *c_path = env->GetStringUTFChars(path, NULL); 431 LOGV("... pattern = %s", c_pattern); 432 LOGV("... attr_id = %#X", attr_id); 433 DBusMessage *reply = 434 dbus_func_args(env, nat->conn, c_path, 435 DBUS_DEVICE_IFACE, "GetServiceAttributeValue", 436 DBUS_TYPE_STRING, &c_pattern, 437 DBUS_TYPE_UINT16, &attr_id, 438 DBUS_TYPE_INVALID); 439 env->ReleaseStringUTFChars(pattern, c_pattern); 440 env->ReleaseStringUTFChars(path, c_path); 441 return reply ? dbus_returns_int32(env, reply) : -1; 442 } 443 #endif 444 return -1; 445 } 446 447 static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object, 448 jstring address) { 449 LOGV("%s", __FUNCTION__); 450 jboolean result = JNI_FALSE; 451 #ifdef HAVE_BLUETOOTH 452 native_data_t *nat = get_native_data(env, object); 453 if (nat) { 454 const char *c_address = env->GetStringUTFChars(address, NULL); 455 DBusError err; 456 dbus_error_init(&err); 457 LOGV("... address = %s", c_address); 458 DBusMessage *reply = 459 dbus_func_args_timeout(env, nat->conn, -1, 460 get_adapter_path(env, object), 461 DBUS_ADAPTER_IFACE, "CancelDeviceCreation", 462 DBUS_TYPE_STRING, &c_address, 463 DBUS_TYPE_INVALID); 464 env->ReleaseStringUTFChars(address, c_address); 465 if (!reply) { 466 if (dbus_error_is_set(&err)) { 467 LOG_AND_FREE_DBUS_ERROR(&err); 468 } else 469 LOGE("DBus reply is NULL in function %s", __FUNCTION__); 470 return JNI_FALSE; 471 } else { 472 result = JNI_TRUE; 473 } 474 dbus_message_unref(reply); 475 } 476 #endif 477 return JNI_FALSE; 478 } 479 480 static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) { 481 LOGV("%s", __FUNCTION__); 482 #ifdef HAVE_BLUETOOTH 483 native_data_t *nat = get_native_data(env, object); 484 if (nat) { 485 const char *c_object_path = env->GetStringUTFChars(object_path, NULL); 486 bool ret = dbus_func_args_async(env, nat->conn, -1, 487 NULL, 488 NULL, 489 NULL, 490 get_adapter_path(env, object), 491 DBUS_ADAPTER_IFACE, 492 "RemoveDevice", 493 DBUS_TYPE_OBJECT_PATH, &c_object_path, 494 DBUS_TYPE_INVALID); 495 env->ReleaseStringUTFChars(object_path, c_object_path); 496 return ret ? JNI_TRUE : JNI_FALSE; 497 } 498 #endif 499 return JNI_FALSE; 500 } 501 502 static jint enableNative(JNIEnv *env, jobject object) { 503 #ifdef HAVE_BLUETOOTH 504 LOGV("%s", __FUNCTION__); 505 return bt_enable(); 506 #endif 507 return -1; 508 } 509 510 static jint disableNative(JNIEnv *env, jobject object) { 511 #ifdef HAVE_BLUETOOTH 512 LOGV("%s", __FUNCTION__); 513 return bt_disable(); 514 #endif 515 return -1; 516 } 517 518 static jint isEnabledNative(JNIEnv *env, jobject object) { 519 #ifdef HAVE_BLUETOOTH 520 LOGV("%s", __FUNCTION__); 521 return bt_is_enabled(); 522 #endif 523 return -1; 524 } 525 526 static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object, 527 jstring address, bool confirm, 528 int nativeData) { 529 #ifdef HAVE_BLUETOOTH 530 LOGV("%s", __FUNCTION__); 531 native_data_t *nat = get_native_data(env, object); 532 if (nat) { 533 DBusMessage *msg = (DBusMessage *)nativeData; 534 DBusMessage *reply; 535 if (confirm) { 536 reply = dbus_message_new_method_return(msg); 537 } else { 538 reply = dbus_message_new_error(msg, 539 "org.bluez.Error.Rejected", "User rejected confirmation"); 540 } 541 542 if (!reply) { 543 LOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or" 544 "RequestPairingConsent to D-Bus\n", __FUNCTION__); 545 dbus_message_unref(msg); 546 return JNI_FALSE; 547 } 548 549 dbus_connection_send(nat->conn, reply, NULL); 550 dbus_message_unref(msg); 551 dbus_message_unref(reply); 552 return JNI_TRUE; 553 } 554 #endif 555 return JNI_FALSE; 556 } 557 558 static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address, 559 int passkey, int nativeData) { 560 #ifdef HAVE_BLUETOOTH 561 LOGV("%s", __FUNCTION__); 562 native_data_t *nat = get_native_data(env, object); 563 if (nat) { 564 DBusMessage *msg = (DBusMessage *)nativeData; 565 DBusMessage *reply = dbus_message_new_method_return(msg); 566 if (!reply) { 567 LOGE("%s: Cannot create message reply to return Passkey code to " 568 "D-Bus\n", __FUNCTION__); 569 dbus_message_unref(msg); 570 return JNI_FALSE; 571 } 572 573 dbus_message_append_args(reply, DBUS_TYPE_UINT32, (uint32_t *)&passkey, 574 DBUS_TYPE_INVALID); 575 576 dbus_connection_send(nat->conn, reply, NULL); 577 dbus_message_unref(msg); 578 dbus_message_unref(reply); 579 return JNI_TRUE; 580 } 581 #endif 582 return JNI_FALSE; 583 } 584 585 static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstring address, 586 jbyteArray hash, jbyteArray randomizer, int nativeData) { 587 #ifdef HAVE_BLUETOOTH 588 LOGV("%s", __FUNCTION__); 589 native_data_t *nat = get_native_data(env, object); 590 if (nat) { 591 DBusMessage *msg = (DBusMessage *)nativeData; 592 DBusMessage *reply = dbus_message_new_method_return(msg); 593 jbyte *h_ptr = env->GetByteArrayElements(hash, NULL); 594 jbyte *r_ptr = env->GetByteArrayElements(randomizer, NULL); 595 if (!reply) { 596 LOGE("%s: Cannot create message reply to return remote OOB data to " 597 "D-Bus\n", __FUNCTION__); 598 dbus_message_unref(msg); 599 return JNI_FALSE; 600 } 601 602 dbus_message_append_args(reply, 603 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &h_ptr, 16, 604 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &r_ptr, 16, 605 DBUS_TYPE_INVALID); 606 607 env->ReleaseByteArrayElements(hash, h_ptr, 0); 608 env->ReleaseByteArrayElements(randomizer, r_ptr, 0); 609 610 dbus_connection_send(nat->conn, reply, NULL); 611 dbus_message_unref(msg); 612 dbus_message_unref(reply); 613 return JNI_TRUE; 614 } 615 #endif 616 return JNI_FALSE; 617 } 618 619 static jboolean setAuthorizationNative(JNIEnv *env, jobject object, jstring address, 620 jboolean val, int nativeData) { 621 #ifdef HAVE_BLUETOOTH 622 LOGV("%s", __FUNCTION__); 623 native_data_t *nat = get_native_data(env, object); 624 if (nat) { 625 DBusMessage *msg = (DBusMessage *)nativeData; 626 DBusMessage *reply; 627 if (val) { 628 reply = dbus_message_new_method_return(msg); 629 } else { 630 reply = dbus_message_new_error(msg, 631 "org.bluez.Error.Rejected", "Authorization rejected"); 632 } 633 if (!reply) { 634 LOGE("%s: Cannot create message reply D-Bus\n", __FUNCTION__); 635 dbus_message_unref(msg); 636 return JNI_FALSE; 637 } 638 639 dbus_connection_send(nat->conn, reply, NULL); 640 dbus_message_unref(msg); 641 dbus_message_unref(reply); 642 return JNI_TRUE; 643 } 644 #endif 645 return JNI_FALSE; 646 } 647 648 static jboolean setPinNative(JNIEnv *env, jobject object, jstring address, 649 jstring pin, int nativeData) { 650 #ifdef HAVE_BLUETOOTH 651 LOGV("%s", __FUNCTION__); 652 native_data_t *nat = get_native_data(env, object); 653 if (nat) { 654 DBusMessage *msg = (DBusMessage *)nativeData; 655 DBusMessage *reply = dbus_message_new_method_return(msg); 656 if (!reply) { 657 LOGE("%s: Cannot create message reply to return PIN code to " 658 "D-Bus\n", __FUNCTION__); 659 dbus_message_unref(msg); 660 return JNI_FALSE; 661 } 662 663 const char *c_pin = env->GetStringUTFChars(pin, NULL); 664 665 dbus_message_append_args(reply, DBUS_TYPE_STRING, &c_pin, 666 DBUS_TYPE_INVALID); 667 668 dbus_connection_send(nat->conn, reply, NULL); 669 dbus_message_unref(msg); 670 dbus_message_unref(reply); 671 env->ReleaseStringUTFChars(pin, c_pin); 672 return JNI_TRUE; 673 } 674 #endif 675 return JNI_FALSE; 676 } 677 678 static jboolean cancelPairingUserInputNative(JNIEnv *env, jobject object, 679 jstring address, int nativeData) { 680 #ifdef HAVE_BLUETOOTH 681 LOGV("%s", __FUNCTION__); 682 native_data_t *nat = get_native_data(env, object); 683 if (nat) { 684 DBusMessage *msg = (DBusMessage *)nativeData; 685 DBusMessage *reply = dbus_message_new_error(msg, 686 "org.bluez.Error.Canceled", "Pairing User Input was canceled"); 687 if (!reply) { 688 LOGE("%s: Cannot create message reply to return cancelUserInput to" 689 "D-BUS\n", __FUNCTION__); 690 dbus_message_unref(msg); 691 return JNI_FALSE; 692 } 693 694 dbus_connection_send(nat->conn, reply, NULL); 695 dbus_message_unref(msg); 696 dbus_message_unref(reply); 697 return JNI_TRUE; 698 } 699 #endif 700 return JNI_FALSE; 701 } 702 703 static jobjectArray getDevicePropertiesNative(JNIEnv *env, jobject object, 704 jstring path) 705 { 706 #ifdef HAVE_BLUETOOTH 707 LOGV("%s", __FUNCTION__); 708 native_data_t *nat = get_native_data(env, object); 709 if (nat) { 710 DBusMessage *msg, *reply; 711 DBusError err; 712 dbus_error_init(&err); 713 714 const char *c_path = env->GetStringUTFChars(path, NULL); 715 reply = dbus_func_args_timeout(env, 716 nat->conn, -1, c_path, 717 DBUS_DEVICE_IFACE, "GetProperties", 718 DBUS_TYPE_INVALID); 719 env->ReleaseStringUTFChars(path, c_path); 720 721 if (!reply) { 722 if (dbus_error_is_set(&err)) { 723 LOG_AND_FREE_DBUS_ERROR(&err); 724 } else 725 LOGE("DBus reply is NULL in function %s", __FUNCTION__); 726 return NULL; 727 } 728 env->PushLocalFrame(PROPERTIES_NREFS); 729 730 DBusMessageIter iter; 731 jobjectArray str_array = NULL; 732 if (dbus_message_iter_init(reply, &iter)) 733 str_array = parse_remote_device_properties(env, &iter); 734 dbus_message_unref(reply); 735 736 return (jobjectArray) env->PopLocalFrame(str_array); 737 } 738 #endif 739 return NULL; 740 } 741 742 static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) { 743 #ifdef HAVE_BLUETOOTH 744 LOGV("%s", __FUNCTION__); 745 native_data_t *nat = get_native_data(env, object); 746 if (nat) { 747 DBusMessage *msg, *reply; 748 DBusError err; 749 dbus_error_init(&err); 750 751 reply = dbus_func_args_timeout(env, 752 nat->conn, -1, get_adapter_path(env, object), 753 DBUS_ADAPTER_IFACE, "GetProperties", 754 DBUS_TYPE_INVALID); 755 if (!reply) { 756 if (dbus_error_is_set(&err)) { 757 LOG_AND_FREE_DBUS_ERROR(&err); 758 } else 759 LOGE("DBus reply is NULL in function %s", __FUNCTION__); 760 return NULL; 761 } 762 env->PushLocalFrame(PROPERTIES_NREFS); 763 764 DBusMessageIter iter; 765 jobjectArray str_array = NULL; 766 if (dbus_message_iter_init(reply, &iter)) 767 str_array = parse_adapter_properties(env, &iter); 768 dbus_message_unref(reply); 769 770 return (jobjectArray) env->PopLocalFrame(str_array); 771 } 772 #endif 773 return NULL; 774 } 775 776 static jboolean setAdapterPropertyNative(JNIEnv *env, jobject object, jstring key, 777 void *value, jint type) { 778 #ifdef HAVE_BLUETOOTH 779 LOGV("%s", __FUNCTION__); 780 native_data_t *nat = get_native_data(env, object); 781 if (nat) { 782 DBusMessage *msg; 783 DBusMessageIter iter; 784 dbus_bool_t reply = JNI_FALSE; 785 const char *c_key = env->GetStringUTFChars(key, NULL); 786 787 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, 788 get_adapter_path(env, object), 789 DBUS_ADAPTER_IFACE, "SetProperty"); 790 if (!msg) { 791 LOGE("%s: Can't allocate new method call for GetProperties!", 792 __FUNCTION__); 793 env->ReleaseStringUTFChars(key, c_key); 794 return JNI_FALSE; 795 } 796 797 dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID); 798 dbus_message_iter_init_append(msg, &iter); 799 append_variant(&iter, type, value); 800 801 // Asynchronous call - the callbacks come via propertyChange 802 reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1); 803 dbus_message_unref(msg); 804 805 env->ReleaseStringUTFChars(key, c_key); 806 return reply ? JNI_TRUE : JNI_FALSE; 807 808 } 809 #endif 810 return JNI_FALSE; 811 } 812 813 static jboolean setAdapterPropertyStringNative(JNIEnv *env, jobject object, jstring key, 814 jstring value) { 815 #ifdef HAVE_BLUETOOTH 816 const char *c_value = env->GetStringUTFChars(value, NULL); 817 jboolean ret = setAdapterPropertyNative(env, object, key, (void *)&c_value, DBUS_TYPE_STRING); 818 env->ReleaseStringUTFChars(value, (char *)c_value); 819 return ret; 820 #else 821 return JNI_FALSE; 822 #endif 823 } 824 825 static jboolean setAdapterPropertyIntegerNative(JNIEnv *env, jobject object, jstring key, 826 jint value) { 827 #ifdef HAVE_BLUETOOTH 828 return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_UINT32); 829 #else 830 return JNI_FALSE; 831 #endif 832 } 833 834 static jboolean setAdapterPropertyBooleanNative(JNIEnv *env, jobject object, jstring key, 835 jint value) { 836 #ifdef HAVE_BLUETOOTH 837 return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_BOOLEAN); 838 #else 839 return JNI_FALSE; 840 #endif 841 } 842 843 static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path, 844 jstring key, void *value, jint type) { 845 #ifdef HAVE_BLUETOOTH 846 LOGV("%s", __FUNCTION__); 847 native_data_t *nat = get_native_data(env, object); 848 if (nat) { 849 DBusMessage *msg; 850 DBusMessageIter iter; 851 dbus_bool_t reply = JNI_FALSE; 852 853 const char *c_key = env->GetStringUTFChars(key, NULL); 854 const char *c_path = env->GetStringUTFChars(path, NULL); 855 856 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, 857 c_path, DBUS_DEVICE_IFACE, "SetProperty"); 858 if (!msg) { 859 LOGE("%s: Can't allocate new method call for device SetProperty!", __FUNCTION__); 860 env->ReleaseStringUTFChars(key, c_key); 861 env->ReleaseStringUTFChars(path, c_path); 862 return JNI_FALSE; 863 } 864 865 dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID); 866 dbus_message_iter_init_append(msg, &iter); 867 append_variant(&iter, type, value); 868 869 // Asynchronous call - the callbacks come via Device propertyChange 870 reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1); 871 dbus_message_unref(msg); 872 873 env->ReleaseStringUTFChars(path, c_path); 874 env->ReleaseStringUTFChars(key, c_key); 875 876 return reply ? JNI_TRUE : JNI_FALSE; 877 } 878 #endif 879 return JNI_FALSE; 880 } 881 882 static jboolean setDevicePropertyBooleanNative(JNIEnv *env, jobject object, 883 jstring path, jstring key, jint value) { 884 #ifdef HAVE_BLUETOOTH 885 return setDevicePropertyNative(env, object, path, key, 886 (void *)&value, DBUS_TYPE_BOOLEAN); 887 #else 888 return JNI_FALSE; 889 #endif 890 } 891 892 static jboolean setDevicePropertyStringNative(JNIEnv *env, jobject object, 893 jstring path, jstring key, jstring value) { 894 #ifdef HAVE_BLUETOOTH 895 const char *c_value = env->GetStringUTFChars(value, NULL); 896 jboolean ret = setDevicePropertyNative(env, object, path, key, 897 (void *)&c_value, DBUS_TYPE_STRING); 898 env->ReleaseStringUTFChars(value, (char *)c_value); 899 return ret; 900 #else 901 return JNI_FALSE; 902 #endif 903 } 904 905 static jboolean createDeviceNative(JNIEnv *env, jobject object, 906 jstring address) { 907 LOGV("%s", __FUNCTION__); 908 #ifdef HAVE_BLUETOOTH 909 native_data_t *nat = get_native_data(env, object); 910 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 911 struct event_loop_native_data_t *eventLoopNat = 912 get_EventLoop_native_data(env, eventLoop); 913 914 if (nat && eventLoopNat) { 915 const char *c_address = env->GetStringUTFChars(address, NULL); 916 LOGV("... address = %s", c_address); 917 char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); 918 strlcpy(context_address, c_address, BTADDR_SIZE); // for callback 919 920 bool ret = dbus_func_args_async(env, nat->conn, -1, 921 onCreateDeviceResult, 922 context_address, 923 eventLoopNat, 924 get_adapter_path(env, object), 925 DBUS_ADAPTER_IFACE, 926 "CreateDevice", 927 DBUS_TYPE_STRING, &c_address, 928 DBUS_TYPE_INVALID); 929 env->ReleaseStringUTFChars(address, c_address); 930 return ret ? JNI_TRUE : JNI_FALSE; 931 } 932 #endif 933 return JNI_FALSE; 934 } 935 936 static jboolean discoverServicesNative(JNIEnv *env, jobject object, 937 jstring path, jstring pattern) { 938 LOGV("%s", __FUNCTION__); 939 #ifdef HAVE_BLUETOOTH 940 native_data_t *nat = get_native_data(env, object); 941 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 942 struct event_loop_native_data_t *eventLoopNat = 943 get_EventLoop_native_data(env, eventLoop); 944 945 if (nat && eventLoopNat) { 946 const char *c_path = env->GetStringUTFChars(path, NULL); 947 const char *c_pattern = env->GetStringUTFChars(pattern, NULL); 948 int len = env->GetStringLength(path) + 1; 949 char *context_path = (char *)calloc(len, sizeof(char)); 950 strlcpy(context_path, c_path, len); // for callback 951 952 LOGV("... Object Path = %s", c_path); 953 LOGV("... Pattern = %s, strlen = %d", c_pattern, strlen(c_pattern)); 954 955 bool ret = dbus_func_args_async(env, nat->conn, -1, 956 onDiscoverServicesResult, 957 context_path, 958 eventLoopNat, 959 c_path, 960 DBUS_DEVICE_IFACE, 961 "DiscoverServices", 962 DBUS_TYPE_STRING, &c_pattern, 963 DBUS_TYPE_INVALID); 964 env->ReleaseStringUTFChars(path, c_path); 965 env->ReleaseStringUTFChars(pattern, c_pattern); 966 return ret ? JNI_TRUE : JNI_FALSE; 967 } 968 #endif 969 return JNI_FALSE; 970 } 971 972 #ifdef HAVE_BLUETOOTH 973 static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) { 974 jint *handles; 975 jintArray handleArray = NULL; 976 int len; 977 978 DBusError err; 979 dbus_error_init(&err); 980 981 if (dbus_message_get_args(reply, &err, 982 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len, 983 DBUS_TYPE_INVALID)) { 984 handleArray = env->NewIntArray(len); 985 if (handleArray) { 986 env->SetIntArrayRegion(handleArray, 0, len, handles); 987 } else { 988 LOGE("Null array in extract_handles"); 989 } 990 } else { 991 LOG_AND_FREE_DBUS_ERROR(&err); 992 } 993 return handleArray; 994 } 995 #endif 996 997 static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object, 998 jintArray uuids) { 999 LOGV("%s", __FUNCTION__); 1000 #ifdef HAVE_BLUETOOTH 1001 DBusMessage *reply = NULL; 1002 1003 native_data_t *nat = get_native_data(env, object); 1004 1005 jint* svc_classes = env->GetIntArrayElements(uuids, NULL); 1006 if (!svc_classes) return NULL; 1007 1008 int len = env->GetArrayLength(uuids); 1009 reply = dbus_func_args(env, nat->conn, 1010 get_adapter_path(env, object), 1011 DBUS_ADAPTER_IFACE, "AddReservedServiceRecords", 1012 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, 1013 &svc_classes, len, DBUS_TYPE_INVALID); 1014 env->ReleaseIntArrayElements(uuids, svc_classes, 0); 1015 return reply ? extract_handles(env, reply) : NULL; 1016 1017 #endif 1018 return NULL; 1019 } 1020 1021 static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object, 1022 jintArray handles) { 1023 LOGV("%s", __FUNCTION__); 1024 #ifdef HAVE_BLUETOOTH 1025 native_data_t *nat = get_native_data(env, object); 1026 jint *values = env->GetIntArrayElements(handles, NULL); 1027 DBusMessage *msg = NULL; 1028 DBusMessage *reply = NULL; 1029 if (values == NULL) return JNI_FALSE; 1030 1031 jsize len = env->GetArrayLength(handles); 1032 1033 reply = dbus_func_args(env, nat->conn, 1034 get_adapter_path(env, object), 1035 DBUS_ADAPTER_IFACE, "RemoveReservedServiceRecords", 1036 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, 1037 &values, len, DBUS_TYPE_INVALID); 1038 env->ReleaseIntArrayElements(handles, values, NULL); 1039 return reply ? JNI_TRUE : JNI_FALSE; 1040 #endif 1041 return JNI_FALSE; 1042 } 1043 1044 static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object, 1045 jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) { 1046 LOGV("%s", __FUNCTION__); 1047 #ifdef HAVE_BLUETOOTH 1048 native_data_t *nat = get_native_data(env, object); 1049 if (nat) { 1050 const char *c_name = env->GetStringUTFChars(name, NULL); 1051 LOGV("... name = %s", c_name); 1052 LOGV("... uuid1 = %llX", uuidMsb); 1053 LOGV("... uuid2 = %llX", uuidLsb); 1054 LOGV("... channel = %d", channel); 1055 DBusMessage *reply = dbus_func_args(env, nat->conn, 1056 get_adapter_path(env, object), 1057 DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord", 1058 DBUS_TYPE_STRING, &c_name, 1059 DBUS_TYPE_UINT64, &uuidMsb, 1060 DBUS_TYPE_UINT64, &uuidLsb, 1061 DBUS_TYPE_UINT16, &channel, 1062 DBUS_TYPE_INVALID); 1063 env->ReleaseStringUTFChars(name, c_name); 1064 return reply ? dbus_returns_uint32(env, reply) : -1; 1065 } 1066 #endif 1067 return -1; 1068 } 1069 1070 static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) { 1071 LOGV("%s", __FUNCTION__); 1072 #ifdef HAVE_BLUETOOTH 1073 native_data_t *nat = get_native_data(env, object); 1074 if (nat) { 1075 LOGV("... handle = %X", handle); 1076 DBusMessage *reply = dbus_func_args(env, nat->conn, 1077 get_adapter_path(env, object), 1078 DBUS_ADAPTER_IFACE, "RemoveServiceRecord", 1079 DBUS_TYPE_UINT32, &handle, 1080 DBUS_TYPE_INVALID); 1081 return reply ? JNI_TRUE : JNI_FALSE; 1082 } 1083 #endif 1084 return JNI_FALSE; 1085 } 1086 1087 static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path, 1088 jint num_slots) { 1089 LOGV("%s", __FUNCTION__); 1090 #ifdef HAVE_BLUETOOTH 1091 native_data_t *nat = get_native_data(env, object); 1092 if (nat) { 1093 const char *c_object_path = env->GetStringUTFChars(object_path, NULL); 1094 DBusMessage *reply = dbus_func_args(env, nat->conn, 1095 get_adapter_path(env, object), 1096 DBUS_ADAPTER_IFACE, "SetLinkTimeout", 1097 DBUS_TYPE_OBJECT_PATH, &c_object_path, 1098 DBUS_TYPE_UINT32, &num_slots, 1099 DBUS_TYPE_INVALID); 1100 env->ReleaseStringUTFChars(object_path, c_object_path); 1101 return reply ? JNI_TRUE : JNI_FALSE; 1102 } 1103 #endif 1104 return JNI_FALSE; 1105 } 1106 1107 static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring path) { 1108 LOGV("%s", __FUNCTION__); 1109 #ifdef HAVE_BLUETOOTH 1110 native_data_t *nat = get_native_data(env, object); 1111 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1112 struct event_loop_native_data_t *eventLoopNat = 1113 get_EventLoop_native_data(env, eventLoop); 1114 1115 if (nat && eventLoopNat) { 1116 const char *c_path = env->GetStringUTFChars(path, NULL); 1117 1118 int len = env->GetStringLength(path) + 1; 1119 char *context_path = (char *)calloc(len, sizeof(char)); 1120 strlcpy(context_path, c_path, len); // for callback 1121 1122 bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult, 1123 context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE, 1124 "Connect", 1125 DBUS_TYPE_INVALID); 1126 1127 env->ReleaseStringUTFChars(path, c_path); 1128 return ret ? JNI_TRUE : JNI_FALSE; 1129 } 1130 #endif 1131 return JNI_FALSE; 1132 } 1133 1134 static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object, 1135 jstring path) { 1136 LOGV("%s", __FUNCTION__); 1137 #ifdef HAVE_BLUETOOTH 1138 native_data_t *nat = get_native_data(env, object); 1139 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1140 struct event_loop_native_data_t *eventLoopNat = 1141 get_EventLoop_native_data(env, eventLoop); 1142 1143 if (nat && eventLoopNat) { 1144 const char *c_path = env->GetStringUTFChars(path, NULL); 1145 1146 int len = env->GetStringLength(path) + 1; 1147 char *context_path = (char *)calloc(len, sizeof(char)); 1148 strlcpy(context_path, c_path, len); // for callback 1149 1150 bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult, 1151 context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE, 1152 "Disconnect", 1153 DBUS_TYPE_INVALID); 1154 1155 env->ReleaseStringUTFChars(path, c_path); 1156 return ret ? JNI_TRUE : JNI_FALSE; 1157 } 1158 #endif 1159 return JNI_FALSE; 1160 } 1161 1162 static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value, 1163 jstring src_role, jstring bridge) { 1164 LOGV("%s", __FUNCTION__); 1165 #ifdef HAVE_BLUETOOTH 1166 native_data_t *nat = get_native_data(env, object); 1167 if (nat) { 1168 DBusMessage *reply; 1169 const char *c_role = env->GetStringUTFChars(src_role, NULL); 1170 const char *c_bridge = env->GetStringUTFChars(bridge, NULL); 1171 if (value) { 1172 LOGE("setBluetoothTetheringNative true"); 1173 reply = dbus_func_args(env, nat->conn, 1174 get_adapter_path(env, object), 1175 DBUS_NETWORKSERVER_IFACE, 1176 "Register", 1177 DBUS_TYPE_STRING, &c_role, 1178 DBUS_TYPE_STRING, &c_bridge, 1179 DBUS_TYPE_INVALID); 1180 } else { 1181 LOGE("setBluetoothTetheringNative false"); 1182 reply = dbus_func_args(env, nat->conn, 1183 get_adapter_path(env, object), 1184 DBUS_NETWORKSERVER_IFACE, 1185 "Unregister", 1186 DBUS_TYPE_STRING, &c_role, 1187 DBUS_TYPE_INVALID); 1188 } 1189 env->ReleaseStringUTFChars(src_role, c_role); 1190 env->ReleaseStringUTFChars(bridge, c_bridge); 1191 return reply ? JNI_TRUE : JNI_FALSE; 1192 } 1193 #endif 1194 return JNI_FALSE; 1195 } 1196 1197 static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path, 1198 jstring dstRole) { 1199 LOGV("%s", __FUNCTION__); 1200 #ifdef HAVE_BLUETOOTH 1201 LOGE("connectPanDeviceNative"); 1202 native_data_t *nat = get_native_data(env, object); 1203 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1204 struct event_loop_native_data_t *eventLoopNat = 1205 get_EventLoop_native_data(env, eventLoop); 1206 1207 if (nat && eventLoopNat) { 1208 const char *c_path = env->GetStringUTFChars(path, NULL); 1209 const char *dst = env->GetStringUTFChars(dstRole, NULL); 1210 1211 int len = env->GetStringLength(path) + 1; 1212 char *context_path = (char *)calloc(len, sizeof(char)); 1213 strlcpy(context_path, c_path, len); // for callback 1214 1215 bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult, 1216 context_path, eventLoopNat, c_path, 1217 DBUS_NETWORK_IFACE, "Connect", 1218 DBUS_TYPE_STRING, &dst, 1219 DBUS_TYPE_INVALID); 1220 1221 env->ReleaseStringUTFChars(path, c_path); 1222 env->ReleaseStringUTFChars(dstRole, dst); 1223 return ret ? JNI_TRUE : JNI_FALSE; 1224 } 1225 #endif 1226 return JNI_FALSE; 1227 } 1228 1229 static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object, 1230 jstring path) { 1231 LOGV("%s", __FUNCTION__); 1232 #ifdef HAVE_BLUETOOTH 1233 LOGE("disconnectPanDeviceNative"); 1234 native_data_t *nat = get_native_data(env, object); 1235 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1236 struct event_loop_native_data_t *eventLoopNat = 1237 get_EventLoop_native_data(env, eventLoop); 1238 1239 if (nat && eventLoopNat) { 1240 const char *c_path = env->GetStringUTFChars(path, NULL); 1241 1242 int len = env->GetStringLength(path) + 1; 1243 char *context_path = (char *)calloc(len, sizeof(char)); 1244 strlcpy(context_path, c_path, len); // for callback 1245 1246 bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult, 1247 context_path, eventLoopNat, c_path, 1248 DBUS_NETWORK_IFACE, "Disconnect", 1249 DBUS_TYPE_INVALID); 1250 1251 env->ReleaseStringUTFChars(path, c_path); 1252 return ret ? JNI_TRUE : JNI_FALSE; 1253 } 1254 #endif 1255 return JNI_FALSE; 1256 } 1257 1258 static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object, 1259 jstring path, jstring address, 1260 jstring iface) { 1261 LOGV("%s", __FUNCTION__); 1262 #ifdef HAVE_BLUETOOTH 1263 LOGE("disconnectPanServerDeviceNative"); 1264 native_data_t *nat = get_native_data(env, object); 1265 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1266 struct event_loop_native_data_t *eventLoopNat = 1267 get_EventLoop_native_data(env, eventLoop); 1268 1269 if (nat && eventLoopNat) { 1270 const char *c_address = env->GetStringUTFChars(address, NULL); 1271 const char *c_path = env->GetStringUTFChars(path, NULL); 1272 const char *c_iface = env->GetStringUTFChars(iface, NULL); 1273 1274 int len = env->GetStringLength(path) + 1; 1275 char *context_path = (char *)calloc(len, sizeof(char)); 1276 strlcpy(context_path, c_path, len); // for callback 1277 1278 bool ret = dbus_func_args_async(env, nat->conn, -1, 1279 onPanDeviceConnectionResult, 1280 context_path, eventLoopNat, 1281 get_adapter_path(env, object), 1282 DBUS_NETWORKSERVER_IFACE, 1283 "DisconnectDevice", 1284 DBUS_TYPE_STRING, &c_address, 1285 DBUS_TYPE_STRING, &c_iface, 1286 DBUS_TYPE_INVALID); 1287 1288 env->ReleaseStringUTFChars(address, c_address); 1289 env->ReleaseStringUTFChars(iface, c_iface); 1290 env->ReleaseStringUTFChars(path, c_path); 1291 return ret ? JNI_TRUE : JNI_FALSE; 1292 } 1293 #endif 1294 return JNI_FALSE; 1295 } 1296 1297 static jstring registerHealthApplicationNative(JNIEnv *env, jobject object, 1298 jint dataType, jstring role, 1299 jstring name, jstring channelType) { 1300 LOGV("%s", __FUNCTION__); 1301 jstring path = NULL; 1302 #ifdef HAVE_BLUETOOTH 1303 native_data_t *nat = get_native_data(env, object); 1304 if (nat) { 1305 const char *c_role = env->GetStringUTFChars(role, NULL); 1306 const char *c_name = env->GetStringUTFChars(name, NULL); 1307 const char *c_channel_type = env->GetStringUTFChars(channelType, NULL); 1308 char *c_path; 1309 DBusMessage *msg, *reply; 1310 DBusError err; 1311 dbus_error_init(&err); 1312 1313 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, 1314 DBUS_HEALTH_MANAGER_PATH, 1315 DBUS_HEALTH_MANAGER_IFACE, 1316 "CreateApplication"); 1317 1318 if (msg == NULL) { 1319 LOGE("Could not allocate D-Bus message object!"); 1320 return NULL; 1321 } 1322 1323 /* append arguments */ 1324 append_dict_args(msg, 1325 "DataType", DBUS_TYPE_UINT16, &dataType, 1326 "Role", DBUS_TYPE_STRING, &c_role, 1327 "Description", DBUS_TYPE_STRING, &c_name, 1328 "ChannelType", DBUS_TYPE_STRING, &c_channel_type, 1329 DBUS_TYPE_INVALID); 1330 1331 1332 /* Make the call. */ 1333 reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); 1334 1335 env->ReleaseStringUTFChars(role, c_role); 1336 env->ReleaseStringUTFChars(name, c_name); 1337 env->ReleaseStringUTFChars(channelType, c_channel_type); 1338 1339 if (!reply) { 1340 if (dbus_error_is_set(&err)) { 1341 LOG_AND_FREE_DBUS_ERROR(&err); 1342 } 1343 } else { 1344 if (!dbus_message_get_args(reply, &err, 1345 DBUS_TYPE_OBJECT_PATH, &c_path, 1346 DBUS_TYPE_INVALID)) { 1347 if (dbus_error_is_set(&err)) { 1348 LOG_AND_FREE_DBUS_ERROR(&err); 1349 } 1350 } else { 1351 path = env->NewStringUTF(c_path); 1352 } 1353 dbus_message_unref(reply); 1354 } 1355 } 1356 #endif 1357 return path; 1358 } 1359 1360 static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object, 1361 jint dataType, jstring role, 1362 jstring name) { 1363 LOGV("%s", __FUNCTION__); 1364 jstring path = NULL; 1365 #ifdef HAVE_BLUETOOTH 1366 native_data_t *nat = get_native_data(env, object); 1367 if (nat) { 1368 const char *c_role = env->GetStringUTFChars(role, NULL); 1369 const char *c_name = env->GetStringUTFChars(name, NULL); 1370 char *c_path; 1371 1372 DBusMessage *msg, *reply; 1373 DBusError err; 1374 dbus_error_init(&err); 1375 1376 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, 1377 DBUS_HEALTH_MANAGER_PATH, 1378 DBUS_HEALTH_MANAGER_IFACE, 1379 "CreateApplication"); 1380 1381 if (msg == NULL) { 1382 LOGE("Could not allocate D-Bus message object!"); 1383 return NULL; 1384 } 1385 1386 /* append arguments */ 1387 append_dict_args(msg, 1388 "DataType", DBUS_TYPE_UINT16, &dataType, 1389 "Role", DBUS_TYPE_STRING, &c_role, 1390 "Description", DBUS_TYPE_STRING, &c_name, 1391 DBUS_TYPE_INVALID); 1392 1393 1394 /* Make the call. */ 1395 reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); 1396 1397 env->ReleaseStringUTFChars(role, c_role); 1398 env->ReleaseStringUTFChars(name, c_name); 1399 1400 if (!reply) { 1401 if (dbus_error_is_set(&err)) { 1402 LOG_AND_FREE_DBUS_ERROR(&err); 1403 } 1404 } else { 1405 if (!dbus_message_get_args(reply, &err, 1406 DBUS_TYPE_OBJECT_PATH, &c_path, 1407 DBUS_TYPE_INVALID)) { 1408 if (dbus_error_is_set(&err)) { 1409 LOG_AND_FREE_DBUS_ERROR(&err); 1410 } 1411 } else { 1412 path = env->NewStringUTF(c_path); 1413 } 1414 dbus_message_unref(reply); 1415 } 1416 } 1417 #endif 1418 return path; 1419 } 1420 1421 static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object, 1422 jstring path) { 1423 LOGV("%s", __FUNCTION__); 1424 jboolean result = JNI_FALSE; 1425 #ifdef HAVE_BLUETOOTH 1426 native_data_t *nat = get_native_data(env, object); 1427 if (nat) { 1428 const char *c_path = env->GetStringUTFChars(path, NULL); 1429 DBusError err; 1430 dbus_error_init(&err); 1431 DBusMessage *reply = 1432 dbus_func_args_timeout(env, nat->conn, -1, 1433 DBUS_HEALTH_MANAGER_PATH, 1434 DBUS_HEALTH_MANAGER_IFACE, "DestroyApplication", 1435 DBUS_TYPE_OBJECT_PATH, &c_path, 1436 DBUS_TYPE_INVALID); 1437 1438 env->ReleaseStringUTFChars(path, c_path); 1439 1440 if (!reply) { 1441 if (dbus_error_is_set(&err)) { 1442 LOG_AND_FREE_DBUS_ERROR(&err); 1443 } 1444 } else { 1445 result = JNI_TRUE; 1446 } 1447 } 1448 #endif 1449 return result; 1450 } 1451 1452 static jboolean createChannelNative(JNIEnv *env, jobject object, 1453 jstring devicePath, jstring appPath, jstring config, 1454 jint code) { 1455 LOGV("%s", __FUNCTION__); 1456 #ifdef HAVE_BLUETOOTH 1457 native_data_t *nat = get_native_data(env, object); 1458 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1459 struct event_loop_native_data_t *eventLoopNat = 1460 get_EventLoop_native_data(env, eventLoop); 1461 1462 if (nat && eventLoopNat) { 1463 const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); 1464 const char *c_app_path = env->GetStringUTFChars(appPath, NULL); 1465 const char *c_config = env->GetStringUTFChars(config, NULL); 1466 int *data = (int *) malloc(sizeof(int)); 1467 if (data == NULL) return JNI_FALSE; 1468 1469 *data = code; 1470 bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult, 1471 data, eventLoopNat, c_device_path, 1472 DBUS_HEALTH_DEVICE_IFACE, "CreateChannel", 1473 DBUS_TYPE_OBJECT_PATH, &c_app_path, 1474 DBUS_TYPE_STRING, &c_config, 1475 DBUS_TYPE_INVALID); 1476 1477 1478 env->ReleaseStringUTFChars(devicePath, c_device_path); 1479 env->ReleaseStringUTFChars(appPath, c_app_path); 1480 env->ReleaseStringUTFChars(config, c_config); 1481 1482 return ret ? JNI_TRUE : JNI_FALSE; 1483 } 1484 #endif 1485 return JNI_FALSE; 1486 } 1487 1488 static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath, 1489 jstring channelPath, jint code) { 1490 LOGE("%s", __FUNCTION__); 1491 #ifdef HAVE_BLUETOOTH 1492 native_data_t *nat = get_native_data(env, object); 1493 jobject eventLoop = env->GetObjectField(object, field_mEventLoop); 1494 struct event_loop_native_data_t *eventLoopNat = 1495 get_EventLoop_native_data(env, eventLoop); 1496 1497 if (nat && eventLoopNat) { 1498 const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); 1499 const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); 1500 int *data = (int *) malloc(sizeof(int)); 1501 if (data == NULL) return JNI_FALSE; 1502 1503 *data = code; 1504 bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult, 1505 data, eventLoopNat, c_device_path, 1506 DBUS_HEALTH_DEVICE_IFACE, "DestroyChannel", 1507 DBUS_TYPE_OBJECT_PATH, &c_channel_path, 1508 DBUS_TYPE_INVALID); 1509 1510 env->ReleaseStringUTFChars(devicePath, c_device_path); 1511 env->ReleaseStringUTFChars(channelPath, c_channel_path); 1512 1513 return ret ? JNI_TRUE : JNI_FALSE; 1514 } 1515 #endif 1516 return JNI_FALSE; 1517 } 1518 1519 static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) { 1520 LOGE("%s", __FUNCTION__); 1521 #ifdef HAVE_BLUETOOTH 1522 native_data_t *nat = get_native_data(env, object); 1523 if (nat) { 1524 const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); 1525 DBusError err; 1526 dbus_error_init(&err); 1527 1528 DBusMessage *reply = dbus_func_args(env, nat->conn, 1529 c_device_path, 1530 DBUS_HEALTH_DEVICE_IFACE, "GetProperties", 1531 DBUS_TYPE_INVALID); 1532 env->ReleaseStringUTFChars(devicePath, c_device_path); 1533 1534 if (!reply) { 1535 if (dbus_error_is_set(&err)) { 1536 LOG_AND_FREE_DBUS_ERROR(&err); 1537 } 1538 } else { 1539 DBusMessageIter iter; 1540 jobjectArray str_array = NULL; 1541 if (dbus_message_iter_init(reply, &iter)) 1542 str_array = parse_health_device_properties(env, &iter); 1543 dbus_message_unref(reply); 1544 jstring path = (jstring) env->GetObjectArrayElement(str_array, 1); 1545 1546 return path; 1547 } 1548 } 1549 #endif 1550 return NULL; 1551 } 1552 1553 static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring channelPath) { 1554 LOGE("%s", __FUNCTION__); 1555 #ifdef HAVE_BLUETOOTH 1556 native_data_t *nat = get_native_data(env, object); 1557 if (nat) { 1558 const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); 1559 DBusError err; 1560 dbus_error_init(&err); 1561 1562 DBusMessage *reply = dbus_func_args(env, nat->conn, 1563 c_channel_path, 1564 DBUS_HEALTH_CHANNEL_IFACE, "GetProperties", 1565 DBUS_TYPE_INVALID); 1566 env->ReleaseStringUTFChars(channelPath, c_channel_path); 1567 1568 if (!reply) { 1569 if (dbus_error_is_set(&err)) { 1570 LOG_AND_FREE_DBUS_ERROR(&err); 1571 } 1572 } else { 1573 DBusMessageIter iter; 1574 jobjectArray str_array = NULL; 1575 if (dbus_message_iter_init(reply, &iter)) 1576 str_array = parse_health_channel_properties(env, &iter); 1577 dbus_message_unref(reply); 1578 1579 jint len = env->GetArrayLength(str_array); 1580 1581 jstring name, path; 1582 const char *c_name; 1583 1584 for (int i = 0; i < len; i+=2) { 1585 name = (jstring) env->GetObjectArrayElement(str_array, i); 1586 c_name = env->GetStringUTFChars(name, NULL); 1587 1588 if (!strcmp(c_name, "Application")) { 1589 path = (jstring) env->GetObjectArrayElement(str_array, i+1); 1590 env->ReleaseStringUTFChars(name, c_name); 1591 return path; 1592 } 1593 env->ReleaseStringUTFChars(name, c_name); 1594 } 1595 } 1596 } 1597 #endif 1598 return NULL; 1599 } 1600 1601 static jboolean releaseChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) { 1602 LOGV("%s", __FUNCTION__); 1603 #ifdef HAVE_BLUETOOTH 1604 native_data_t *nat = get_native_data(env, object); 1605 if (nat) { 1606 const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); 1607 DBusError err; 1608 dbus_error_init(&err); 1609 1610 DBusMessage *reply = dbus_func_args(env, nat->conn, 1611 c_channel_path, 1612 DBUS_HEALTH_CHANNEL_IFACE, "Release", 1613 DBUS_TYPE_INVALID); 1614 env->ReleaseStringUTFChars(channelPath, c_channel_path); 1615 1616 return reply ? JNI_TRUE : JNI_FALSE; 1617 } 1618 #endif 1619 return JNI_FALSE; 1620 } 1621 1622 static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) { 1623 LOGV("%s", __FUNCTION__); 1624 #ifdef HAVE_BLUETOOTH 1625 native_data_t *nat = get_native_data(env, object); 1626 if (nat) { 1627 const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); 1628 int32_t fd; 1629 DBusError err; 1630 dbus_error_init(&err); 1631 1632 DBusMessage *reply = dbus_func_args(env, nat->conn, 1633 c_channel_path, 1634 DBUS_HEALTH_CHANNEL_IFACE, "Acquire", 1635 DBUS_TYPE_INVALID); 1636 env->ReleaseStringUTFChars(channelPath, c_channel_path); 1637 1638 if (!reply) { 1639 if (dbus_error_is_set(&err)) { 1640 LOG_AND_FREE_DBUS_ERROR(&err); 1641 } 1642 return NULL; 1643 } 1644 1645 fd = dbus_returns_unixfd(env, reply); 1646 if (fd == -1) return NULL; 1647 1648 // Create FileDescriptor object 1649 jobject fileDesc = jniCreateFileDescriptor(env, fd); 1650 if (fileDesc == NULL) { 1651 // FileDescriptor constructor has thrown an exception 1652 releaseChannelFdNative(env, object, channelPath); 1653 close(fd); 1654 return NULL; 1655 } 1656 1657 // Wrap it in a ParcelFileDescriptor 1658 jobject parcelFileDesc = newParcelFileDescriptor(env, fileDesc); 1659 if (parcelFileDesc == NULL) { 1660 // ParcelFileDescriptor constructor has thrown an exception 1661 releaseChannelFdNative(env, object, channelPath); 1662 close(fd); 1663 return NULL; 1664 } 1665 1666 return parcelFileDesc; 1667 } 1668 #endif 1669 return NULL; 1670 } 1671 1672 1673 1674 static JNINativeMethod sMethods[] = { 1675 /* name, signature, funcPtr */ 1676 {"classInitNative", "()V", (void*)classInitNative}, 1677 {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, 1678 {"setupNativeDataNative", "()Z", (void *)setupNativeDataNative}, 1679 {"tearDownNativeDataNative", "()Z", (void *)tearDownNativeDataNative}, 1680 {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, 1681 {"getAdapterPathNative", "()Ljava/lang/String;", (void*)getAdapterPathNative}, 1682 1683 {"isEnabledNative", "()I", (void *)isEnabledNative}, 1684 {"enableNative", "()I", (void *)enableNative}, 1685 {"disableNative", "()I", (void *)disableNative}, 1686 1687 {"getAdapterPropertiesNative", "()[Ljava/lang/Object;", (void *)getAdapterPropertiesNative}, 1688 {"getDevicePropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", 1689 (void *)getDevicePropertiesNative}, 1690 {"setAdapterPropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;)Z", 1691 (void *)setAdapterPropertyStringNative}, 1692 {"setAdapterPropertyBooleanNative", "(Ljava/lang/String;I)Z", 1693 (void *)setAdapterPropertyBooleanNative}, 1694 {"setAdapterPropertyIntegerNative", "(Ljava/lang/String;I)Z", 1695 (void *)setAdapterPropertyIntegerNative}, 1696 1697 {"startDiscoveryNative", "()Z", (void*)startDiscoveryNative}, 1698 {"stopDiscoveryNative", "()Z", (void *)stopDiscoveryNative}, 1699 1700 {"readAdapterOutOfBandDataNative", "()[B", (void *)readAdapterOutOfBandDataNative}, 1701 {"createPairedDeviceNative", "(Ljava/lang/String;I)Z", (void *)createPairedDeviceNative}, 1702 {"createPairedDeviceOutOfBandNative", "(Ljava/lang/String;I)Z", 1703 (void *)createPairedDeviceOutOfBandNative}, 1704 {"cancelDeviceCreationNative", "(Ljava/lang/String;)Z", (void *)cancelDeviceCreationNative}, 1705 {"removeDeviceNative", "(Ljava/lang/String;)Z", (void *)removeDeviceNative}, 1706 {"getDeviceServiceChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)I", 1707 (void *)getDeviceServiceChannelNative}, 1708 1709 {"setPairingConfirmationNative", "(Ljava/lang/String;ZI)Z", 1710 (void *)setPairingConfirmationNative}, 1711 {"setPasskeyNative", "(Ljava/lang/String;II)Z", (void *)setPasskeyNative}, 1712 {"setRemoteOutOfBandDataNative", "(Ljava/lang/String;[B[BI)Z", (void *)setRemoteOutOfBandDataNative}, 1713 {"setAuthorizationNative", "(Ljava/lang/String;ZI)Z", (void *)setAuthorizationNative}, 1714 {"setPinNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)setPinNative}, 1715 {"cancelPairingUserInputNative", "(Ljava/lang/String;I)Z", 1716 (void *)cancelPairingUserInputNative}, 1717 {"setDevicePropertyBooleanNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", 1718 (void *)setDevicePropertyBooleanNative}, 1719 {"setDevicePropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", 1720 (void *)setDevicePropertyStringNative}, 1721 {"createDeviceNative", "(Ljava/lang/String;)Z", (void *)createDeviceNative}, 1722 {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative}, 1723 {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative}, 1724 {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative}, 1725 {"addReservedServiceRecordsNative", "([I)[I", (void *) addReservedServiceRecordsNative}, 1726 {"removeReservedServiceRecordsNative", "([I)Z", (void *) removeReservedServiceRecordsNative}, 1727 {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative}, 1728 // HID functions 1729 {"connectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)connectInputDeviceNative}, 1730 {"disconnectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectInputDeviceNative}, 1731 1732 {"setBluetoothTetheringNative", "(ZLjava/lang/String;Ljava/lang/String;)Z", 1733 (void *)setBluetoothTetheringNative}, 1734 {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z", 1735 (void *)connectPanDeviceNative}, 1736 {"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative}, 1737 {"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", 1738 (void *)disconnectPanServerDeviceNative}, 1739 // Health function 1740 {"registerHealthApplicationNative", 1741 "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 1742 (void *)registerHealthApplicationNative}, 1743 {"registerHealthApplicationNative", 1744 "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 1745 (void *)registerSinkHealthApplicationNative}, 1746 1747 {"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z", 1748 (void *)unregisterHealthApplicationNative}, 1749 {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z", 1750 (void *)createChannelNative}, 1751 {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", 1752 (void *)destroyChannelNative}, 1753 {"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative}, 1754 {"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;", 1755 (void *)getChannelApplicationNative}, 1756 {"getChannelFdNative", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", (void *)getChannelFdNative}, 1757 {"releaseChannelFdNative", "(Ljava/lang/String;)Z", (void *)releaseChannelFdNative}, 1758 }; 1759 1760 1761 int register_android_server_BluetoothService(JNIEnv *env) { 1762 return AndroidRuntime::registerNativeMethods(env, 1763 "android/server/BluetoothService", sMethods, NELEM(sMethods)); 1764 } 1765 1766 } /* namespace android */ 1767