蓝牙协议

adb shell setprop persist.bluetooth.btsnoopenable true,开启蓝牙hci-snoop的开关。
persist.bluetooth.btsnoopenable 全局变量的存储路径因安卓版本而有些许差异:
Android 8的存储路径:/data/property/persist.bluetooth.btsnoopenable/
Android 9的存储路径:/data/property/persistent_properties/

初始化协议栈:
在这里插入图片描述
1.蓝牙JNI层通过dlopen()的系统调用根据蓝牙协议栈动态库名libbluetooth.so获取到该库对应的句柄,相当于文件描述符吧。
2.再通过dlsym()查找到bluetoothInterface对应的HAL函数接口,即内存地址。
3.通过获取到的函数接口初始化协议栈,主要设置了一组回调函数,同时协议栈主要创建了两个重要的子线程:stack_manager,bt_jni_workqueue,上述时序图里黄颜色标注。

蓝牙协议:HFP蓝牙通话,A2DP蓝牙音乐,bpap通话记录的同步.Avrcp:控制音乐播放暂停,获取音乐信息.
通话log:AT+CLCC:通信状态信息
AT+CHLD:响应点击接听指令,用于第三方通话
AT+CHUP:挂断指令
蓝牙音乐log:AVRCP:音乐播放状态
A2DP连接:AVDTP:get Capabilities-> set Configuration->AVDTP Open
AVRCP:AVRCP Get Capabilities->AVRCP Get Play Status->AVRCP List Player Application Setting Attributes->AVRCP Regiest Notification->AVRCP Get Element Attributes
L2CAP:连接SDP,AVDTP,RFCOMM,AVCTP
蓝牙的基本框架:
1:主要代码路径:framework下bluetooth,
起点:package/app/Bluetooth/
调用底层C/C++实现相关接口,主要功能发送各种蓝牙功能,并且反馈给java层.
Package下的Bluetooth中包含了相互独立的java包,每个包是一个协议,实现一个具体的功能,
BtService:统一管理,控制其他服务.
A2dp:蓝牙音乐,蓝牙耳机.
Avrcp:音频/视频通过连接的蓝牙控制,比如放歌是控制暂停等.
Gatt:低功耗BLE有关的,比如蓝牙按键
Hdp:蓝牙医疗
hfp和hfpclient:蓝牙通话有关,比如蓝牙通话的相关操作.
hid:蓝牙键盘/鼠标
map:同步蓝牙短信相关.
opp:蓝牙传输,比如传输文件等.
Pan:个人局域网
Pbap:同步电话本,联系人和通话记录
Sap:蓝牙通话,主要和SIM相关
Sdp:蓝牙服务发现/获取相关
每一个服务都是相互独立,毫不影响,继承自ProfileService,由AdapterService服务统一管理.
每一个服务在farmework中都存在对应的客户端类,通过binder进行跨进程通信.
每一个服务在jni中对存在对应的C/C++类,通过JNI机制相互调用.
每一个服务的启动,对应的binder和JNI机制的调用原理和方法,流程几乎都是一样的.

StateMachine状态机:管理连接的状态,连接状态变化的通知,连接之后触发与底层native层交互,
Pbap:Disconnected,Connecting,Disconnecting,Connected
Hfp:Disconnecting,Connected,AudioOn,Connected
A2dp:Disconnected,Pending,Connected
Avrcp:Disconnected,connected
连接状态中有:enter(),processMessage(),exit().
协议中都有service:通过binder与framework对应的客户端进行通信
比如HeadsetClientService.java是一个服务类,里面有一个BluetoothHeadsetClientBinder内部类,该类主要负责和 (framework中蓝牙通话的相关动作)BluetoothHeadsetClient进行跨进程通信,
HeadsetClientService也是BluetoothHeadsetClientBinder和HeadsetClientStateMachine之间的桥梁.

蓝牙通话机制HFP协议:
1.Framework目录下主要有
BluetoothHeadsetClient.java:主要负责蓝牙通话的相关动作,
比如Accept call接听,hold call保持通话,reject call拒绝通话,terminatecall 终止通话.
dial拨号
BluetoothHeadsetClientCall.java:主要负责蓝牙通话状态,比如来电,去电,mID,mUUID,getStatus(CALL_STATE_ACTIVE活性,HELD保持,DIALING拨号中,ALERTING提醒,INCOMING来电,WAITING等待,HELD BY RESPONSE AND HOLD响应并保留,TERMINATED终止)
1.蓝牙服务端的相关代码:package/app/BlueTooth/hfpclient
有3个类:
HeadsetClientHalConstants.java类里面只是定义了一些int/boolean 类型的值。
HeadsetClientService.java是一个服务类,里面有一个BluetoothHeadsetClientBinder内部类,该类主要负责和 (framework中蓝牙通话的相关动作)BluetoothHeadsetClient进行跨进程通信,
HeadsetClientService也是BluetoothHeadsetClientBinder和HeadsetClientStateMachine之间的桥梁.

