现在的位置: 首页 > 综合 > 正文

ANDROID的 BLUETOOTH 实现机制

2018年08月25日 ⁄ 综合 ⁄ 共 6078字 ⁄ 字号 评论关闭

  从 ANDROID3.0 开始BLUETOOTH  API 提供了对
Bluetooth profile协议的支持。目前
ANDROID4.0 API
提供了五种蓝牙无线接口规范(Bluetooth profile
)的 支持

,用来在设备之间提供蓝牙通讯实现特定功能:包括 Headset

Hands-Free profile
(实现蓝牙耳机功能), A2dp profile
(第二代蓝牙声音设备协议,用来在蓝牙设备之间实现高质量的声音传输),InputDevice
profile(实现蓝牙输入设备功能), Bluetooth
 Panprofile
(实现蓝牙个人局域网功能), BluetoothHealth
profile(实现蓝牙健康设备规范,用来与支持蓝牙健康设备规范的设备进行蓝牙通讯)。另外还有
Bluetooth Pbapprofile
(实现蓝牙电话本功能),但接口和其它profile
实现不一致

      
ANDROIDBluetooth profile API的实现主要采用了中介模式、代理模式及状态模式等。

      应用通过一个统一的类
BluetoothAdapter
(蓝牙本地适配器类)与这些蓝牙设备协议对应的
BLUETOOTH  API
进行交互。

        BluetoothAdapter 也是所有蓝牙对象交互的入口。通过BluetoothAdapter 除了实现
BLUETOOTH profile
API 的调用外,还提供发现其它蓝牙设备、查询配对成功的设备、使用已知的MAC 地址实例化蓝牙设备、创建一个
BluetoothServerSocket 对象来监听其它蓝牙设备以及根据地质实例化蓝牙设备等功能。因此几乎所有的蓝牙对象和所有的蓝牙服务都维护一个BluetoothAdapter 单例对象,
BluetoothAdapter 单例对象通过
BluetoothAdapter
类提供的getDefaultAdapter 函数获得。
BluetoothAdapter 对象可以说是整个系统交互的中介,是中介设计模式的采用。

      而几个蓝牙设备协议的实现借助几个
ANDROID
服务来实现,并通过代理对象对外提供 BLUETOOTH  APIHeadset 对应的代理对象为
BluetoothHeadset
A2dp
对应的代理对象为 BluetoothA2dp
InputDevice
profile对应的代理对象为
BluetoothInputDevice
Bluetooth
 Pan 对应的代理对象为BluetoothPan
Bluetooth Health 对应的代理对象为
BluetoothHealth

      通过 BluetoothAdapter 类提供的getProfileProxy 函数根据不同的
profile参数实例化对应的代理对象,
getProfileProxy
函数还传给代理对象一个实现BluetoothProfile.ServiceListener 接口的监听对象。

      代理对象实例化时与代理的服务进行绑定,与服务进行绑定成功后调用对应监听对象的
onServiceConnected
回调函数,并通过回调函数把代理对象传给应用,应用通过代理对象通过
BINDER
访问蓝牙设备服务。

       Headset 对应蓝牙服务为BluetoothHeadsetServiceBluetoothHandsfree
对象, A2dp profile
对应的蓝牙服务为 BluetoothA2dpService ,而
InputDevice
profile
Bluetooth
Healthprofile
Bluetooth

 Panprofile
都由BluetoothService
服务来实现。

Bluetooth Pbapprofile
对应的服务是
BluetoothPbapService

       BluetoothAdapter 对象相关类图如下:

      

        图中几个蓝牙服务
