android4.2 Bluetooth记录01-结构和代码分布

作者:cnhua5更新于 08月21日访问(697)评论(2)

在android4.2中,Google更换了android的蓝牙协议栈,从Bluez换成Bluedroid,我也是初涉这个方面,顺便记录一下。
http://source.android.com/devices/bluetooth.html

android development对于4.3蓝牙的介绍:

android提供BlueDroid作为默认的协议栈,BlueDroid分为两个部分:

1、Bluetooth Embedded System(BTE),它实现了BT的核心功能。

2、Bluetooth Application Layer (BTA),用于和android framework层交互。

BT 系统服务通过JNI与BT stack交互,并且通过Binder IPC通信与应用交互。这个系统服务同时也提供给RD获取不同的BT profiles;下面的图标展示BT stack的一个大体的结构:

一、application Framework

这个层的代码主要是利用android.bluetooth APIS 和 bluetooth hardware进行交互。 也就是通过Binder IPC机制调用bluetooth 进程;

代码位于framework/base/core/java/android.bluetooth/下。

比如A2DP的连接:framework/base/core/java/android.bluetooth/BluetoothA2dp.java中的connect(Bluetoothevice)方法。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}

通过Binder IPC 通信机制,调用到packages/apps/Bluetooth/src/com.android.bluetooth.a2dp/A2dpService.java下一个内部私有类

A2dpService是一个继承于ProfileService,而ProfileService是继承于Service的。

private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub{}的connect(BluetoothDevice)方法。

1
2
3
4
5
public boolean connect(BluetoothDevice device) {
A2dpService service = getService();
if (service == null) return false;
return service.connect(device);
}

然后调用到A2dpService的connect(BluetoothDevice)方法。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public boolean connect(BluetoothDevice device) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission"); if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
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;
}

这个过程就是Bluetooth Application Framework与Bluetooth Process的调用过程。

二、Bluetooth System service

Bluetooth System service位于packages/apps/Bluetooth下,它打包成一个android app包,并且在android framework 层实现BT service
和各种profile。BT app会通过JNI调用到HAL层。

A2dpService的connect方法会发送一个
StateMachine.sendMessage(A2dpStateMachine.CONNECT,
device)的message,这个message会被A2dpStateMachine对象的processMessage(Message)方法接
收到:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;

最重要的一句:connectA2dpNative(getByteAddress(device);

即会通过JNI调用到Native;

private native boolean connectA2dpNative(byte[] address);

三、JNI

与android.bluetooth有关的JNI代码位于packages/apps/bluetooth/jni下,JNI 的代码会调用到HAL层,并且在确信一些BT操作被触发时,会从HAL
获取一些回调。比如当BT设备被发现时。

再回到A2dp连接的例子中来,BT System Service通过JNI会调用到com_android_bluetooth_a2dp.cpp中:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}

重点代码是:status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr);

这个sBluetoothA2dpInterface结构体对象是在initNative(JNIEnv *env, jobject object)方法时得到的。

1
2
3
4
5
if ( (sBluetoothA2dpInterface = (btav_interface_t *)
btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
ALOGE("Failed to get Bluetooth A2DP Interface");
return;
}

四、HAL

硬件抽象层定义android.bluetooth APIs和BT process调用的标准接口,并且你必须实现这些接口来让你的BT hardware功能运行正常。BT HAL的
的头文件位于hardware/libhardware/include/hardware/bluetooth.h和hardware/libhardware/include/hardware/bt_*.h 文件中。

JNI中sBluetoothA2dpInterface是一个btav_interface_t结构体,位于hardware/libhardware/include/hardware/bt_av.h中,定义为:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;

五、BT stack

作为默认的BT stack,(4.2之前是bluez作为协议栈的)

代码位于external/bluetooth/bluedroid下,这个stack实现了通用的BT HAL并且也可以通过扩展和改变配置来自定义。

A2dp的连接会调用到external/bluetooth/bluedroid/btif/src/btif_av.c的connect方法。

1
2
3
4
5
6
7
static bt_status_t connect(bt_bdaddr_t *bd_addr)
{
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
CHECK_BTAV_INIT(); return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);
}

六、Vendor extension

为了追踪添加自定义拓展和一个HCI层,你可以创建一个libbt-vendor模块并且指定这些组件。

下一篇BT enable/disable
http://my.eoe.cn/cnhua5/archive/10667.html