**HeadsetClientStateMachine是一个状态机,即管理连接的状态,和通话的相关操作,也是通话时java和c/c++之间的桥梁,
通过JNI机制和com_android_bluetooth_hfpclient里面的方法相互调用.
2.JNI相关代码,package/app/Bluetooth/jni/
com_android_bluetooth_hfpclient.cpp:蓝牙通话动作,拨号,接听,挂断,拒绝实际的执行者.
DialerBTHfpService:是开机之后启动的

3.执行流程:
1.BluetoothHeadsetClient是一个api,由第三方apk直接调用,可以进行拨号/接听/拒接/挂断操作,对的是dial(),acceptcall(),rejectcall(),terminatecall(),
2.HeadsetClientService是一个服务,BluetoothHeadsetClientBinder是它的内部类,
BluetoothHeadsetClientBinder是BluetoothHeadsetClient在HeadsetClientService中的代理,通过aidl进行方法的调用。
3.connected(已连接的状态)是HeadsetClientStateMachine的其中一种状态,通话相关的操作都建立在已连接的状态之上,其他三种状态是disconnected,connecting.
4.AudioOn状态,HeadsetClientService根据不同的方法给状态机发送不同的消息,最后通过HeadsetClientStateMachine根据JNI机制调用.
5.com_android_bluetooth_hfpclient.cpp对应的方法,最后调用底层c/c++来真正的实现拨号/接听/拒接/挂断.
在这里插入图片描述

只有dial方法最后调用dialNative,其他都调用handleCallActionNativegetByteAddress((mCurrentDevice), action, 0),只是action参数不同.(自己代码的状态机调用handleCallActionNative(byte[] address,int action,int index))

如果有来电,对方挂断,这些都是com_android_bluetooth_hfpclient.cpp通过JNI机制调用通话状态机的方法sendCallChangedIntent,将电话的状态包含在BluetoothHeadsetClientCall.java中通过广播发送出来,第三方apk监听状态就可以进行相应的操作.
onCall()->STACK_EVENT->EVENT_TYPE_CALL->dataIndictor()->setCallState()->sendCallChangeIntent()->updateCallMultiParty->sendCallChangeIntent()
1.自己的apk需要注册BluetoothHeadsetClientCall相关广播,监听来电,接通,对方挂断的状态,获取蓝牙电话的信息,比如电话号码,设备信息.
2.通过BluetoothAdapter获取并且初始化BluetoothHeadsetClient对象,然后就可以直接调用dial/acceptcall/rejectCall/terminatecall.

在操作连接HFP协议失败时,我们就可以从以下六个方面分析原因:
1、 应用层是否正确调用连接的相关API
2、 应用层是否正确设置监听广播
3、 当前蓝牙的ACL链路是否建立成功
4、 SDP服务搜索HFP协议是否正常完成
5、 RFCOMM是否连接成功
6、 AT命令是否依次交互完成

AT命令依次交互的顺序为:
BRSF -> BAC(AG、HF都支持codec协商) -> CIND=? -> CIND? -> CMER -> CHLD=?(AG、HF都支持三方通话) -> ……

PBAP执行流程:
1.蓝牙打开过程中,会启动BluetoothPbapService,
case START_LISTENER:
会启动mServerSockets = ObexServerSockets.create(this);
会监听:ACTION_CONNECTION_ACCESS_REPLY:连接访问回复,有3种状态:waitforauth(等待授权),connected(连接),finished(完成)
AUTH_RESPONSE_ACTION:授权响应的动作
AUTH_CANCELLED_ACTION:授权取消
建立连接:
2.BluetoothPbapActivity用于展示client和server建立连接前的用户交互,用户确认client pbap request的时候启动(BluetoothPbapAuthenticator.waitUserConfirmation().等待用户授权确认时启动.)
3.BluetoothPbapVcardManager.java提供了PB,ich,och,mch,cch等对象的方法,这些数据是从电话记录数据库中获取到的,数据库url为CallLog.calls.CONTENT_URI
4.BluetoothPbapObexServer.java中维护了BluetoothPbapVcardManager对象,在BluetoothPbapObexServer中接收到client的调用后,通过BluetoothPbapVcardManager对象获取对应的数据,返回给client端(通过obex body stream进行发送)
状态改变:
5.应用层通过Pbap Client Profile建立对目标对象的连接.
调用BluetoothPbapClient.java中的connect(BluetoothDevice device),(通过IBluetoothPbapClient
Binder机制)调到PbapClientService.java中,创建PbapClientStateMachine对象,并调用其start()方法.
pbapClientStateMachine.start();new PbapClientStateMachine创建后,就进入connecting状态.
setInitialState(mConnecting);
6.pbapClientStateMachine.java中进入Connecting中,注册sdp广播,发送MSG_SDP_COMPLETE,在该消息处理中发送MSG_CONNECT到PbapClientConnectionHandler中,MSG_CONNECT消息处理中原本会创建socket以及obex session.我们直接调用NativeInterface.connect(mDevice);client状态机转为connected状态.
7.进入pbapClientStateMachine的connected状态后,
调用mService.checkIfNeedDeleteOldData(mCurrentDevice, false)接口直接删除旧的数据.downloadCalllogs(),downloadSim(),downloadPhonebook().
调用添加通讯录和通话记录的接口,onIndexDataIndEvent()中调用processContactItemCallback,processCallLogItemCallback.
*Pbap都是在PbapClientConnectionHandler.java中调用底层接口的.
OBEX:对象交换协议

