a2dp
以下内容都是基于Android6.0的基础上讲的,相对于android4.4架构有了很大改动。
先借用一下图用一下。
上图描述的是蓝牙协议栈,通过该图,查看A2dp的代码在协议栈的调用流程。其分层架构如下:
1.蓝牙的系统服务service通过JNI与bluedroid协议栈进行通信。协议栈分为两层,Bluetooth Embedded System(BTE)和Bluetooth APPlication Layer(BTA)。这两层和framework层应用进行通信。
2.蓝牙服务通过Binder IPC通信与应用程序交互。
一、接下来将深入Framework层讲解蓝牙的连接
1)那就从connectInt()开始
synchronized void connectInt(localBluetoothProfile profile) {
if (!ensurePaired()) {
return;
}
if (profile.connect(mDevice)) {
if (Utils.D) {
Log.d(TAG, "command sent successfully:CONNECT " + describe(profile));
}
return;
}
Log.i(TAG, "failed to connect " + profile.toString() + " to " + mName);
}
2)若profile为a2dpprofile,则A2dpProfile.connect()
public boolean connect(BluetoothDevice device) {
if (mService == null) return false;
List<BluetoothDevice> sinks = getConnectedDevices();
if (sinks != null) {
for (BluetoothDevice sink : sinks) {
mService.disconnect(sink);
}
}
return mService.connect(device);
}
上面的代码就很好理解了,查询已连接的设备,然后断开。只有先把蓝牙节点给释放掉才能供给其它使用。
3)BluetoothA2dp.connect()
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
if (mService != null && isEnabled() &&
isvalidDevice(device)) {
try {
return mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new throwable()));
return false;
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
BluetoothA2dp类是干什么的呢?它是蓝牙a2dp服务的代理对象,就是上层想要使用就必须用到它了。获取BluetoothA2dp的方法就是BluetoothAdapter.getProfileProxy()
4.A2dpService.connect()
mStateMachine.sendmessage(A2dpStateMachine.CONNECT, device);
发送一个蓝牙连接的消息给A2dpStateMachine进行连接操作。a2dp连接之前肯定处于disconnect状态,所以进行连接时要一步一个脚印。大家注意下面一段代码是mDisconnected里的。
switch(message.what) {
case CONNECT:
BluetoothDevice device = (BluetoothDevice) message.obj;
broadcastConnectionState(device, 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到底使用哪一个呢?那就要看你的机器是发送连接还是接收连接了。就到这了,接下来的东西其实我没搞太明白,就不误导大家了。
如果感觉不错,就赞一下。
相关阅读
带上耳机听听音乐看看视频已成为现代生活中的之中时尚潮流。不同的耳机有着不同的佩戴方法,若是佩戴不当容易造成听力损伤,接下来的
工具1、最新版本IVT_BlueSoleil_10.0.492.12、破解软件Bluesoleil 8.XXX Patch Tool链接:http://pan.baidu.com/s/1jGvXPhc 密
Galaxy Buds耳机值不值得买 三星真无线蓝牙耳机Galaxy
Galaxy Buds耳机怎么样?值不值得买?下面小编带来三星真无线蓝牙耳机Galaxy Buds上手体验,希望对大家有所帮助。三星真无线蓝牙耳机Ga
具体的步骤流程: 1 控制面板——>网络和Internet——>网络共享中心——>更改适配器——>Bluetooth网络链接右键点击属性——>
HFP协议目前HFP的使用场景有车载蓝牙,耳机和PDA,定义了AG和HFP两种角色。 AG(Audio Gate)音频网关—音频设备输入输出网关