diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch) | |
tree | 35051494d2af230dce54d6b31c6af8fc24091316 /core/jni/android_server_BluetoothEventLoop.cpp | |
download | frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2 |
Initial Contribution
Diffstat (limited to 'core/jni/android_server_BluetoothEventLoop.cpp')
-rw-r--r-- | core/jni/android_server_BluetoothEventLoop.cpp | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp new file mode 100644 index 0000000..395a45c --- /dev/null +++ b/core/jni/android_server_BluetoothEventLoop.cpp @@ -0,0 +1,642 @@ +/* +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define LOG_TAG "BluetoothEventLoop.cpp" + +#include "android_bluetooth_common.h" +#include "android_runtime/AndroidRuntime.h" +#include "JNIHelp.h" +#include "jni.h" +#include "utils/Log.h" +#include "utils/misc.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> + +#ifdef HAVE_BLUETOOTH +#include <dbus/dbus.h> +#endif + +namespace android { + +#ifdef HAVE_BLUETOOTH +static jfieldID field_mNativeData; + +static jmethodID method_onModeChanged; +static jmethodID method_onDiscoveryStarted; +static jmethodID method_onDiscoveryCompleted; +static jmethodID method_onRemoteDeviceFound; +static jmethodID method_onRemoteDeviceDisappeared; +static jmethodID method_onRemoteClassUpdated; +static jmethodID method_onRemoteNameUpdated; +static jmethodID method_onRemoteNameFailed; +static jmethodID method_onRemoteAliasChanged; +static jmethodID method_onRemoteAliasCleared; +static jmethodID method_onRemoteDeviceConnected; +static jmethodID method_onRemoteDeviceDisconnectRequested; +static jmethodID method_onRemoteDeviceDisconnected; +static jmethodID method_onBondingCreated; +static jmethodID method_onBondingRemoved; + +static jmethodID method_onCreateBondingResult; +static jmethodID method_onGetRemoteServiceChannelResult; + +static jmethodID method_onPasskeyAgentRequest; +static jmethodID method_onPasskeyAgentCancel; + +struct 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. */ + jobject me; + JNIEnv *env; +}; + +// Only valid during waitForAndDispatchEventNative() +static native_data_t *event_loop_nat; + +static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { + return (native_data_t *)(env->GetIntField(object, + field_mNativeData)); +} + +#endif +static void classInitNative(JNIEnv* env, jclass clazz) { + LOGV(__FUNCTION__); + +#ifdef HAVE_BLUETOOTH + method_onModeChanged = env->GetMethodID(clazz, "onModeChanged", "(Ljava/lang/String;)V"); + method_onDiscoveryStarted = env->GetMethodID(clazz, "onDiscoveryStarted", "()V"); + method_onDiscoveryCompleted = env->GetMethodID(clazz, "onDiscoveryCompleted", "()V"); + method_onRemoteDeviceFound = env->GetMethodID(clazz, "onRemoteDeviceFound", "(Ljava/lang/String;IS)V"); + method_onRemoteDeviceDisappeared = env->GetMethodID(clazz, "onRemoteDeviceDisappeared", "(Ljava/lang/String;)V"); + method_onRemoteClassUpdated = env->GetMethodID(clazz, "onRemoteClassUpdated", "(Ljava/lang/String;I)V"); + method_onRemoteNameUpdated = env->GetMethodID(clazz, "onRemoteNameUpdated", "(Ljava/lang/String;Ljava/lang/String;)V"); + method_onRemoteNameFailed = env->GetMethodID(clazz, "onRemoteNameFailed", "(Ljava/lang/String;)V"); + method_onRemoteAliasChanged = env->GetMethodID(clazz, "onRemoteAliasChanged", "(Ljava/lang/String;Ljava/lang/String;)V"); + method_onRemoteDeviceConnected = env->GetMethodID(clazz, "onRemoteDeviceConnected", "(Ljava/lang/String;)V"); + method_onRemoteDeviceDisconnectRequested = env->GetMethodID(clazz, "onRemoteDeviceDisconnectRequested", "(Ljava/lang/String;)V"); + method_onRemoteDeviceDisconnected = env->GetMethodID(clazz, "onRemoteDeviceDisconnected", "(Ljava/lang/String;)V"); + method_onBondingCreated = env->GetMethodID(clazz, "onBondingCreated", "(Ljava/lang/String;)V"); + method_onBondingRemoved = env->GetMethodID(clazz, "onBondingRemoved", "(Ljava/lang/String;)V"); + + method_onCreateBondingResult = env->GetMethodID(clazz, "onCreateBondingResult", "(Ljava/lang/String;Z)V"); + + method_onPasskeyAgentRequest = env->GetMethodID(clazz, "onPasskeyAgentRequest", "(Ljava/lang/String;I)V"); + method_onPasskeyAgentCancel = env->GetMethodID(clazz, "onPasskeyAgentCancel", "(Ljava/lang/String;)V"); + method_onGetRemoteServiceChannelResult = env->GetMethodID(clazz, "onGetRemoteServiceChannelResult", "(Ljava/lang/String;I)V"); + + field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I"); +#endif +} + +static void initializeNativeDataNative(JNIEnv* env, jobject object) { + LOGV(__FUNCTION__); +#ifdef HAVE_BLUETOOTH + native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); + if (NULL == nat) { + LOGE("%s: out of memory!", __FUNCTION__); + return; + } + env->SetIntField(object, field_mNativeData, (jint)nat); + + { + DBusError err; + dbus_error_init(&err); + dbus_threads_init_default(); + nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err)) { + LOGE("%s: Could not get onto the system bus!", __FUNCTION__); + dbus_error_free(&err); + } + } +#endif +} + +static void cleanupNativeDataNative(JNIEnv* env, jobject object) { + LOGV(__FUNCTION__); +#ifdef HAVE_BLUETOOTH + native_data_t *nat = + (native_data_t *)env->GetIntField(object, field_mNativeData); + if (nat) { + free(nat); + } +#endif +} + +#ifdef HAVE_BLUETOOTH +static jboolean add_adapter_event_match(JNIEnv *env, native_data_t *nat); +static void remove_adapter_event_match(JNIEnv *env, native_data_t *nat); +static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, + void *data); +static DBusHandlerResult passkey_agent_event_filter(DBusConnection *conn, + DBusMessage *msg, + void *data); + +static const DBusObjectPathVTable passkey_agent_vtable = { + NULL, passkey_agent_event_filter, NULL, NULL, NULL, NULL +}; +#endif + +static jboolean setUpEventLoopNative(JNIEnv *env, jobject object) { +#ifdef HAVE_BLUETOOTH + LOGV(__FUNCTION__); + dbus_threads_init_default(); + native_data_t *nat = get_native_data(env, object); + if (nat != NULL && nat->conn != NULL) { + if (!dbus_connection_add_filter(nat->conn, event_filter, nat, NULL)){ + return JNI_FALSE; + } + + if (add_adapter_event_match(env, nat) != JNI_TRUE) { + return JNI_FALSE; + } + + const char *path = "/android/bluetooth/PasskeyAgent"; + if (!dbus_connection_register_object_path(nat->conn, path, + &passkey_agent_vtable, NULL)) { + LOGE("%s: Can't register object path %s for agent!", + __FUNCTION__, path); + return JNI_FALSE; + } + + DBusError err; + dbus_error_init(&err); + + // RegisterDefaultPasskeyAgent() will fail until hcid is up, so keep + // trying for 10 seconds. + int attempt; + for (attempt = 1000; attempt > 0; attempt--) { + DBusMessage *reply = dbus_func_args_error(env, nat->conn, &err, + BLUEZ_DBUS_BASE_PATH, + "org.bluez.Security", "RegisterDefaultPasskeyAgent", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (reply) { + // Success + dbus_message_unref(reply); + return JNI_TRUE; + } else if (dbus_error_has_name(&err, + "org.freedesktop.DBus.Error.ServiceUnknown")) { + // hcid is still down, retry + dbus_error_free(&err); + usleep(10000); // 10 ms + } else { + // Some other error we weren't expecting + LOG_AND_FREE_DBUS_ERROR(&err); + return JNI_FALSE; + } + } + LOGE("Time-out trying to call RegisterDefaultPasskeyAgent(), " + "is hcid running?"); + return JNI_FALSE; + } + +#endif + return JNI_FALSE; +} + +static void tearDownEventLoopNative(JNIEnv *env, jobject object) { + LOGV(__FUNCTION__); +#ifdef HAVE_BLUETOOTH + native_data_t *nat = get_native_data(env, object); + if (nat != NULL && nat->conn != NULL) { + + const char *path = "/android/bluetooth/PasskeyAgent"; + DBusMessage *reply = + dbus_func_args(env, nat->conn, BLUEZ_DBUS_BASE_PATH, + "org.bluez.Security", "UnregisterDefaultPasskeyAgent", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (reply) dbus_message_unref(reply); + + DBusError err; + dbus_error_init(&err); + (void)dbus_connection_remove_filter(nat->conn, + event_filter, + nat); + + dbus_connection_unregister_object_path(nat->conn, path); + + remove_adapter_event_match(env, nat); + } +#endif +} + +#ifdef HAVE_BLUETOOTH +static const char *const adapter_event_match = + "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'"; + +static jboolean add_adapter_event_match(JNIEnv *env, native_data_t *nat) { + if (nat == NULL || nat->conn == NULL) { + LOGE("%s: Not connected to d-bus!", __FUNCTION__); + return JNI_FALSE; + } + DBusError err; + dbus_error_init(&err); + dbus_bus_add_match(nat->conn, adapter_event_match, &err); + if (dbus_error_is_set(&err)) { + LOG_AND_FREE_DBUS_ERROR(&err); + return JNI_FALSE; + } + return JNI_TRUE; +} + +static void remove_adapter_event_match(JNIEnv *env, native_data_t *nat) { + if (nat->conn == NULL) { + LOGE("%s: Not connected to d-bus!", __FUNCTION__); + return; + } + DBusError err; + dbus_error_init(&err); + dbus_bus_remove_match(nat->conn, adapter_event_match, &err); + if (dbus_error_is_set(&err)) { + LOG_AND_FREE_DBUS_ERROR(&err); + } +} + +// Called by dbus during WaitForAndDispatchEventNative() +static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, + void *data) { + native_data_t *nat; + JNIEnv *env; + DBusError err; + + dbus_error_init(&err); + + nat = (native_data_t *)data; + env = nat->env; + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) { + LOGV("%s: not interested (not a signal).", __FUNCTION__); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + LOGV("%s: Received signal %s:%s", __FUNCTION__, + dbus_message_get_interface(msg), dbus_message_get_member(msg)); + + if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteDeviceFound")) { + char *c_address; + int n_class; + short n_rssi; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_UINT32, &n_class, + DBUS_TYPE_INT16, &n_rssi, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s class = %#X rssi = %hd", c_address, n_class, + n_rssi); + env->CallVoidMethod(nat->me, + method_onRemoteDeviceFound, + env->NewStringUTF(c_address), + (jint)n_class, + (jshort)n_rssi); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "DiscoveryStarted")) { + LOGI("DiscoveryStarted signal received"); + env->CallVoidMethod(nat->me, method_onDiscoveryStarted); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "DiscoveryCompleted")) { + LOGI("DiscoveryCompleted signal received"); + env->CallVoidMethod(nat->me, method_onDiscoveryCompleted); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteDeviceDisappeared")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, method_onRemoteDeviceDisappeared, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteClassUpdated")) { + char *c_address; + int n_class; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_UINT32, &n_class, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, method_onRemoteClassUpdated, + env->NewStringUTF(c_address), (jint)n_class); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteNameUpdated")) { + char *c_address; + char *c_name; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_STRING, &c_name, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s, name = %s", c_address, c_name); + env->CallVoidMethod(nat->me, + method_onRemoteNameUpdated, + env->NewStringUTF(c_address), + env->NewStringUTF(c_name)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteNameFailed")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onRemoteNameFailed, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteAliasChanged")) { + char *c_address, *c_alias; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_STRING, &c_alias, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s, alias = %s", c_address, c_alias); + env->CallVoidMethod(nat->me, + method_onRemoteAliasChanged, + env->NewStringUTF(c_address), + env->NewStringUTF(c_alias)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteAliasCleared")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onRemoteAliasCleared, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteDeviceConnected")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onRemoteDeviceConnected, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteDeviceDisconnectRequested")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onRemoteDeviceDisconnectRequested, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "RemoteDeviceDisconnected")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onRemoteDeviceDisconnected, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "BondingCreated")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onBondingCreated, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.bluez.Adapter", + "BondingRemoved")) { + char *c_address; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_address, + DBUS_TYPE_INVALID)) { + LOGV("... address = %s", c_address); + env->CallVoidMethod(nat->me, + method_onBondingRemoved, + env->NewStringUTF(c_address)); + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; + } else { + LOGV("... ignored"); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +// Called by dbus during WaitForAndDispatchEventNative() +static DBusHandlerResult passkey_agent_event_filter(DBusConnection *conn, + DBusMessage *msg, + void *data) { + native_data_t *nat = event_loop_nat; + JNIEnv *env; + + + env = nat->env; + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) { + LOGV("%s: not interested (not a method call).", __FUNCTION__); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + LOGV("%s: Received method %s:%s", __FUNCTION__, + dbus_message_get_interface(msg), dbus_message_get_member(msg)); + + if (dbus_message_is_method_call(msg, + "org.bluez.PasskeyAgent", "Request")) { + + const char *adapter; + const char *address; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &adapter, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID)) { + LOGE("%s: Invalid arguments for Request() method", __FUNCTION__); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + LOGV("... address = %s", address); + + dbus_message_ref(msg); // increment refcount because we pass to java + + env->CallVoidMethod(nat->me, method_onPasskeyAgentRequest, + env->NewStringUTF(address), (int)msg); + + return DBUS_HANDLER_RESULT_HANDLED; + + } else if (dbus_message_is_method_call(msg, + "org.bluez.PasskeyAgent", "Cancel")) { + + const char *adapter; + const char *address; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &adapter, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID)) { + LOGE("%s: Invalid arguments for Cancel() method", __FUNCTION__); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + LOGV("... address = %s", address); + + env->CallVoidMethod(nat->me, method_onPasskeyAgentCancel, + env->NewStringUTF(address)); + + return DBUS_HANDLER_RESULT_HANDLED; + + } else if (dbus_message_is_method_call(msg, + "org.bluez.PasskeyAgent", "Release")) { + LOGE("We are no longer the passkey agent!"); + } else { + LOGV("... ignored"); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} +#endif + +static jboolean waitForAndDispatchEventNative(JNIEnv *env, jobject object, + jint timeout_ms) { +#ifdef HAVE_BLUETOOTH + //LOGV("%s: %8d (pid %d tid %d)",__FUNCTION__, time(NULL), getpid(), gettid()); // too chatty + native_data_t *nat = get_native_data(env, object); + if (nat != NULL && nat->conn != NULL) { + jboolean ret; + nat->me = object; + nat->env = env; + event_loop_nat = nat; + ret = dbus_connection_read_write_dispatch(nat->conn, + timeout_ms) == TRUE ? + JNI_TRUE : JNI_FALSE; + event_loop_nat = NULL; + nat->me = NULL; + nat->env = NULL; + return ret; + } +#endif + return JNI_FALSE; +} + +#ifdef HAVE_BLUETOOTH +void onCreateBondingResult(DBusMessage *msg, void *user) { + LOGV(__FUNCTION__); + + const char *address = (const char *)user; + DBusError err; + dbus_error_init(&err); + JNIEnv *env = event_loop_nat->env; + + LOGV("... address = %s", address); + + jboolean result = JNI_TRUE; + if (dbus_set_error_from_message(&err, msg)) { + /* if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) */ + LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message); + result = JNI_FALSE; + dbus_error_free(&err); + } + + env->CallVoidMethod(event_loop_nat->me, + method_onCreateBondingResult, + env->NewStringUTF(address), + result); + free(user); +} + +void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user) { + LOGV(__FUNCTION__); + + const char *address = (const char *) user; + DBusError err; + dbus_error_init(&err); + JNIEnv *env = event_loop_nat->env; + jint channel = -2; + + LOGV("... address = %s", context->address); + + if (dbus_set_error_from_message(&err, msg) || + !dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &channel, + DBUS_TYPE_INVALID)) { + /* if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) */ + LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } + +done: + env->CallVoidMethod(event_loop_nat->me, + method_onGetRemoteServiceChannelResult, + env->NewStringUTF(address), + channel); + free(user); +} +#endif + +static JNINativeMethod sMethods[] = { + /* name, signature, funcPtr */ + {"classInitNative", "()V", (void *)classInitNative}, + {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, + {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, + {"setUpEventLoopNative", "()Z", (void *)setUpEventLoopNative}, + {"tearDownEventLoopNative", "()V", (void *)tearDownEventLoopNative}, + {"waitForAndDispatchEventNative", "(I)Z", (void *)waitForAndDispatchEventNative} +}; + +int register_android_server_BluetoothEventLoop(JNIEnv *env) { + return AndroidRuntime::registerNativeMethods(env, + "android/server/BluetoothEventLoop", sMethods, NELEM(sMethods)); +} + +} /* namespace android */ |