[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/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数组就分析完成了,哎~,奇淫技巧,呵呵~~

 

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

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/u011960402/article/details/13768785
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