蓝牙之六-A2dp代码调用流程
2017-06-07 23:56
99 查看
上图描述的是蓝牙协议栈,通过该图,查看A2dp的代码在协议栈的调用流程。其分层架构如下:
1.蓝牙的系统服务service通过JNI与bluedroid协议栈进行通信。协议栈分为两层,Bluetooth Embedded System(BTE)和Bluetooth Application Layer(BTA)。这两层和framework层应用进行通信。
2.蓝牙服务通过Binder IPC通信与应用程序交互。
3.系统服务给开发者提供了获取各种profile的接口。
Application framework
该层使用android.bluetooth APIs和Bluetooth hardware进行通信。通过Binder IPC机制和Bluetooth进程进行通信。该层代码位于frameworks/base/core/java/android/bluetooth/目录下。 如A2DP连接frameworks/base/core/java/android/bluetooth/BluetoothA2dp.java
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; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
该方法通过Binder IPC通信机制,调用packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java下的内部私有类。通过aidl机制实现。
<packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java> private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub { public boolean connect(BluetoothDevice device) { A2dpService service = getService(); if (service == null) return false; return service.connect(device); } }1
2
3
4
5
6
7
8
然后调用到A2dpService的connect的方法。
<packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java> public class A2dpService extends ProfileService { ... public boolean connect(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { return false; } ParcelUuid[] featureUuids = device.getUuids(); if ((BluetoothUuid.containsAnyUuid(featureUuids, A2DP_SOURCE_UUID)) && !(BluetoothUuid.containsAllUuids(featureUuids ,A2DP_SOURCE_SINK_UUIDS))) { Log.e(TAG,"Remote does not have A2dp Sink UUID"); return false; } int connectionState = mStateMachine.getConnectionState(device); if (connectionState == BluetoothProfile.STATE_CONNECTED || connectionState == BluetoothProfile.STATE_CONNECTING) { return false; } mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device); return true; } .... private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub { public boolean connect(BluetoothDevice device) { A2dpService service = getService(); if (service == null) return false; return service.connect(device); } } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
上述过程就是Bluetooth application framework与Bluetooth process的调用过程。
Bluetooth System service
这部分代码位于packages/apps/Bluetooth下,在framework层实现蓝牙服务和各种profile,以apps形式存在。该层通过JNI调用HAL层代码。 A2dpService的connect方法会发送状态机改变消息,
mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
这个消息会被A2dpStateMachine对象的processMessage(Message)方法接收:
switch(message.what) { case CONNECT: BluetoothDevice device = (BluetoothDevice) message.obj; broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); if (!connectA2dpNative(getByteAddress(device)) ) { broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); break; } synchronized (A2dpStateMachine.this) { mTargetDevice = device; transitionTo(mPending); } // TODO(BT) remove CONNECT_TIMEOUT when the stack // sends back events consistently sendMessageDelayed(CONNECT_TIMEOUT, 30000); break;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
上述的connectA2dpNative(getByteAddress(device))会通过JNI调用Native方法。
<packages/apps/Bluetooth/jni/com_android_bluetooth_a2dp.cpp> 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; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
JNI
和JNI相关的代码在package/apps/Bluetooth/jni目录下,上一节的connectA2dpNative方法就是这个目录的代码。JNI层代码调用到HAL代码并且从HAL接收到回调。 A2dp连接中,会调用sBluetoothA2dpInterface->connect实现。
<packages/apps/Bluetooth/jni/com_android_bluetooth_a2dp.cpp> static void initNative(JNIEnv *env, jobject object) { const bt_interface_t* btInf; bt_status_t status; ... if ( (sBluetoothA2dpInterface = (btav_interface_t *) btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) { ALOGE("Failed to get Bluetooth A2DP Interface"); return; } if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks)) != BT_STATUS_SUCCESS) { ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status); sBluetoothA2dpInterface = NULL; return; } mCallbacksObj = env->NewGlobalRef(object); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在initNative中获得sBluetoothA2dpInterface对象。
HAL
硬件抽象层定义了android.bluetooth APIs和Bluetooth process调用的接口。Bluetooth 的HAL层代码在: hardware/libhardware/include/hardware/bluetooth.h,HAL层的以下代码也要重视:
hardware/libhardware/include/hardware/bt_common_types.h //A2DP profile定义 hardware/libhardware/include/hardware/bt_av.h //GATT profile 定义 hardware/libhardware/include/hardware/bt_gatt_types.h hardware/libhardware/include/hardware/bt_gatt_client.h hardware/libhardware/include/hardware/bt_gatt_server.h hardware/libhardware/include/hardware/bt_gatt.h //HFP profile定义 hardware/libhardware/include/hardware/bt_hf.h //HDP profile 定义 hardware/libhardware/include/hardware/bt_hl.h //MAP profile hardware/libhardware/include/hardware/bt_mce.h //HFP client profile hardware/libhardware/include/hardware/bt_hf_client.h //pan profile hardware/libhardware/include/hardware/bt_pan.h //AVRCP profile hardware/libhardware/include/hardware/bt_rc.h hardware/libhardware/include/hardware/bt_hh.h //SDP profile hardware/libhardware/include/hardware/bt_sdp.h //RFCOMM sockets hardware/libhardware/include/hardware/bt_sock.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
JNI中的sBluetoothA2dpInterface是btav_interface_t结构体,位于hardware/libhardware/include/hardware/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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BT stack
协议栈在/system/bt下,实现了HAL层和扩展配置等。包括BTA和BTE量大组件,BTA实现了蓝牙设备管理、状态管理及一些应用规范。而BTE则通过HCI与厂商蓝牙芯片交互以实现了蓝牙协议栈的通用功能和相关协议。另外,BTE还包括一个统一内核接口(GKI),蓝牙芯片厂商可借助GKI快速轻松得移植蓝牙协议栈到其他操作系统或手机平台上。 A2dp的连接将调用
<system/bt/btif/src/btif_av.c> static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid) { btif_av_connect_req_t connect_req; connect_req.target_bda = bd_addr; connect_req.uuid = uuid; BTIF_TRACE_EVENT("%s", __FUNCTION__); btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req); return BT_STATUS_SUCCESS; }1
2
3
4
5
6
7
8
9
10
11
12
Vendor extensions
增加自定义扩展或者HCI层追踪,可以创建libbt-vendor模块并指定这些组件。
相关文章推荐
- 蓝牙之六-A2dp代码调用流程
- 蓝牙之六-A2dp代码调用流程
- 蓝牙之六-A2dp代码调用流程
- 蓝牙之六-A2dp代码调用流程
- ceph存储 FUSE调用流程代码分析
- 代码流程分析二:Settings-蓝牙分析-新增rawgelWhile分析一
- iOS蓝牙调用的一般流程
- iOS蓝牙调用的一般流程
- iOS蓝牙调用的一般流程
- 代码流程分析二:Settings-蓝牙分析-搜索设备原理
- 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程
- 蓝牙驱动层调用流程
- Android bluetooth介绍(二): android 蓝牙代码架构及其uart 到rfcomm流程
- AudioRecord工作流程(蓝牙a2dp的状态下)
- 代码流程分析二:Settings-蓝牙分析-switch开关分析
- 代码流程分析二:Settings-蓝牙分析-新增rawgelWhile分析二
- cocos2dx 2.1.4 程序运行脉络解析1— win32版本的相关代码调用流程
- Launcher代码研究-APK调用流程
- Android bluetooth介绍(二): android 蓝牙代码架构及其uart 到rfcomm流程
- Android bluetooth介绍(二): android 蓝牙代码架构及其uart 到rfcomm流程