我们先从宏观感受一下avdtp协议是个啥东东, 和 a2dp 是啥关系。 在蓝牙协议中的层次。以及他是如何和 例如l2cap 、sdp、a2dp 配合的。先从宏观把握,我们在逐步展开对 avdtp 的源码分析。
我们先从生活中的小例子感性的认识一下 avdtp 在 蓝牙协议中的作用。
1. 生活类比:蓝牙音频连接就像“点歌听歌”的过程
想象这样一个场景:
你在车里(车机 = 音箱 = A2DP Sink),朋友(手机 = 点歌机 = A2DP Source)说“我来放首歌给你听”,然后你们需要经历这样几个步骤:
-
互相认识(SDP):你要先确认朋友有播放音乐的能力。
-
建立通道(L2CAP):你们要找一个通信频道。
-
协商规则(AVDTP):你告诉朋友你的音箱支持什么格式,朋友告诉你它打算用什么格式。
-
开始播放(A2DP Media):音乐开始通过媒体通道传输。
2. 车机作为 A2DP Sink 的角色 —— 连接流程详解
蓝牙音频连接总的来说分为两种情况:
1. 情况一:车机主动连接手机
1. 总流程
车机发起连接 → SDP 查询手机支持的服务 → 建立 L2CAP Signaling 信令通道 → AVDTP 握手(发现能力、配置参数) → 建立 L2CAP Media 媒体通道 → 接收音频
2. 详细步骤:
步骤 | 协议 | 内容 | 类比场景 |
---|---|---|---|
1 | SDP | 车机发起 SDP 查询,发现手机是否支持 A2DP Source 服务 | 你问朋友:“你有音乐播放器吗?” |
2 | L2CAP | 建立信令通道(PSM = 0x0019)用于 AVDTP 协议通信 | 找了个频道和朋友说话 |
3 | AVDTP | 发起 Discover 命令 → 获取手机有哪些 SEID(音频流终端) 发 GetCapabilities → 获取格式能力 | 你问:“你打算放 MP3 还是 AAC?” |
4 | AVDTP | SetConfiguration:告诉手机用哪一套格式 Open:准备打开流 Start:开始播放 | “OK,我调音箱为 AAC,准备好了,你放吧” |
5 | L2CAP | 建立媒体通道(PSM = 动态分配,一般为 0x0041~) | 专门留出一个通道让他只传音乐 |
6 | A2DP | 音频数据通过媒体通道传输 | 歌曲开始响起来啦 |
步骤一:SDP 服务发现
-
使用目标手机的 BluetoothDevice 对象发起 SDP 查询
-
查询 UUID:
0000110a-0000-1000-8000-00805f9b34fb
(A2DP Source Profile) -
获取结果:包括服务名称、支持的协议层(L2CAP、AVDTP)和版本等
步骤二:建立信令通道(L2CAP)
-
使用 SDP 得知信令通道的协议号:PSM = 0x0019(AVDTP)
-
调用 L2CAP API 主动连接该 PSM,成功后会触发
avdt_l2c_appl()
回调(连接完成)
步骤三:AVDTP 信令交互(命令 / 响应)
建立后,车机通过信令通道发送一系列命令:
命令 | 含义 | 说明 |
---|---|---|
Discover | 查询对方有哪些流终端(Stream Endpoint) | 手机返回一组 SEID(Stream Endpoint ID) |
GetCapabilities | 获取指定 SEID 的能力参数 | 返回媒体类型、编码格式(SBC、AAC)等 |
SetConfiguration | 设置要使用的参数 | 告诉手机我们选择哪个 SEID、格式和参数 |
Open | 打开音频流连接 | 等待手机返回成功 |
Start | 启动媒体传输 | 通知手机可以开始发音频数据 |
步骤四:建立媒体通道(L2CAP)
-
一旦信令通道中
Start
命令响应成功 -
手机将主动发起对车机的 媒体通道连接请求
- 使用 L2CAP 的动态 PSM(一般在 0x0040~ 范围内分配)
-
车机通过回调
avdt_l2c_appl()
的媒体通道路径接收此连接请求 -
成功建立后,该通道用于传输实时音频数据
2. 情况二:手机主动连接车机
1. 总流程
手机发起连接 → SDP 查询车机支持的服务 → 建立 L2CAP Signaling 通道 → AVDTP 握手 → 建立 Media 通道 → 播放音频
其实和上面一样,只是连接发起方是手机,车机在回调中被动响应:
步骤 | 协议 | 内容 | 类比场景 |
---|---|---|---|
1 | SDP | 手机发起 SDP 查询,发现车机是否支持 A2DP Sink | 手机问:“你是个音箱吗?” |
2 | L2CAP | 手机连接车机的 AVDTP 信令 PSM(0x0019) 车机触发回调 avdt_l2c_appl | 手机说:“我来连接你!” |
3 | AVDTP | 手机发起 Discover → GetCapabilities → SetConfiguration → Open → Start,车机回应 | 手机说:“我打算放 AAC,你支持吗?” 车机回应:“可以” |
4 | L2CAP | 手机再连接媒体 PSM,车机回应 | 手机说:“我来给你开个专门传音乐的通道” |
5 | A2DP | 手机开始传输音频数据,车机播放 | 开始放歌啦 |
流程几乎一样,但顺序如下:
-
手机通过 SDP 查询车机是否支持 A2DP Sink(UUID:
0000110b-...
) -
手机主动连接车机 L2CAP 信令 PSM(0x0019)
-
车机接收到连接回调,调用
avdt_l2c_appl()
注册回调 -
手机作为 AVDTP 控制端,发起一系列 AVDTP 命令(Discover → GetCapabilities → SetConfiguration → Open → Start)
-
车机根据命令进行响应
-
手机在 Start 成功后,主动连接媒体通道
-
媒体连接建立后,开始发送音频数据
3. AVDTP 和 A2DP 的关系
协议 | 作用 | 类比 |
---|---|---|
A2DP | 高层协议,定义了音频传输规范、格式、媒体处理等 | 总经理,定方向和政策:“我们要听高质量音乐” |
AVDTP | 低层传输协议,负责信令和媒体通道的管理 | 秘书,安排通道、建立会话:“在哪儿说、怎么说、啥时候开始说” |
L2CAP | 传输层协议,负责数据通道的建立 | 电话线路,管你说啥都要先打通 |
SDP | 服务发现协议,找出对方支持哪些服务 | 电话簿:“看看朋友有没有音乐播放器” |
为什么要这样分层?
- 便于解耦、复用。比如 AVDTP 除了服务 A2DP,还服务过 AVCTP(远程控制);
- 各个协议关注不同方面(发现、通道管理、传输等),模块化设计利于扩展和调试;
- 便于移植不同平台或设备(比如耳机、音响、电视、车机)都可以重用相同底层逻辑。
4. 总结类比回顾
类比元素 | 对应协议层 | 职责 |
---|---|---|
电话簿 | SDP | 查服务 |
电话线路 | L2CAP | 建立传输通道 |
会话安排人 | AVDTP | 安排音频通道、配置 |
总经理 | A2DP | 决定播放策略和格式 |
播放器 | 媒体通道 | 真正播放音乐的数据流 |