blob: 8a69ba4384603a55fe244e1cc97de958e466871c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2** Copyright 2008, 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 "BluetoothEventLoop.cpp"
18
19#include "android_bluetooth_common.h"
20#include "android_runtime/AndroidRuntime.h"
Robert Greenwalt28d139f2009-04-02 22:41:08 -070021#include "cutils/sockets.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include "JNIHelp.h"
23#include "jni.h"
24#include "utils/Log.h"
25#include "utils/misc.h"
26
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <errno.h>
31#include <unistd.h>
32
33#ifdef HAVE_BLUETOOTH
34#include <dbus/dbus.h>
35#endif
36
37namespace android {
38
Nick Pelly16fb88a2009-10-07 07:44:03 +020039#define CREATE_DEVICE_ALREADY_EXISTS 1
40#define CREATE_DEVICE_SUCCESS 0
41#define CREATE_DEVICE_FAILED -1
42
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043#ifdef HAVE_BLUETOOTH
44static jfieldID field_mNativeData;
45
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070046static jmethodID method_onPropertyChanged;
47static jmethodID method_onDevicePropertyChanged;
48static jmethodID method_onDeviceFound;
49static jmethodID method_onDeviceDisappeared;
50static jmethodID method_onDeviceCreated;
51static jmethodID method_onDeviceRemoved;
Jaikumar Ganesh5e59ca82009-09-11 12:16:19 -070052static jmethodID method_onDeviceDisconnectRequested;
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -070053static jmethodID method_onNetworkDeviceDisconnected;
54static jmethodID method_onNetworkDeviceConnected;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070056static jmethodID method_onCreatePairedDeviceResult;
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -070057static jmethodID method_onCreateDeviceResult;
58static jmethodID method_onDiscoverServicesResult;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070059static jmethodID method_onGetDeviceServiceChannelResult;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070061static jmethodID method_onRequestPinCode;
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -070062static jmethodID method_onRequestPasskey;
Jaikumar Ganesh32d85712009-09-10 22:00:05 -070063static jmethodID method_onRequestPasskeyConfirmation;
64static jmethodID method_onRequestPairingConsent;
65static jmethodID method_onDisplayPasskey;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070066static jmethodID method_onRequestOobData;
67static jmethodID method_onAgentOutOfBandDataAvailable;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070068static jmethodID method_onAgentAuthorize;
69static jmethodID method_onAgentCancel;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -070070
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070071static jmethodID method_onInputDevicePropertyChanged;
Jaikumar Ganeshde075032010-07-19 16:28:27 -070072static jmethodID method_onInputDeviceConnectionResult;
Danica Chang6fdd0c62010-08-11 14:54:43 -070073static jmethodID method_onPanDevicePropertyChanged;
74static jmethodID method_onPanDeviceConnectionResult;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -070075static jmethodID method_onHealthDevicePropertyChanged;
76static jmethodID method_onHealthDeviceChannelChanged;
Jaikumar Ganeshb5d2d452011-09-07 14:16:52 -070077static jmethodID method_onHealthDeviceConnectionResult;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -070078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079typedef event_loop_native_data_t native_data_t;
80
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -070081#define EVENT_LOOP_REFS 10
82
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
84 return (native_data_t *)(env->GetIntField(object,
85 field_mNativeData));
86}
87
Robert Greenwalt28d139f2009-04-02 22:41:08 -070088native_data_t *get_EventLoop_native_data(JNIEnv *env, jobject object) {
89 return get_native_data(env, object);
90}
91
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092#endif
93static void classInitNative(JNIEnv* env, jclass clazz) {
Steve Block71f2cf12011-10-20 11:56:00 +010094 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095
96#ifdef HAVE_BLUETOOTH
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -070097 method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged",
98 "([Ljava/lang/String;)V");
99 method_onDevicePropertyChanged = env->GetMethodID(clazz,
100 "onDevicePropertyChanged",
101 "(Ljava/lang/String;[Ljava/lang/String;)V");
102 method_onDeviceFound = env->GetMethodID(clazz, "onDeviceFound",
103 "(Ljava/lang/String;[Ljava/lang/String;)V");
104 method_onDeviceDisappeared = env->GetMethodID(clazz, "onDeviceDisappeared",
105 "(Ljava/lang/String;)V");
106 method_onDeviceCreated = env->GetMethodID(clazz, "onDeviceCreated", "(Ljava/lang/String;)V");
107 method_onDeviceRemoved = env->GetMethodID(clazz, "onDeviceRemoved", "(Ljava/lang/String;)V");
Jaikumar Ganesh5e59ca82009-09-11 12:16:19 -0700108 method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested",
109 "(Ljava/lang/String;)V");
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700110 method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected",
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700111 "(Ljava/lang/String;Ljava/lang/String;I)V");
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700112 method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected",
113 "(Ljava/lang/String;)V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700115 method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult",
116 "(Ljava/lang/String;I)V");
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -0700117 method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult",
Nick Pelly16fb88a2009-10-07 07:44:03 +0200118 "(Ljava/lang/String;I)V");
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -0700119 method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult",
120 "(Ljava/lang/String;Z)V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700122 method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize",
Matthew Xiea0c68032011-06-25 21:47:07 -0700123 "(Ljava/lang/String;Ljava/lang/String;I)V");
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -0700124 method_onAgentOutOfBandDataAvailable = env->GetMethodID(clazz, "onAgentOutOfBandDataAvailable",
125 "(Ljava/lang/String;)Z");
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700126 method_onAgentCancel = env->GetMethodID(clazz, "onAgentCancel", "()V");
127 method_onRequestPinCode = env->GetMethodID(clazz, "onRequestPinCode",
128 "(Ljava/lang/String;I)V");
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700129 method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey",
130 "(Ljava/lang/String;I)V");
Jaikumar Ganesh32d85712009-09-10 22:00:05 -0700131 method_onRequestPasskeyConfirmation = env->GetMethodID(clazz, "onRequestPasskeyConfirmation",
132 "(Ljava/lang/String;II)V");
133 method_onRequestPairingConsent = env->GetMethodID(clazz, "onRequestPairingConsent",
134 "(Ljava/lang/String;I)V");
135 method_onDisplayPasskey = env->GetMethodID(clazz, "onDisplayPasskey",
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -0700136 "(Ljava/lang/String;II)V");
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700137 method_onInputDevicePropertyChanged = env->GetMethodID(clazz, "onInputDevicePropertyChanged",
Danica Chang6fdd0c62010-08-11 14:54:43 -0700138 "(Ljava/lang/String;[Ljava/lang/String;)V");
Jaikumar Ganeshde075032010-07-19 16:28:27 -0700139 method_onInputDeviceConnectionResult = env->GetMethodID(clazz, "onInputDeviceConnectionResult",
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800140 "(Ljava/lang/String;I)V");
Danica Chang6fdd0c62010-08-11 14:54:43 -0700141 method_onPanDevicePropertyChanged = env->GetMethodID(clazz, "onPanDevicePropertyChanged",
142 "(Ljava/lang/String;[Ljava/lang/String;)V");
143 method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -0800144 "(Ljava/lang/String;I)V");
Jaikumar Ganeshb5d2d452011-09-07 14:16:52 -0700145 method_onHealthDeviceConnectionResult = env->GetMethodID(clazz,
146 "onHealthDeviceConnectionResult",
147 "(II)V");
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -0700148 method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged",
149 "(Ljava/lang/String;[Ljava/lang/String;)V");
150 method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged",
151 "(Ljava/lang/String;Ljava/lang/String;Z)V");
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -0700152 method_onRequestOobData = env->GetMethodID(clazz, "onRequestOobData",
153 "(Ljava/lang/String;I)V");
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
156#endif
157}
158
159static void initializeNativeDataNative(JNIEnv* env, jobject object) {
Steve Block71f2cf12011-10-20 11:56:00 +0100160 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161#ifdef HAVE_BLUETOOTH
162 native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
163 if (NULL == nat) {
Steve Block3762c312012-01-06 19:20:56 +0000164 ALOGE("%s: out of memory!", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 return;
166 }
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700167
168 pthread_mutex_init(&(nat->thread_mutex), NULL);
169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 env->SetIntField(object, field_mNativeData, (jint)nat);
171
172 {
173 DBusError err;
174 dbus_error_init(&err);
175 dbus_threads_init_default();
176 nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
177 if (dbus_error_is_set(&err)) {
Steve Block3762c312012-01-06 19:20:56 +0000178 ALOGE("%s: Could not get onto the system bus!", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 dbus_error_free(&err);
180 }
Nick Pelly9e0a1952009-06-17 15:27:59 -0700181 dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 }
183#endif
184}
185
186static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
Steve Block71f2cf12011-10-20 11:56:00 +0100187 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188#ifdef HAVE_BLUETOOTH
189 native_data_t *nat =
190 (native_data_t *)env->GetIntField(object, field_mNativeData);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700191
192 pthread_mutex_destroy(&(nat->thread_mutex));
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 if (nat) {
195 free(nat);
196 }
197#endif
198}
199
200#ifdef HAVE_BLUETOOTH
201static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
202 void *data);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700203DBusHandlerResult agent_event_filter(DBusConnection *conn,
204 DBusMessage *msg,
205 void *data);
206static int register_agent(native_data_t *nat,
207 const char *agent_path, const char *capabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208
209static const DBusObjectPathVTable agent_vtable = {
210 NULL, agent_event_filter, NULL, NULL, NULL, NULL
211};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212
Nick Pelly4a364132009-06-18 15:05:34 -0700213static unsigned int unix_events_to_dbus_flags(short events) {
214 return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
215 (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
216 (events & DBUS_WATCH_ERROR ? POLLERR : 0) |
217 (events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
218}
219
220static short dbus_flags_to_unix_events(unsigned int flags) {
221 return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) |
222 (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) |
223 (flags & POLLERR ? DBUS_WATCH_ERROR : 0) |
224 (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0);
225}
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700226
227static jboolean setUpEventLoop(native_data_t *nat) {
Steve Block71f2cf12011-10-20 11:56:00 +0100228 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 if (nat != NULL && nat->conn != NULL) {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700231 dbus_threads_init_default();
232 DBusError err;
233 dbus_error_init(&err);
234
hyungseoung.yoo5ec09722011-08-05 23:01:56 -0700235 const char *agent_path = "/android/bluetooth/agent";
236 const char *capabilities = "DisplayYesNo";
237 if (register_agent(nat, agent_path, capabilities) < 0) {
238 dbus_connection_unregister_object_path (nat->conn, agent_path);
239 return JNI_FALSE;
240 }
241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 // Add a filter for all incoming messages
243 if (!dbus_connection_add_filter(nat->conn, event_filter, nat, NULL)){
244 return JNI_FALSE;
245 }
246
247 // Set which messages will be processed by this dbus connection
248 dbus_bus_add_match(nat->conn,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700249 "type='signal',interface='org.freedesktop.DBus'",
250 &err);
251 if (dbus_error_is_set(&err)) {
252 LOG_AND_FREE_DBUS_ERROR(&err);
253 return JNI_FALSE;
254 }
255 dbus_bus_add_match(nat->conn,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'",
257 &err);
258 if (dbus_error_is_set(&err)) {
259 LOG_AND_FREE_DBUS_ERROR(&err);
260 return JNI_FALSE;
261 }
262 dbus_bus_add_match(nat->conn,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700263 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 &err);
265 if (dbus_error_is_set(&err)) {
266 LOG_AND_FREE_DBUS_ERROR(&err);
267 return JNI_FALSE;
268 }
269 dbus_bus_add_match(nat->conn,
Jaikumar Ganesh56d26132010-07-15 15:56:04 -0700270 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'",
271 &err);
272 if (dbus_error_is_set(&err)) {
273 LOG_AND_FREE_DBUS_ERROR(&err);
274 return JNI_FALSE;
275 }
276 dbus_bus_add_match(nat->conn,
277 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'",
278 &err);
279 if (dbus_error_is_set(&err)) {
280 LOG_AND_FREE_DBUS_ERROR(&err);
281 return JNI_FALSE;
282 }
283 dbus_bus_add_match(nat->conn,
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700284 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'",
285 &err);
286 if (dbus_error_is_set(&err)) {
287 LOG_AND_FREE_DBUS_ERROR(&err);
288 return JNI_FALSE;
289 }
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -0700290
291 dbus_bus_add_match(nat->conn,
292 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
293 &err);
294 if (dbus_error_is_set(&err)) {
295 LOG_AND_FREE_DBUS_ERROR(&err);
296 return JNI_FALSE;
297 }
298
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700299 dbus_bus_add_match(nat->conn,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700300 "type='signal',interface='org.bluez.AudioSink'",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 &err);
302 if (dbus_error_is_set(&err)) {
303 LOG_AND_FREE_DBUS_ERROR(&err);
304 return JNI_FALSE;
305 }
306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 return JNI_TRUE;
308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 return JNI_FALSE;
310}
311
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700312
313const char * get_adapter_path(DBusConnection *conn) {
Jaikumar Ganesh32d85712009-09-10 22:00:05 -0700314 DBusMessage *msg = NULL, *reply = NULL;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700315 DBusError err;
316 const char *device_path = NULL;
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700317 int attempt = 0;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700318
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700319 for (attempt = 0; attempt < 1000 && reply == NULL; attempt ++) {
320 msg = dbus_message_new_method_call("org.bluez", "/",
321 "org.bluez.Manager", "DefaultAdapter");
322 if (!msg) {
Steve Block3762c312012-01-06 19:20:56 +0000323 ALOGE("%s: Can't allocate new method call for get_adapter_path!",
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700324 __FUNCTION__);
325 return NULL;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700326 }
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700327 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
328 dbus_error_init(&err);
329 reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
330
331 if (!reply) {
332 if (dbus_error_is_set(&err)) {
333 if (dbus_error_has_name(&err,
334 "org.freedesktop.DBus.Error.ServiceUnknown")) {
335 // bluetoothd is still down, retry
336 LOG_AND_FREE_DBUS_ERROR(&err);
337 usleep(10000); // 10 ms
338 continue;
339 } else {
340 // Some other error we weren't expecting
341 LOG_AND_FREE_DBUS_ERROR(&err);
342 }
343 }
344 goto failed;
345 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700346 }
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700347 if (attempt == 1000) {
Steve Block3762c312012-01-06 19:20:56 +0000348 ALOGE("Time out while trying to get Adapter path, is bluetoothd up ?");
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700349 goto failed;
350 }
351
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700352 if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH,
353 &device_path, DBUS_TYPE_INVALID)
354 || !device_path){
355 if (dbus_error_is_set(&err)) {
356 LOG_AND_FREE_DBUS_ERROR(&err);
357 }
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700358 goto failed;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700359 }
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700360 dbus_message_unref(msg);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700361 return device_path;
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700362
363failed:
364 dbus_message_unref(msg);
365 return NULL;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700366}
367
368static int register_agent(native_data_t *nat,
369 const char * agent_path, const char * capabilities)
370{
371 DBusMessage *msg, *reply;
372 DBusError err;
Nicu Pavel75d14c32011-05-05 13:11:12 +0300373 dbus_bool_t oob = TRUE;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700374
375 if (!dbus_connection_register_object_path(nat->conn, agent_path,
376 &agent_vtable, nat)) {
Steve Block3762c312012-01-06 19:20:56 +0000377 ALOGE("%s: Can't register object path %s for agent!",
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700378 __FUNCTION__, agent_path);
379 return -1;
380 }
381
382 nat->adapter = get_adapter_path(nat->conn);
Jaikumar Ganesh176c3d62009-09-01 09:56:56 -0700383 if (nat->adapter == NULL) {
384 return -1;
385 }
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700386 msg = dbus_message_new_method_call("org.bluez", nat->adapter,
387 "org.bluez.Adapter", "RegisterAgent");
388 if (!msg) {
Steve Block3762c312012-01-06 19:20:56 +0000389 ALOGE("%s: Can't allocate new method call for agent!",
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700390 __FUNCTION__);
391 return -1;
392 }
393 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
394 DBUS_TYPE_STRING, &capabilities,
395 DBUS_TYPE_INVALID);
396
397 dbus_error_init(&err);
398 reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
399 dbus_message_unref(msg);
400
401 if (!reply) {
Steve Block3762c312012-01-06 19:20:56 +0000402 ALOGE("%s: Can't register agent!", __FUNCTION__);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700403 if (dbus_error_is_set(&err)) {
404 LOG_AND_FREE_DBUS_ERROR(&err);
405 }
406 return -1;
407 }
408
409 dbus_message_unref(reply);
410 dbus_connection_flush(nat->conn);
411
412 return 0;
413}
414
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700415static void tearDownEventLoop(native_data_t *nat) {
Steve Block71f2cf12011-10-20 11:56:00 +0100416 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 if (nat != NULL && nat->conn != NULL) {
418
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700419 DBusMessage *msg, *reply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 DBusError err;
421 dbus_error_init(&err);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700422 const char * agent_path = "/android/bluetooth/agent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700424 msg = dbus_message_new_method_call("org.bluez",
425 nat->adapter,
426 "org.bluez.Adapter",
427 "UnregisterAgent");
Jaikumar Ganesh9b0fe602009-06-11 15:10:45 -0700428 if (msg != NULL) {
429 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path,
430 DBUS_TYPE_INVALID);
431 reply = dbus_connection_send_with_reply_and_block(nat->conn,
432 msg, -1, &err);
433
434 if (!reply) {
435 if (dbus_error_is_set(&err)) {
436 LOG_AND_FREE_DBUS_ERROR(&err);
437 dbus_error_free(&err);
438 }
439 } else {
440 dbus_message_unref(reply);
441 }
442 dbus_message_unref(msg);
443 } else {
Steve Block3762c312012-01-06 19:20:56 +0000444 ALOGE("%s: Can't create new method call!", __FUNCTION__);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700447 dbus_connection_flush(nat->conn);
448 dbus_connection_unregister_object_path(nat->conn, agent_path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449
450 dbus_bus_remove_match(nat->conn,
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700451 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".AudioSink'",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 &err);
453 if (dbus_error_is_set(&err)) {
454 LOG_AND_FREE_DBUS_ERROR(&err);
455 }
456 dbus_bus_remove_match(nat->conn,
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700457 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'",
458 &err);
459 if (dbus_error_is_set(&err)) {
460 LOG_AND_FREE_DBUS_ERROR(&err);
461 }
462 dbus_bus_remove_match(nat->conn,
463 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'",
464 &err);
465 if (dbus_error_is_set(&err)) {
466 LOG_AND_FREE_DBUS_ERROR(&err);
467 }
468 dbus_bus_remove_match(nat->conn,
469 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'",
470 &err);
471 if (dbus_error_is_set(&err)) {
472 LOG_AND_FREE_DBUS_ERROR(&err);
473 }
474 dbus_bus_remove_match(nat->conn,
475 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 &err);
477 if (dbus_error_is_set(&err)) {
478 LOG_AND_FREE_DBUS_ERROR(&err);
479 }
480 dbus_bus_remove_match(nat->conn,
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -0700481 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
482 &err);
483 if (dbus_error_is_set(&err)) {
484 LOG_AND_FREE_DBUS_ERROR(&err);
485 }
486 dbus_bus_remove_match(nat->conn,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 "type='signal',interface='org.bluez.audio.Manager'",
488 &err);
489 if (dbus_error_is_set(&err)) {
490 LOG_AND_FREE_DBUS_ERROR(&err);
491 }
492 dbus_bus_remove_match(nat->conn,
493 "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'",
494 &err);
495 if (dbus_error_is_set(&err)) {
496 LOG_AND_FREE_DBUS_ERROR(&err);
497 }
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700498 dbus_bus_remove_match(nat->conn,
499 "type='signal',interface='org.freedesktop.DBus'",
500 &err);
501 if (dbus_error_is_set(&err)) {
502 LOG_AND_FREE_DBUS_ERROR(&err);
503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504
505 dbus_connection_remove_filter(nat->conn, event_filter, nat);
506 }
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700507}
508
509
510#define EVENT_LOOP_EXIT 1
511#define EVENT_LOOP_ADD 2
512#define EVENT_LOOP_REMOVE 3
Albert Mojirf4c64042011-06-20 16:14:13 +0200513#define EVENT_LOOP_WAKEUP 4
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700514
515dbus_bool_t dbusAddWatch(DBusWatch *watch, void *data) {
516 native_data_t *nat = (native_data_t *)data;
517
518 if (dbus_watch_get_enabled(watch)) {
519 // note that we can't just send the watch and inspect it later
520 // because we may get a removeWatch call before this data is reacted
521 // to by our eventloop and remove this watch.. reading the add first
522 // and then inspecting the recently deceased watch would be bad.
523 char control = EVENT_LOOP_ADD;
524 write(nat->controlFdW, &control, sizeof(char));
525
526 int fd = dbus_watch_get_fd(watch);
527 write(nat->controlFdW, &fd, sizeof(int));
528
529 unsigned int flags = dbus_watch_get_flags(watch);
530 write(nat->controlFdW, &flags, sizeof(unsigned int));
531
532 write(nat->controlFdW, &watch, sizeof(DBusWatch*));
533 }
534 return true;
535}
536
537void dbusRemoveWatch(DBusWatch *watch, void *data) {
538 native_data_t *nat = (native_data_t *)data;
539
540 char control = EVENT_LOOP_REMOVE;
541 write(nat->controlFdW, &control, sizeof(char));
542
543 int fd = dbus_watch_get_fd(watch);
544 write(nat->controlFdW, &fd, sizeof(int));
545
546 unsigned int flags = dbus_watch_get_flags(watch);
547 write(nat->controlFdW, &flags, sizeof(unsigned int));
548}
549
550void dbusToggleWatch(DBusWatch *watch, void *data) {
551 if (dbus_watch_get_enabled(watch)) {
552 dbusAddWatch(watch, data);
553 } else {
554 dbusRemoveWatch(watch, data);
555 }
556}
557
Albert Mojirf4c64042011-06-20 16:14:13 +0200558void dbusWakeup(void *data) {
559 native_data_t *nat = (native_data_t *)data;
560
561 char control = EVENT_LOOP_WAKEUP;
562 write(nat->controlFdW, &control, sizeof(char));
563}
564
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700565static void handleWatchAdd(native_data_t *nat) {
566 DBusWatch *watch;
567 int newFD;
568 unsigned int flags;
569
570 read(nat->controlFdR, &newFD, sizeof(int));
571 read(nat->controlFdR, &flags, sizeof(unsigned int));
572 read(nat->controlFdR, &watch, sizeof(DBusWatch *));
Nick Pelly4a364132009-06-18 15:05:34 -0700573 short events = dbus_flags_to_unix_events(flags);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700574
575 for (int y = 0; y<nat->pollMemberCount; y++) {
576 if ((nat->pollData[y].fd == newFD) &&
577 (nat->pollData[y].events == events)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100578 ALOGV("DBusWatch duplicate add");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700579 return;
580 }
581 }
582 if (nat->pollMemberCount == nat->pollDataSize) {
Steve Block71f2cf12011-10-20 11:56:00 +0100583 ALOGV("Bluetooth EventLoop poll struct growing");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700584 struct pollfd *temp = (struct pollfd *)malloc(
585 sizeof(struct pollfd) * (nat->pollMemberCount+1));
586 if (!temp) {
587 return;
588 }
589 memcpy(temp, nat->pollData, sizeof(struct pollfd) *
590 nat->pollMemberCount);
591 free(nat->pollData);
592 nat->pollData = temp;
593 DBusWatch **temp2 = (DBusWatch **)malloc(sizeof(DBusWatch *) *
594 (nat->pollMemberCount+1));
595 if (!temp2) {
596 return;
597 }
598 memcpy(temp2, nat->watchData, sizeof(DBusWatch *) *
599 nat->pollMemberCount);
600 free(nat->watchData);
601 nat->watchData = temp2;
602 nat->pollDataSize++;
603 }
604 nat->pollData[nat->pollMemberCount].fd = newFD;
605 nat->pollData[nat->pollMemberCount].revents = 0;
606 nat->pollData[nat->pollMemberCount].events = events;
607 nat->watchData[nat->pollMemberCount] = watch;
608 nat->pollMemberCount++;
609}
610
611static void handleWatchRemove(native_data_t *nat) {
612 int removeFD;
613 unsigned int flags;
614
615 read(nat->controlFdR, &removeFD, sizeof(int));
616 read(nat->controlFdR, &flags, sizeof(unsigned int));
Nick Pelly4a364132009-06-18 15:05:34 -0700617 short events = dbus_flags_to_unix_events(flags);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700618
619 for (int y = 0; y < nat->pollMemberCount; y++) {
620 if ((nat->pollData[y].fd == removeFD) &&
621 (nat->pollData[y].events == events)) {
622 int newCount = --nat->pollMemberCount;
623 // copy the last live member over this one
624 nat->pollData[y].fd = nat->pollData[newCount].fd;
625 nat->pollData[y].events = nat->pollData[newCount].events;
626 nat->pollData[y].revents = nat->pollData[newCount].revents;
627 nat->watchData[y] = nat->watchData[newCount];
628 return;
629 }
630 }
Steve Block8564c8d2012-01-05 23:22:43 +0000631 ALOGW("WatchRemove given with unknown watch");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700632}
633
634static void *eventLoopMain(void *ptr) {
635 native_data_t *nat = (native_data_t *)ptr;
636 JNIEnv *env;
637
638 JavaVMAttachArgs args;
639 char name[] = "BT EventLoop";
640 args.version = nat->envVer;
641 args.name = name;
642 args.group = NULL;
643
644 nat->vm->AttachCurrentThread(&env, &args);
645
646 dbus_connection_set_watch_functions(nat->conn, dbusAddWatch,
647 dbusRemoveWatch, dbusToggleWatch, ptr, NULL);
Albert Mojirf4c64042011-06-20 16:14:13 +0200648 dbus_connection_set_wakeup_main_function(nat->conn, dbusWakeup, ptr, NULL);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700649
Jaikumar Ganeshb8aa0372010-03-31 11:23:49 -0700650 nat->running = true;
651
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700652 while (1) {
653 for (int i = 0; i < nat->pollMemberCount; i++) {
654 if (!nat->pollData[i].revents) {
655 continue;
656 }
657 if (nat->pollData[i].fd == nat->controlFdR) {
658 char data;
659 while (recv(nat->controlFdR, &data, sizeof(char), MSG_DONTWAIT)
660 != -1) {
661 switch (data) {
662 case EVENT_LOOP_EXIT:
663 {
664 dbus_connection_set_watch_functions(nat->conn,
665 NULL, NULL, NULL, NULL, NULL);
666 tearDownEventLoop(nat);
667 nat->vm->DetachCurrentThread();
Johannes Carlssoned0d1ab2010-03-08 10:19:31 +0100668
669 int fd = nat->controlFdR;
670 nat->controlFdR = 0;
671 close(fd);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700672 return NULL;
673 }
674 case EVENT_LOOP_ADD:
675 {
676 handleWatchAdd(nat);
677 break;
678 }
679 case EVENT_LOOP_REMOVE:
680 {
681 handleWatchRemove(nat);
682 break;
683 }
Albert Mojirf4c64042011-06-20 16:14:13 +0200684 case EVENT_LOOP_WAKEUP:
685 {
686 // noop
687 break;
688 }
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700689 }
690 }
691 } else {
Nick Pelly4a364132009-06-18 15:05:34 -0700692 short events = nat->pollData[i].revents;
693 unsigned int flags = unix_events_to_dbus_flags(events);
694 dbus_watch_handle(nat->watchData[i], flags);
695 nat->pollData[i].revents = 0;
696 // can only do one - it may have caused a 'remove'
697 break;
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700698 }
699 }
Jaikumar Ganeshb8aa0372010-03-31 11:23:49 -0700700 while (dbus_connection_dispatch(nat->conn) ==
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700701 DBUS_DISPATCH_DATA_REMAINS) {
702 }
703
704 poll(nat->pollData, nat->pollMemberCount, -1);
705 }
706}
707#endif // HAVE_BLUETOOTH
708
709static jboolean startEventLoopNative(JNIEnv *env, jobject object) {
710 jboolean result = JNI_FALSE;
711#ifdef HAVE_BLUETOOTH
712 event_loop_native_data_t *nat = get_native_data(env, object);
713
714 pthread_mutex_lock(&(nat->thread_mutex));
715
Jaikumar Ganeshb8aa0372010-03-31 11:23:49 -0700716 nat->running = false;
717
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700718 if (nat->pollData) {
Steve Block8564c8d2012-01-05 23:22:43 +0000719 ALOGW("trying to start EventLoop a second time!");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700720 pthread_mutex_unlock( &(nat->thread_mutex) );
721 return JNI_FALSE;
722 }
723
Iliyan Malchev8d25cb82012-02-17 12:16:49 -0800724 nat->pollData = (struct pollfd *)calloc(
725 DEFAULT_INITIAL_POLLFD_COUNT, sizeof(struct pollfd));
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700726 if (!nat->pollData) {
Steve Block3762c312012-01-06 19:20:56 +0000727 ALOGE("out of memory error starting EventLoop!");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700728 goto done;
729 }
730
Iliyan Malchev8d25cb82012-02-17 12:16:49 -0800731 nat->watchData = (DBusWatch **)calloc(
732 DEFAULT_INITIAL_POLLFD_COUNT, sizeof(DBusWatch *));
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700733 if (!nat->watchData) {
Steve Block3762c312012-01-06 19:20:56 +0000734 ALOGE("out of memory error starting EventLoop!");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700735 goto done;
736 }
737
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700738 nat->pollDataSize = DEFAULT_INITIAL_POLLFD_COUNT;
739 nat->pollMemberCount = 1;
740
741 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(nat->controlFdR))) {
Steve Block3762c312012-01-06 19:20:56 +0000742 ALOGE("Error getting BT control socket");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700743 goto done;
744 }
745 nat->pollData[0].fd = nat->controlFdR;
746 nat->pollData[0].events = POLLIN;
747
748 env->GetJavaVM( &(nat->vm) );
749 nat->envVer = env->GetVersion();
750
751 nat->me = env->NewGlobalRef(object);
752
753 if (setUpEventLoop(nat) != JNI_TRUE) {
Steve Block3762c312012-01-06 19:20:56 +0000754 ALOGE("failure setting up Event Loop!");
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700755 goto done;
756 }
757
758 pthread_create(&(nat->thread), NULL, eventLoopMain, nat);
759 result = JNI_TRUE;
760
761done:
762 if (JNI_FALSE == result) {
Johannes Carlssoned0d1ab2010-03-08 10:19:31 +0100763 if (nat->controlFdW) {
764 close(nat->controlFdW);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700765 nat->controlFdW = 0;
Johannes Carlssoned0d1ab2010-03-08 10:19:31 +0100766 }
767 if (nat->controlFdR) {
768 close(nat->controlFdR);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700769 nat->controlFdR = 0;
770 }
771 if (nat->me) env->DeleteGlobalRef(nat->me);
772 nat->me = NULL;
773 if (nat->pollData) free(nat->pollData);
774 nat->pollData = NULL;
775 if (nat->watchData) free(nat->watchData);
776 nat->watchData = NULL;
777 nat->pollDataSize = 0;
778 nat->pollMemberCount = 0;
779 }
780
781 pthread_mutex_unlock(&(nat->thread_mutex));
782#endif // HAVE_BLUETOOTH
783 return result;
784}
785
786static void stopEventLoopNative(JNIEnv *env, jobject object) {
787#ifdef HAVE_BLUETOOTH
788 native_data_t *nat = get_native_data(env, object);
789
790 pthread_mutex_lock(&(nat->thread_mutex));
791 if (nat->pollData) {
792 char data = EVENT_LOOP_EXIT;
793 ssize_t t = write(nat->controlFdW, &data, sizeof(char));
794 void *ret;
795 pthread_join(nat->thread, &ret);
796
797 env->DeleteGlobalRef(nat->me);
798 nat->me = NULL;
799 free(nat->pollData);
800 nat->pollData = NULL;
801 free(nat->watchData);
802 nat->watchData = NULL;
803 nat->pollDataSize = 0;
804 nat->pollMemberCount = 0;
Johannes Carlssoned0d1ab2010-03-08 10:19:31 +0100805
806 int fd = nat->controlFdW;
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700807 nat->controlFdW = 0;
Johannes Carlssoned0d1ab2010-03-08 10:19:31 +0100808 close(fd);
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700809 }
Jaikumar Ganeshb8aa0372010-03-31 11:23:49 -0700810 nat->running = false;
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700811 pthread_mutex_unlock(&(nat->thread_mutex));
812#endif // HAVE_BLUETOOTH
813}
814
815static jboolean isEventLoopRunningNative(JNIEnv *env, jobject object) {
816 jboolean result = JNI_FALSE;
817#ifdef HAVE_BLUETOOTH
818 native_data_t *nat = get_native_data(env, object);
819
820 pthread_mutex_lock(&(nat->thread_mutex));
Jaikumar Ganeshb8aa0372010-03-31 11:23:49 -0700821 if (nat->running) {
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700822 result = JNI_TRUE;
823 }
824 pthread_mutex_unlock(&(nat->thread_mutex));
825
826#endif // HAVE_BLUETOOTH
827 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828}
829
830#ifdef HAVE_BLUETOOTH
831extern DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env);
832
833// Called by dbus during WaitForAndDispatchEventNative()
834static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
835 void *data) {
836 native_data_t *nat;
837 JNIEnv *env;
838 DBusError err;
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700839 DBusHandlerResult ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840
841 dbus_error_init(&err);
842
843 nat = (native_data_t *)data;
Robert Greenwalt28d139f2009-04-02 22:41:08 -0700844 nat->vm->GetEnv((void**)&env, nat->envVer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100846 ALOGV("%s: not interested (not a signal).", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
848 }
849
Steve Block71f2cf12011-10-20 11:56:00 +0100850 ALOGV("%s: Received signal %s:%s from %s", __FUNCTION__,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700851 dbus_message_get_interface(msg), dbus_message_get_member(msg),
852 dbus_message_get_path(msg));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700854 env->PushLocalFrame(EVENT_LOOP_REFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 if (dbus_message_is_signal(msg,
856 "org.bluez.Adapter",
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700857 "DeviceFound")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 char *c_address;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700859 DBusMessageIter iter;
860 jobjectArray str_array = NULL;
861 if (dbus_message_iter_init(msg, &iter)) {
862 dbus_message_iter_get_basic(&iter, &c_address);
863 if (dbus_message_iter_next(&iter))
864 str_array =
865 parse_remote_device_properties(env, &iter);
866 }
867 if (str_array != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 env->CallVoidMethod(nat->me,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700869 method_onDeviceFound,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 env->NewStringUTF(c_address),
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700871 str_array);
872 } else
873 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700874 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 } else if (dbus_message_is_signal(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700876 "org.bluez.Adapter",
877 "DeviceDisappeared")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 char *c_address;
879 if (dbus_message_get_args(msg, &err,
880 DBUS_TYPE_STRING, &c_address,
881 DBUS_TYPE_INVALID)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100882 ALOGV("... address = %s", c_address);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700883 env->CallVoidMethod(nat->me, method_onDeviceDisappeared,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 env->NewStringUTF(c_address));
885 } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700886 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 } else if (dbus_message_is_signal(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700888 "org.bluez.Adapter",
889 "DeviceCreated")) {
890 char *c_object_path;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 if (dbus_message_get_args(msg, &err,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700892 DBUS_TYPE_OBJECT_PATH, &c_object_path,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 DBUS_TYPE_INVALID)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100894 ALOGV("... address = %s", c_object_path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 env->CallVoidMethod(nat->me,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700896 method_onDeviceCreated,
897 env->NewStringUTF(c_object_path));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700899 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 } else if (dbus_message_is_signal(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700901 "org.bluez.Adapter",
902 "DeviceRemoved")) {
903 char *c_object_path;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 if (dbus_message_get_args(msg, &err,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700905 DBUS_TYPE_OBJECT_PATH, &c_object_path,
906 DBUS_TYPE_INVALID)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100907 ALOGV("... Object Path = %s", c_object_path);
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700908 env->CallVoidMethod(nat->me,
909 method_onDeviceRemoved,
910 env->NewStringUTF(c_object_path));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700912 goto success;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700913 } else if (dbus_message_is_signal(msg,
914 "org.bluez.Adapter",
915 "PropertyChanged")) {
916 jobjectArray str_array = parse_adapter_property_change(env, msg);
917 if (str_array != NULL) {
918 /* Check if bluetoothd has (re)started, if so update the path. */
919 jstring property =(jstring) env->GetObjectArrayElement(str_array, 0);
920 const char *c_property = env->GetStringUTFChars(property, NULL);
921 if (!strncmp(c_property, "Powered", strlen("Powered"))) {
922 jstring value =
923 (jstring) env->GetObjectArrayElement(str_array, 1);
924 const char *c_value = env->GetStringUTFChars(value, NULL);
925 if (!strncmp(c_value, "true", strlen("true")))
926 nat->adapter = get_adapter_path(nat->conn);
927 env->ReleaseStringUTFChars(value, c_value);
928 }
929 env->ReleaseStringUTFChars(property, c_property);
930
931 env->CallVoidMethod(nat->me,
932 method_onPropertyChanged,
933 str_array);
934 } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700935 goto success;
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -0700936 } else if (dbus_message_is_signal(msg,
937 "org.bluez.Device",
938 "PropertyChanged")) {
939 jobjectArray str_array = parse_remote_device_property_change(env, msg);
940 if (str_array != NULL) {
941 const char *remote_device_path = dbus_message_get_path(msg);
942 env->CallVoidMethod(nat->me,
943 method_onDevicePropertyChanged,
944 env->NewStringUTF(remote_device_path),
945 str_array);
946 } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -0700947 goto success;
Jaikumar Ganesh5e59ca82009-09-11 12:16:19 -0700948 } else if (dbus_message_is_signal(msg,
949 "org.bluez.Device",
950 "DisconnectRequested")) {
951 const char *remote_device_path = dbus_message_get_path(msg);
952 env->CallVoidMethod(nat->me,
953 method_onDeviceDisconnectRequested,
954 env->NewStringUTF(remote_device_path));
955 goto success;
Jaikumar Ganesh545e6702010-06-04 10:23:03 -0700956 } else if (dbus_message_is_signal(msg,
957 "org.bluez.Input",
958 "PropertyChanged")) {
959
960 jobjectArray str_array =
961 parse_input_property_change(env, msg);
962 if (str_array != NULL) {
963 const char *c_path = dbus_message_get_path(msg);
964 env->CallVoidMethod(nat->me,
965 method_onInputDevicePropertyChanged,
966 env->NewStringUTF(c_path),
967 str_array);
968 } else {
969 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
970 }
971 goto success;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700972 } else if (dbus_message_is_signal(msg,
973 "org.bluez.Network",
974 "PropertyChanged")) {
975
976 jobjectArray str_array =
977 parse_pan_property_change(env, msg);
978 if (str_array != NULL) {
979 const char *c_path = dbus_message_get_path(msg);
980 env->CallVoidMethod(nat->me,
981 method_onPanDevicePropertyChanged,
982 env->NewStringUTF(c_path),
983 str_array);
984 } else {
985 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
986 }
987 goto success;
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -0700988 } else if (dbus_message_is_signal(msg,
989 "org.bluez.NetworkServer",
990 "DeviceDisconnected")) {
991 char *c_address;
992 if (dbus_message_get_args(msg, &err,
993 DBUS_TYPE_STRING, &c_address,
994 DBUS_TYPE_INVALID)) {
995 env->CallVoidMethod(nat->me,
996 method_onNetworkDeviceDisconnected,
997 env->NewStringUTF(c_address));
998 } else {
999 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
1000 }
1001 goto success;
1002 } else if (dbus_message_is_signal(msg,
1003 "org.bluez.NetworkServer",
1004 "DeviceConnected")) {
1005 char *c_address;
Jaikumar Ganesh707952e2010-09-13 19:04:54 -07001006 char *c_iface;
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -07001007 uint16_t uuid;
1008
1009 if (dbus_message_get_args(msg, &err,
1010 DBUS_TYPE_STRING, &c_address,
Jaikumar Ganesh707952e2010-09-13 19:04:54 -07001011 DBUS_TYPE_STRING, &c_iface,
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -07001012 DBUS_TYPE_UINT16, &uuid,
1013 DBUS_TYPE_INVALID)) {
1014 env->CallVoidMethod(nat->me,
1015 method_onNetworkDeviceConnected,
1016 env->NewStringUTF(c_address),
Jaikumar Ganesh707952e2010-09-13 19:04:54 -07001017 env->NewStringUTF(c_iface),
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -07001018 uuid);
1019 } else {
1020 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
1021 }
1022 goto success;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07001023 } else if (dbus_message_is_signal(msg,
1024 "org.bluez.HealthDevice",
1025 "ChannelConnected")) {
1026 const char *c_path = dbus_message_get_path(msg);
1027 const char *c_channel_path;
1028 jboolean exists = JNI_TRUE;
1029 if (dbus_message_get_args(msg, &err,
1030 DBUS_TYPE_OBJECT_PATH, &c_channel_path,
1031 DBUS_TYPE_INVALID)) {
1032 env->CallVoidMethod(nat->me,
1033 method_onHealthDeviceChannelChanged,
1034 env->NewStringUTF(c_path),
1035 env->NewStringUTF(c_channel_path),
1036 exists);
1037 } else {
1038 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
1039 }
1040 goto success;
1041 } else if (dbus_message_is_signal(msg,
Jaikumar Ganeshae37d062011-08-20 18:15:16 -07001042 "org.bluez.HealthDevice",
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07001043 "ChannelDeleted")) {
1044
1045 const char *c_path = dbus_message_get_path(msg);
1046 const char *c_channel_path;
1047 jboolean exists = JNI_FALSE;
1048 if (dbus_message_get_args(msg, &err,
1049 DBUS_TYPE_OBJECT_PATH, &c_channel_path,
1050 DBUS_TYPE_INVALID)) {
1051 env->CallVoidMethod(nat->me,
1052 method_onHealthDeviceChannelChanged,
1053 env->NewStringUTF(c_path),
1054 env->NewStringUTF(c_channel_path),
1055 exists);
1056 } else {
1057 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
1058 }
1059 goto success;
1060 } else if (dbus_message_is_signal(msg,
1061 "org.bluez.HealthDevice",
1062 "PropertyChanged")) {
1063 jobjectArray str_array =
1064 parse_health_device_property_change(env, msg);
1065 if (str_array != NULL) {
1066 const char *c_path = dbus_message_get_path(msg);
1067 env->CallVoidMethod(nat->me,
1068 method_onHealthDevicePropertyChanged,
1069 env->NewStringUTF(c_path),
1070 str_array);
1071 } else {
1072 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
1073 }
1074 goto success;
Jaikumar Ganeshc1520ec2010-08-31 19:55:10 -07001075 }
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001076
1077 ret = a2dp_event_filter(msg, env);
1078 env->PopLocalFrame(NULL);
1079 return ret;
1080
1081success:
1082 env->PopLocalFrame(NULL);
1083 return DBUS_HANDLER_RESULT_HANDLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084}
1085
1086// Called by dbus during WaitForAndDispatchEventNative()
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001087DBusHandlerResult agent_event_filter(DBusConnection *conn,
1088 DBusMessage *msg, void *data) {
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001089 native_data_t *nat = (native_data_t *)data;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 JNIEnv *env;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
Steve Block71f2cf12011-10-20 11:56:00 +01001092 ALOGV("%s: not interested (not a method call).", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1094 }
Steve Block6215d3f2012-01-04 20:05:49 +00001095 ALOGI("%s: Received method %s:%s", __FUNCTION__,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 dbus_message_get_interface(msg), dbus_message_get_member(msg));
1097
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001098 if (nat == NULL) return DBUS_HANDLER_RESULT_HANDLED;
1099
1100 nat->vm->GetEnv((void**)&env, nat->envVer);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001101 env->PushLocalFrame(EVENT_LOOP_REFS);
1102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (dbus_message_is_method_call(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001104 "org.bluez.Agent", "Cancel")) {
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001105 env->CallVoidMethod(nat->me, method_onAgentCancel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 // reply
1107 DBusMessage *reply = dbus_message_new_method_return(msg);
1108 if (!reply) {
Steve Block3762c312012-01-06 19:20:56 +00001109 ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001110 goto failure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 }
1112 dbus_connection_send(nat->conn, reply, NULL);
1113 dbus_message_unref(reply);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001114 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115
1116 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001117 "org.bluez.Agent", "Authorize")) {
1118 char *object_path;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 const char *uuid;
1120 if (!dbus_message_get_args(msg, NULL,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001121 DBUS_TYPE_OBJECT_PATH, &object_path,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 DBUS_TYPE_STRING, &uuid,
1123 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001124 ALOGE("%s: Invalid arguments for Authorize() method", __FUNCTION__);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001125 goto failure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 }
1127
Steve Block71f2cf12011-10-20 11:56:00 +01001128 ALOGV("... object_path = %s", object_path);
1129 ALOGV("... uuid = %s", uuid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130
Matthew Xiea0c68032011-06-25 21:47:07 -07001131 dbus_message_ref(msg); // increment refcount because we pass to java
Jeff Brown14fcf902011-07-14 03:54:36 -07001132 env->CallVoidMethod(nat->me, method_onAgentAuthorize,
Matthew Xiea0c68032011-06-25 21:47:07 -07001133 env->NewStringUTF(object_path), env->NewStringUTF(uuid),
1134 int(msg));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001136 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001138 "org.bluez.Agent", "OutOfBandAvailable")) {
1139 char *object_path;
1140 if (!dbus_message_get_args(msg, NULL,
1141 DBUS_TYPE_OBJECT_PATH, &object_path,
1142 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001143 ALOGE("%s: Invalid arguments for OutOfBandData available() method", __FUNCTION__);
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001144 goto failure;
1145 }
1146
Steve Block71f2cf12011-10-20 11:56:00 +01001147 ALOGV("... object_path = %s", object_path);
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001148
1149 bool available =
1150 env->CallBooleanMethod(nat->me, method_onAgentOutOfBandDataAvailable,
1151 env->NewStringUTF(object_path));
1152
1153
1154 // reply
1155 if (available) {
1156 DBusMessage *reply = dbus_message_new_method_return(msg);
1157 if (!reply) {
Steve Block3762c312012-01-06 19:20:56 +00001158 ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001159 goto failure;
1160 }
1161 dbus_connection_send(nat->conn, reply, NULL);
1162 dbus_message_unref(reply);
1163 } else {
1164 DBusMessage *reply = dbus_message_new_error(msg,
1165 "org.bluez.Error.DoesNotExist", "OutofBand data not available");
1166 if (!reply) {
Steve Block3762c312012-01-06 19:20:56 +00001167 ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001168 goto failure;
1169 }
1170 dbus_connection_send(nat->conn, reply, NULL);
1171 dbus_message_unref(reply);
1172 }
1173 goto success;
1174 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001175 "org.bluez.Agent", "RequestPinCode")) {
1176 char *object_path;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 if (!dbus_message_get_args(msg, NULL,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001178 DBUS_TYPE_OBJECT_PATH, &object_path,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001180 ALOGE("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001181 goto failure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 }
1183
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001184 dbus_message_ref(msg); // increment refcount because we pass to java
1185 env->CallVoidMethod(nat->me, method_onRequestPinCode,
1186 env->NewStringUTF(object_path),
1187 int(msg));
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001188 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001190 "org.bluez.Agent", "RequestPasskey")) {
1191 char *object_path;
1192 if (!dbus_message_get_args(msg, NULL,
1193 DBUS_TYPE_OBJECT_PATH, &object_path,
1194 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001195 ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001196 goto failure;
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001197 }
1198
1199 dbus_message_ref(msg); // increment refcount because we pass to java
1200 env->CallVoidMethod(nat->me, method_onRequestPasskey,
1201 env->NewStringUTF(object_path),
1202 int(msg));
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001203 goto success;
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001204 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001205 "org.bluez.Agent", "RequestOobData")) {
1206 char *object_path;
1207 if (!dbus_message_get_args(msg, NULL,
1208 DBUS_TYPE_OBJECT_PATH, &object_path,
1209 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001210 ALOGE("%s: Invalid arguments for RequestOobData() method", __FUNCTION__);
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07001211 goto failure;
1212 }
1213
1214 dbus_message_ref(msg); // increment refcount because we pass to java
1215 env->CallVoidMethod(nat->me, method_onRequestOobData,
1216 env->NewStringUTF(object_path),
1217 int(msg));
1218 goto success;
1219 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001220 "org.bluez.Agent", "DisplayPasskey")) {
1221 char *object_path;
1222 uint32_t passkey;
1223 if (!dbus_message_get_args(msg, NULL,
1224 DBUS_TYPE_OBJECT_PATH, &object_path,
1225 DBUS_TYPE_UINT32, &passkey,
1226 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001227 ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001228 goto failure;
1229 }
1230
1231 dbus_message_ref(msg); // increment refcount because we pass to java
1232 env->CallVoidMethod(nat->me, method_onDisplayPasskey,
1233 env->NewStringUTF(object_path),
1234 passkey,
1235 int(msg));
1236 goto success;
1237 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001238 "org.bluez.Agent", "RequestConfirmation")) {
1239 char *object_path;
1240 uint32_t passkey;
1241 if (!dbus_message_get_args(msg, NULL,
1242 DBUS_TYPE_OBJECT_PATH, &object_path,
1243 DBUS_TYPE_UINT32, &passkey,
1244 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001245 ALOGE("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001246 goto failure;
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001247 }
1248
1249 dbus_message_ref(msg); // increment refcount because we pass to java
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001250 env->CallVoidMethod(nat->me, method_onRequestPasskeyConfirmation,
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001251 env->NewStringUTF(object_path),
1252 passkey,
1253 int(msg));
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001254 goto success;
Jaikumar Ganeshb0eca412009-07-16 18:26:28 -07001255 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001256 "org.bluez.Agent", "RequestPairingConsent")) {
1257 char *object_path;
1258 if (!dbus_message_get_args(msg, NULL,
1259 DBUS_TYPE_OBJECT_PATH, &object_path,
1260 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001261 ALOGE("%s: Invalid arguments for RequestPairingConsent() method", __FUNCTION__);
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001262 goto failure;
1263 }
1264
1265 dbus_message_ref(msg); // increment refcount because we pass to java
1266 env->CallVoidMethod(nat->me, method_onRequestPairingConsent,
1267 env->NewStringUTF(object_path),
1268 int(msg));
1269 goto success;
1270 } else if (dbus_message_is_method_call(msg,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001271 "org.bluez.Agent", "Release")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272 // reply
1273 DBusMessage *reply = dbus_message_new_method_return(msg);
1274 if (!reply) {
Steve Block3762c312012-01-06 19:20:56 +00001275 ALOGE("%s: Cannot create message reply\n", __FUNCTION__);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001276 goto failure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 }
1278 dbus_connection_send(nat->conn, reply, NULL);
1279 dbus_message_unref(reply);
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001280 goto success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 } else {
Steve Block71f2cf12011-10-20 11:56:00 +01001282 ALOGV("%s:%s is ignored", dbus_message_get_interface(msg), dbus_message_get_member(msg));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 }
1284
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001285failure:
1286 env->PopLocalFrame(NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
Jaikumar Ganesh6d56b532009-08-24 17:11:11 -07001288
1289success:
1290 env->PopLocalFrame(NULL);
1291 return DBUS_HANDLER_RESULT_HANDLED;
1292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293}
1294#endif
1295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296
1297#ifdef HAVE_BLUETOOTH
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001298
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001299void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001300 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001302 native_data_t *nat = (native_data_t *)n;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 const char *address = (const char *)user;
1304 DBusError err;
1305 dbus_error_init(&err);
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001306 JNIEnv *env;
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001307 jstring addr;
1308
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001309 nat->vm->GetEnv((void**)&env, nat->envVer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310
Steve Block71f2cf12011-10-20 11:56:00 +01001311 ALOGV("... address = %s", address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312
1313 jint result = BOND_RESULT_SUCCESS;
1314 if (dbus_set_error_from_message(&err, msg)) {
1315 if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) {
1316 // Pins did not match, or remote device did not respond to pin
1317 // request in time
Steve Block71f2cf12011-10-20 11:56:00 +01001318 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 result = BOND_RESULT_AUTH_FAILED;
1320 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationRejected")) {
1321 // We rejected pairing, or the remote side rejected pairing. This
1322 // happens if either side presses 'cancel' at the pairing dialog.
Steve Block71f2cf12011-10-20 11:56:00 +01001323 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 result = BOND_RESULT_AUTH_REJECTED;
1325 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationCanceled")) {
1326 // Not sure if this happens
Steve Block71f2cf12011-10-20 11:56:00 +01001327 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 result = BOND_RESULT_AUTH_CANCELED;
1329 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.ConnectionAttemptFailed")) {
1330 // Other device is not responding at all
Steve Block71f2cf12011-10-20 11:56:00 +01001331 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 result = BOND_RESULT_REMOTE_DEVICE_DOWN;
1333 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AlreadyExists")) {
1334 // already bonded
Steve Block71f2cf12011-10-20 11:56:00 +01001335 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 result = BOND_RESULT_SUCCESS;
1337 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") &&
1338 !strcmp(err.message, "Bonding in progress")) {
Steve Block71f2cf12011-10-20 11:56:00 +01001339 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 goto done;
1341 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") &&
1342 !strcmp(err.message, "Discover in progress")) {
Steve Block71f2cf12011-10-20 11:56:00 +01001343 ALOGV("... error = %s (%s)\n", err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 result = BOND_RESULT_DISCOVERY_IN_PROGRESS;
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001345 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.RepeatedAttempts")) {
Steve Block71f2cf12011-10-20 11:56:00 +01001346 ALOGV("... error = %s (%s)\n", err.name, err.message);
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001347 result = BOND_RESULT_REPEATED_ATTEMPTS;
1348 } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationTimeout")) {
Steve Block71f2cf12011-10-20 11:56:00 +01001349 ALOGV("... error = %s (%s)\n", err.name, err.message);
Jaikumar Ganesh32d85712009-09-10 22:00:05 -07001350 result = BOND_RESULT_AUTH_TIMEOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 } else {
Steve Block3762c312012-01-06 19:20:56 +00001352 ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 result = BOND_RESULT_ERROR;
1354 }
1355 }
1356
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001357 addr = env->NewStringUTF(address);
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001358 env->CallVoidMethod(nat->me,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001359 method_onCreatePairedDeviceResult,
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001360 addr,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 result);
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001362 env->DeleteLocalRef(addr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363done:
1364 dbus_error_free(&err);
1365 free(user);
1366}
1367
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001368void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001369 ALOGV("%s", __FUNCTION__);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001370
1371 native_data_t *nat = (native_data_t *)n;
1372 const char *address= (const char *)user;
1373 DBusError err;
1374 dbus_error_init(&err);
1375 JNIEnv *env;
1376 nat->vm->GetEnv((void**)&env, nat->envVer);
1377
Steve Block71f2cf12011-10-20 11:56:00 +01001378 ALOGV("... Address = %s", address);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001379
Nick Pelly16fb88a2009-10-07 07:44:03 +02001380 jint result = CREATE_DEVICE_SUCCESS;
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001381 if (dbus_set_error_from_message(&err, msg)) {
Nick Pelly16fb88a2009-10-07 07:44:03 +02001382 if (dbus_error_has_name(&err, "org.bluez.Error.AlreadyExists")) {
1383 result = CREATE_DEVICE_ALREADY_EXISTS;
Jaikumar Ganeshcf5f6522010-02-17 17:19:26 -08001384 } else {
1385 result = CREATE_DEVICE_FAILED;
Nick Pelly16fb88a2009-10-07 07:44:03 +02001386 }
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001387 LOG_AND_FREE_DBUS_ERROR(&err);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001388 }
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001389 jstring addr = env->NewStringUTF(address);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001390 env->CallVoidMethod(nat->me,
1391 method_onCreateDeviceResult,
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001392 addr,
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001393 result);
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001394 env->DeleteLocalRef(addr);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001395 free(user);
1396}
1397
1398void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001399 ALOGV("%s", __FUNCTION__);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001400
1401 native_data_t *nat = (native_data_t *)n;
1402 const char *path = (const char *)user;
1403 DBusError err;
1404 dbus_error_init(&err);
1405 JNIEnv *env;
1406 nat->vm->GetEnv((void**)&env, nat->envVer);
1407
Steve Block71f2cf12011-10-20 11:56:00 +01001408 ALOGV("... Device Path = %s", path);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001409
1410 bool result = JNI_TRUE;
1411 if (dbus_set_error_from_message(&err, msg)) {
1412 LOG_AND_FREE_DBUS_ERROR(&err);
1413 result = JNI_FALSE;
1414 }
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001415 jstring jPath = env->NewStringUTF(path);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001416 env->CallVoidMethod(nat->me,
1417 method_onDiscoverServicesResult,
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001418 jPath,
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001419 result);
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001420 env->DeleteLocalRef(jPath);
Jaikumar Ganesh1caa6d12009-09-18 11:32:54 -07001421 free(user);
1422}
1423
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001424void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001425 ALOGV("%s", __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426
1427 const char *address = (const char *) user;
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001428 native_data_t *nat = (native_data_t *) n;
1429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 DBusError err;
1431 dbus_error_init(&err);
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001432 JNIEnv *env;
1433 nat->vm->GetEnv((void**)&env, nat->envVer);
1434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 jint channel = -2;
1436
Steve Block71f2cf12011-10-20 11:56:00 +01001437 ALOGV("... address = %s", address);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438
1439 if (dbus_set_error_from_message(&err, msg) ||
1440 !dbus_message_get_args(msg, &err,
1441 DBUS_TYPE_INT32, &channel,
1442 DBUS_TYPE_INVALID)) {
Steve Block3762c312012-01-06 19:20:56 +00001443 ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 dbus_error_free(&err);
1445 }
1446
1447done:
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001448 jstring addr = env->NewStringUTF(address);
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001449 env->CallVoidMethod(nat->me,
Jaikumar Ganeshd5ac1ae2009-05-05 22:26:12 -07001450 method_onGetDeviceServiceChannelResult,
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001451 addr,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 channel);
Jaikumar Ganesha7c0bdc2010-06-03 16:50:57 -07001453 env->DeleteLocalRef(addr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 free(user);
1455}
Jaikumar Ganeshde075032010-07-19 16:28:27 -07001456
1457void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001458 ALOGV("%s", __FUNCTION__);
Jaikumar Ganeshde075032010-07-19 16:28:27 -07001459
1460 native_data_t *nat = (native_data_t *)n;
1461 const char *path = (const char *)user;
1462 DBusError err;
1463 dbus_error_init(&err);
1464 JNIEnv *env;
1465 nat->vm->GetEnv((void**)&env, nat->envVer);
1466
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -08001467 jint result = INPUT_OPERATION_SUCCESS;
Jaikumar Ganeshde075032010-07-19 16:28:27 -07001468 if (dbus_set_error_from_message(&err, msg)) {
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -08001469 if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
1470 result = INPUT_CONNECT_FAILED_ATTEMPT_FAILED;
1471 } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".AlreadyConnected")) {
1472 result = INPUT_CONNECT_FAILED_ALREADY_CONNECTED;
1473 } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
1474 // TODO():This is flaky, need to change Bluez to add new error codes
1475 if (!strcmp(err.message, "Transport endpoint is not connected")) {
1476 result = INPUT_DISCONNECT_FAILED_NOT_CONNECTED;
1477 } else {
1478 result = INPUT_OPERATION_GENERIC_FAILURE;
1479 }
1480 } else {
1481 result = INPUT_OPERATION_GENERIC_FAILURE;
1482 }
Jaikumar Ganeshde075032010-07-19 16:28:27 -07001483 LOG_AND_FREE_DBUS_ERROR(&err);
Jaikumar Ganeshde075032010-07-19 16:28:27 -07001484 }
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -08001485
Steve Block71f2cf12011-10-20 11:56:00 +01001486 ALOGV("... Device Path = %s, result = %d", path, result);
Jaikumar Ganeshde075032010-07-19 16:28:27 -07001487 jstring jPath = env->NewStringUTF(path);
1488 env->CallVoidMethod(nat->me,
1489 method_onInputDeviceConnectionResult,
1490 jPath,
1491 result);
1492 env->DeleteLocalRef(jPath);
1493 free(user);
1494}
1495
Danica Chang6fdd0c62010-08-11 14:54:43 -07001496void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001497 ALOGV("%s", __FUNCTION__);
Danica Chang6fdd0c62010-08-11 14:54:43 -07001498
1499 native_data_t *nat = (native_data_t *)n;
1500 const char *path = (const char *)user;
1501 DBusError err;
1502 dbus_error_init(&err);
1503 JNIEnv *env;
1504 nat->vm->GetEnv((void**)&env, nat->envVer);
1505
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -08001506 jint result = PAN_OPERATION_SUCCESS;
Danica Chang6fdd0c62010-08-11 14:54:43 -07001507 if (dbus_set_error_from_message(&err, msg)) {
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -08001508 if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
1509 result = PAN_CONNECT_FAILED_ATTEMPT_FAILED;
1510 } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
1511 // TODO():This is flaky, need to change Bluez to add new error codes
1512 if (!strcmp(err.message, "Device already connected")) {
1513 result = PAN_CONNECT_FAILED_ALREADY_CONNECTED;
1514 } else if (!strcmp(err.message, "Device not connected")) {
1515 result = PAN_DISCONNECT_FAILED_NOT_CONNECTED;
1516 } else {
1517 result = PAN_OPERATION_GENERIC_FAILURE;
1518 }
1519 } else {
1520 result = PAN_OPERATION_GENERIC_FAILURE;
1521 }
Danica Chang6fdd0c62010-08-11 14:54:43 -07001522 LOG_AND_FREE_DBUS_ERROR(&err);
Danica Chang6fdd0c62010-08-11 14:54:43 -07001523 }
Jaikumar Ganeshfbe807d2011-01-19 13:59:32 -08001524
Steve Block71f2cf12011-10-20 11:56:00 +01001525 ALOGV("... Pan Device Path = %s, result = %d", path, result);
Danica Chang6fdd0c62010-08-11 14:54:43 -07001526 jstring jPath = env->NewStringUTF(path);
1527 env->CallVoidMethod(nat->me,
1528 method_onPanDeviceConnectionResult,
1529 jPath,
1530 result);
1531 env->DeleteLocalRef(jPath);
1532 free(user);
1533}
1534
Jaikumar Ganeshb5d2d452011-09-07 14:16:52 -07001535void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
Steve Block71f2cf12011-10-20 11:56:00 +01001536 ALOGV("%s", __FUNCTION__);
Jaikumar Ganeshb5d2d452011-09-07 14:16:52 -07001537
1538 native_data_t *nat = (native_data_t *)n;
1539 DBusError err;
1540 dbus_error_init(&err);
1541 JNIEnv *env;
1542 nat->vm->GetEnv((void**)&env, nat->envVer);
1543
1544 jint result = HEALTH_OPERATION_SUCCESS;
1545 if (dbus_set_error_from_message(&err, msg)) {
1546 if (!strcmp(err.name, BLUEZ_ERROR_IFC ".InvalidArgs")) {
1547 result = HEALTH_OPERATION_INVALID_ARGS;
1548 } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".HealthError")) {
1549 result = HEALTH_OPERATION_ERROR;
1550 } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotFound")) {
1551 result = HEALTH_OPERATION_NOT_FOUND;
1552 } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotAllowed")) {
1553 result = HEALTH_OPERATION_NOT_ALLOWED;
1554 } else {
1555 result = HEALTH_OPERATION_GENERIC_FAILURE;
1556 }
1557 LOG_AND_FREE_DBUS_ERROR(&err);
1558 }
1559
Jaikumar Ganeshb5d2d452011-09-07 14:16:52 -07001560 jint code = *(int *) user;
Steve Block71f2cf12011-10-20 11:56:00 +01001561 ALOGV("... Health Device Code = %d, result = %d", code, result);
Jaikumar Ganeshb5d2d452011-09-07 14:16:52 -07001562 env->CallVoidMethod(nat->me,
1563 method_onHealthDeviceConnectionResult,
1564 code,
1565 result);
1566 free(user);
1567}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568#endif
1569
1570static JNINativeMethod sMethods[] = {
1571 /* name, signature, funcPtr */
1572 {"classInitNative", "()V", (void *)classInitNative},
1573 {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
1574 {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
Robert Greenwalt28d139f2009-04-02 22:41:08 -07001575 {"startEventLoopNative", "()V", (void *)startEventLoopNative},
1576 {"stopEventLoopNative", "()V", (void *)stopEventLoopNative},
1577 {"isEventLoopRunningNative", "()Z", (void *)isEventLoopRunningNative}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578};
1579
1580int register_android_server_BluetoothEventLoop(JNIEnv *env) {
1581 return AndroidRuntime::registerNativeMethods(env,
1582 "android/server/BluetoothEventLoop", sMethods, NELEM(sMethods));
1583}
1584
1585} /* namespace android */