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