A2DP协议源码分析:
蓝牙音乐播放分为两端:source,sink,source一般为音频流输出端,sink接收音频流方.
客户端framework/bluetooth.
输出客户端:BluetoothA2dp.java
输入客户端:BluetoothA2dpSink.java
服务端:Bluetooth/a2dp
输出服务端:A2dpService.java
A2dpStateMachine.java(状态机)
输入服务端:A2dpSinkService.java
A2dpSinkStateMachine.java
BluetoothA2dp中doBind():主要将客户端对应的服务端A2dpService连接起来,finalize方法中调用cloase()取消注册,解除绑定.
1.Connect():主要将主设备和从设备连接起来,形成一条通路.
对于profile.connect(mDevice)会根据profile调用各自对应的connect方法。(如手机音频则对应HeadsetProfile,媒体音频对应A2dpProfile.connect()),mService.connect(device)最终会调到Bluetooth应用中A2dpService.java内部类BluetoothA2dpBinder的connect方法.
A2dpService的connect()函数会对priority和连接状态进行检查,不符合返回false,符合向A2dpStateMachine发消息A2dpStateMachine.CONNECT.
此时状态机中的状态应该是Disconnected,disconnected状态处理调用(getconnectA2dpNativeByteAddress(device)),会调到hardware,蓝牙协议栈,进行连接.
2.协议栈中的状态改变会回调给状态机中的onConnectionStateChanged函数,函数会发STACK_EVENT(携带状态和蓝牙地址),此时Pending state收到STACK_EVENT消息调用processConnectionEvent()正常连接成功会先收到CONNECTION_STATE_CONNECTING,在收到CONNECTION_STATE_CONNECTED,连接成功,向外发送连接成功的广播,状态机切换到Connected状态,(项目中没有做broadcastConnectionState向AudioManager中设置A2DP的连接状态,返回值用来延时发送广播,音频系统根据当前状态判断音频从(蓝牙A2DP,扬声器,耳机)发出.)
setAvrcpAbsoluteVolume():设置从设备的声音大小
adjustAvrcpAbsoluteVolume():也是设置声音的,仅能输入4个int值.
AudioManager.ADJUST_LOWER减小, AudioManager.ADJUST_RAISE增加,AudioManager.ADJUST_MUTE静音,AudioManager.ADJUST_UNMUTE取消静音

A2DP连接过程.
蓝牙自动连接时,3秒会自己触发
在BTManager.java中public boolean a2dpConnect(String mac) {}触发A2DP的连接
1.从CachedBluetoothDevice类中,调用connectInt(),调用profile.connect(mDevice)
2.当profile是A2dpProfile时,调用A2dpProfile.connect(),然后调用BluetoothA2dp.connect()
,通过aidl,调用A2dpService的内部类BluetoothA2dpBinder.connect(),调用A2dpService的connect()方法,
会对priority和连接状态进行检查,不符合返回false,符合向A2dpStateMachine发消息A2dpStateMachine.CONNECT.
AVRCP协议:
建立AVRCP连接、发送控制指令、获取歌曲信息等等,基本都是按照一套具体的操作流程

蓝牙通话过程
NativeInterface,调用onCmdResult
发送StackEvent.EVENT_TYPE_CMD_RESULT
主要sendCallChangedIntent,
Bluetooth侧
收到StackEvent.EVENT_TYPE_CMD_RESULT调用queryCallsDone(),调用sendCallChangedIntent(),发送消息BluetoothHeadsetClient.ACTION_CALL_CHANGED:
UI侧
BTManagerHelper:收到BluetoothHeadsetClient.ACTION_CALL_CHANGED:
发MSG_HFP_CALL_CHANGE消息,收到MSG_HFP_CALL_CHANGE调用notifyHFPCallChanged->
onCallChanged (BTHFPListener)

A2DP协议是否连接成功:主要看AVDTP是否连接上,L2CAP用来建立AVDTP连接<

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值