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
get_field(JNIEnv * env,jclass clazz,const char * member,const char * mtype)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
dbus_func_args_async_callback(DBusPendingCall * call,void * data)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
dbus_func_args_async_valist(JNIEnv * env,DBusConnection * conn,int timeout_ms,void (* user_cb)(DBusMessage *,void *,void *),void * user,void * nat,const char * path,const char * ifc,const char * func,int first_arg_type,va_list args)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
dbus_func_args_async(JNIEnv * env,DBusConnection * conn,int timeout_ms,void (* reply)(DBusMessage *,void *,void *),void * user,void * nat,const char * path,const char * ifc,const char * func,int first_arg_type,...)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.
dbus_func_args_timeout_valist(JNIEnv * env,DBusConnection * conn,int timeout_ms,DBusError * err,const char * path,const char * ifc,const char * func,int first_arg_type,va_list args)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
dbus_func_args_timeout(JNIEnv * env,DBusConnection * conn,int timeout_ms,const char * path,const char * ifc,const char * func,int first_arg_type,...)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
dbus_func_args(JNIEnv * env,DBusConnection * conn,const char * path,const char * ifc,const char * func,int first_arg_type,...)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
dbus_func_args_error(JNIEnv * env,DBusConnection * conn,DBusError * err,const char * path,const char * ifc,const char * func,int first_arg_type,...)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
dbus_returns_int32(JNIEnv * env,DBusMessage * reply)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
dbus_returns_uint32(JNIEnv * env,DBusMessage * reply)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
dbus_returns_string(JNIEnv * env,DBusMessage * reply)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
dbus_returns_boolean(JNIEnv * env,DBusMessage * reply)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
set_object_array_element(JNIEnv * env,jobjectArray strArray,const char * value,int index)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
dbus_returns_array_of_object_path(JNIEnv * env,DBusMessage * reply)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
dbus_returns_array_of_strings(JNIEnv * env,DBusMessage * reply)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
dbus_returns_array_of_bytes(JNIEnv * env,DBusMessage * reply)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
append_variant(DBusMessageIter * iter,int type,void * val)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
get_property(DBusMessageIter iter,Properties * properties,int max_num_properties,int * prop_index,property_value * value,int * len)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
create_prop_array(JNIEnv * env,jobjectArray strArray,Properties * property,property_value * value,int len,int * array_index)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
parse_properties(JNIEnv * env,DBusMessageIter * iter,Properties * properties,const int max_num_properties)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
parse_property_change(JNIEnv * env,DBusMessage * msg,Properties * properties,int max_num_properties)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
parse_adapter_property_change(JNIEnv * env,DBusMessage * msg)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
parse_remote_device_property_change(JNIEnv * env,DBusMessage * msg)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
parse_adapter_properties(JNIEnv * env,DBusMessageIter * iter)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
parse_remote_device_properties(JNIEnv * env,DBusMessageIter * iter)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
get_bdaddr(const char * str,bdaddr_t * ba)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
get_bdaddr_as_string(const bdaddr_t * ba,char * str)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
debug_no_encrypt()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