BluetoothHeadsetService
BluetoothA2dpService
BluetoothService
BluetoothPbapService
BluetoothDeviceProfileState
BluetoothHandsfree
BluetoothEventLoop对象都
维护一个
BluetoothAdapter 对象(使用
BluetoothAdapter 类提供的
getDefaultAdapter
函数获得),并通过 BluetoothAdapter 对象提供的getProfileProxy 函数根据
profile类型
获得要访问的代理对象,还通过 BluetoothAdapter 对象访问其它蓝牙对象。

      
图中几个代理对象都是
BluetoothProfile
接口的实现,并都维护一个 ServiceListener 监听对象。BluetoothHeadset 对象通过
IBluetoothHeadset
BluetoothHeadsetService
服务进行BINDER 调用,
BluetoothA2dp 对象通过
IBluetoothA2dp
BluetoothA2dpService 服务进行
BINDER 调用,而
BluetoothInputDevice
BluetoothPan
BluetoothHealth 对象通过
IBluetooth
调用BluetoothService
API

       代理对象本身及
BluetoothAudioGateway
对象也可以通过 BluetoothAdapter 对象访问其它蓝牙对象来获得蓝牙设备信息和状态。

        BluetoothAdapter 对象提供的接口除了getProfileProxy 外主要有以下几个:

        getRemoteDevice()  获得远端设备,返回一个BluetoothDevice 对象;

        getBondedDevices()  获得已配对设备,返回绑定(配对)到本地蓝牙的BluetoothDevice 对象集合;

        getState()    获得本地蓝牙的当前状态,包括STATE_ON
STATE_OFF
STATE_TURNING_ON
STATE_TURNING_OFF 四种状态,由
BluetoothAdapterStateMachine 状态机进行维护

        isEnabled()   返回当前蓝牙是否可用状态,和getState()==STATE_ON 对应。

        enable()     打开本地蓝牙

        disable()     关闭本地蓝牙

        getUuids()  返回本地蓝牙支持的UUIDs 数组

        isDiscovering()   本地蓝牙当前正处于蓝牙设备发现过程

        cancelDiscovery()  取消当前蓝牙设备发现过程

         另外还提供创建
RfcommSocket
监听通道的 API

        BluetoothAdapter 对象通过六个API 来创建
RfcommSocket 数据连接监听通道
(
三个使用固定端口三个使用随机端口) 及一个
SCO
监听通道(面向连接方式,主要用于话音传输)。三个创建使用固定端口的监听通道
API
:一个用来创建需要认证和加密的使用固定 socket 端口的API (需要
BLUETOOTH_ADMIN 权限许可);一个用来创建不加密不认证的透明固定端口的
RFCOMMSocket API ;一个用来创建加密不认证的固定端口的
RFCOMMSocket API
。三个创建使用随机端口的监听RfcommSocket 通道
API (一个创建加密认证通道、一个创建透明通道、一个创建加密无认证通道),随机端口的产生由
BluetoothAdapter 的内部对象
RfcommChannelPicker
负责产生。

       对于蓝牙服务端,可以调用
BluetoothAdapter
对象的这些 API 来创建一个
BluetoothServerSocket
对象,初始化一个服务端 RfcommSocket 监听通道,并调用BluetoothServerSocket 对象的
accept 函数接收对方连接(实际调用刚实例化的监听
RfcommSocket
accept 函数)。当成功与对方建立连接后,
BluetoothServerSocket 对象的
accept
函数返回一个新RfcommSocket 通道,用来作为设备之间的数据传输的通讯通道。

       每个 RfcommSocket 通道对应一个BluetoothSocket 对象。
BluetoothServerSocket 对象实例化时根据
BluetoothServerSocket
实例化函数传进来的通道socket 类型、是否需要认证对方设备、连接是否加密、远端
socket 端口等参数来实例化一个
BluetoothSocket
对象,socket 端口参数为空时使用产生的随机端口。实例化
BluetoothSocket 对象时使用的
socket
端口值为1
30
之间的数,但10
11
12
19
四个保留端口留给其它Profile 使用。

      
BluetoothSocket
对象的实例化函数中还实例化了一个 BluetoothInputStream 对象和BluetoothOutputStream 对象,用作交换数据使用。

       BluetoothSocket 对象还可以由蓝牙客户端设备来实例化,即由BluetoothDevice 对象来实例化。每个
