BT_蓝牙音乐协议分析

协议架构

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

其中针对业务层的逻辑,涉及到了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的回调;

相关推荐
K1t05 分钟前
Android-UI设计
android·ui
吃汉堡吃到饱1 小时前
【Android】浅析MVC与MVP
android·mvc
深海呐8 小时前
Android AlertDialog圆角背景不生效的问题
android
ljl_jiaLiang8 小时前
android10 系统定制:增加应用使用数据埋点,应用使用时长统计
android·系统定制
花花鱼8 小时前
android 删除系统原有的debug.keystore,系统运行的时候,重新生成新的debug.keystore,来完成App的运行。
android
canonical_entropy9 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
落落落sss9 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
沛沛老爹10 小时前
服务监控插件全览:提升微服务可观测性的利器
微服务·云原生·架构·datadog·influx·graphite
huaqianzkh11 小时前
了解华为云容器引擎(Cloud Container Engine)
云原生·架构·华为云
消失的旧时光-194311 小时前
kotlin的密封类
android·开发语言·kotlin