[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)

plugin的define,嗯?有点意思,赶快去看看。于是跳转到这个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 bluez 编译,[android源码分析]bluez起动过程中的各种plugin的初始化(一)-bluetooth_builtin数组所耍的花样...相关推荐

  1. 【转】ABP源码分析二:ABP中配置的注册和初始化

    一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数必然已完成了执行 ...

  2. Android上百实例源码分析以及开源分析集合打包

    感谢网友banketree的收集,压缩包的内容如下: 1.360新版特性界面源代码 实现了360新版特性界面的效果,主要涉及到Qt的一些事件处理与自定义控件.但源码好像是c++. 2.aidl跨进程调 ...

  3. Android主流三方库源码分析(九、深入理解EventBus源码)

    一.EventBus使用流程概念 1.Android事件发布/订阅框架 2.事件传递既可用于Android四大组件间通信 3.EventBus的优点是代码简洁,使用简单,事件发布.订阅充分解耦 4.首 ...

  4. Android Camera 系统架构源码分析

    Android Camera 系统架构源码分析(1)---->Camera的初始化 Android Camera 系统架构源码分析(2)---->Camera的startPreview和s ...

  5. Android 系统(78)---《android framework常用api源码分析》之 app应用安装流程

    <android framework常用api源码分析>之 app应用安装流程 <android framework常用api源码分析>android生态在中国已经发展非常庞大 ...

  6. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  7. Android录音下————AudioRecord源码分析

    Android录音下----AudioRecord源码分析 文章目录 Android录音下----AudioRecord源码分析 一.概述 1.主要分析点 2.储备知识 二.getMinBufferS ...

  8. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  9. Android 双开沙箱 VirtualApp 源码分析(一)

    最近发现了一个非常好的开源项目,基本实现了一个 Android 上的沙箱环境,不过应用场景最多的还是应用双开. VA github: https://github.com/asLody/Virtual ...

  10. Android 双开沙箱 VirtualApp 源码分析(六)ContentProvider

    上一章:Android 双开沙箱 VirtualApp 源码分析(五)BroadcastReceiver Provider 注册 回顾前面,Activity 启动的时候会检查 Application ...

最新文章

  1. 不可不知的sudo命令
  2. facade 模式和gateway模式的区别
  3. OpenCV透视变换应用于图像的实例(附完整源代码)
  4. c++ 指针拼接字符串_字符串拼接+和concat的区别
  5. 10款常用Java测试工具
  6. 《程序员面试宝典》精华 面向对象部分
  7. 说说emit(上)基本操作
  8. SqlHelper 类
  9. 【软考 系统架构设计师】软件架构设计⑦ 构件与中间件技术
  10. SpringBoot实现本地、网络文件下载、zip压缩包批量下载
  11. 使用 matlab 数字图像处理(三)—— 实现图像的旋转(不使用 imrotate)
  12. Linux怎么有两个vmdk文件,「Linux」- 挂载 VMDK 文件
  13. 光纤模块与光纤收发器使用方法
  14. 【文献翻译】用于5G蜂窝的毫米波移动通信:我看行!
  15. python订单管理系统功能_后台系统:订单管理
  16. 智慧社区综合信息服务平台,让你的社区更智能
  17. 为什么有些大公司技术弱爆了?
  18. 第三代测序技术在微生物研究中的应用
  19. 插画版 Kubernetes 指南
  20. python学习笔记之pdf文档提取

热门文章

  1. 小米升鸿蒙系统,小米11升级鸿蒙系统
  2. 2022年陕西省职业院校技能大赛中职组网络安全赛项规程
  3. 高等数学:第六章 定积分的应用(3)体积
  4. 微信小程序实现扫码登录网站
  5. DFS+记忆化搜索 -- 简单练习
  6. 绘画软件:krita for Mac
  7. 现在唯一可以得到卡巴斯基激活码的地方
  8. 谷歌浏览器将网页保存为图片或者pdf
  9. 利用幅度谱和相位谱重构图像
  10. 常见电容器图片_常用电容器的标识方法(图)