[android源码分析]sdp Server的启动分析
SDP server是蓝牙启动过程中的一个非常重要部分。本文简单介绍一下这个函数的实现。
[cpp] view plaincopy
int start_sdp_server(uint16_t mtu, const char *did, uint32_t flags)
{
//这里传入的flags是SDP_SERVER_COMPAT
//所以compat值是有效的,master应该是0
int compat = flags & SDP_SERVER_COMPAT;
int master = flags & SDP_SERVER_MASTER;
GIOChannel *io;
info("Starting SDP server");
//初始化server,详细见2.3.4.1
if (init_server(mtu, master, compat) < 0) {
error("Server initialization failed");
return -1;
}
//did就是传入的device id,也就是main_opts.deviceid,他是根据DeviceID这个值来设置的,根据我们的main.conf,他的值就是android:generic:1.5
if (did && strlen(did) > 0) {
const char *ptr = did;
uint16_t vid = 0x0000, pid = 0x0000, ver = 0x0000;
//vid=android
//pid=generic
//version=1.5
vid = (uint16_t) strtol(ptr, NULL, 16);
ptr = strchr(ptr, ':');
if (ptr) {
pid = (uint16_t) strtol(ptr + 1, NULL, 16);
ptr = strchr(ptr + 1, ':');
if (ptr)
ver = (uint16_t) strtol(ptr + 1, NULL, 16);
//注册device id,仍然是一个service record的注册,不详细分析了,也会有UUIDS的property change哦
register_device_id(vid, pid, ver);
}
}
//对刚刚建的L2cap通道进行监听
io = g_io_channel_unix_new(l2cap_sock);
g_io_channel_set_close_on_unref(io, TRUE);
//也就是accept了,处理函数是io_accept_event
l2cap_id = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
io_accept_event, &l2cap_sock);
g_io_channel_unref(io);
//若是compat,则对unix_sock进行监听,处理函数同样是io_accept_event
if (compat && unix_sock > fileno(stderr)) {
io = g_io_channel_unix_new(unix_sock);
g_io_channel_set_close_on_unref(io, TRUE);
unix_id = g_io_add_watch(io,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
io_accept_event, &unix_sock);
g_io_channel_unref(io);
}
return 0;
}
2.3.4.1 init_server
这个从注释来看,就是sdp server的一些初始化,包括创建l2cap和unix socket用于discovery和registerclient来进行独立地访问。具体我们还是从代码的角度来分析:
[cpp] view plaincopy
static int init_server(uint16_t mtu, int master, int compat)
{
struct l2cap_options opts;
struct sockaddr_l2 l2addr;
struct sockaddr_un unaddr;
socklen_t optlen;
/* Register the public browse group root */
//注册public browse group root,不详细介绍,上面的service record创建中有详细介绍过
register_public_browse_group();
//注册一个sdp server的service record
/* Register the SDP server's service record */
register_server_service();
//创建L2CAP的socket
/* Create L2CAP socket */
l2cap_sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
if (l2cap_sock < 0) {
error("opening L2CAP socket: %s", strerror(errno));
return -1;
}
memset(&l2addr, 0, sizeof(l2addr));
l2addr.l2_family = AF_BLUETOOTH;
//addr 是any
bacpy(&l2addr.l2_bdaddr, BDADDR_ANY);
//psm是SDP
l2addr.l2_psm = htobs(SDP_PSM);
//就是把该l2cap和bdaddr_any绑定
if (bind(l2cap_sock, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) {
error("binding L2CAP socket: %s", strerror(errno));
return -1;
}
//要做master,其实我们默认配置可选的,所以,这里就不会走到了
if (master) {
int opt = L2CAP_LM_MASTER;
if (setsockopt(l2cap_sock, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) {
error("setsockopt: %s", strerror(errno));
return -1;
}
}
//设置mtu,默认传入的mtu是0,也就是使用kernel中的默认配置
if (mtu > 0) {
memset(&opts, 0, sizeof(opts));
optlen = sizeof(opts);
if (getsockopt(l2cap_sock, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) {
error("getsockopt: %s", strerror(errno));
return -1;
}
opts.omtu = mtu;
opts.imtu = mtu;
if (setsockopt(l2cap_sock, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {
error("setsockopt: %s", strerror(errno));
return -1;
}
}
//开始监听,最多5个,下面就可以accept了
if (listen(l2cap_sock, 5) < 0) {
error("listen: %s", strerror(errno));
return -1;
}
//compat默认是1
if (!compat) {
unix_sock = -1;
return 0;
}
//得到bluetooth的控制socket
//这是和上层socket的一个通信,具体在上层用到的时候,我们再来分析
unix_sock = android_get_control_socket("bluetooth");
if (unix_sock < 0) {
error("Unable to get the control socket for 'bluetooth'");
return -1;
}
//监听
if (listen(unix_sock, 5)) {
error("Listening on local socket failed: %s", strerror(errno));
return -1;
}
info("Got Unix socket fd '%d' from environment", unix_sock);
}
[android源码分析]sdp Server的启动分析相关推荐
- android源码解析------Media多媒体framework层分析
1.packages\providers\MediaProvider :含以下 java 文件 MediaProvider.java MediaScannerReceiver.java MediaSc ...
- 【Android 源码学习】系统架构和启动流程
Android 源码学习 系统架构和启动流程 望舒课堂 学习记录整理.以及以下参考文章的整理汇总.便于我个人的学习记录. 感谢IngresGe,Gityuan的精彩文章.为我们这些初探android系 ...
- Android 源码 PackageManagerService 启动流程分析
<Android 源码 installPackage 流程分析>一节着重分析了 apk 安装流程,接下来我们分析 PackageManagerService 启动时都做了些什么? 执行 P ...
- Android 源码分析 Activity的启动模式
一直想抽空针对AMS进行源码分析,无奈一方面因为很忙,另外AMS很复杂,涉及的知识点也比较多,今天利用五一假期对AMS的一个方面,Activity的启动模式进行源码分析,这里面包括了ActivityR ...
- Android4.0源码Launcher启动流程分析【android源码Launcher系列一】
最近研究ICS4.0的Launcher,发现4.0和2.3有稍微点区别,但是区别不是特别大,所以我就先整理一下Launcher启动的大致流程. Launcher其实是贯彻于手机的整个系统的,时时刻刻都 ...
- Android中ICS4.0源码Launcher启动流程分析【android源码Launcher系列一】
最近研究ICS4.0的Launcher,发现4.0和2.3有稍微点区别,但是区别不是特别大,所以我就先整理一下Launcher启动的大致流程.Launcher其实是贯彻于手机的整个系统的,时时刻刻都在 ...
- Android源码分析--MediaServer源码分析(二)
在上一篇博客中Android源码分析–MediaServer源码分析(一),我们知道了ProcessState和defaultServiceManager,在分析源码的过程中,我们被Android的B ...
- Android源码分析-PackageManagerService(PMS)源码分析(三)- queryIntentActivities函数来查找activity
queryIntentActivities函数的作用: 在Android应用程序开发中,用startActivity可以开启另外一个Activity或应用.startActivity函数必须包含Int ...
- android源码分析
01_Android系统概述 02_Android系统的开发综述 03_Android的Linux内核与驱动程序 04_Android的底层库和程序 05_Android的JAVA虚拟机和JAVA环境 ...
最新文章
- python--微信小程序获取手机号码报错
- matlab利用t-SNE实现高维数据可视化(tsne函数用法实例)
- IDEA、Sublime、Eclipse、VSCode 常用快捷键整合
- 数据库中触发器、事务
- 2021计算机应用基础形考答案模块2,国家开放大学计算机应用基础模块2形考答案-20210603091431.docx-原创力文档...
- matlab实现浮点转定点,浮点转定点方法总结.doc
- win2003下面显示dbgprint的输出内容
- Maven常见警告解决办法
- mysql语句判断是否存在记录,没有则插入新纪录否则不执行
- 102 二叉树层序遍历Binary Tree Level Order Traversal @ Python
- 提高笔记本无线网络速度
- java 开源esb_五大开源ESB项目
- css空心三角形_CSS实现空心三角指示箭头
- 心理学中的催眠术怎么学[为本教育]
- 支付宝里面基金的猫腻?为什么计算对不上?
- 82.【LibraryManger】
- 计算机网络-应用层和传输层协议分析实验(PacketTracer)
- 把图片放大后还很清晰的办法
- 梅宏:学海无涯苦作舟
- 38个PS常用工具箱快捷键,找工具不慌、不忙、不乱(纯干货)