Loading core/java/android/server/BluetoothEventLoop.java +13 −43 Original line number Diff line number Diff line Loading @@ -111,57 +111,27 @@ class BluetoothEventLoop { return mPasskeyAgentRequestData; } private synchronized boolean waitForAndDispatchEvent(int timeout_ms) { return waitForAndDispatchEventNative(timeout_ms); } private native boolean waitForAndDispatchEventNative(int timeout_ms); private native void startEventLoopNative(); private native void stopEventLoopNative(); private native boolean isEventLoopRunningNative(); /* package */ synchronized void start() { /* package */ void start() { if (mThread != null) { // Already running. return; } mThread = new Thread("Bluetooth Event Loop") { @Override public void run() { try { if (setUpEventLoopNative()) { mStarted = true; while (!mInterrupted) { waitForAndDispatchEvent(0); sleep(500); } } // tear down even in the error case to clean // up anything we started to setup tearDownEventLoopNative(); } catch (InterruptedException e) { } if (DBG) log("Event Loop thread finished"); mThread = null; } }; if (!isEventLoopRunningNative()) { if (DBG) log("Starting Event Loop thread"); mInterrupted = false; mThread.start(); startEventLoopNative(); } private native boolean setUpEventLoopNative(); private native void tearDownEventLoopNative(); public synchronized void stop() { if (mThread != null) { mInterrupted = true; try { mThread.join(); mThread = null; } catch (InterruptedException e) { Log.i(TAG, "Interrupted waiting for Event Loop thread to join"); } public void stop() { if (isEventLoopRunningNative()) { if (DBG) log("Stopping Event Loop thread"); stopEventLoopNative(); } } public synchronized boolean isEventLoopRunning() { return mThread != null && mStarted; public boolean isEventLoopRunning() { return isEventLoopRunningNative(); } /*package*/ void onModeChanged(String bluezMode) { Loading core/jni/android_bluetooth_common.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -46,8 +46,9 @@ jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, } typedef struct { void (*user_cb)(DBusMessage *, void *); void (*user_cb)(DBusMessage *, void *, void *); void *user; void *nat; JNIEnv *env; } dbus_async_call_t; Loading @@ -63,7 +64,7 @@ void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { if (msg) { if (req->user_cb) { // The user may not deref the message object. req->user_cb(msg, req->user); req->user_cb(msg, req->user, req->nat); } dbus_message_unref(msg); } Loading @@ -74,11 +75,14 @@ void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { free(req); } dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*user_cb)(DBusMessage *, void *), void (*user_cb)(DBusMessage *, void *, void*), void *user, void *nat, const char *path, const char *ifc, const char *func, Loading Loading @@ -111,6 +115,7 @@ dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, pending->env = env; pending->user_cb = user_cb; pending->user = user; pending->nat = nat; //pending->method = msg; reply = dbus_connection_send_with_reply(conn, msg, Loading @@ -132,8 +137,9 @@ done: dbus_bool_t dbus_func_args_async(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*reply)(DBusMessage *, void *), void (*reply)(DBusMessage *, void *, void*), void *user, void *nat, const char *path, const char *ifc, const char *func, Loading @@ -144,7 +150,7 @@ dbus_bool_t dbus_func_args_async(JNIEnv *env, va_start(lst, first_arg_type); ret = dbus_func_args_async_valist(env, conn, timeout_ms, reply, user, reply, user, nat, path, ifc, func, first_arg_type, lst); va_end(lst); Loading core/jni/android_bluetooth_common.h +25 −16 Original line number Diff line number Diff line Loading @@ -24,7 +24,9 @@ #include "utils/Log.h" #include <errno.h> #include <pthread.h> #include <stdint.h> #include <sys/poll.h> #ifdef HAVE_BLUETOOTH #include <dbus/dbus.h> Loading @@ -45,6 +47,9 @@ namespace android { #define BTADDR_SIZE 18 // size of BT address character array (including null) // size of the dbus event loops pollfd structure, hopefully never to be grown #define DEFAULT_INITIAL_POLLFD_COUNT 8 jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, Loading @@ -63,29 +68,33 @@ jfieldID get_field(JNIEnv *env, struct event_loop_native_data_t { DBusConnection *conn; /* These variables are set in waitForAndDispatchEventNative() and are valid only within the scope of this function. At any other time, they are NULL. */ /* protects the thread */ pthread_mutex_t thread_mutex; pthread_t thread; /* our comms socket */ /* mem for the list of sockets to listen to */ struct pollfd *pollData; int pollMemberCount; int pollDataSize; /* mem for matching set of dbus watch ptrs */ DBusWatch **watchData; /* pair of sockets for event loop control, Reader and Writer */ int controlFdR; int controlFdW; /* our vm and env Version for future env generation */ JavaVM *vm; int envVer; /* reference to our java self */ jobject me; JNIEnv *env; }; dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*reply)(DBusMessage *, void *), void *user, const char *path, const char *ifc, const char *func, int first_arg_type, va_list args); dbus_bool_t dbus_func_args_async(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*reply)(DBusMessage *, void *), void (*reply)(DBusMessage *, void *, void *), void *user, void *nat, const char *path, const char *ifc, const char *func, Loading core/jni/android_server_BluetoothA2dpService.cpp +10 −9 Original line number Diff line number Diff line Loading @@ -52,12 +52,11 @@ typedef struct { static native_data_t *nat = NULL; // global native data extern event_loop_native_data_t *event_loop_nat; // for the event loop JNIEnv #endif #ifdef HAVE_BLUETOOTH static void onConnectSinkResult(DBusMessage *msg, void *user); static void onDisconnectSinkResult(DBusMessage *msg, void *user); static void onConnectSinkResult(DBusMessage *msg, void *user, void *nat); static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *nat); #endif /* Returns true on success (even if adapter is present but disabled). Loading Loading @@ -175,7 +174,8 @@ static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, (void *)c_path_copy, c_path, onConnectSinkResult, (void *)c_path_copy, nat, c_path, "org.bluez.audio.Sink", "Connect", DBUS_TYPE_INVALID); Loading @@ -202,7 +202,8 @@ static jboolean disconnectSinkNative(JNIEnv *env, jobject object, bool ret = dbus_func_args_async(env, nat->conn, -1, onDisconnectSinkResult, (void *)c_path_copy, c_path, onDisconnectSinkResult, (void *)c_path_copy, nat, c_path, "org.bluez.audio.Sink", "Disconnect", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); Loading Loading @@ -233,13 +234,13 @@ static jboolean isSinkConnectedNative(JNIEnv *env, jobject object, jstring path) } #ifdef HAVE_BLUETOOTH static void onConnectSinkResult(DBusMessage *msg, void *user) { static void onConnectSinkResult(DBusMessage *msg, void *user, void *natData) { LOGV(__FUNCTION__); char *c_path = (char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env = event_loop_nat->env; JNIEnv *env = nat->env; LOGV("... path = %s", c_path); if (dbus_set_error_from_message(&err, msg)) { Loading @@ -258,13 +259,13 @@ static void onConnectSinkResult(DBusMessage *msg, void *user) { free(c_path); } static void onDisconnectSinkResult(DBusMessage *msg, void *user) { static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *natData) { LOGV(__FUNCTION__); char *c_path = (char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env = event_loop_nat->env; JNIEnv *env = nat->env; LOGV("... path = %s", c_path); if (dbus_set_error_from_message(&err, msg)) { Loading core/jni/android_server_BluetoothDeviceService.cpp +19 −5 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ namespace android { // We initialize these variables when we load class // android.server.BluetoothDeviceService static jfieldID field_mNativeData; static jfieldID field_mEventLoop; typedef struct { JNIEnv *env; Loading @@ -57,8 +58,10 @@ typedef struct { const char *adapter; // dbus object name of the local adapter } native_data_t; void onCreateBondingResult(DBusMessage *msg, void *user); void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user); extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *, jobject); void onCreateBondingResult(DBusMessage *msg, void *user, void *nat); void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user, void *nat); /** Get native data stored in the opaque (Java code maintained) pointer mNativeData * Perform quick sanity check, if there are any problems return NULL Loading @@ -78,6 +81,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH field_mNativeData = get_field(env, clazz, "mNativeData", "I"); field_mEventLoop = get_field(env, clazz, "mEventLoop", "Landroid/server/BluetoothEventLoop;"); #endif } Loading Loading @@ -472,14 +477,19 @@ static jboolean createBondingNative(JNIEnv *env, jobject object, LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_address = env->GetStringUTFChars(address, NULL); LOGV("... address = %s", c_address); char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); strlcpy(context_address, c_address, BTADDR_SIZE); // for callback bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, onCreateBondingResult, // callback context_address, // user data context_address, eventLoopNat, nat->adapter, DBUS_CLASS_NAME, "CreateBonding", DBUS_TYPE_STRING, &c_address, Loading Loading @@ -856,7 +866,10 @@ static jboolean getRemoteServiceChannelNative(JNIEnv *env, jobject object, #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_address = env->GetStringUTFChars(address, NULL); char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); strlcpy(context_address, c_address, BTADDR_SIZE); Loading @@ -866,6 +879,7 @@ static jboolean getRemoteServiceChannelNative(JNIEnv *env, jobject object, bool ret = dbus_func_args_async(env, nat->conn, 20000, // ms onGetRemoteServiceChannelResult, context_address, eventLoopNat, nat->adapter, DBUS_CLASS_NAME, "GetRemoteServiceChannel", DBUS_TYPE_STRING, &c_address, Loading Loading
core/java/android/server/BluetoothEventLoop.java +13 −43 Original line number Diff line number Diff line Loading @@ -111,57 +111,27 @@ class BluetoothEventLoop { return mPasskeyAgentRequestData; } private synchronized boolean waitForAndDispatchEvent(int timeout_ms) { return waitForAndDispatchEventNative(timeout_ms); } private native boolean waitForAndDispatchEventNative(int timeout_ms); private native void startEventLoopNative(); private native void stopEventLoopNative(); private native boolean isEventLoopRunningNative(); /* package */ synchronized void start() { /* package */ void start() { if (mThread != null) { // Already running. return; } mThread = new Thread("Bluetooth Event Loop") { @Override public void run() { try { if (setUpEventLoopNative()) { mStarted = true; while (!mInterrupted) { waitForAndDispatchEvent(0); sleep(500); } } // tear down even in the error case to clean // up anything we started to setup tearDownEventLoopNative(); } catch (InterruptedException e) { } if (DBG) log("Event Loop thread finished"); mThread = null; } }; if (!isEventLoopRunningNative()) { if (DBG) log("Starting Event Loop thread"); mInterrupted = false; mThread.start(); startEventLoopNative(); } private native boolean setUpEventLoopNative(); private native void tearDownEventLoopNative(); public synchronized void stop() { if (mThread != null) { mInterrupted = true; try { mThread.join(); mThread = null; } catch (InterruptedException e) { Log.i(TAG, "Interrupted waiting for Event Loop thread to join"); } public void stop() { if (isEventLoopRunningNative()) { if (DBG) log("Stopping Event Loop thread"); stopEventLoopNative(); } } public synchronized boolean isEventLoopRunning() { return mThread != null && mStarted; public boolean isEventLoopRunning() { return isEventLoopRunningNative(); } /*package*/ void onModeChanged(String bluezMode) { Loading
core/jni/android_bluetooth_common.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -46,8 +46,9 @@ jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, } typedef struct { void (*user_cb)(DBusMessage *, void *); void (*user_cb)(DBusMessage *, void *, void *); void *user; void *nat; JNIEnv *env; } dbus_async_call_t; Loading @@ -63,7 +64,7 @@ void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { if (msg) { if (req->user_cb) { // The user may not deref the message object. req->user_cb(msg, req->user); req->user_cb(msg, req->user, req->nat); } dbus_message_unref(msg); } Loading @@ -74,11 +75,14 @@ void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { free(req); } dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*user_cb)(DBusMessage *, void *), void (*user_cb)(DBusMessage *, void *, void*), void *user, void *nat, const char *path, const char *ifc, const char *func, Loading Loading @@ -111,6 +115,7 @@ dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, pending->env = env; pending->user_cb = user_cb; pending->user = user; pending->nat = nat; //pending->method = msg; reply = dbus_connection_send_with_reply(conn, msg, Loading @@ -132,8 +137,9 @@ done: dbus_bool_t dbus_func_args_async(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*reply)(DBusMessage *, void *), void (*reply)(DBusMessage *, void *, void*), void *user, void *nat, const char *path, const char *ifc, const char *func, Loading @@ -144,7 +150,7 @@ dbus_bool_t dbus_func_args_async(JNIEnv *env, va_start(lst, first_arg_type); ret = dbus_func_args_async_valist(env, conn, timeout_ms, reply, user, reply, user, nat, path, ifc, func, first_arg_type, lst); va_end(lst); Loading
core/jni/android_bluetooth_common.h +25 −16 Original line number Diff line number Diff line Loading @@ -24,7 +24,9 @@ #include "utils/Log.h" #include <errno.h> #include <pthread.h> #include <stdint.h> #include <sys/poll.h> #ifdef HAVE_BLUETOOTH #include <dbus/dbus.h> Loading @@ -45,6 +47,9 @@ namespace android { #define BTADDR_SIZE 18 // size of BT address character array (including null) // size of the dbus event loops pollfd structure, hopefully never to be grown #define DEFAULT_INITIAL_POLLFD_COUNT 8 jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, Loading @@ -63,29 +68,33 @@ jfieldID get_field(JNIEnv *env, struct event_loop_native_data_t { DBusConnection *conn; /* These variables are set in waitForAndDispatchEventNative() and are valid only within the scope of this function. At any other time, they are NULL. */ /* protects the thread */ pthread_mutex_t thread_mutex; pthread_t thread; /* our comms socket */ /* mem for the list of sockets to listen to */ struct pollfd *pollData; int pollMemberCount; int pollDataSize; /* mem for matching set of dbus watch ptrs */ DBusWatch **watchData; /* pair of sockets for event loop control, Reader and Writer */ int controlFdR; int controlFdW; /* our vm and env Version for future env generation */ JavaVM *vm; int envVer; /* reference to our java self */ jobject me; JNIEnv *env; }; dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*reply)(DBusMessage *, void *), void *user, const char *path, const char *ifc, const char *func, int first_arg_type, va_list args); dbus_bool_t dbus_func_args_async(JNIEnv *env, DBusConnection *conn, int timeout_ms, void (*reply)(DBusMessage *, void *), void (*reply)(DBusMessage *, void *, void *), void *user, void *nat, const char *path, const char *ifc, const char *func, Loading
core/jni/android_server_BluetoothA2dpService.cpp +10 −9 Original line number Diff line number Diff line Loading @@ -52,12 +52,11 @@ typedef struct { static native_data_t *nat = NULL; // global native data extern event_loop_native_data_t *event_loop_nat; // for the event loop JNIEnv #endif #ifdef HAVE_BLUETOOTH static void onConnectSinkResult(DBusMessage *msg, void *user); static void onDisconnectSinkResult(DBusMessage *msg, void *user); static void onConnectSinkResult(DBusMessage *msg, void *user, void *nat); static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *nat); #endif /* Returns true on success (even if adapter is present but disabled). Loading Loading @@ -175,7 +174,8 @@ static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, (void *)c_path_copy, c_path, onConnectSinkResult, (void *)c_path_copy, nat, c_path, "org.bluez.audio.Sink", "Connect", DBUS_TYPE_INVALID); Loading @@ -202,7 +202,8 @@ static jboolean disconnectSinkNative(JNIEnv *env, jobject object, bool ret = dbus_func_args_async(env, nat->conn, -1, onDisconnectSinkResult, (void *)c_path_copy, c_path, onDisconnectSinkResult, (void *)c_path_copy, nat, c_path, "org.bluez.audio.Sink", "Disconnect", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); Loading Loading @@ -233,13 +234,13 @@ static jboolean isSinkConnectedNative(JNIEnv *env, jobject object, jstring path) } #ifdef HAVE_BLUETOOTH static void onConnectSinkResult(DBusMessage *msg, void *user) { static void onConnectSinkResult(DBusMessage *msg, void *user, void *natData) { LOGV(__FUNCTION__); char *c_path = (char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env = event_loop_nat->env; JNIEnv *env = nat->env; LOGV("... path = %s", c_path); if (dbus_set_error_from_message(&err, msg)) { Loading @@ -258,13 +259,13 @@ static void onConnectSinkResult(DBusMessage *msg, void *user) { free(c_path); } static void onDisconnectSinkResult(DBusMessage *msg, void *user) { static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *natData) { LOGV(__FUNCTION__); char *c_path = (char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env = event_loop_nat->env; JNIEnv *env = nat->env; LOGV("... path = %s", c_path); if (dbus_set_error_from_message(&err, msg)) { Loading
core/jni/android_server_BluetoothDeviceService.cpp +19 −5 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ namespace android { // We initialize these variables when we load class // android.server.BluetoothDeviceService static jfieldID field_mNativeData; static jfieldID field_mEventLoop; typedef struct { JNIEnv *env; Loading @@ -57,8 +58,10 @@ typedef struct { const char *adapter; // dbus object name of the local adapter } native_data_t; void onCreateBondingResult(DBusMessage *msg, void *user); void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user); extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *, jobject); void onCreateBondingResult(DBusMessage *msg, void *user, void *nat); void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user, void *nat); /** Get native data stored in the opaque (Java code maintained) pointer mNativeData * Perform quick sanity check, if there are any problems return NULL Loading @@ -78,6 +81,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH field_mNativeData = get_field(env, clazz, "mNativeData", "I"); field_mEventLoop = get_field(env, clazz, "mEventLoop", "Landroid/server/BluetoothEventLoop;"); #endif } Loading Loading @@ -472,14 +477,19 @@ static jboolean createBondingNative(JNIEnv *env, jobject object, LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); if (nat) { jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_address = env->GetStringUTFChars(address, NULL); LOGV("... address = %s", c_address); char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); strlcpy(context_address, c_address, BTADDR_SIZE); // for callback bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, onCreateBondingResult, // callback context_address, // user data context_address, eventLoopNat, nat->adapter, DBUS_CLASS_NAME, "CreateBonding", DBUS_TYPE_STRING, &c_address, Loading Loading @@ -856,7 +866,10 @@ static jboolean getRemoteServiceChannelNative(JNIEnv *env, jobject object, #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { jobject eventLoop = env->GetObjectField(object, field_mEventLoop); struct event_loop_native_data_t *eventLoopNat = get_EventLoop_native_data(env, eventLoop); if (nat && eventLoopNat) { const char *c_address = env->GetStringUTFChars(address, NULL); char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); strlcpy(context_address, c_address, BTADDR_SIZE); Loading @@ -866,6 +879,7 @@ static jboolean getRemoteServiceChannelNative(JNIEnv *env, jobject object, bool ret = dbus_func_args_async(env, nat->conn, 20000, // ms onGetRemoteServiceChannelResult, context_address, eventLoopNat, nat->adapter, DBUS_CLASS_NAME, "GetRemoteServiceChannel", DBUS_TYPE_STRING, &c_address, Loading