• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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