ZT eoe android4.2 Bluetooth记录01-结构和代码分布的更多相关文章

  1. MySQL数据库储存引擎Inoodb一--记录储存结构

    在开文我先说明一下,接下来的数据库知识文章都是在微信公众号“我们都是小青蛙”学习然后在通过自己的理解进行书写的.有兴趣的朋友可以去关注这个微信公众号.话不多说,我们在日常使用数据库进行数据持 久化的时 ...

  2. 如何提升我的HTML&CSS技术,编写有结构的代码

    前言 之前写了四篇HTML和CSS的知识点,也相当于是一个知识点汇总.有需要的可以收藏,平时开发过程中应该会遇到这些点,到时候再查看这些博客可能更容易理解.从这篇开始更多的介绍开发过程经常让人头痛的前 ...

  3. (转)Uri详解之——Uri结构与代码提取

    前言:依然没有前言…… 相关博客:1.<Uri详解之——Uri结构与代码提取>2.<Uri详解之二——通过自定义Uri外部启动APP与Notification启动> 上几篇给大 ...

  4. Uri详解之——Uri结构与代码提取

    目录(?)[+] 前言:依然没有前言…… 相关博客:1.<Uri详解之——Uri结构与代码提取>2.<Uri详解之二——通过自定义Uri外部启动APP与Notification启动& ...

  5. ADB结构及代码分析【转】

    本文转载自:http://blog.csdn.net/happylifer/article/details/7682563 最近因为需要,看了下adb的源代码,感觉这个作者很牛,设计的很好,于是稍微做 ...

  6. 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码?

    go语言的开发工具推荐? go语言开发普通程序及开发web程序的时候,应该以哪种目录结构组织代码? 求推荐go语言开发工具及go语言应该以哪种目录结构组织代码? >> golang这个答案 ...

  7. Python查询Mysql时返回字典结构的代码

    Python查询Mysql时返回字典结构的代码 MySQLdb默认查询结果都是返回tuple,输出时候不是很方便,必须按照0,1这样读取,无意中在网上找到简单的修改方法,就是传递一个cursors.D ...

  8. android4.3 Bluetooth(le)分析之startLeScan分析

    BluetoothAdapter.java中有low enery(le)的一些方法,android提供了这些方法,但源码中并未找到这些方法的调用之处.本文档主要分析这类方法的执行流程,来了解下le到底 ...

  9. android4.3 Bluetooth分析之扫描分析

    android4.3中引入了蓝牙低能耗le(low energy),相应的也有一些方法/类.不过代码里,并没有找到初始调用的地方.所以这里还是先只分析下bt普通的扫描流程(类似android 4.2) ...

随机推荐

  1. webstorm皮肤外观样式快速设置,CMD的使用方法,webstorm11激活方法

    一.皮肤外观设置 因为这里是上班时间写的,其客套话就不多bb.步入正题 1.首先设置webstorm整体面板颜色 file->settings->Appearance&Behavi ...

  2. MYSQL根据字段名查询所属表

    MYSQL里面需要根据某个字段名,查询该字段名所在的表.这种情况主要是出现在比如你忘了表名,只知道有这样一个字段名,想找出那张表.第二种情况可能是,同一个字段名属于外键,你想找出例如  ID 这个字段 ...

  3. 【持续更新】一个简洁、易用的美赛LaTeX模板: easyMCM

    目录 1 当前美赛模板通行情况的概述 2 easymcm宏包说明 2.1 与mcmthesis的关系之说明 2.2 easymcm宏包的简介 2.3 美赛模板下载地址 3 常见问题的解决方案 若您无意 ...

  4. [codeup] 1126 看电视

    题目描述 暑假到了,小明终于可以开心的看电视了.但是小明喜欢的节目太多了,他希望尽量多的看到完整的节目. 现在他把他喜欢的电视节目的转播时间表给你,你能帮他合理安排吗? 输入 输入包含多组测试数据.每 ...

  5. 问题集录--Java高级软件工程师面试考纲(转)

    如果要应聘高级开发工程师职务,仅仅懂得Java的基础知识是远远不够的,还必须懂得常用数据结构.算法.网络.操作系统等知识.因此本文不会讲解具体的技术,笔者综合自己应聘各大公司的经历,整理了一份大公司对 ...

  6. 使用<% =Type%>获取后台值时报错:控件包含代码块(即 <% ... %>),因此无法修改控件集合。

    <% =Type%>不能放在runat="server"的标签中,删掉runat="server"之后dev的控件回调第一次发生时会刷新页面,有ru ...

  7. C# 开发者审查代码的41条建议

    1. 确保没有任何警告(warnings). 2.如果先执行Code Analysis(启用所有Microsoft Rules)再消除所有警告就更好了. 3. 去掉所有没有用到的usings.编码过程 ...

  8. @Resource和@Autowired区别

    @Resource和@Autowired都是做bean的注入时使用 历史:  @Autowired     属于Spring的注解    org.springframework.beans.facto ...

  9. MySQL 学习 --- 数据结构和索引

    本文参考了多篇文章集成的笔记,希望各位学习之前可以阅读以下参考资料先 概述 文章分几个部分 :第一部分介绍了B-Tree 和 B+Tree 这种数据结构作为索引:第二部分介绍索引的最左前缀原则和覆盖索 ...

  10. 撩课-Web大前端每天5道面试题-Day23

    1.为什么用Nodejs,它有哪些优缺点? 优点: 事件驱动,通过闭包很容易实现客户端的生命活期. 不用担心多线程,锁,并行计算的问题 V8引擎速度非常快 对于游戏来说,写一遍游戏逻辑代码,前端后端通 ...