以下内容都是基于android6.0的故事,相对于android4.4架构有了很大的变化。
先借个图用一下吧。
上图显示了蓝牙协议栈。 此图显示了在协议栈中调用A2dp代码的流程。 分层结构如下。
1 .蓝牙系统服务服务通过JNI与bluedroid协议栈通信。 协议栈分为两层:蓝牙嵌入式系统(bte )和蓝牙应用程序层(BTA )。 这两层与框架层APP应用程序进行通信。
蓝牙服务通过Binder IPC通信与APP应用程序交互。
3 .系统服务为开发者提供了获取各种配置文件的接口。
一.接下来,我们将深入探讨Framework层的蓝牙连接
1 )那么,从connectInt ) )开始
同步语音连接(localbluetoothprofileprofile ) if (! ensurePaired (() ) { return; }if(profile.connect(mdevice ) ) if ) utils.d ) log.d ) tag,' commandsentsuccesfully 3360 connect ' describe ) ) }log.I(tag,' failedtoconnect ' profile.tostring ) )、' to ' mName ); }2)如果配置文件是a2dp配置文件,则为a2dp配置文件. connect () ) )。
publicbooleanconnect (bluetoothdevicedevice ) if ) mservice==null )返回假; listbluetoothdevicesinks=getconnecteddevices (; if(sinks!=null () for ) bluetoothdevicesink:sinks ) mservice.disconnect(sink ); }returnmservice.connect(device ); }上面的代码很清楚。 检查连接的设备并断开连接。 释放蓝牙节点后,可以供其他使用。
3 )蓝牙a2dp.connect () )。
publicbooleanconnect (蓝牙设备) if ) DBG ) log ) ) connect ) device ); if(mservice!=nullisenabled(isvaliddevice )设备) try{returnmservice.connect )设备; }catch(remoteexceptione ) log.e ) tag,' stack : ' log.getstacktracestring (new throwable ) ); 返回假; }if(mservice==null ) log.w ) tag,' Proxy not attached to service '; 返回假; }蓝牙a2dp类是做什么的呢? 这是蓝牙a2dp服务器的代理,上层尝试使用时必须使用。 如何获取蓝牙a2dp,请参阅蓝牙adapter.getprofileproxy ()
4.A2DP服务. connect (
mstate machine.sendmessage (a2 dpstatemachine.connect,device ); 将蓝牙连接消息发送到A2dpStateMachine进行连接操作。 a2dp连接之前一定是disconnect状态,所以连接的时候会一点一点地。 请注意,以下代码位于mDisconnected中。
switch(message.what ) case connect :蓝牙devicedevice=)蓝牙设备(message.obj ); broadcastconnectionstate(dev
ice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED);----(1) if (!connectA2dpNative(getByteAddress(device)) ) {-----(2) broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); break; } synchronized (A2dpStateMachine.this) { mTargetDevice = device; transitionTo(mPending);---------(3) } // TODO(BT) remove CONNECT_TIMEOUT when the stack // sends back events consistently sendMessageDelayed(CONNECT_TIMEOUT, 30000); break;上面的(1)处是发送一个连接蓝牙状态改变事件。
(2)进行a2dp连接,很明显就要进入jni里了
(3)状态转换到==》pending==>connected
JNI
5.这里只讲连接,所以下面要分析jni了
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) { jbyte *addr; bt_bdaddr_t * btAddr; bt_status_t status; ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface); if (!sBluetoothA2dpInterface) return JNI_FALSE; addr = env->GetByteArrayElements(address, NULL); btAddr = (bt_bdaddr_t *) addr; if (!addr) { jniThrowIOException(env, EINVAL); return JNI_FALSE; } if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { ALOGE("Failed HF connection, status: %d", status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;}那么这个sBluetoothA2dpInterface这个是什么呢?其实这个就相当于java中对外提供的api接口,只是在c中是头文件而已。
既然是蓝牙肯定是在蓝牙的头文件里bt_av.h里
typedef struct { /** set to sizeof(btav_interface_t) */ size_t size; /** * Register the BtAv callbacks */ bt_status_t (*init)( btav_callbacks_t* callbacks ); /** connect to headset */ bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); /** dis-connect from headset */ bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); /** Closes the interface. */ void (*cleanup)( void );} btav_interface_t;接下来就调用到./btif/src/btif_av.c
static const btav_interface_t bt_av_src_interface = { sizeof(btav_interface_t), init_src, src_connect_sink, disconnect, cleanup_src,};static const btav_interface_t bt_av_sink_interface = { sizeof(btav_interface_t), init_sink, sink_connect_src, disconnect, cleanup_sink,};至于a2dp的断开,流程和连接类似,请大家自行分析。
上面有两个connect到底使用哪一个呢?那就要看你的机器是发送连接还是接收连接了。就到这了,接下来的东西其实我没搞太明白,就不误导大家了。
如果感觉不错,就赞一下。