协议架构

上面描述的就是整体的协议架构,我们针对蓝牙音乐的协议架构分析,其中涉及到了几个协议:

其中针对业务层的逻辑,涉及到了A2DP和AVRCP协议;
AVRCP
AVRCP全称:Audio/Video Remote Control Profile,即音频/视频远程控制配置文件。
AVRCP设计用于提供控制TV,Hi-Fi设备等的标准接口,此配置文件用于许可单个远程控制设备(或其他设备)控制所有用于可以接入的A/V设备。AVRCP定义了如何控制流媒体的特征。包括暂停、停止、启动重放、音量控制及其他类型的远程控制操作(其实和DLNA的指令控制类似);
AVRCP是一种在蓝牙协议栈A2DP/AVRCP上实现的控制技术;
A2DP
A2DP全称:Advenced Audio Distribution Profile,即蓝牙音频传输模型协定;
A2DP规定了使用蓝牙异步传输信道方式,传输高质量音乐文件数据的协议堆栈软件和使用方法,基于该协议就能通过以蓝牙方式传输高品质的音乐。例如使用蓝牙耳机或蓝牙音响设备来收听音乐了;
针对上述的相关的协议,其实和蓝牙命令请求和响应有密切的关联;

Command & Event
Command
我们整理一下蓝牙音乐过程中涉及到的常见的一些Command;
Protocol | JNI | Command | Desc |
---|---|---|---|
A2dpSink | BluetoothA2dpSinkServiceJni | classInitNative | 初始化A2dpSink Native |
A2dpSink | BluetoothA2dpSinkServiceJni | connectA2dpNative | 用于连接A2dp |
Sdp | BluetoothSdpJni | sdpCreateOppOpsRecordNative | 创建服务记录列表 |
Sdp | BluetoothSdpJni | sdpSearchNative | 搜索服务 |
Avrcp | BluetoothAvrcpControllerJni | getPlayerListNative | 获取播放列表 |
Avrcp | BluetoothAvrcpControllerJni | sendPassThroughCommandNative | 68:播放 70:暂停 75:下一首 76:上一首 |
Event
Event代表的就是上层业务层向下发送指令到底层返回的callback响应;
Protocol | JNI | Event | Desc |
---|---|---|---|
A2dpSink | BluetoothA2dpSinkServiceJni | bta2dp_connection_state_callback | 响应A2dp服务连接 |
Sdp | BluetoothSdpJni | sdp_search_callback | 响应sdp服务搜索结果 |
A2dpSink | BluetoothA2dpSinkServiceJni | bta2dp_audio_config_callback | A2dp audio配置变化回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_connection_state_callback | Avrcp服务连接状态回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_get_rcfeatures_callback | |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_play_status_changed_callback | 当前播放状态变化信息回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_track_changed_callback | TrackInfo信息变化回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_set_addressed_player_callback | 设置address地址信息结果回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_uids_changed_callback | uid变化回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_get_folder_items_callback | 获取文件夹目录信息回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_playerapplicationsetting_callback | 播放器设置结果回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_playerapplicationsetting_changed_callback | 更换播放器结果回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_available_player_changed_callback | 播放可行性变化回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_addressed_player_update_callback | address信息变化回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_play_position_changed_callback | 播放进度条信息回调 |
Avrcp | BluetoothAvrcpControllerJni | btavrcp_passthrough_response_callback | 指令响应结果回调 |
A2dpSink | BluetoothA2dpSinkServiceJni | bta2dp_audio_state_callback | A2dp audio状态变化结果回调 |
协议分析
我们按照蓝牙音乐的播放流程逐一分析涉及到的协议;
A2dpSink 连接
这个过程中涉及到的Command和Event为:
-
Command
- connectA2dpNative
-
Event
- bta2dp_connection_state_callback
- bta2dp_audio_config_callback
connectA2dpNative
Operation
ruby
01-01 00:07:30.619 1713 2134 I BluetoothA2dpSinkServiceJni: connectA2dpNative: sBluetoothA2dpInterface: 0x77307fd3e8
01-01 00:07:30.619 1713 1713 D A2dpSinkStateMachine: Connection state 30:AA:E4:42:C7:DD: 0->1
01-01 00:07:30.619 1713 2134 I btif_av : sink_connect_src: Peer 30:aa:e4:42:c7:dd
01-01 00:07:30.619 1713 2134 D A2dpSinkStateMachine: Exit Disconnected: 1
01-01 00:07:30.619 1713 2134 D A2dpSinkStateMachine: Enter Pending: 1
01-01 00:07:30.619 1713 1794 I bt_btif_queue: queue_int_add: adding connection request: address=30:aa:e4:42:c7:dd UUID=110B busy=false
01-01 00:07:30.619 1713 1794 I bt_btif_queue: btif_queue_connect_next: executing connection request: address=30:aa:e4:42:c7:dd UUID=110B busy=false
01-01 00:07:30.619 1713 1794 I bt_btif : connect_int: peer_address=30:aa:e4:42:c7:dd uuid=0x110b
01-01 00:07:30.619 1713 1794 D bt_btif : BtifAvPeer *BtifAvSink::FindOrCreatePeer(const RawAddress &, tBTA_AV_HNDL): peer_address=30:aa:e4:42:c7:dd bta_handle=0x0
01-01 00:07:30.619 1713 1794 I btif_av : BtifAvPeer *BtifAvSink::FindOrCreatePeer(const RawAddress &, tBTA_AV_HNDL): Create peer: peer_address=30:aa:e4:42:c7:dd bta_handle=0x41 peer_id=0
01-01 00:07:30.619 1713 1794 D bt_btif : virtual void BtifAvStateMachine::StateIdle::OnEnter(): Peer 30:aa:e4:42:c7:dd
01-01 00:07:30.619 1713 1794 W bt_btif : btif_av_get_peer_sep: No active peer found
01-01 00:07:30.619 1713 1794 I bt_btif_a2dp: btif_a2dp_on_idle: ## ON A2DP IDLE ## peer_sep = 1
01-01 00:07:30.619 1713 1794 W bt_btif : btif_av_get_peer_sep: No active peer found
01-01 00:07:30.619 1713 1794 I bt_btif_a2dp_source: btif_a2dp_source_on_idle: state=STATE_OFF
01-01 00:07:30.619 1713 1794 D bt_btif : virtual bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t, void *): Peer 30:aa:e4:42:c7:dd : event=BTIF_AV_CONNECT_REQ_EVT(0x19) flags=0x0(None) active_peer=false
01-01 00:07:30.619 1713 1794 I bt_bta_av: BTA_AvOpen: peer 30:aa:e4:42:c7:dd handle:0x41 use_rc=true sec_mask=0x12 uuid=0x110b
01-01 00:07:30.619 1294 1294 D BTDevConnectionPolicy: Received Intent for device: 30:AA:E4:42:C7:DD android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED
01-01 00:07:30.620 1294 1294 D GwmBTDevConnePolicy: Received Intent for device: 30:AA:E4:42:C7:DD android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED
01-01 00:07:30.620 1713 2064 I bt_btif : bta_sys_event: Event 0x1209
01-01 00:07:30.620 1713 2064 D bt_btif : bta_av_do_disc_a2dp: peer_addr: 30:aa:e4:42:c7:dd use_rc: 1 switch_res:0, oc:0
01-01 00:07:30.620 1713 2064 D bt_btm : BTM_GetRole
01-01 00:07:30.620 1713 2064 D bt_btif : bta_av_do_disc_a2dp: ok_continue: 1 wait:0x0, q_tag: 0
01-01 00:07:30.620 1713 2064 D bt_btif : bta_av_save_addr: peer=30:aa:e4:42:c7:dd recfg_sup:1, suspend_sup:1
01-01 00:07:30.620 1294 1294 D BTDevConnectionPolicy: Received BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED currState = 1
01-01 00:07:30.620 1713 2064 I bt_bta_av: bta_av_save_addr: reset flags old_addr=00:00:00:00:00:00 new_addr=30:aa:e4:42:c7:dd
01-01 00:07:30.620 1294 1294 E GwmBTDevConnePolicy: notifyGWMConnectionStatus currentState = 1
01-01 00:07:30.620 1713 2064 D bt_bta_av: SetAvdtpVersion: AVDTP version for 30:aa:e4:42:c7:dd set to 0x103
01-01 00:07:30.620 1713 2064 D bt_btif : bta_dm_pm_cback: st(2), id(18), app(0)
01-01 00:07:30.620 1294 1294 D GwmBTDevConnePolicy: notifyGWMConnectionStatus() Ignoring state: 1
01-01 00:07:30.620 1713 2064 D bt_btif : bta_av_do_disc_a2dp: Initiate SDP discovery for peer 30:aa:e4:42:c7:dd : uuid_int=0x110b sdp_uuid=0x110a
01-01 00:07:30.620 1713 2064 I a2dp_api: A2DP_FindService: peer: 30:aa:e4:42:c7:dd UUID: 0x110a
01-01 00:07:30.620 1713 2064 I bt_sdp : sdp_conn_originate: SDP - Originate started for peer 30:aa:e4:42:c7:dd
01-01 00:07:30.620 1713 2064 D bt_l2cap: l2cu_allocate_ccb: cid 0x0000
01-01 00:07:30.620 1713 2064 D bt_l2cap: l2cu_enqueue_ccb CID: 0x0043 priority: 2
01-01 00:07:30.620 1713 2064 D bt_l2cap: l2c_link_adjust_chnl_allocation
01-01 00:07:30.620 1713 2064 I bt_l2cap: CID:0x0041 FCR Mode:0 Priority:2 TxDataRate:1 RxDataRate:1 Quota:200
01-01 00:07:30.620 1713 2064 I bt_l2cap: CID:0x0043 FCR Mode:0 Priority:2 TxDataRate:1 RxDataRate:1 Quota:200
01-01 00:07:30.620 1713 2064 I bt_l2cap: L2CAP - LCID: 0x0043 st: CLOSED evt: UPPER_LAYER_CONNECT_REQ
01-01 00:07:30.620 1713 2064 D bt_btm : btm_sec_l2cap_access_req() is_originator:1, 0x3090e688, psm=0x0001
01-01 00:07:30.620 1713 2064 I bt_btm : btm_find_or_alloc_dev
01-01 00:07:30.620 1713 2064 D bt_btm : btm_sec_is_serv_level0: PSM: 0x0001 -> mode 4 level 0 service
01-01 00:07:30.620 1713 2064 D bt_l2cap: l2c_link_sec_comp2: status=17, p_ref_data=0x773090e688, BD_ADDR=30:aa:e4:42:c7:dd
01-01 00:07:30.620 1713 2064 I bt_l2cap: L2CAP - LCID: 0x0043 st: CLOSED evt: SECURITY_COMPLETE
01-01 00:07:30.620 1713 2064 D bt_l2cap: TotalWin=6,Hndl=0x2,Quota=8,Unack=2,RRQuota=0,RRUnack=0
01-01 00:07:30.620 1713 2064 D bt_l2cap: RR scan pri=2, lcid=0x0041, q_cout=0
01-01 00:07:30.620 1713 2064 D bt_l2cap: RR scan pri=2, lcid=0x0043, q_cout=0
01-01 00:07:30.620 1713 2064 I bt_l2cap: L2CAP - L2CA_conn_req(psm: 0x0001) returned CID: 0x0043
01-01 00:07:30.620 1713 1794 D bt_btif : virtual void BtifAvStateMachine::StateIdle::OnExit(): Peer 30:aa:e4:42:c7:dd
01-01 00:07:30.620 1713 1794 D bt_btif : virtual void BtifAvStateMachine::StateOpening::OnEnter(): Peer 30:aa:e4:42:c7:dd
01-01 00:07:30.620 1713 1794 I btif_av : btif_report_connection_state: peer_address=30:aa:e4:42:c7:dd state=1
01-01 00:07:30.620 1713 1794 I BluetoothA2dpSinkServiceJni: bta2dp_connection_state_callback
..................
01-01 00:07:30.915 1713 1794 I BluetoothA2dpSinkServiceJni: bta2dp_audio_config_callback
01-01 00:07:31.103 1713 1794 I BluetoothA2dpSinkServiceJni: bta2dp_connection_state_callback
通过上述log,我们可以知道,当上层发送了connect A2dp指令之后,底层将该请求添加到了bt_btif_queue队列中了,然后等待该queue中执行的执行;
然后通过bta2dp_audio_config_callback和bta2dp_connection_state_callback接收到connect的结果反馈;
Protocol
connectA2dpNative 协议分析
yaml
Frame 283: 17 bytes on wire (136 bits), 17 bytes captured (136 bits)
Encapsulation type: Bluetooth H4 with linux header (99)
Arrival Time: Jan 1, 2020 00:07:30.685660000 CST
[Time shift for this packet: 0.000000000 seconds]
Epoch Time: 1577808450.685660000 seconds
[Time delta from previous captured frame: 0.000557000 seconds]
[Time delta from previous displayed frame: 0.000557000 seconds]
[Time since reference or first frame: 8.423062000 seconds]
Frame Number: 283
Frame Length: 17 bytes (136 bits)
Capture Length: 17 bytes (136 bits)
[Frame is marked: False]
[Frame is ignored: False]
Point-to-Point Direction: Sent (0)
[Protocols in frame: bluetooth:hci_h4:bthci_acl:btl2cap]
Bluetooth
[Source: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Destination: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
Bluetooth HCI H4
[Direction: Sent (0x00)]
HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 12
Data
[Connect in frame: 109]
[Source BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Source Device Name: HAVAL_6720]
[Source Role: Master (1)]
[Destination BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination Device Name: dupz]
[Destination Role: Slave (2)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 109]
Bluetooth L2CAP Protocol
Length: 8
CID: L2CAP Signaling Channel (0x0001)
Command: Connection Request
Command Code: Connection Request (0x02)
Command Identifier: 0x0f
Command Length: 4
PSM: AVDTP (0x0019)
Source CID: Dynamically Allocated Channel (0x0045)
[Service: Audio Source (0x110a)]
首先我们先分析一下:
ruby
Bluetooth
[Source: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Destination: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
- Source:代表了指令的发起方,即指令发送者,BarrotTe_50:67:20,代表了车机端,04:7f:0e:50:67:20为车机端的蓝牙地址;
- Destination:代表了指令的接收方,HuaweiDe_42:c7:dd,代表了手机端,30:aa:e4:42:c7:dd为手机端的蓝牙地址;
css
Bluetooth HCI H4
[Direction: Sent (0x00)]
HCI Packet Type: ACL Data (0x02)
- HCI H4:代表了UART的transport,这一块涉及到的是Transport层,用于实现Host和Controller的交互;
H4是UART传输中最简单的一个Transport,只是在HCI raw data的前面加一个type就行。
H4定义了5种类型的packet type:
HCI packet type | HCI packet indicator | Desc |
---|---|---|
HCI Command packet | 0x01 | 由蓝牙协议栈发送给芯片的命令 |
HCI ACL Data packet | 0x02 | 蓝牙协议栈跟蓝牙芯片双向交互的普通数据 |
HCI Synchronous Data packet | 0x03 | 蓝牙芯片跟蓝牙协议栈双向交互的通话/语音识别等音频数据 |
HCI Event packet | 0x04 | 由蓝牙芯片上报给蓝牙协议栈的事件 |
HCI ISO Data packet | 0x05 | LE audio用的数据包格式(这部分是在core 5.2才添加的) |
- Sent (0x00):代表了发送,一共有两个类型的发送方式:一种是单独的包(00);一种是连续的包(01 10 11);
yaml
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 12
Data
[Connect in frame: 109]
[Source BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Source Device Name: HAVAL_6720]
[Source Role: Master (1)]
[Destination BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination Device Name: dupz]
[Destination Role: Slave (2)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 109]
上面描述了BT Device Master和Slave的信息
-
Master
- Source BD_ADDR:车机端蓝牙地址
- Source Device Name:车机端蓝牙名称
- Source Role:车机端角色
-
Slave
- Destination BD_ADDR:手机端蓝牙地址
- Destination Device Name:手机端蓝牙名称
- Destination Role:手机端蓝牙角色
yaml
Bluetooth L2CAP Protocol
Length: 8
CID: L2CAP Signaling Channel (0x0001)
Command: Connection Request
Command Code: Connection Request (0x02)
Command Identifier: 0x0f
Command Length: 4
PSM: AVDTP (0x0019)
Source CID: Dynamically Allocated Channel (0x0045)
[Service: Audio Source (0x110a)]
- CID:Channel Identifiers,通道标识符,这里使用了Signaling Channel (0x0001)
- Command Code:命令code
- Command Identifier:命令标识符
- PSM:代表给什么协议来建立l2cap连接,这里使用了AVDTP,对应了上述架构图中A2DP协议下关联了AVDTP协议;
- Source CID:Source Channel Identifiers;
- Service: Audio Source (0x110a):表明了在该过程中需要启动的Service;
bta2dp_connection_state_callback
yaml
Frame 289: 21 bytes on wire (168 bits), 21 bytes captured (168 bits)
Encapsulation type: Bluetooth H4 with linux header (99)
Arrival Time: Jan 1, 2020 00:07:30.707200000 CST
[Time shift for this packet: 0.000000000 seconds]
Epoch Time: 1577808450.707200000 seconds
[Time delta from previous captured frame: 0.000283000 seconds]
[Time delta from previous displayed frame: 0.000283000 seconds]
[Time since reference or first frame: 8.444602000 seconds]
Frame Number: 289
Frame Length: 21 bytes (168 bits)
Capture Length: 21 bytes (168 bits)
[Frame is marked: False]
[Frame is ignored: False]
Point-to-Point Direction: Received (1)
[Protocols in frame: bluetooth:hci_h4:bthci_acl:btl2cap]
Bluetooth
[Source: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
Bluetooth HCI H4
[Direction: Rcvd (0x01)]
HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 16
Data
[Connect in frame: 109]
[Source BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Source Device Name: dupz]
[Source Role: Slave (2)]
[Destination BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Destination Device Name: HAVAL_6720]
[Destination Role: Master (1)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 109]
Bluetooth L2CAP Protocol
Length: 12
CID: L2CAP Signaling Channel (0x0001)
Command: Connection Response
Command Code: Connection Response (0x03)
Command Identifier: 0x0f
Command Length: 8
Destination CID: Dynamically Allocated Channel (0x004b)
Source CID: Dynamically Allocated Channel (0x0045)
Result: Successful (0x0000)
Status: No further information available (0x0000)
在这个Response响应中,Result的值为:Successful,表示A2DPSinkService已经连接成功;
bta2dp_audio_config_callback
yaml
Frame 353: 25 bytes on wire (200 bits), 25 bytes captured (200 bits)
Encapsulation type: Bluetooth H4 with linux header (99)
Arrival Time: Jan 1, 2020 00:07:30.915044000 CST
[Time shift for this packet: 0.000000000 seconds]
Epoch Time: 1577808450.915044000 seconds
[Time delta from previous captured frame: 0.000876000 seconds]
[Time delta from previous displayed frame: 0.000876000 seconds]
[Time since reference or first frame: 8.652446000 seconds]
Frame Number: 353
Frame Length: 25 bytes (200 bits)
Capture Length: 25 bytes (200 bits)
[Frame is marked: False]
[Frame is ignored: False]
Point-to-Point Direction: Sent (0)
[Protocols in frame: bluetooth:hci_h4:bthci_acl:btl2cap:btavdtp]
Bluetooth
[Source: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Destination: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
Bluetooth HCI H4
[Direction: Sent (0x00)]
HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 20
Data
[Connect in frame: 109]
[Source BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Source Device Name: HAVAL_6720]
[Source Role: Master (1)]
[Destination BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination Device Name: dupz]
[Destination Role: Slave (2)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 109]
Bluetooth L2CAP Protocol
Length: 16
CID: Dynamically Allocated Channel (0x004b)
[Connect in frame: 283]
[Service: Audio Source (0x110a)]
[PSM: AVDTP (0x0019)]
Bluetooth AVDTP Protocol
Signal: SetConfiguration (Command)
1000 .... = Transaction: 0x8
.... 00.. = Packet Type: Single (0x0)
.... ..00 = Message Type: Command (0x0)
00.. .... = RFA: 0x0
..00 0011 = Signal: SetConfiguration (0x03)
ACP SEID [2 - Audio Source]
0000 10.. = ACP SEID: 2
.... ..00 = RFA: 0x0
INT SEID [2 - Audio Source]
0000 10.. = INT SEID: 2
.... ..00 = RFA: 0x0
Capabilities
Service: Media Transport
Service Category: Media Transport (0x01)
Length of Service Category: 0x00
Service: Media Codec - Audio MPEG-2,4 AAC
Service Category: Media Codec (0x07)
Length of Service Category: 0x08
0000 .... = Media Type: Audio (0x0)
.... 0000 = RFA: 0x0
Media Codec Audio Type: MPEG-2,4 AAC (0x02)
1... .... = MPEG2 AAC LC: True
.0.. .... = MPEG4 AAC LC: False
..0. .... = MPEG4 AAC LTP: False
...0 .... = MPEG4 AAC Scalable: False
.... 0000 = RFA: 0x0
0... .... = Sampling Frequency 8000 Hz: False
.0.. .... = Sampling Frequency 11025 Hz: False
..0. .... = Sampling Frequency 12000 Hz: False
...0 .... = Sampling Frequency 16000 Hz: False
.... 0... = Sampling Frequency 22050 Hz: False
.... .0.. = Sampling Frequency 24000 Hz: False
.... ..0. = Sampling Frequency 32000 Hz: False
.... ...1 = Sampling Frequency 44100 Hz: True
0... .... = Sampling Frequency 48000 Hz: False
.0.. .... = Sampling Frequency 64000 Hz: False
..0. .... = Sampling Frequency 88200 Hz: False
...0 .... = Sampling Frequency 96000 Hz: False
.... 0... = Channels 1: False
.... .1.. = Channels 2: True
.... ..00 = RFA: 0x0
0... .... .... .... .... .... = VBR Supported: False
.000 0010 1110 1110 0000 0000 = Bit Rate: 0x02ee00
在 Bluetooth AVDTP Protocol 协议块中的 Capabilities 中,描述了Audio Source的多个信息:
-
Service: Media Transport
-
Service: Media Codec
-
Media Type:Audio
-
Media Codec Audio Type:MPEG-2,4 AAC
-
Sampling rate:44100 Hz
-
Channel:CHANNEL_OUT_STEREO
-
Bit Rate(码率):0x02ee00
-
码率类型:
- VBR:可变码率编码
- CBR:恒定码率编码
-
AVRCP 连接
在Avrcp协议中涉及到了AVCTP协议;
AVCTP协议描述了蓝牙设备间Audio/Video的控制信号交换的格式和机制,他是一个总体的协议,具体的控制信息由其指定的协议(AVRCP)实现,AVCTP协议本身只指定控制Command和Response的总体的格式;
yaml
........................
Bluetooth
[Source: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Destination: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
Bluetooth HCI H4
[Direction: Sent (0x00)]
HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 12
Data
[Connect in frame: 109]
[Source BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Source Device Name: HAVAL_6720]
[Source Role: Master (1)]
[Destination BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination Device Name: dupz]
[Destination Role: Slave (2)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 109]
Bluetooth L2CAP Protocol
Length: 8
CID: L2CAP Signaling Channel (0x0001)
Command: Connection Request
Command Code: Connection Request (0x02)
Command Identifier: 0x17
Command Length: 4
PSM: AVCTP-Control (0x0017)
Source CID: Dynamically Allocated Channel (0x0048)
[Service: A/V Remote Control Target (0x110c)]
上述为AVCTP-Control建立L2CAP连接的Command,对应H4的Sent (0x00);
yaml
........................
Bluetooth
[Source: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
Bluetooth HCI H4
[Direction: Rcvd (0x01)]
HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 16
Data
[Connect in frame: 109]
[Source BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Source Device Name: dupz]
[Source Role: Slave (2)]
[Destination BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Destination Device Name: HAVAL_6720]
[Destination Role: Master (1)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 109]
Bluetooth L2CAP Protocol
Length: 12
CID: L2CAP Signaling Channel (0x0001)
Command: Connection Response
Command Code: Connection Response (0x03)
Command Identifier: 0x17
Command Length: 8
Destination CID: Dynamically Allocated Channel (0x005d)
Source CID: Dynamically Allocated Channel (0x0048)
Result: Successful (0x0000)
Status: No further information available (0x0000)
上述为AVCTP-Control建立L2CAP连接的Response,Result为Successful,对应H4的Rcvd (0x01),代表了接收;
音乐信息加载
这个过程中,包含了多种类型的信息,包括歌曲信息、音乐播放状态、音乐进度信息;
歌曲信息
歌曲信息对应了btavrcp_track_changed_callback回调;
yaml
........................
Bluetooth L2CAP Protocol
Length: 123
CID: Dynamically Allocated Channel (0x0048)
[Connect in frame: 392]
[Service: A/V Remote Control Target (0x110c)]
[PSM: AVCTP-Control (0x0017)]
Bluetooth AVCTP Protocol
1001 .... = Transaction: 0x9
.... 00.. = Packet Type: Single (0x0)
.... ..1. = C/R: Response (0x1)
.... ...0 = IPID: Profile OK (0x0)
Profile Identifier: A/V Remote Control (0x110e)
Bluetooth AVRCP Profile
0000 .... = Reserved: 0x0
.... 1100 = Ctype: Stable (0xc)
0100 1... = Subunit Type: Panel (0x09)
.... .000 = Subunit ID: 0x0
Opcode: Vendor dependent (0x00)
Company ID: 00:19:58 (Bluetooth SIG, Inc.)
PDU ID: GetElementAttributes (0x20)
0000 00.. = RFA: 0x00
.... ..00 = Packet Type: Single (0x0)
Parameter Length: 110
Number of Attributes: 7
Attribute Entries
Attribute [ Title]: 忘了你忘了我
Attribute ID: Title (0x00000001)
Character Set: UTF-8 (106)
Value Length: 18
Value: 忘了你忘了我
Attribute [ Artist]: 王杰
Attribute ID: Artist (0x00000002)
Character Set: UTF-8 (106)
Value Length: 6
Value: 王杰
Attribute [ Album]: 忘了你‧忘了我
Attribute ID: Album (0x00000003)
Character Set: UTF-8 (106)
Value Length: 21
Value: 忘了你‧忘了我
Attribute [ Media Number]: 1
Attribute ID: Media Number (0x00000004)
Character Set: UTF-8 (106)
Value Length: 1
Value: 1
Attribute [Total Number of Media]: 1
Attribute ID: Total Number of Media (0x00000005)
Character Set: UTF-8 (106)
Value Length: 1
Value: 1
Attribute [ Genre]:
Attribute ID: Genre (0x00000006)
Character Set: UTF-8 (106)
Value Length: 0
Value:
Attribute [ Playing Time]: 279000
Attribute ID: Playing Time (0x00000007)
Character Set: UTF-8 (106)
Value Length: 6
Value: 279000
[Response Time: 498/1000ms]
[Command in frame: 502]
上述的TrackInfo信息中包含了音乐的Title、Artist、Album、Media Number、Number of Media、Genre、Playing Time信息;
音乐播放状态 & 音乐进度信息
这个过程中对应了Event中的btavrcp_play_status_changed_callback和btavrcp_play_position_changed_callback;
yaml
........................
Bluetooth L2CAP Protocol
Length: 13
CID: Dynamically Allocated Channel (0x005d)
[Connect in frame: 392]
[Service: A/V Remote Control Target (0x110c)]
[PSM: AVCTP-Control (0x0017)]
Bluetooth AVCTP Protocol
0001 .... = Transaction: 0x1
.... 00.. = Packet Type: Single (0x0)
.... ..0. = C/R: Command (0x0)
.... ...0 = IPID: Profile OK (0x0)
Profile Identifier: A/V Remote Control (0x110e)
Bluetooth AVRCP Profile
0000 .... = Reserved: 0x0
.... 0001 = Ctype: Status (0x1)
0100 1... = Subunit Type: Panel (0x09)
.... .000 = Subunit ID: 0x0
Opcode: Vendor dependent (0x00)
Company ID: 00:19:58 (Bluetooth SIG, Inc.)
PDU ID: GetPlayStatus (0x30)
0000 00.. = RFA: 0x00
.... ..00 = Packet Type: Single (0x0)
Parameter Length: 0
[Response Time: 24/1000ms]
[Response in frame: 685]
- 这里涉及到了一个概念:PDU,Protocol Data Unit,L2CAP和底层交互用的数据包,PDU ID代表了数据包标识为GetPlayStatus;


上述为PDU ID对应的PDU Name以及Command Type;
-
C/R:代表了该数据帧的类型
- 命令帧(0)
- 响应帧(1)
-
IPID:在响应帧中表示无效的配置文件标识符(1),否则为0;在数据帧中为0;
-
Profile Identifier:表示根据所识别的Profile定义的规则对命令/响应帧进行编码
-
Company ID:蓝牙认证联盟的注册代码
对应的Response:
yaml
..............................
Bluetooth L2CAP Protocol
Length: 22
CID: Dynamically Allocated Channel (0x0048)
[Connect in frame: 392]
[Service: A/V Remote Control Target (0x110c)]
[PSM: AVCTP-Control (0x0017)]
Bluetooth AVCTP Protocol
0001 .... = Transaction: 0x1
.... 00.. = Packet Type: Single (0x0)
.... ..1. = C/R: Response (0x1)
.... ...0 = IPID: Profile OK (0x0)
Profile Identifier: A/V Remote Control (0x110e)
Bluetooth AVRCP Profile
0000 .... = Reserved: 0x0
.... 1100 = Ctype: Stable (0xc)
0100 1... = Subunit Type: Panel (0x09)
.... .000 = Subunit ID: 0x0
Opcode: Vendor dependent (0x00)
Company ID: 00:19:58 (Bluetooth SIG, Inc.)
PDU ID: GetPlayStatus (0x30)
0000 00.. = RFA: 0x00
.... ..00 = Packet Type: Single (0x0)
Parameter Length: 9
Song Length: 279000
Song Position: 1989
Play Status: Playing (0x01)
[Response Time: 24/1000ms]
[Command in frame: 681]
- C/R:响应(1),Response
- Song Length:音乐时长
- Song Position:position信息,可以通俗的理解为进度条信息
- Play Status:播放状态
Play Status | Value | Desc |
---|---|---|
Stopped | 0x00 | 停止 |
Playing | 0x01 | 播放 |
Paused | 0x02 | 暂停 |
Fwd Seek | 0x03 | 下一首 |
Rev Seek | 0x04 | 上一首 |
Reserved | 0x05 - 0xfe | 保留状态 |
Error | 0xff | 错误状态 |
Avrcp 指令
yaml
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: key_code: xx, key_state: 0
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: key_code: xx, key_state: 1
01-01 00:07:56.595 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: xx, pressed: 0
01-01 00:07:56.596 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: xx, pressed: 1
Avrcp指令下发过程中,涉及到了sendPassThroughCommandNative方法,其中通过key_code来确认控制指令,key_state来控制操作过程中需要响应的动作;
key_code
key_code | value | Desc |
---|---|---|
PASS_THRU_CMD_ID_PLAY | 0x44 | 播放 |
PASS_THRU_CMD_ID_PAUSE | 0x46 | 暂停 |
PASS_THRU_CMD_ID_FORWARD | 0x4B | 下一首 |
PASS_THRU_CMD_ID_BACKWARD | 0x4C | 上一首 |
PASS_THRU_CMD_ID_VOL_UP | 0x41 | 音量调高 |
PASS_THRU_CMD_ID_VOL_DOWN | 0x42 | 音量调低 |
PASS_THRU_CMD_ID_STOP | 0x45 | 停止 |
key_state
Key State | value | Desc |
---|---|---|
KEY_STATE_PRESSED | 0 | 按下 |
KEY_STATE_RELEASED | 1 | 松开 |
每一个指令都对应了两个动作:按下和松开;
代码需要对这两种动作进行相应的指令发送和响应接收;
Playing
yaml
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: key_code: 68, key_state: 0
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:07:56.540 1713 2180 I BluetoothAvrcpControllerJni: key_code: 68, key_state: 1
01-01 00:07:56.595 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 68, pressed: 0
01-01 00:07:56.596 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 68, pressed: 1
PRESSED 指令发送/响应
yaml
........................
Bluetooth HCI ACL Packet
.... 0000 0000 0010 = Connection Handle: 0x002
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 12
Data
[Connect in frame: 109]
[Source BD_ADDR: BarrotTe_50:67:20 (04:7f:0e:50:67:20)]
[Source Device Name: HAVAL_6720]
[Source Role: Master (1)]
[Destination BD_ADDR: HuaweiDe_42:c7:dd (30:aa:e4:42:c7:dd)]
[Destination Device Name: dupz]
[Destination Role: Slave (2)]
[Last Role Change in Frame: 107]
[Current Mode: Active Mode (0)]
[Last Mode Change in Frame: 515]
Bluetooth L2CAP Protocol
Length: 8
CID: Dynamically Allocated Channel (0x005d)
[Connect in frame: 392]
[Service: A/V Remote Control Target (0x110c)]
[PSM: AVCTP-Control (0x0017)]
Bluetooth AVCTP Protocol
0000 .... = Transaction: 0x0
.... 00.. = Packet Type: Single (0x0)
.... ..0. = C/R: Command (0x0)
.... ...0 = IPID: Profile OK (0x0)
Profile Identifier: A/V Remote Control (0x110e)
Bluetooth AVRCP Profile
0000 .... = Reserved: 0x0
.... 0000 = Ctype: Control (0x0)
0100 1... = Subunit Type: Panel (0x09)
.... .000 = Subunit ID: 0x0
Opcode: Pass Through (0x7c)
0... .... = State: Pushed (0x0)
.100 0100 = Operation ID: PLAY (0x44)
Data Length: 0x00
[Response Time: 54/200ms]
[Response in frame: 556]
- State:Pushed,对应了PRESSED动作;
- Operation ID:PLAY,对应了上述的0x44指令,播放指令;
- C/R:Command,代表了本次数据帧类型为指令类型;
yaml
..............................
Bluetooth L2CAP Protocol
Length: 8
CID: Dynamically Allocated Channel (0x0048)
[Connect in frame: 392]
[Service: A/V Remote Control Target (0x110c)]
[PSM: AVCTP-Control (0x0017)]
Bluetooth AVCTP Protocol
0000 .... = Transaction: 0x0
.... 00.. = Packet Type: Single (0x0)
.... ..1. = C/R: Response (0x1)
.... ...0 = IPID: Profile OK (0x0)
Profile Identifier: A/V Remote Control (0x110e)
Bluetooth AVRCP Profile
0000 .... = Reserved: 0x0
.... 1001 = Ctype: Accepted (0x9)
0100 1... = Subunit Type: Panel (0x09)
.... .000 = Subunit ID: 0x0
Opcode: Pass Through (0x7c)
0... .... = State: Pushed (0x0)
.100 0100 = Operation ID: PLAY (0x44)
Data Length: 0x00
[Response Time: 54/200ms]
[Command in frame: 552]
- C/R:Response
- Operation ID:PLAY (0x44)
RELEASED 指令发送/响应
RELEASED 动作指令和 PRESSED 类似;
Audio State Callback
play指令发送完成之后,等待底层响应,然后会上报Audio State Callback;
yaml
01-01 00:07:56.595 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 68, pressed: 0
01-01 00:07:56.596 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 68, pressed: 1
01-01 00:07:57.033 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_status_changed_callback
01-01 00:07:57.033 1713 1794 I BluetoothA2dpSinkServiceJni: bta2dp_audio_state_callback
这里涉及到了AVDTP信道通讯流程;
yaml
..............................
Bluetooth L2CAP Protocol
Length: 3
CID: Dynamically Allocated Channel (0x0045)
[Connect in frame: 283]
[Service: Audio Source (0x110a)]
[PSM: AVDTP (0x0019)]
Bluetooth AVDTP Protocol
Signal: Start (Command)
0011 .... = Transaction: 0x3
.... 00.. = Packet Type: Single (0x0)
.... ..00 = Message Type: Command (0x0)
00.. .... = RFA: 0x0
..00 0111 = Signal: Start (0x07)
ACP SEID [2 - Audio Sink] item 1
0000 10.. = ACP SEID: 2
.... ..00 = RFA: 0x0
手机端接收来气车机端Start Play 指令;
- RFA:保留给将来添加(Reserved for Future Additions)
- ACP SEID:流端点 id = 2
yaml
..............................
Bluetooth L2CAP Protocol
Length: 2
CID: Dynamically Allocated Channel (0x004b)
[Connect in frame: 283]
[Service: Audio Source (0x110a)]
[PSM: AVDTP (0x0019)]
Bluetooth AVDTP Protocol
Signal: Start (ResponseAccept)
0011 .... = Transaction: 0x3
.... 00.. = Packet Type: Single (0x0)
.... ..10 = Message Type: ResponseAccept (0x2)
00.. .... = RFA: 0x0
..00 0111 = Signal: Start (0x07)
- Packet Type:消息类型
Packet Type | Value |
---|---|
Single Packet | 0x0 |
Start Packet | 0x1 |
Continue Packet | 0x2 |
End Packet | 0x3 |
- Message type:方法类型
Message Type | Value |
---|---|
Command | 0x0 |
General Reject | 0x1 |
Response Accept | 0x2 |
Response Reject | 0x3 |
- Signal:信令标识符
Signal Identifier | Value |
---|---|
Reserved | 0x00 |
AVDTP_DISCOVER | 0x01 |
AVDTP_GET_CAPABILITIES | 0x02 |
AVDTP_SET_CONFIGURATION | 0x03 |
AVDTP_GET_CONFIGURATION | 0x04 |
AVDTP_RECONFIGURE | 0x05 |
AVDTP_OPEN | 0x06 |
AVDTP_START | 0x07 |
AVDTP_CLOSE | 0x08 |
AVDTP_SUSPEND | 0x09 |
AVDTP_ABORT | 0x0A |
AVDTP_SECURITY_CONTROL | 0x0B |
AVDTP_GET_ALL_CAPABILITIES | 0x0C |
AVDTP_DELAYREPORT | 0x0D |
从这里开启了AudioTrack的工作,开启从手机端向车机端实时的传输音频数据;
所以这里就又涉及到了一种协议:RTP;
- RTP:Real-time Transport Protocol,实时传输协议,RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。
RTP是一种运行在传输层的协议,通常基于 UDP 协议,但也支持 TCP 协议;
yaml
..............................
Bluetooth L2CAP Protocol
Length: 577
CID: Dynamically Allocated Channel (0x0046)
[Connect in frame: 361]
[Service: Audio Source (0x110a)]
[PSM: AVDTP (0x0019)]
Bluetooth A2DP Profile
[ACP SEID: 2]
[INT SEID: 2]
[Codec: MPEG-2,4 AAC (0x02)]
[Stream Start in Frame: 574]
[Stream End in Frame: 4434]
[Stream Number: 1]
Real-Time Transport Protocol
[Stream setup by BT A2DP (frame 3662)]
[Setup frame: 3662]
[Setup Method: BT A2DP]
10.. .... = Version: RFC 1889 Version (2)
..0. .... = Padding: False
...0 .... = Extension: False
.... 0000 = Contributing source identifiers count: 0
1... .... = Marker: True
Payload type: Unknown (96)
Sequence number: 2793
[Extended sequence number: 68329]
Timestamp: 2859008
Synchronization Source identifier: 0x00000002 (2)
Data (565 bytes)
Data: 47fc0000b090800300ffff2b211bd465ee094160c2244047...
[Length: 565]
- Version:RTP协议的版本号
- Padding:填充标志,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分
- Extension:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头
- Contributing source identifiers count:CSRC计数器,占4位,指示CSRC 标识符的个数
- Marker:标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始
- Payload type:有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分 是用来区分音频流和视频流的,这样便于客户端进行解析
- Sequence number:序列号,占16位,发送方在每发送完一个RTP包后就将该域的值增加1,接收方可以由该域检测包的丢失及恢复包序列。序列号的初始值是随机的
- Timestamp:时间戳,占32位,记录了该包中数据的第一个字节的采样时刻。它是去除抖动和实现同步不可缺少的
- Synchronization Source identifier:SSRC,同步源标识符,占32位,同步源就是指RTP包流的来源。在同一个RTP会话中不能有两个相同的SSRC值。 该标识符是随机选取的 RFC1889推荐了MD5随机算法

RTP协议实时Audio数据流是连续、持续的,直到遇到Paused或Stopped指令;
Paused
暂停的操作流程基本上也是相同的;
yaml
01-01 00:09:15.042 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:09:15.042 1713 2180 I BluetoothAvrcpControllerJni: key_code: 70, key_state: 0
01-01 00:09:15.043 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:09:15.043 1713 2180 I BluetoothAvrcpControllerJni: key_code: 70, key_state: 1
01-01 00:09:15.226 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 70, pressed: 0
01-01 00:09:15.227 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 70, pressed: 1
01-01 00:09:16.387 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_status_changed_callback
01-01 00:09:16.402 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_status_changed_callback
01-01 00:09:18.346 1713 1794 I BluetoothA2dpSinkServiceJni: bta2dp_audio_state_callback
上层发送了Paused指令之后,底层会上报Audio State变化状态,然后上层根据 Audio State 来执行对应的处理逻辑;
yaml
..............................
Bluetooth L2CAP Protocol
Length: 3
CID: Dynamically Allocated Channel (0x0045)
[Connect in frame: 283]
[Service: Audio Source (0x110a)]
[PSM: AVDTP (0x0019)]
Bluetooth AVDTP Protocol
Signal: Start (Command)
0101 .... = Transaction: 0x5
.... 00.. = Packet Type: Single (0x0)
.... ..00 = Message Type: Command (0x0)
00.. .... = RFA: 0x0
..00 0111 = Signal: Start (0x07)
ACP SEID [2 - Audio Sink] item 1
0000 10.. = ACP SEID: 2
.... ..00 = RFA: 0x0
yaml
..............................
Bluetooth L2CAP Protocol
Length: 2
CID: Dynamically Allocated Channel (0x004b)
[Connect in frame: 283]
[Service: Audio Source (0x110a)]
[PSM: AVDTP (0x0019)]
Bluetooth AVDTP Protocol
Signal: Start (ResponseAccept)
0101 .... = Transaction: 0x5
.... 00.. = Packet Type: Single (0x0)
.... ..10 = Message Type: ResponseAccept (0x2)
00.. .... = RFA: 0x0
..00 0111 = Signal: Start (0x07)
Playing和Paused不一致的地方在于:Transaction属性;
- 0x3:
- 0x5:
FORWARD & BACKWARD
对应的指令为PASS_THRU_CMD_ID_FORWARD和PASS_THRU_CMD_ID_BACKWARD;
Forward
yaml
01-01 00:08:31.791 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:08:31.791 1713 2180 I BluetoothAvrcpControllerJni: key_code: 75, key_state: 0
01-01 00:08:31.791 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:08:31.791 1713 2180 I BluetoothAvrcpControllerJni: key_code: 75, key_state: 1
01-01 00:08:31.826 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_status_changed_callback
01-01 00:08:31.826 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_position_changed_callback
01-01 00:08:31.870 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 75, pressed: 0
01-01 00:08:31.891 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 75, pressed: 1
01-01 00:08:32.347 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_track_changed_callback
01-01 00:08:32.427 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_track_changed_callback
01-01 00:08:32.826 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_status_changed_callback
Backward
yaml
01-01 00:09:02.573 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:09:02.573 1713 2180 I BluetoothAvrcpControllerJni: key_code: 76, key_state: 0
01-01 00:09:02.574 1713 2180 I BluetoothAvrcpControllerJni: sendPassThroughCommandNative: sBluetoothAvrcpInterface: 0x77307fd890
01-01 00:09:02.574 1713 2180 I BluetoothAvrcpControllerJni: key_code: 76, key_state: 1
01-01 00:09:02.626 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 76, pressed: 0
01-01 00:09:02.626 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_passthrough_response_callback: id: 76, pressed: 1
01-01 00:09:02.852 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_track_changed_callback
01-01 00:09:02.906 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_track_changed_callback
01-01 00:09:03.346 1713 1794 I BluetoothAvrcpControllerJni: btavrcp_play_status_changed_callback
在该过程中,只涉及到了track_changed_callback和play_status_changed_callback的回调;