从ANDROID3.0开始BLUETOOTH API提供了对Bluetooth profile协议的支持。目前ANDROID4.0 API提供了五种蓝牙无线接口规范(Bluetooth profile)的支持,用来在设备之间提供蓝牙通讯实现特定功能:包括 Headset和Hands-Freeprofile(实现蓝牙耳机功能),A2dpprofile(第二代蓝牙声音设备协议,用来在蓝牙设备之间实现高质量的声音传输),InputDeviceprofile(实现蓝牙输入设备功能),Bluetooth Panprofile(实现蓝牙个人局域网功能),Bluetooth Healthprofile(实现蓝牙健康设备规范,用来与支持蓝牙健康设备规范的设备进行蓝牙通讯)。另外还有Bluetooth Pbapprofile(实现蓝牙电话本功能),但接口和其它profile实现不一致。
ANDROID对 Bluetooth profile API的实现主要采用了中介模式、代理模式及状态模式等。
应用通过一个统一的类BluetoothAdapter(蓝牙本地适配器类)与这些蓝牙设备协议对应的BLUETOOTH API进行交互。
BluetoothAdapter也是所有蓝牙对象交互的入口。通过BluetoothAdapter除了实现BLUETOOTHprofile API的调用外,还提供发现其它蓝牙设备、查询配对成功的设备、使用已知的MAC地址实例化蓝牙设备、创建一个BluetoothServerSocket对象来监听其它蓝牙设备以及根据地质实例化蓝牙设备等功能。因此几乎所有的蓝牙对象和所有的蓝牙服务都维护一个BluetoothAdapter单例对象,BluetoothAdapter单例对象通过BluetoothAdapter类提供的getDefaultAdapter函数获得。BluetoothAdapter对象可以说是整个系统交互的中介,是中介设计模式的采用。
而几个蓝牙设备协议的实现借助几个ANDROID服务来实现,并通过代理对象对外提供BLUETOOTH API。Headset对应的代理对象为BluetoothHeadset,A2dp对应的代理对象为BluetoothA2dp,InputDeviceprofile对应的代理对象为BluetoothInputDevice,Bluetooth Pan对应的代理对象为BluetoothPan,Bluetooth Health对应的代理对象为BluetoothHealth。
通过BluetoothAdapter类提供的getProfileProxy函数根据不同的profile参数实例化对应的代理对象,getProfileProxy函数还传给代理对象一个实现BluetoothProfile.ServiceListener接口的监听对象。
代理对象实例化时与代理的服务进行绑定,与服务进行绑定成功后调用对应监听对象的onServiceConnected回调函数,并通过回调函数把代理对象传给应用,应用通过代理对象通过BINDER访问蓝牙设备服务。
Headset 对应蓝牙服务为BluetoothHeadsetService及BluetoothHandsfree对象,A2dpprofile对应的蓝牙服务为BluetoothA2dpService,而InputDeviceprofile、Bluetooth Healthprofile及Bluetooth Panprofile都由BluetoothService服务来实现。Bluetooth Pbap profile对应的服务是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 InputDeviceProfile,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对象提供的一个状态机对象进行维护。
欢迎转载,转载时请尊重原创注明出处。