3 eventloop在jni層的詳細分析
Eventloop在整個bluetooth的jni層和bluez之間的交互,以及jni和framework層之間的交互過程中有著舉足輕重的作用。所以,本文仍然需要花費一定的筆墨來分析它,當然由於它更像是一個橋梁,我們的分析有可能就不是那麼的深入了,會從比較宏觀地角度來看待這個東西的作用。
當然,一切的一切還是要從源碼來說:
[cpp]
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的建立
[cpp]
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中
[cpp]
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的主函數了,我們可以猜到,他會一直在運行。
[cpp]
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相關的操作,具體的分析如下:
[cpp]
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中所涉及的所有部分就全部分析完成了哦。