BluetoothDevice 对象对应一个远端蓝牙设备。
BluetoothDevice
对象使用BluetoothSocket 对象向蓝牙服务端请求连接。通过
BluetoothSocket 对象还可以查询远端蓝牙设备的信息如设备名、
MAC
地址、绑定状态、蓝牙类型等。

       BluetoothDevice 对象提供了四个创建RfcommSocket 的函数(两个用于创建安全连接,两个用于创建透明连接,而两个安全连接和两个透明连接中一个通过SDP 设备发现功能产生的随机
socket 端口,一个使用固定
socket
端口)   及一个创建
SCO socket
(用于话音传输)的函数 createScoSocket
createScoSocket 及创建透明固定socket 端口的
API 的使用需要
BLUETOOTH_ADMIN
权限许可。设备发现功能的实现由SdpHelper 对象来实现。

       下图是 BluetoothService相关类图:

     

    

      BluetoothService服务采用三个
ProfileHandler对象提供相关
Profile API的服务。
BluetoothPanProfileHandler用于
Bluetooth PanProfile
BluetoothInputProfileHandler
用于
Bluetooth InputDevice
Profile
BluetoothHealthProfileHandler
用于
Bluetooth HealthProfile

      三个 ProfileHandler对象通过父对象
BluetoothService与其它蓝牙对象交互。
三个 ProfileHandler对象本身都有一个以
BluetoothDevice 对象为key
HashMap 以维护已连接设备状态。

        BluetoothPanProfileHandl 对象还通过ConnectivityManager
INetworkManagementService
BluetoothTetheringDataTracker
三个对象和接口与数据连接服务交互实现蓝牙连接共享功能。数据连接服务机制见博主的另一篇博文《第十一篇 ANDROID系统网络连接和管理机制
》。

        BluetoothHealthProfileHandler 使用BluetoothHealthAppConfiguration 对象指示一个登记用来与医疗蓝牙设备通讯和接收健康蓝牙设备发来的数据的对象,也称为sink
角色,与 sink 通讯的健康蓝牙设备称为 Source

      应用通过调用
BluetoothHealth
代理对象的
registerSinkAppConfiguration
函数在 BluetoothHealthProfileHandler 对象中登记一个BluetoothHealthAppConfiguration 对象。

      应用使用 BluetoothHealth 代理对象的connectChannelToSource
connectChannelToSink 函数实现
sink
Source
的连接。

        BluetoothHealthProfileHandler使用
IBluetoothHealthCallback回调接口
通过
BluetoothHealth 代理对象向
应用发送事件通知。

       BluetoothService服务还包括几个状态机对象
,采用了状态设计模式。

       一个
BluetoothAdapterStateMachine
状态机
,处理和
维护本地蓝牙的状态
事件,包括
BluetoothOn
Switching
HotOffWarmUp
PowerOff
PerProcessState
等几个状态对象,初始状态为
PowerOff
BluetoothAdapterStateMachine
状态机
通过IBluetoothStateChangeCallback
接口
BluetoothAdapter 对象通知本地蓝牙的状态。

       在
PowerOff
状态接收到
BluetoothService
服务发来的
USER_TURN_ON
消息时(由应用调用
BluetoothAdapter 对象的enable
函数触发)完成本地蓝牙模块和固件的加载,还启动一个BluetoothEventLoop
对象,通过 JNI
启动一个线程接收本地蓝牙模块
bluez
产生的蓝牙信号。

       
两个
BluetoothProfileState
状态机
,其中 一个维护A2dp Profile
连接状态
的管理,
另外 一个维护
Health Profile连接
状态 的管理。

       
还有
一个以蓝牙设备地址为
key
BluetoothDeviceProfileState状态机
HashMap集合
为每个已配对远程设备提供一个相关的
BluetoothDeviceProfileState
状态机,用来跟踪所有的蓝牙
Profile的输入输出连接。

          InputDevice profile 连接
状态的管理由

BluetoothInputProfileHandler对象提供的一个
状态机对象进行
维护。

转自“http://www.tuicool.com/articles/Evaqmi

抱歉!评论已关闭.