3 eventloop在jni层的详细分析
Eventloop在整个bluetooth的jni层和bluez之间的交互,以及jni和framework层之间的交互过程中有着举足轻重的作用。所以,本文仍然需要花费一定的笔墨来分析它,当然由于它更像是一个桥梁,我们的分析有可能就不是那么的深入了,会从比较宏观地角度来看待这个东西的作用。
当然,一切的一切还是要从源码来说:
static jboolean startEventLoopNative(JNIEnv *env, jobject object) {
jboolean result = JNI_FALSE;
#ifdef HAVE_BLUETOOTH
event_loop_native_data_t *nat = get_native_data(env, object);
pthread_mutex_lock(&(nat->thread_mutex));
//这个是用来判断eventloop是否启动的
nat->running = false;
if (nat->pollData) {
LOGW("trying to start EventLoop a second time!");
pthread_mutex_unlock( &(nat->thread_mutex) );
return JNI_FALSE;
}
//申请pollfa
nat->pollData = (struct pollfd *)malloc(sizeof(struct pollfd) *
DEFAULT_INITIAL_POLLFD_COUNT);
if (!nat->pollData) {
LOGE("out of memory error starting EventLoop!");
goto done;
}
//申请dbus的watch data
nat->watchData = (DBusWatch **)malloc(sizeof(DBusWatch *) *
DEFAULT_INITIAL_POLLFD_COUNT);
if (!nat->watchData) {
LOGE("out of memory error starting EventLoop!");
goto done;
}
//初始化为0
memset(nat->pollData, 0, sizeof(struct pollfd) *
DEFAULT_INITIAL_POLLFD_COUNT);
memset(nat->watchData, 0, sizeof(DBusWatch *) *
DEFAULT_INITIAL_POLLFD_COUNT);
//datasize和member count的初始化
nat->pollDataSize = DEFAULT_INITIAL_POLLFD_COUNT;
nat->pollMemberCount = 1;
//申请socket 对,保存到controlFdR
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(nat->controlFdR))) {
LOGE("Error getting BT control socket");
goto done;
}
//data 0是其中一个,可以猜到了是通过socket在内部通信的
nat->pollData[0].fd = nat->controlFdR;
nat->pollData[0].events = POLLIN;
env->GetJavaVM( &(nat->vm) );
nat->envVer = env->GetVersion();
nat->me = env->NewGlobalRef(object);
//建立eventloop,详细分析见3.1
if (setUpEventLoop(nat) != JNI_TRUE) {
LOGE("failure setting up Event Loop!");
goto done;
}
//建立eventloopmain的thread,他肯定就是在不停地运行了,详细分析见3.2
pthread_create(&(nat->thread), NULL, eventLoopMain, nat);
result = JNI_TRUE;
done:
if (JNI_FALSE == result) {
if (nat->controlFdW) {
close(nat->controlFdW);
nat->controlFdW = 0;
}
if (nat->controlFdR) {
close(nat->controlFdR);
nat->controlFdR = 0;
}
if (nat->me) env->DeleteGlobalRef(nat->me);
nat->me = NULL;
if (nat->pollData) free(nat->pollData);
nat->pollData = NULL;
if (nat->watchData) free(nat->watchData);
nat->watchData = NULL;
nat->pollDataSize = 0;
nat->pollMemberCount = 0;
}
pthread_mutex_unlock(&(nat->thread_mutex));
#endif // HAVE_BLUETOOTH
return result;
}
3.1 eventloop的建立
static jboolean setUpEventLoop(native_data_t *nat) {
LOGV("%s", __FUNCTION__);
if (nat != NULL && nat->conn != NULL) {
dbus_threads_init_default();
DBusError err;
dbus_error_init(&err);
const char *agent_path = "/android/bluetooth/agent";
const char *capabilities = "DisplayYesNo";
//主要就是调用bluez的registeragent函数,见3.1.1
if (register_agent(nat, agent_path, capabilities) < 0) {
dbus_connection_unregister_object_path (nat->conn, agent_path);
return JNI_FALSE;
}
//这里是加入一个对event的过滤,所以我们上文中的propertychang之类的都是在这里面处理的,我们在后面对对应的event分析处理的时候再分析
// Add a filter for all incoming messages
if (!dbus_connection_add_filter(nat->conn, event_filter, nat, NULL)){
return JNI_FALSE;
}
//下面就是我们会watch这些interface。
// Set which messages will be processed by this dbus connection
dbus_bus_add_match(nat->conn,
"type='signal',interface='org.freedesktop.DBus'",
&err);
if (dbus_error_is_set(&err)) {
LOG_AND_FREE_DBUS_ERROR(&err);
return JNI_FALSE;
……
}
3.1.1 注册agent
这个又回到了bluez,在adapter.c中
static DBusMessage *register_agent(DBusConnection *conn, DBusMessage *msg,
void *data)
{
const char *path, *name, *capability;
struct agent *agent;
struct btd_adapter *adapter = data;
uint8_t cap;
//得到capability的值
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &capability, DBUS_TYPE_INVALID))
return NULL;
//看是否有了agent
if (adapter->agent)
return btd_error_already_exists(msg);
//解析capability,我们的输入时display yes no,所以就是有显示,有输入输出了
cap = parse_io_capability(capability);
if (cap == IO_CAPABILITY_INVALID)
return btd_error_invalid_args(msg);
name = dbus_message_get_sender(msg);
//建agent结构体
agent = agent_create(adapter, name, path, cap,
(agent_remove_cb) agent_removed, adapter);
if (!agent)
return btd_error_failed(msg, "Failed to create a new agent");
//agent和对应的adapter关联起来
adapter->agent = agent;
DBG("Agent registered for hci%d at %s:%s", adapter->dev_id, name,
path);
//设置io capability,就是设置dev的io_capability
adapter_ops->set_io_capability(adapter->dev_id, cap);
return dbus_message_new_method_return(msg);
}
所以,总的来说,还是蛮简单的,就是建了一个agent的结构体,然后把它和对应的adapter关联起来,同时设置了dev的io capability。
3.2 eventLoopMain分析
这个函数就是eventloop的主函数了,我们可以猜到,他会一直在运行。
static void *eventLoopMain(void *ptr) {
native_data_t *nat = (native_data_t *)ptr;
JNIEnv *env;
JavaVMAttachArgs args;
char name[] = "BT EventLoop";
args.version = nat->envVer;
args.name = name;
args.group = NULL;
nat->vm->AttachCurrentThread(&env, &args);
//设置dbus的watch函数,就是监听了和wakeup,这里其实是dbus的一些通信机制,
//我们可以不了解,只要知道最终我们是使用event_filter对event进行处理的就可以了
dbus_connection_set_watch_functions(nat->conn, dbusAddWatch,
dbusRemoveWatch, dbusToggleWatch, ptr, NULL);
dbus_connection_set_wakeup_main_function(nat->conn, dbusWakeup, ptr, NULL);
//这里就表示eventloop ok了
nat->running = true;
//下面这个while大概的意思就是通过一个本地的socket进行读写,然后到最后进行处理
while (1) {
……
}
这个函数更多的是涉及机制的问题,所以我们并没有详细的解析。
至此,eventloop的分析就全部完成了,他只是一个工具,下面的章节中,我们会详细分析这个工具给我们带来的便利。
4、其它的一些操作
除了上面涉及到的一系列的操作,在蓝牙打开的过程中还有一些jni层的操作,首先一个函数就是setBluetoothTetheringNative,他的主要作用就是使能或者说注册pan相关的操作,具体的分析如下:
static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value,
jstring src_role, jstring bridge) {
LOGV("%s", __FUNCTION__);
#ifdef HAVE_BLUETOOTH
native_data_t *nat = get_native_data(env, object);
if (nat) {
DBusMessage *reply;
const char *c_role = env->GetStringUTFChars(src_role, NULL);
const char *c_bridge = env->GetStringUTFChars(bridge, NULL);
if (value) {
LOGE("setBluetoothTetheringNative true");
//设置为true,所以,就是register了,是networkserver的interface
reply = dbus_func_args(env, nat->conn,
get_adapter_path(env, object),
DBUS_NETWORKSERVER_IFACE,
"Register",
DBUS_TYPE_STRING, &c_role,
DBUS_TYPE_STRING, &c_bridge,
DBUS_TYPE_INVALID);
} else {
LOGE("setBluetoothTetheringNative false");
reply = dbus_func_args(env, nat->conn,
get_adapter_path(env, object),
DBUS_NETWORKSERVER_IFACE,
"Unregister",
DBUS_TYPE_STRING, &c_role,
DBUS_TYPE_INVALID);
}
env->ReleaseStringUTFChars(src_role, c_role);
env->ReleaseStringUTFChars(bridge, c_bridge);
return reply ? JNI_TRUE : JNI_FALSE;
}
#endif
return JNI_FALSE;
}
在jni中,他的接口是:
static GDBusMethodTable server_methods[] = {
{ "Register", "ss", "", register_server },
……}
所以,最终会调用register_server函数来实现:
static DBusMessage *register_server(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct network_server *ns = data;
DBusMessage *reply;
const char *uuid, *bridge;
//得到参数
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
DBUS_TYPE_STRING, &bridge, DBUS_TYPE_INVALID))
return NULL;
//看uuid是否是nap
if (g_strcmp0(uuid, "nap"))
return btd_error_failed(msg, "Invalid UUID");
//看recored_id是否已经存在
if (ns->record_id)
return btd_error_already_exists(msg);
reply = dbus_message_new_method_return(msg);
if (!reply)
return NULL;
//若是没有,就注册server record
ns->record_id = register_server_record(ns);
if (!ns->record_id)
return btd_error_failed(msg, "SDP record registration failed");
g_free(ns->bridge);
ns->bridge = g_strdup(bridge);
//dbus disconnect的时候有的一个监听
ns->watch_id = g_dbus_add_disconnect_watch(conn,
dbus_message_get_sender(msg),
server_disconnect, ns, NULL);
return reply;
}
所以,总的来说还是蛮简单,就不深入详细分析了。
至此,jni中所涉及的所有部分就全部分析完成了哦。
若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·