当前位置: 代码迷 >> Android >> [android源码分析]bluez起动过程中的各种plugin的初始化(一)-bluetooth_builtin数组所耍的花样
  详细解决方案

[android源码分析]bluez起动过程中的各种plugin的初始化(一)-bluetooth_builtin数组所耍的花样

热度:30   发布时间:2016-04-28 07:30:07.0
[android源码分析]bluez启动过程中的各种plugin的初始化(一)--__bluetooth_builtin数组所耍的花样

在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/shfor i in $*do    echo "extern struct bluetooth_plugin_desc __bluetooth_builtin_$i;"doneechoecho "static struct bluetooth_plugin_desc *__bluetooth_builtin[] = {"for i in $*do    echo "  &__bluetooth_builtin_$i,"doneecho "  NULL"echo "};"

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

Makefile.am文件中:

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

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

 

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

  相关解决方案