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