[android源码分析]bluez启动过程中的各种plugin的初始化(一)--

xiaoxiao2021-03-01  2

在bluez启动过程中,各种插件的初始化尤为重要,没有这些插件,很多功能将无法实现。

2.3.5 plugin的初始化

插件的初始化,是什么的干活,其实还是很重要的,我们来看看吧。

gboolean plugin_init(GKeyFile *config, const char *enable, const char *disable) { GSList *list; GDir *dir; const gchar *file; char **conf_disabled, **cli_disabled, **cli_enabled; unsigned int i; /* Make a call to BtIO API so its symbols got resolved before the * plugins are loaded. */ //不知道这里调了干嘛 bt_io_error_quark(); //有config文件,会去解析General中的DisablePlugins,我们其实可以看到它是没有的 if (config) conf_disabled = g_key_file_get_string_list(config, "General", "DisablePlugins", NULL, NULL); else conf_disabled = NULL; //这个enable是null,所以忽略 if (enable) cli_enabled = g_strsplit_set(enable, ", ", -1); else cli_enabled = NULL; //disable也是null,忽略 if (disable) cli_disabled = g_strsplit_set(disable, ", ", -1); else cli_disabled = NULL; DBG("Loading builtin plugins"); //这里是遍历__bluetooth_builtin数组了,__bluetooth_builtin数组这里有必要详细解释一下,见2.3.5.1 for (i = 0; __bluetooth_builtin[i]; i++) { //enable_plugin因为conf_disabled,cli_enabled,cli_disabled均为null,所以什么都没有做,直接return true了 if (!enable_plugin(__bluetooth_builtin[i]->name, conf_disabled, cli_enabled, cli_disabled)) continue; //下面就是加入plugin了,这里又会发生些什么好玩的东西呢,我们看2.3.5.2 add_plugin(NULL, __bluetooth_builtin[i]); } //看是否有PLUGINDIR,从Android.mk中可以发现: /*-DPLUGINDIR=\"/system/lib/bluez-plugin\*/ //PLUGINDI就是/system/lib/bluez-plugin这个目录,所以,我们这里要继续往下看了 if (strlen(PLUGINDIR) == 0) goto start; DBG("Loading plugins %s", PLUGINDIR); //打开这个路径 dir = g_dir_open(PLUGINDIR, 0, NULL); if (!dir) goto start; //打开这个文件夹,并去除每个文件的名字 while ((file = g_dir_read_name(dir)) != NULL) { struct bluetooth_plugin_desc *desc; void *handle; gchar *filename; //以lib开头,或者不以.so结尾,我们都认为是有问题的,直接跳出 if (g_str_has_prefix(file, "lib") == TRUE || g_str_has_suffix(file, ".so") == FALSE) continue; //filename就是该文件的包含目录的完整文件名 filename = g_build_filename(PLUGINDIR, file, NULL); //打开这个动态库 handle = dlopen(filename, RTLD_NOW); if (handle == NULL) { error("Can't load plugin %s: %s", filename, dlerror()); g_free(filename); continue; } g_free(filename); //找到bluetooth_plugin_desc desc = dlsym(handle, "bluetooth_plugin_desc"); if (desc == NULL) { error("Can't load plugin description: %s", dlerror()); dlclose(handle); continue; } //使能,什么都不做,和上面一样 if (!enable_plugin(desc->name, conf_disabled, cli_enabled, cli_disabled)) { dlclose(handle); continue; } //加到plugin中去,最终plugin中包含hciops, audio,health,input,network if (add_plugin(handle, desc) == FALSE) dlclose(handle); } start: for (list = plugins; list; list = list->next) { struct bluetooth_plugin *plugin = list->data; //调用对应的plugin的init函数,以hciops为例进行分析,详细见2.3.5.3 if (plugin->desc->init() < 0) { error("Failed to init %s plugin", plugin->desc->name); continue; } //把active置位true plugin->active = TRUE; } g_strfreev(conf_disabled); g_strfreev(cli_enabled); g_strfreev(cli_disabled); return TRUE; }

2.3.5.1 __bluetooth_builtin数组所耍的花样

呵呵,这个数组我看了有一会了,为什么呢?因为他里面用了一些我们所谓的奇淫技巧,这样的代码用起来是蛮方便的,可是等别人去阅读的时候就是个悲剧啊。

首先,很简单,我们去搜索一下,立即就能发现这个数组的定义:

extern struct bluetooth_plugin_desc __bluetooth_builtin_hciops; static struct bluetooth_plugin_desc *__bluetooth_builtin[] = { &__bluetooth_builtin_hciops, NULL };

简单吧,里面就只有一个元素:&__bluetooth_builtin_hciops,这个元素是extern的,肯定就是在别的地方定义啦,于是去搜索一下呗,奶奶个熊的,你发现搜索不到这个东西,没有&__bluetooth_builtin_hciops啊,要崩溃了吧,哈哈。

在某一个月黑风高的夜晚,我咬着铅笔头,冥思苦想这个问题,突然间,我发现这个hciops好熟悉,bluez里面有这个文件啊,就决定去这个文件里面看看,在不起眼的最后一行,发现了如下语句:

BLUETOOTH_PLUGIN_DEFINE(hciops, VERSION, BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit)

plugindefine,嗯?有点意思,赶快去看看。于是跳转到这个BLUETOOTH_PLUGIN_DEFINE定义的地方:

//在Android.mk中,这个define是有的,所以,就看上面的,不看else了 #ifdef BLUETOOTH_PLUGIN_BUILTIN //于是根据这个定义,把上面的宏替代之后就是: /* struct bluetooth_plugin_desc __bluetooth_builtin_hciops = { hciops, VERSION, BLUETOOTH_PLUGIN_PRIORITY_LOW, hciops_init, hciops_exit }; */ //哈哈,众里寻他千百度啊,简单吧~~嘻嘻。。 #define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \ struct bluetooth_plugin_desc __bluetooth_builtin_ ## name = { \ #name, version, priority, init, exit \ }; #else #define BLUETOOTH_PLUGIN_DEFINE(name, version, priority, init, exit) \ extern struct bluetooth_plugin_desc bluetooth_plugin_desc \ __attribute__ ((visibility("default"))); \ struct bluetooth_plugin_desc bluetooth_plugin_desc = { \ #name, version, priority, init, exit \ }; #endif

额外资讯:

大家继续往后面看会发现,android加载别的plugin的方法是遍历system/lib/bluez-plugin目录下的动态库,从而进行加载的,然后在原生bluez中则不是这样实现的。因为实现的方法实在不错,所以这里也简单介绍一下:

就在我开开心心地以为我自己很牛x的时候,打印了一下__bluetooth_builtin数组,突然发现它里面不止一个hicops,然后赶紧偷偷搜索了一下BLUETOOTH_PLUGIN_DEFINE,发现它出来了竟然有近十个,啊~~这些东东都是什么时候加进去的啊?

继续来搜索__bluetooth_builtin,这次把非c文件也搜索了下,我坚信肯定是makefile或者什么别的文件在捣乱。呵呵,果然,找到了src下面的genbuiltin文件,我们来看一下写的什么:

#!/bin/sh for i in $* do echo "extern struct bluetooth_plugin_desc __bluetooth_builtin_$i;" done echo echo "static struct bluetooth_plugin_desc *__bluetooth_builtin[] = {" for i in $* do echo " &__bluetooth_builtin_$i," done echo " NULL" echo "};"

#从这个文件就可以看出来个大概了,看样子,他们把__bluetooth_builtin_**别的东西都加入到了*__bluetooth_builtin这个数组中去了。考虑到这个文件是一个shell的文件,$*就是所有传入的参数了,我们去看调用他的地方吧,所以,我们继续搜索一下genbuiltin。哈哈,果然找到了,藏得还蛮深的嘛,小样:

Makefile.am文件中:

//第一行就是要编译的文件 src/builtin.h: src/genbuiltin $(builtin_sources) //这个就是输入到$@文件中,就是builtin.h中,所以,我们后面看到的builtin文件其实是已经改变过的,至于builtin_modules就是根据各种宏定义来取舍的,具体大家自己去分析了,我就不再多说了 $(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_modules) > $@

至此,__bluetooth_builtin数组就分析完成了,哎~,奇淫技巧,呵呵~~

若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·

相关资源:敏捷开发V1.0.pptx
转载请注明原文地址: https://www.6miu.com/read-3850088.html

最新回复(0)