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 LOG_TAG "bluetooth_common.cpp" 18 19 #include "android_bluetooth_common.h" 20 #include "JNIHelp.h" 21 #include "jni.h" 22 #include "utils/Log.h" 23 #include "utils/misc.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <unistd.h> 30 #include <cutils/properties.h> 31 32 #ifdef HAVE_BLUETOOTH 33 #include <dbus/dbus.h> 34 #endif 35 36 namespace android { 37 38 #ifdef HAVE_BLUETOOTH 39 40 static Properties remote_device_properties[] = { 41 {"Address", DBUS_TYPE_STRING}, 42 {"Name", DBUS_TYPE_STRING}, 43 {"Icon", DBUS_TYPE_STRING}, 44 {"Class", DBUS_TYPE_UINT32}, 45 {"UUIDs", DBUS_TYPE_ARRAY}, 46 {"Services", DBUS_TYPE_ARRAY}, 47 {"Paired", DBUS_TYPE_BOOLEAN}, 48 {"Connected", DBUS_TYPE_BOOLEAN}, 49 {"Trusted", DBUS_TYPE_BOOLEAN}, 50 {"Blocked", DBUS_TYPE_BOOLEAN}, 51 {"Alias", DBUS_TYPE_STRING}, 52 {"Nodes", DBUS_TYPE_ARRAY}, 53 {"Adapter", DBUS_TYPE_OBJECT_PATH}, 54 {"LegacyPairing", DBUS_TYPE_BOOLEAN}, 55 {"RSSI", DBUS_TYPE_INT16}, 56 {"TX", DBUS_TYPE_UINT32}, 57 {"Broadcaster", DBUS_TYPE_BOOLEAN} 58 }; 59 60 static Properties adapter_properties[] = { 61 {"Address", DBUS_TYPE_STRING}, 62 {"Name", DBUS_TYPE_STRING}, 63 {"Class", DBUS_TYPE_UINT32}, 64 {"Powered", DBUS_TYPE_BOOLEAN}, 65 {"Discoverable", DBUS_TYPE_BOOLEAN}, 66 {"DiscoverableTimeout", DBUS_TYPE_UINT32}, 67 {"Pairable", DBUS_TYPE_BOOLEAN}, 68 {"PairableTimeout", DBUS_TYPE_UINT32}, 69 {"Discovering", DBUS_TYPE_BOOLEAN}, 70 {"Devices", DBUS_TYPE_ARRAY}, 71 {"UUIDs", DBUS_TYPE_ARRAY}, 72 }; 73 74 static Properties input_properties[] = { 75 {"Connected", DBUS_TYPE_BOOLEAN}, 76 }; 77 78 static Properties pan_properties[] = { 79 {"Connected", DBUS_TYPE_BOOLEAN}, 80 {"Interface", DBUS_TYPE_STRING}, 81 {"UUID", DBUS_TYPE_STRING}, 82 }; 83 84 static Properties health_device_properties[] = { 85 {"MainChannel", DBUS_TYPE_OBJECT_PATH}, 86 }; 87 88 static Properties health_channel_properties[] = { 89 {"Type", DBUS_TYPE_STRING}, 90 {"Device", DBUS_TYPE_OBJECT_PATH}, 91 {"Application", DBUS_TYPE_OBJECT_PATH}, 92 }; 93 94 typedef union { 95 char *str_val; 96 int int_val; 97 char **array_val; 98 } property_value; 99 100 jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, 101 const char *mtype) { 102 jfieldID field = env->GetFieldID(clazz, member, mtype); 103 if (field == NULL) { 104 ALOGE("Can't find member %s", member); 105 } 106 return field; 107 } 108 109 typedef struct { 110 void (*user_cb)(DBusMessage *, void *, void *); 111 void *user; 112 void *nat; 113 JNIEnv *env; 114 } dbus_async_call_t; 115 116 void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { 117 118 dbus_async_call_t *req = (dbus_async_call_t *)data; 119 DBusMessage *msg; 120 121 /* This is guaranteed to be non-NULL, because this function is called only 122 when once the remote method invokation returns. */ 123 msg = dbus_pending_call_steal_reply(call); 124 125 if (msg) { 126 if (req->user_cb) { 127 // The user may not deref the message object. 128 req->user_cb(msg, req->user, req->nat); 129 } 130 dbus_message_unref(msg); 131 } 132 133 //dbus_message_unref(req->method); 134 dbus_pending_call_cancel(call); 135 dbus_pending_call_unref(call); 136 free(req); 137 } 138 139 static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, 140 DBusConnection *conn, 141 int timeout_ms, 142 void (*user_cb)(DBusMessage *, 143 void *, 144 void*), 145 void *user, 146 void *nat, 147 const char *path, 148 const char *ifc, 149 const char *func, 150 int first_arg_type, 151 va_list args) { 152 DBusMessage *msg = NULL; 153 const char *name; 154 dbus_async_call_t *pending; 155 dbus_bool_t reply = FALSE; 156 157 /* Compose the command */ 158 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); 159 160 if (msg == NULL) { 161 ALOGE("Could not allocate D-Bus message object!"); 162 goto done; 163 } 164 165 /* append arguments */ 166 if (!dbus_message_append_args_valist(msg, first_arg_type, args)) { 167 ALOGE("Could not append argument to method call!"); 168 goto done; 169 } 170 171 /* Make the call. */ 172 pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t)); 173 if (pending) { 174 DBusPendingCall *call; 175 176 pending->env = env; 177 pending->user_cb = user_cb; 178 pending->user = user; 179 pending->nat = nat; 180 //pending->method = msg; 181 182 reply = dbus_connection_send_with_reply(conn, msg, 183 &call, 184 timeout_ms); 185 if (reply == TRUE) { 186 dbus_pending_call_set_notify(call, 187 dbus_func_args_async_callback, 188 pending, 189 NULL); 190 } 191 } 192 193 done: 194 if (msg) dbus_message_unref(msg); 195 return reply; 196 } 197 198 dbus_bool_t dbus_func_args_async(JNIEnv *env, 199 DBusConnection *conn, 200 int timeout_ms, 201 void (*reply)(DBusMessage *, void *, void*), 202 void *user, 203 void *nat, 204 const char *path, 205 const char *ifc, 206 const char *func, 207 int first_arg_type, 208 ...) { 209 dbus_bool_t ret; 210 va_list lst; 211 va_start(lst, first_arg_type); 212 213 ret = dbus_func_args_async_valist(env, conn, 214 timeout_ms, 215 reply, user, nat, 216 path, ifc, func, 217 first_arg_type, lst); 218 va_end(lst); 219 return ret; 220 } 221 222 // If err is NULL, then any errors will be ALOGE'd, and free'd and the reply 223 // will be NULL. 224 // If err is not NULL, then it is assumed that dbus_error_init was already 225 // called, and error's will be returned to the caller without logging. The 226 // return value is NULL iff an error was set. The client must free the error if 227 // set. 228 DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env, 229 DBusConnection *conn, 230 int timeout_ms, 231 DBusError *err, 232 const char *path, 233 const char *ifc, 234 const char *func, 235 int first_arg_type, 236 va_list args) { 237 238 DBusMessage *msg = NULL, *reply = NULL; 239 const char *name; 240 bool return_error = (err != NULL); 241 242 if (!return_error) { 243 err = (DBusError*)malloc(sizeof(DBusError)); 244 dbus_error_init(err); 245 } 246 247 /* Compose the command */ 248 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); 249 250 if (msg == NULL) { 251 ALOGE("Could not allocate D-Bus message object!"); 252 goto done; 253 } 254 255 /* append arguments */ 256 if (!dbus_message_append_args_valist(msg, first_arg_type, args)) { 257 ALOGE("Could not append argument to method call!"); 258 goto done; 259 } 260 261 /* Make the call. */ 262 reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err); 263 if (!return_error && dbus_error_is_set(err)) { 264 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg); 265 } 266 267 done: 268 if (!return_error) { 269 free(err); 270 } 271 if (msg) dbus_message_unref(msg); 272 return reply; 273 } 274 275 DBusMessage * dbus_func_args_timeout(JNIEnv *env, 276 DBusConnection *conn, 277 int timeout_ms, 278 const char *path, 279 const char *ifc, 280 const char *func, 281 int first_arg_type, 282 ...) { 283 DBusMessage *ret; 284 va_list lst; 285 va_start(lst, first_arg_type); 286 ret = dbus_func_args_timeout_valist(env, conn, timeout_ms, NULL, 287 path, ifc, func, 288 first_arg_type, lst); 289 va_end(lst); 290 return ret; 291 } 292 293 DBusMessage * dbus_func_args(JNIEnv *env, 294 DBusConnection *conn, 295 const char *path, 296 const char *ifc, 297 const char *func, 298 int first_arg_type, 299 ...) { 300 DBusMessage *ret; 301 va_list lst; 302 va_start(lst, first_arg_type); 303 ret = dbus_func_args_timeout_valist(env, conn, -1, NULL, 304 path, ifc, func, 305 first_arg_type, lst); 306 va_end(lst); 307 return ret; 308 } 309 310 DBusMessage * dbus_func_args_error(JNIEnv *env, 311 DBusConnection *conn, 312 DBusError *err, 313 const char *path, 314 const char *ifc, 315 const char *func, 316 int first_arg_type, 317 ...) { 318 DBusMessage *ret; 319 va_list lst; 320 va_start(lst, first_arg_type); 321 ret = dbus_func_args_timeout_valist(env, conn, -1, err, 322 path, ifc, func, 323 first_arg_type, lst); 324 va_end(lst); 325 return ret; 326 } 327 328 jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply) { 329 330 DBusError err; 331 jint ret = -1; 332 333 dbus_error_init(&err); 334 if (!dbus_message_get_args(reply, &err, 335 DBUS_TYPE_UNIX_FD, &ret, 336 DBUS_TYPE_INVALID)) { 337 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 338 } 339 dbus_message_unref(reply); 340 return ret; 341 } 342 343 344 jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply) { 345 346 DBusError err; 347 jint ret = -1; 348 349 dbus_error_init(&err); 350 if (!dbus_message_get_args(reply, &err, 351 DBUS_TYPE_INT32, &ret, 352 DBUS_TYPE_INVALID)) { 353 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 354 } 355 dbus_message_unref(reply); 356 return ret; 357 } 358 359 jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply) { 360 361 DBusError err; 362 jint ret = -1; 363 364 dbus_error_init(&err); 365 if (!dbus_message_get_args(reply, &err, 366 DBUS_TYPE_UINT32, &ret, 367 DBUS_TYPE_INVALID)) { 368 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 369 } 370 dbus_message_unref(reply); 371 return ret; 372 } 373 374 jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply) { 375 376 DBusError err; 377 jstring ret = NULL; 378 const char *name; 379 380 dbus_error_init(&err); 381 if (dbus_message_get_args(reply, &err, 382 DBUS_TYPE_STRING, &name, 383 DBUS_TYPE_INVALID)) { 384 ret = env->NewStringUTF(name); 385 } else { 386 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 387 } 388 dbus_message_unref(reply); 389 390 return ret; 391 } 392 393 jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply) { 394 DBusError err; 395 jboolean ret = JNI_FALSE; 396 dbus_bool_t val = FALSE; 397 398 dbus_error_init(&err); 399 400 /* Check the return value. */ 401 if (dbus_message_get_args(reply, &err, 402 DBUS_TYPE_BOOLEAN, &val, 403 DBUS_TYPE_INVALID)) { 404 ret = val == TRUE ? JNI_TRUE : JNI_FALSE; 405 } else { 406 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 407 } 408 409 dbus_message_unref(reply); 410 return ret; 411 } 412 413 static void set_object_array_element(JNIEnv *env, jobjectArray strArray, 414 const char *value, int index) { 415 jstring obj; 416 obj = env->NewStringUTF(value); 417 env->SetObjectArrayElement(strArray, index, obj); 418 env->DeleteLocalRef(obj); 419 } 420 421 jobjectArray dbus_returns_array_of_object_path(JNIEnv *env, 422 DBusMessage *reply) { 423 424 DBusError err; 425 char **list; 426 int i, len; 427 jobjectArray strArray = NULL; 428 429 dbus_error_init(&err); 430 if (dbus_message_get_args (reply, 431 &err, 432 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, 433 &list, &len, 434 DBUS_TYPE_INVALID)) { 435 jclass stringClass; 436 jstring classNameStr; 437 438 stringClass = env->FindClass("java/lang/String"); 439 strArray = env->NewObjectArray(len, stringClass, NULL); 440 441 for (i = 0; i < len; i++) 442 set_object_array_element(env, strArray, list[i], i); 443 } else { 444 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 445 } 446 447 dbus_message_unref(reply); 448 return strArray; 449 } 450 451 jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply) { 452 453 DBusError err; 454 char **list; 455 int i, len; 456 jobjectArray strArray = NULL; 457 458 dbus_error_init(&err); 459 if (dbus_message_get_args (reply, 460 &err, 461 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, 462 &list, &len, 463 DBUS_TYPE_INVALID)) { 464 jclass stringClass; 465 jstring classNameStr; 466 467 //ALOGV("%s: there are %d elements in string array!", __FUNCTION__, len); 468 469 stringClass = env->FindClass("java/lang/String"); 470 strArray = env->NewObjectArray(len, stringClass, NULL); 471 472 for (i = 0; i < len; i++) 473 set_object_array_element(env, strArray, list[i], i); 474 } else { 475 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 476 } 477 478 dbus_message_unref(reply); 479 return strArray; 480 } 481 482 jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply) { 483 484 DBusError err; 485 int i, len; 486 jbyte *list; 487 jbyteArray byteArray = NULL; 488 489 dbus_error_init(&err); 490 if (dbus_message_get_args(reply, &err, 491 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &list, &len, 492 DBUS_TYPE_INVALID)) { 493 //ALOGV("%s: there are %d elements in byte array!", __FUNCTION__, len); 494 byteArray = env->NewByteArray(len); 495 if (byteArray) 496 env->SetByteArrayRegion(byteArray, 0, len, list); 497 498 } else { 499 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 500 } 501 502 dbus_message_unref(reply); 503 return byteArray; 504 } 505 506 void append_variant(DBusMessageIter *iter, int type, void *val) 507 { 508 DBusMessageIter value_iter; 509 char var_type[2] = { type, '\0'}; 510 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, var_type, &value_iter); 511 dbus_message_iter_append_basic(&value_iter, type, val); 512 dbus_message_iter_close_container(iter, &value_iter); 513 } 514 515 static void dict_append_entry(DBusMessageIter *dict, 516 const char *key, int type, void *val) 517 { 518 DBusMessageIter dict_entry; 519 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, 520 NULL, &dict_entry); 521 522 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key); 523 append_variant(&dict_entry, type, val); 524 dbus_message_iter_close_container(dict, &dict_entry); 525 } 526 527 static void append_dict_valist(DBusMessageIter *iterator, const char *first_key, 528 va_list var_args) 529 { 530 DBusMessageIter dict; 531 int val_type; 532 const char *val_key; 533 void *val; 534 535 dbus_message_iter_open_container(iterator, DBUS_TYPE_ARRAY, 536 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 537 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 538 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 539 540 val_key = first_key; 541 while (val_key) { 542 val_type = va_arg(var_args, int); 543 val = va_arg(var_args, void *); 544 dict_append_entry(&dict, val_key, val_type, val); 545 val_key = va_arg(var_args, char *); 546 } 547 548 dbus_message_iter_close_container(iterator, &dict); 549 } 550 551 void append_dict_args(DBusMessage *reply, const char *first_key, ...) 552 { 553 DBusMessageIter iter; 554 va_list var_args; 555 556 dbus_message_iter_init_append(reply, &iter); 557 558 va_start(var_args, first_key); 559 append_dict_valist(&iter, first_key, var_args); 560 va_end(var_args); 561 } 562 563 564 int get_property(DBusMessageIter iter, Properties *properties, 565 int max_num_properties, int *prop_index, property_value *value, int *len) { 566 DBusMessageIter prop_val, array_val_iter; 567 char *property = NULL; 568 uint32_t array_type; 569 char *str_val; 570 int i, j, type, int_val; 571 572 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 573 return -1; 574 dbus_message_iter_get_basic(&iter, &property); 575 if (!dbus_message_iter_next(&iter)) 576 return -1; 577 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) 578 return -1; 579 for (i = 0; i < max_num_properties; i++) { 580 if (!strncmp(property, properties[i].name, strlen(property))) 581 break; 582 } 583 *prop_index = i; 584 if (i == max_num_properties) 585 return -1; 586 587 dbus_message_iter_recurse(&iter, &prop_val); 588 type = properties[*prop_index].type; 589 if (dbus_message_iter_get_arg_type(&prop_val) != type) { 590 ALOGE("Property type mismatch in get_property: %d, expected:%d, index:%d", 591 dbus_message_iter_get_arg_type(&prop_val), type, *prop_index); 592 return -1; 593 } 594 595 switch(type) { 596 case DBUS_TYPE_STRING: 597 case DBUS_TYPE_OBJECT_PATH: 598 dbus_message_iter_get_basic(&prop_val, &value->str_val); 599 *len = 1; 600 break; 601 case DBUS_TYPE_UINT32: 602 case DBUS_TYPE_INT16: 603 case DBUS_TYPE_BOOLEAN: 604 dbus_message_iter_get_basic(&prop_val, &int_val); 605 value->int_val = int_val; 606 *len = 1; 607 break; 608 case DBUS_TYPE_ARRAY: 609 dbus_message_iter_recurse(&prop_val, &array_val_iter); 610 array_type = dbus_message_iter_get_arg_type(&array_val_iter); 611 *len = 0; 612 value->array_val = NULL; 613 if (array_type == DBUS_TYPE_OBJECT_PATH || 614 array_type == DBUS_TYPE_STRING){ 615 j = 0; 616 do { 617 j ++; 618 } while(dbus_message_iter_next(&array_val_iter)); 619 dbus_message_iter_recurse(&prop_val, &array_val_iter); 620 // Allocate an array of char * 621 *len = j; 622 char **tmp = (char **)malloc(sizeof(char *) * *len); 623 if (!tmp) 624 return -1; 625 j = 0; 626 do { 627 dbus_message_iter_get_basic(&array_val_iter, &tmp[j]); 628 j ++; 629 } while(dbus_message_iter_next(&array_val_iter)); 630 value->array_val = tmp; 631 } 632 break; 633 default: 634 return -1; 635 } 636 return 0; 637 } 638 639 void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property, 640 property_value *value, int len, int *array_index ) { 641 char **prop_val = NULL; 642 char buf[32] = {'\0'}, buf1[32] = {'\0'}; 643 int i; 644 645 char *name = property->name; 646 int prop_type = property->type; 647 648 set_object_array_element(env, strArray, name, *array_index); 649 *array_index += 1; 650 651 if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) { 652 sprintf(buf, "%d", value->int_val); 653 set_object_array_element(env, strArray, buf, *array_index); 654 *array_index += 1; 655 } else if (prop_type == DBUS_TYPE_BOOLEAN) { 656 sprintf(buf, "%s", value->int_val ? "true" : "false"); 657 658 set_object_array_element(env, strArray, buf, *array_index); 659 *array_index += 1; 660 } else if (prop_type == DBUS_TYPE_ARRAY) { 661 // Write the length first 662 sprintf(buf1, "%d", len); 663 set_object_array_element(env, strArray, buf1, *array_index); 664 *array_index += 1; 665 666 prop_val = value->array_val; 667 for (i = 0; i < len; i++) { 668 set_object_array_element(env, strArray, prop_val[i], *array_index); 669 *array_index += 1; 670 } 671 } else { 672 set_object_array_element(env, strArray, (const char *) value->str_val, *array_index); 673 *array_index += 1; 674 } 675 } 676 677 jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties, 678 const int max_num_properties) { 679 DBusMessageIter dict_entry, dict; 680 jobjectArray strArray = NULL; 681 property_value value; 682 int i, size = 0,array_index = 0; 683 int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type; 684 struct { 685 property_value value; 686 int len; 687 bool used; 688 } values[max_num_properties]; 689 int t, j; 690 691 jclass stringClass = env->FindClass("java/lang/String"); 692 DBusError err; 693 dbus_error_init(&err); 694 695 for (i = 0; i < max_num_properties; i++) { 696 values[i].used = false; 697 } 698 699 if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) 700 goto failure; 701 dbus_message_iter_recurse(iter, &dict); 702 do { 703 len = 0; 704 if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) 705 goto failure; 706 dbus_message_iter_recurse(&dict, &dict_entry); 707 708 if (!get_property(dict_entry, properties, max_num_properties, &prop_index, 709 &value, &len)) { 710 size += 2; 711 if (properties[prop_index].type == DBUS_TYPE_ARRAY) 712 size += len; 713 values[prop_index].value = value; 714 values[prop_index].len = len; 715 values[prop_index].used = true; 716 } else { 717 goto failure; 718 } 719 } while(dbus_message_iter_next(&dict)); 720 721 strArray = env->NewObjectArray(size, stringClass, NULL); 722 723 for (i = 0; i < max_num_properties; i++) { 724 if (values[i].used) { 725 create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len, 726 &array_index); 727 728 if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used 729 && values[i].value.array_val != NULL) 730 free(values[i].value.array_val); 731 } 732 733 } 734 return strArray; 735 736 failure: 737 if (dbus_error_is_set(&err)) 738 LOG_AND_FREE_DBUS_ERROR(&err); 739 for (i = 0; i < max_num_properties; i++) 740 if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true 741 && values[i].value.array_val != NULL) 742 free(values[i].value.array_val); 743 return NULL; 744 } 745 746 jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg, 747 Properties *properties, int max_num_properties) { 748 DBusMessageIter iter; 749 DBusError err; 750 jobjectArray strArray = NULL; 751 jclass stringClass= env->FindClass("java/lang/String"); 752 int len = 0, prop_index = -1; 753 int array_index = 0, size = 0; 754 property_value value; 755 756 dbus_error_init(&err); 757 if (!dbus_message_iter_init(msg, &iter)) 758 goto failure; 759 760 if (!get_property(iter, properties, max_num_properties, 761 &prop_index, &value, &len)) { 762 size += 2; 763 if (properties[prop_index].type == DBUS_TYPE_ARRAY) 764 size += len; 765 strArray = env->NewObjectArray(size, stringClass, NULL); 766 767 create_prop_array(env, strArray, &properties[prop_index], 768 &value, len, &array_index); 769 770 if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL) 771 free(value.array_val); 772 773 return strArray; 774 } 775 failure: 776 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 777 return NULL; 778 } 779 780 jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg) { 781 return parse_property_change(env, msg, (Properties *) &adapter_properties, 782 sizeof(adapter_properties) / sizeof(Properties)); 783 } 784 785 jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg) { 786 return parse_property_change(env, msg, (Properties *) &remote_device_properties, 787 sizeof(remote_device_properties) / sizeof(Properties)); 788 } 789 790 jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg) { 791 return parse_property_change(env, msg, (Properties *) &input_properties, 792 sizeof(input_properties) / sizeof(Properties)); 793 } 794 795 jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg) { 796 return parse_property_change(env, msg, (Properties *) &pan_properties, 797 sizeof(pan_properties) / sizeof(Properties)); 798 } 799 800 jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter) { 801 return parse_properties(env, iter, (Properties *) &adapter_properties, 802 sizeof(adapter_properties) / sizeof(Properties)); 803 } 804 805 jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter) { 806 return parse_properties(env, iter, (Properties *) &remote_device_properties, 807 sizeof(remote_device_properties) / sizeof(Properties)); 808 } 809 810 jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter) { 811 return parse_properties(env, iter, (Properties *) &input_properties, 812 sizeof(input_properties) / sizeof(Properties)); 813 } 814 815 jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter) { 816 return parse_properties(env, iter, (Properties *) &health_device_properties, 817 sizeof(health_device_properties) / sizeof(Properties)); 818 } 819 820 jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg) { 821 return parse_property_change(env, msg, (Properties *) &health_device_properties, 822 sizeof(health_device_properties) / sizeof(Properties)); 823 } 824 825 jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter) { 826 return parse_properties(env, iter, (Properties *) &health_channel_properties, 827 sizeof(health_channel_properties) / sizeof(Properties)); 828 } 829 830 int get_bdaddr(const char *str, bdaddr_t *ba) { 831 char *d = ((char *)ba) + 5, *endp; 832 int i; 833 for(i = 0; i < 6; i++) { 834 *d-- = strtol(str, &endp, 16); 835 if (*endp != ':' && i != 5) { 836 memset(ba, 0, sizeof(bdaddr_t)); 837 return -1; 838 } 839 str = endp + 1; 840 } 841 return 0; 842 } 843 844 void get_bdaddr_as_string(const bdaddr_t *ba, char *str) { 845 const uint8_t *b = (const uint8_t *)ba; 846 sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", 847 b[5], b[4], b[3], b[2], b[1], b[0]); 848 } 849 850 bool debug_no_encrypt() { 851 return false; 852 #if 0 853 char value[PROPERTY_VALUE_MAX] = ""; 854 855 property_get("debug.bt.no_encrypt", value, ""); 856 if (!strncmp("true", value, PROPERTY_VALUE_MAX) || 857 !strncmp("1", value, PROPERTY_VALUE_MAX)) { 858 ALOGD("mandatory bluetooth encryption disabled"); 859 return true; 860 } else { 861 return false; 862 } 863 #endif 864 } 865 #endif 866 867 } /* namespace android */ 868