Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android源碼解析]Eventloop在jni層的分析

[Android源碼解析]Eventloop在jni層的分析

編輯:關於Android編程

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中所涉及的所有部分就全部分析完成了哦。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved