blob: 6ae3e35c24dd03cc11c081fec1299fc9dd443f4d [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
36namespace android {
37
38#ifdef HAVE_BLUETOOTH
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070039
40static 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},
Jaikumar Ganesh14faa3b2011-03-30 14:04:42 -070046 {"Services", DBUS_TYPE_ARRAY},
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070047 {"Paired", DBUS_TYPE_BOOLEAN},
48 {"Connected", DBUS_TYPE_BOOLEAN},
49 {"Trusted", DBUS_TYPE_BOOLEAN},
Jaikumar Ganesh6eb300e2010-08-04 11:26:38 -070050 {"Blocked", DBUS_TYPE_BOOLEAN},
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070051 {"Alias", DBUS_TYPE_STRING},
52 {"Nodes", DBUS_TYPE_ARRAY},
53 {"Adapter", DBUS_TYPE_OBJECT_PATH},
54 {"LegacyPairing", DBUS_TYPE_BOOLEAN},
55 {"RSSI", DBUS_TYPE_INT16},
Jaikumar Ganesh14faa3b2011-03-30 14:04:42 -070056 {"TX", DBUS_TYPE_UINT32},
57 {"Broadcaster", DBUS_TYPE_BOOLEAN}
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070058};
59
60static Properties adapter_properties[] = {
61 {"Address", DBUS_TYPE_STRING},
62 {"Name", DBUS_TYPE_STRING},
63 {"Class", DBUS_TYPE_UINT32},
64 {"Powered", DBUS_TYPE_BOOLEAN},
65 {"Discoverable", DBUS_TYPE_BOOLEAN},
66 {"DiscoverableTimeout", DBUS_TYPE_UINT32},
67 {"Pairable", DBUS_TYPE_BOOLEAN},
68 {"PairableTimeout", DBUS_TYPE_UINT32},
69 {"Discovering", DBUS_TYPE_BOOLEAN},
70 {"Devices", DBUS_TYPE_ARRAY},
Jaikumar Ganesh94278c92010-05-03 15:45:58 -070071 {"UUIDs", DBUS_TYPE_ARRAY},
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070072};
73
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070074static Properties input_properties[] = {
75 {"Connected", DBUS_TYPE_BOOLEAN},
76};
77
Danica Chang6fdd0c62010-08-11 14:54:43 -070078static Properties pan_properties[] = {
79 {"Connected", DBUS_TYPE_BOOLEAN},
80 {"Interface", DBUS_TYPE_STRING},
81 {"UUID", DBUS_TYPE_STRING},
82};
83
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -070084typedef union {
85 char *str_val;
86 int int_val;
87 char **array_val;
88} property_value;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090jfieldID get_field(JNIEnv *env, jclass clazz, const char *member,
91 const char *mtype) {
92 jfieldID field = env->GetFieldID(clazz, member, mtype);
93 if (field == NULL) {
94 LOGE("Can't find member %s", member);
95 }
96 return field;
97}
98
99typedef struct {
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700100 void (*user_cb)(DBusMessage *, void *, void *);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 void *user;
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700102 void *nat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 JNIEnv *env;
104} dbus_async_call_t;
105
106void dbus_func_args_async_callback(DBusPendingCall *call, void *data) {
107
108 dbus_async_call_t *req = (dbus_async_call_t *)data;
109 DBusMessage *msg;
110
111 /* This is guaranteed to be non-NULL, because this function is called only
112 when once the remote method invokation returns. */
113 msg = dbus_pending_call_steal_reply(call);
114
115 if (msg) {
116 if (req->user_cb) {
117 // The user may not deref the message object.
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700118 req->user_cb(msg, req->user, req->nat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 }
120 dbus_message_unref(msg);
121 }
122
123 //dbus_message_unref(req->method);
124 dbus_pending_call_cancel(call);
125 dbus_pending_call_unref(call);
126 free(req);
127}
128
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700129static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 DBusConnection *conn,
131 int timeout_ms,
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700132 void (*user_cb)(DBusMessage *,
133 void *,
134 void*),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 void *user,
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700136 void *nat,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 const char *path,
138 const char *ifc,
139 const char *func,
140 int first_arg_type,
141 va_list args) {
142 DBusMessage *msg = NULL;
143 const char *name;
144 dbus_async_call_t *pending;
145 dbus_bool_t reply = FALSE;
146
147 /* Compose the command */
148 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
149
150 if (msg == NULL) {
151 LOGE("Could not allocate D-Bus message object!");
152 goto done;
153 }
154
155 /* append arguments */
156 if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
157 LOGE("Could not append argument to method call!");
158 goto done;
159 }
160
161 /* Make the call. */
162 pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t));
163 if (pending) {
164 DBusPendingCall *call;
165
166 pending->env = env;
167 pending->user_cb = user_cb;
168 pending->user = user;
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700169 pending->nat = nat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 //pending->method = msg;
171
172 reply = dbus_connection_send_with_reply(conn, msg,
173 &call,
174 timeout_ms);
175 if (reply == TRUE) {
176 dbus_pending_call_set_notify(call,
177 dbus_func_args_async_callback,
178 pending,
179 NULL);
180 }
181 }
182
183done:
184 if (msg) dbus_message_unref(msg);
185 return reply;
186}
187
188dbus_bool_t dbus_func_args_async(JNIEnv *env,
189 DBusConnection *conn,
190 int timeout_ms,
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700191 void (*reply)(DBusMessage *, void *, void*),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 void *user,
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700193 void *nat,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 const char *path,
195 const char *ifc,
196 const char *func,
197 int first_arg_type,
198 ...) {
199 dbus_bool_t ret;
200 va_list lst;
201 va_start(lst, first_arg_type);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 ret = dbus_func_args_async_valist(env, conn,
204 timeout_ms,
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700205 reply, user, nat,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 path, ifc, func,
207 first_arg_type, lst);
208 va_end(lst);
209 return ret;
210}
211
212// If err is NULL, then any errors will be LOGE'd, and free'd and the reply
213// will be NULL.
214// If err is not NULL, then it is assumed that dbus_error_init was already
215// called, and error's will be returned to the caller without logging. The
216// return value is NULL iff an error was set. The client must free the error if
217// set.
218DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env,
219 DBusConnection *conn,
220 int timeout_ms,
221 DBusError *err,
222 const char *path,
223 const char *ifc,
224 const char *func,
225 int first_arg_type,
226 va_list args) {
227
228 DBusMessage *msg = NULL, *reply = NULL;
229 const char *name;
230 bool return_error = (err != NULL);
231
232 if (!return_error) {
233 err = (DBusError*)malloc(sizeof(DBusError));
234 dbus_error_init(err);
235 }
236
237 /* Compose the command */
238 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
239
240 if (msg == NULL) {
241 LOGE("Could not allocate D-Bus message object!");
242 goto done;
243 }
244
245 /* append arguments */
246 if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
247 LOGE("Could not append argument to method call!");
248 goto done;
249 }
250
251 /* Make the call. */
252 reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err);
253 if (!return_error && dbus_error_is_set(err)) {
254 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg);
255 }
256
257done:
258 if (!return_error) {
259 free(err);
260 }
261 if (msg) dbus_message_unref(msg);
262 return reply;
263}
264
265DBusMessage * dbus_func_args_timeout(JNIEnv *env,
266 DBusConnection *conn,
267 int timeout_ms,
268 const char *path,
269 const char *ifc,
270 const char *func,
271 int first_arg_type,
272 ...) {
273 DBusMessage *ret;
274 va_list lst;
275 va_start(lst, first_arg_type);
276 ret = dbus_func_args_timeout_valist(env, conn, timeout_ms, NULL,
277 path, ifc, func,
278 first_arg_type, lst);
279 va_end(lst);
280 return ret;
281}
282
283DBusMessage * dbus_func_args(JNIEnv *env,
284 DBusConnection *conn,
285 const char *path,
286 const char *ifc,
287 const char *func,
288 int first_arg_type,
289 ...) {
290 DBusMessage *ret;
291 va_list lst;
292 va_start(lst, first_arg_type);
293 ret = dbus_func_args_timeout_valist(env, conn, -1, NULL,
294 path, ifc, func,
295 first_arg_type, lst);
296 va_end(lst);
297 return ret;
298}
299
300DBusMessage * dbus_func_args_error(JNIEnv *env,
301 DBusConnection *conn,
302 DBusError *err,
303 const char *path,
304 const char *ifc,
305 const char *func,
306 int first_arg_type,
307 ...) {
308 DBusMessage *ret;
309 va_list lst;
310 va_start(lst, first_arg_type);
311 ret = dbus_func_args_timeout_valist(env, conn, -1, err,
312 path, ifc, func,
313 first_arg_type, lst);
314 va_end(lst);
315 return ret;
316}
317
318jint dbus_returns_int32(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_INT32, &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
333jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply) {
334
335 DBusError err;
336 jint ret = -1;
337
338 dbus_error_init(&err);
339 if (!dbus_message_get_args(reply, &err,
340 DBUS_TYPE_UINT32, &ret,
341 DBUS_TYPE_INVALID)) {
342 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
343 }
344 dbus_message_unref(reply);
345 return ret;
346}
347
348jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply) {
349
350 DBusError err;
351 jstring ret = NULL;
352 const char *name;
353
354 dbus_error_init(&err);
355 if (dbus_message_get_args(reply, &err,
356 DBUS_TYPE_STRING, &name,
357 DBUS_TYPE_INVALID)) {
358 ret = env->NewStringUTF(name);
359 } else {
360 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
361 }
362 dbus_message_unref(reply);
363
364 return ret;
365}
366
367jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply) {
368 DBusError err;
369 jboolean ret = JNI_FALSE;
370 dbus_bool_t val = FALSE;
371
372 dbus_error_init(&err);
373
374 /* Check the return value. */
375 if (dbus_message_get_args(reply, &err,
376 DBUS_TYPE_BOOLEAN, &val,
377 DBUS_TYPE_INVALID)) {
378 ret = val == TRUE ? JNI_TRUE : JNI_FALSE;
379 } else {
380 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
381 }
382
383 dbus_message_unref(reply);
384 return ret;
385}
386
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700387static void set_object_array_element(JNIEnv *env, jobjectArray strArray,
388 const char *value, int index) {
389 jstring obj;
390 obj = env->NewStringUTF(value);
391 env->SetObjectArrayElement(strArray, index, obj);
392 env->DeleteLocalRef(obj);
393}
394
395jobjectArray dbus_returns_array_of_object_path(JNIEnv *env,
396 DBusMessage *reply) {
397
398 DBusError err;
399 char **list;
400 int i, len;
401 jobjectArray strArray = NULL;
402
403 dbus_error_init(&err);
404 if (dbus_message_get_args (reply,
405 &err,
406 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
407 &list, &len,
408 DBUS_TYPE_INVALID)) {
409 jclass stringClass;
410 jstring classNameStr;
411
412 stringClass = env->FindClass("java/lang/String");
413 strArray = env->NewObjectArray(len, stringClass, NULL);
414
415 for (i = 0; i < len; i++)
416 set_object_array_element(env, strArray, list[i], i);
417 } else {
418 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
419 }
420
421 dbus_message_unref(reply);
422 return strArray;
423}
424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply) {
426
427 DBusError err;
428 char **list;
429 int i, len;
430 jobjectArray strArray = NULL;
431
432 dbus_error_init(&err);
433 if (dbus_message_get_args (reply,
434 &err,
435 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
436 &list, &len,
437 DBUS_TYPE_INVALID)) {
438 jclass stringClass;
439 jstring classNameStr;
440
441 //LOGV("%s: there are %d elements in string array!", __FUNCTION__, len);
442
443 stringClass = env->FindClass("java/lang/String");
444 strArray = env->NewObjectArray(len, stringClass, NULL);
445
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700446 for (i = 0; i < len; i++)
447 set_object_array_element(env, strArray, list[i], i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 } else {
449 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
450 }
451
452 dbus_message_unref(reply);
453 return strArray;
454}
455
456jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply) {
457
458 DBusError err;
459 int i, len;
460 jbyte *list;
461 jbyteArray byteArray = NULL;
462
463 dbus_error_init(&err);
464 if (dbus_message_get_args(reply, &err,
465 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &list, &len,
466 DBUS_TYPE_INVALID)) {
467 //LOGV("%s: there are %d elements in byte array!", __FUNCTION__, len);
468 byteArray = env->NewByteArray(len);
469 if (byteArray)
470 env->SetByteArrayRegion(byteArray, 0, len, list);
471
472 } else {
473 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
474 }
475
476 dbus_message_unref(reply);
477 return byteArray;
478}
479
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700480void append_variant(DBusMessageIter *iter, int type, void *val)
481{
482 DBusMessageIter value_iter;
483 char var_type[2] = { type, '\0'};
484 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, var_type, &value_iter);
485 dbus_message_iter_append_basic(&value_iter, type, val);
486 dbus_message_iter_close_container(iter, &value_iter);
487}
488
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700489int get_property(DBusMessageIter iter, Properties *properties,
490 int max_num_properties, int *prop_index, property_value *value, int *len) {
491 DBusMessageIter prop_val, array_val_iter;
492 char *property = NULL;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700493 uint32_t array_type;
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700494 char *str_val;
495 int i, j, type, int_val;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700496
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700497 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700498 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700499 dbus_message_iter_get_basic(&iter, &property);
500 if (!dbus_message_iter_next(&iter))
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700501 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700502 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700503 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700504 for (i = 0; i < max_num_properties; i++) {
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700505 if (!strncmp(property, properties[i].name, strlen(property)))
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700506 break;
507 }
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700508 *prop_index = i;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700509 if (i == max_num_properties)
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700510 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700511
512 dbus_message_iter_recurse(&iter, &prop_val);
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700513 type = properties[*prop_index].type;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700514 if (dbus_message_iter_get_arg_type(&prop_val) != type) {
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700515 LOGE("Property type mismatch in get_property: %d, expected:%d, index:%d",
516 dbus_message_iter_get_arg_type(&prop_val), type, *prop_index);
517 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700518 }
519
520 switch(type) {
521 case DBUS_TYPE_STRING:
522 case DBUS_TYPE_OBJECT_PATH:
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700523 dbus_message_iter_get_basic(&prop_val, &value->str_val);
524 *len = 1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700525 break;
526 case DBUS_TYPE_UINT32:
527 case DBUS_TYPE_INT16:
528 case DBUS_TYPE_BOOLEAN:
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700529 dbus_message_iter_get_basic(&prop_val, &int_val);
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700530 value->int_val = int_val;
531 *len = 1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700532 break;
533 case DBUS_TYPE_ARRAY:
534 dbus_message_iter_recurse(&prop_val, &array_val_iter);
535 array_type = dbus_message_iter_get_arg_type(&array_val_iter);
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700536 *len = 0;
537 value->array_val = NULL;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700538 if (array_type == DBUS_TYPE_OBJECT_PATH ||
539 array_type == DBUS_TYPE_STRING){
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700540 j = 0;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700541 do {
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700542 j ++;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700543 } while(dbus_message_iter_next(&array_val_iter));
544 dbus_message_iter_recurse(&prop_val, &array_val_iter);
545 // Allocate an array of char *
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700546 *len = j;
547 char **tmp = (char **)malloc(sizeof(char *) * *len);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700548 if (!tmp)
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700549 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700550 j = 0;
551 do {
552 dbus_message_iter_get_basic(&array_val_iter, &tmp[j]);
553 j ++;
554 } while(dbus_message_iter_next(&array_val_iter));
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700555 value->array_val = tmp;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700556 }
557 break;
558 default:
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700559 return -1;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700560 }
Jaikumar Ganesh8bc8ce42009-06-24 16:42:51 -0700561 return 0;
562}
563
564void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property,
565 property_value *value, int len, int *array_index ) {
566 char **prop_val = NULL;
567 char buf[32] = {'\0'}, buf1[32] = {'\0'};
568 int i;
569
570 char *name = property->name;
571 int prop_type = property->type;
572
573 set_object_array_element(env, strArray, name, *array_index);
574 *array_index += 1;
575
576 if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) {
577 sprintf(buf, "%d", value->int_val);
578 set_object_array_element(env, strArray, buf, *array_index);
579 *array_index += 1;
580 } else if (prop_type == DBUS_TYPE_BOOLEAN) {
581 sprintf(buf, "%s", value->int_val ? "true" : "false");
582
583 set_object_array_element(env, strArray, buf, *array_index);
584 *array_index += 1;
585 } else if (prop_type == DBUS_TYPE_ARRAY) {
586 // Write the length first
587 sprintf(buf1, "%d", len);
588 set_object_array_element(env, strArray, buf1, *array_index);
589 *array_index += 1;
590
591 prop_val = value->array_val;
592 for (i = 0; i < len; i++) {
593 set_object_array_element(env, strArray, prop_val[i], *array_index);
594 *array_index += 1;
595 }
596 } else {
597 set_object_array_element(env, strArray, (const char *) value->str_val, *array_index);
598 *array_index += 1;
599 }
600}
601
602jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
603 const int max_num_properties) {
604 DBusMessageIter dict_entry, dict;
605 jobjectArray strArray = NULL;
606 property_value value;
607 int i, size = 0,array_index = 0;
608 int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type;
609 struct {
610 property_value value;
611 int len;
612 bool used;
613 } values[max_num_properties];
614 int t, j;
615
616 jclass stringClass = env->FindClass("java/lang/String");
617 DBusError err;
618 dbus_error_init(&err);
619
620 for (i = 0; i < max_num_properties; i++) {
621 values[i].used = false;
622 }
623
624 if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
625 goto failure;
626 dbus_message_iter_recurse(iter, &dict);
627 do {
628 len = 0;
629 if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY)
630 goto failure;
631 dbus_message_iter_recurse(&dict, &dict_entry);
632
633 if (!get_property(dict_entry, properties, max_num_properties, &prop_index,
634 &value, &len)) {
635 size += 2;
636 if (properties[prop_index].type == DBUS_TYPE_ARRAY)
637 size += len;
638 values[prop_index].value = value;
639 values[prop_index].len = len;
640 values[prop_index].used = true;
641 } else {
642 goto failure;
643 }
644 } while(dbus_message_iter_next(&dict));
645
646 strArray = env->NewObjectArray(size, stringClass, NULL);
647
648 for (i = 0; i < max_num_properties; i++) {
649 if (values[i].used) {
650 create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len,
651 &array_index);
652
653 if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used
654 && values[i].value.array_val != NULL)
655 free(values[i].value.array_val);
656 }
657
658 }
659 return strArray;
660
661failure:
662 if (dbus_error_is_set(&err))
663 LOG_AND_FREE_DBUS_ERROR(&err);
664 for (i = 0; i < max_num_properties; i++)
665 if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true
666 && values[i].value.array_val != NULL)
667 free(values[i].value.array_val);
668 return NULL;
669}
670
671jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg,
672 Properties *properties, int max_num_properties) {
673 DBusMessageIter iter;
674 DBusError err;
675 jobjectArray strArray = NULL;
676 jclass stringClass= env->FindClass("java/lang/String");
677 int len = 0, prop_index = -1;
678 int array_index = 0, size = 0;
679 property_value value;
680
681 dbus_error_init(&err);
682 if (!dbus_message_iter_init(msg, &iter))
683 goto failure;
684
685 if (!get_property(iter, properties, max_num_properties,
686 &prop_index, &value, &len)) {
687 size += 2;
688 if (properties[prop_index].type == DBUS_TYPE_ARRAY)
689 size += len;
690 strArray = env->NewObjectArray(size, stringClass, NULL);
691
692 create_prop_array(env, strArray, &properties[prop_index],
693 &value, len, &array_index);
694
695 if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL)
696 free(value.array_val);
697
698 return strArray;
699 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700700failure:
701 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
702 return NULL;
703}
704
705jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg) {
706 return parse_property_change(env, msg, (Properties *) &adapter_properties,
707 sizeof(adapter_properties) / sizeof(Properties));
708}
709
710jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg) {
711 return parse_property_change(env, msg, (Properties *) &remote_device_properties,
712 sizeof(remote_device_properties) / sizeof(Properties));
713}
714
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700715jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg) {
716 return parse_property_change(env, msg, (Properties *) &input_properties,
717 sizeof(input_properties) / sizeof(Properties));
718}
719
Danica Chang6fdd0c62010-08-11 14:54:43 -0700720jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg) {
721 return parse_property_change(env, msg, (Properties *) &pan_properties,
722 sizeof(pan_properties) / sizeof(Properties));
723}
724
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700725jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter) {
726 return parse_properties(env, iter, (Properties *) &adapter_properties,
727 sizeof(adapter_properties) / sizeof(Properties));
728}
729
730jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter) {
731 return parse_properties(env, iter, (Properties *) &remote_device_properties,
732 sizeof(remote_device_properties) / sizeof(Properties));
733}
734
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700735jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter) {
736 return parse_properties(env, iter, (Properties *) &input_properties,
737 sizeof(input_properties) / sizeof(Properties));
738}
739
Nick Pelly0b6955a2009-05-26 19:13:43 -0700740int get_bdaddr(const char *str, bdaddr_t *ba) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 char *d = ((char *)ba) + 5, *endp;
742 int i;
743 for(i = 0; i < 6; i++) {
744 *d-- = strtol(str, &endp, 16);
745 if (*endp != ':' && i != 5) {
746 memset(ba, 0, sizeof(bdaddr_t));
Nick Pelly0b6955a2009-05-26 19:13:43 -0700747 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 }
749 str = endp + 1;
750 }
Nick Pelly0b6955a2009-05-26 19:13:43 -0700751 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752}
753
754void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
755 const uint8_t *b = (const uint8_t *)ba;
756 sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
757 b[5], b[4], b[3], b[2], b[1], b[0]);
758}
759
760bool debug_no_encrypt() {
761 return false;
762#if 0
763 char value[PROPERTY_VALUE_MAX] = "";
764
765 property_get("debug.bt.no_encrypt", value, "");
766 if (!strncmp("true", value, PROPERTY_VALUE_MAX) ||
767 !strncmp("1", value, PROPERTY_VALUE_MAX)) {
768 LOGD("mandatory bluetooth encryption disabled");
769 return true;
770 } else {
771 return false;
772 }
773#endif
774}
775#endif
776
777} /* namespace android */