文档章节

Bluedroid的结构和代码分布

s
 sflfqx
发布于 2014/08/12 16:15
字数 1082
阅读 779
收藏 2
点赞 0
评论 0

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

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 {

    
    size_t          size;
    
    bt_status_t (*init)( btav_callbacks_t* callbacks );

    
    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );

    
    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );

    
    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模块并且指定这些组件。


本文转载自:http://blog.sina.com.cn/s/blog_69b5d2a50101f2ew.html

共有 人打赏支持
s
粉丝 42
博文 202
码字总数 0
作品 0
深圳
高级程序员
Bluetooth in Android 4.2 and 4.3(一):综述

从Android 4.2开始,Bluetooth stack发生了重大改变:从Bluez换成了由Google和Broadcom联合开发的Bluedroid(当然,核心的部分还是Broadcom 的,Google主要是做了和上层Framework相关的部分)...

sflfqx
2014/08/12
0
0
Android4.4 之Bluetooth整理

Android 4.4上蓝牙协议栈采用的是BRCM和Google共同开发的bluedroid,代替了之前的Bluez. 一、 Bluetooth 源码分布 (基于Android 4.4 ) 1. packages/apps/Settings/src/com/android/settin...

sflfqx
2014/08/12
0
0
【分享】iTOP4412开发板-Bluetooth移植文档

本文转自迅为:http://www.topeetboard.com 近期需要把Bluetooth移植到iTOP-4412 开发平台,查阅了相关资料,经过一段时间的研究、调试,终于成功的将蓝牙功能移植到了开发板上面,这里笔者记...

topeet
2015/07/20
415
0
Android 4.4 Bluetooth学习之一

一、写在前面的话 近来由于项目需求需要搞蓝牙这一块,之前在上家公司带LC(本地连接)组时也做过一点蓝牙,在Android系统中也解过一些bug,但是不够系统,现在正好比较系统的学习蓝牙。 二、...

方治兵
2014/01/10
0
2
Android4.2蓝牙Enable完全分析

这应该只会是唯一的一篇从头到尾的调用关系都分析一遍的文章,目的是为了帮助初学者从上往下一层一层分析代码,对大量的代码不再害怕。如果是对阅读Android代码很熟悉的人可以略过这一篇。 ...

sflfqx
2014/08/12
0
0
Android 4.2蓝牙介绍

Tieto公司某蓝牙大牛写得《程序员》投稿文章 Android 4.2蓝牙介绍 蓝牙一词源于公元十世纪丹麦国王HaraldBlatand名字中的Blatand。Blatand的英文之意就是Blue tooth。这是因为这位让丹麦人引...

sflfqx
2014/08/12
0
0
Android 4.2蓝牙介绍

Tieto公司某蓝牙大牛写得《程序员》投稿文章 Android 4.2蓝牙介绍 蓝牙一词源于公元十世纪丹麦国王HaraldBlatand名字中的Blatand。Blatand的英文之意就是Blue tooth。这是因为这位让丹麦人引...

ChaosWu
2013/09/12
0
0
Bluedroid与BluZ,蓝牙测试方法的变动(基于bludroid和BlueZ的对比)

android4.2以后,增加了bludroid,在做测试时,会发现与之前的bluez的测试,有着较大的变动。下面罗列一些bluedroid的不同点,以及之前bluez的测试命令验证(该部分是用bluez做的测试,针对b...

sflfqx
2014/08/12
0
0
Android BlueDroid分析: 配置文件(bt_stack.conf bt_vendor.conf )的加载与分析

说明 在Android BlueDroid启动,即stack启动的时候,回去加载好几个配置文件, 然后BlueDroid Stack根据这几个配置文件会进行调整, 例如Device ID(did), Log相关的Trace Level, COD(即Class of ...

sy373466062
2017/02/10
0
0
Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信

Bluetooth结构 1、JAVA层 frameworks/base/core/java/android/bluetooth/ 包含了bluetooth的JAVA类。 2、JNI层 frameworks/base/core/jni/androidbluetooth开头的文件 定义了bluez通过JNI到上......

zhoulc
2013/03/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Weblogic问题解决记录

问题:点击登录,页面刷新但是不进去管理界面。解决:删除cookies再登录。

wffger
1分钟前
0
0
RxJava2的错误处理方案

最近使用retrofit2 + rxKotlin2写接口访问,想尽量平铺代码,于是就想到当借口返回的状态码为「不成功」时(比如:code != 200),就连同网络错误一起,统一在onError方法中处理。想法总是好的...

猴亮屏
8分钟前
0
0
程序的调试信息

调试二进制程序时,经常要借助GDB工具,跟踪程序的执行流程,获取程序执行时变量的值,以发现问题所在。GDB能得到这些信息,是因为编译程序时,编译器保存了相应的信息。Linux下的可执行程序...

qlee
31分钟前
0
0
应用级缓存

缓存命中率 从缓存中读取数据的次数与总读取次数的比例,命中率越高越好 java缓存类型 堆缓存 guavaCache Ehcache3.x 没有序列化和反序列化 堆外缓存ehcache3.x 磁盘缓存 存储在磁盘上 分布式...

writeademo
今天
0
0
python爬虫日志(3)find(),find_all()函数

1.一般来说,为了找到BeautifulSoup对象内任何第一个标签入口,使用find()方法。 以上代码是一个生态金字塔的简单展示,为了找到第一生产者,第一消费者或第二消费者,可以使用Beautiful Sou...

茫羽行
今天
0
0
java:thread:顺序执行多条线程

实现方案: 1.调用线程的join方法:阻塞主线程 2.线程池 package com.java.thread.test;public class MyThread01 implements Runnable {@Overridepublic void run() {Syste...

人觉非常君
今天
0
0
ElasticSearch 重写IK分词器源码设置mysql热词更新词库

常用热词词库的配置方式 1.采用IK 内置词库 优点:部署方便,不用额外指定其他词库位置 缺点:分词单一化,不能指定想分词的词条 2.IK 外置静态词库 优点:部署相对方便,可以通过编辑指定文...

键走偏锋
今天
18
0
Git 2.18版本发布:支持Git协议v2,提升性能

Git 2.18版本发布:支持Git协议v2,提升性能Git 2.18版本发布:支持Git协议v2,提升性能 新版本协议的主要驱动力是使 Git 服务端能够对各种 ref(分支与 tag)进行过滤操作。 这就意味着,G...

linux-tao
今天
0
0
python浏览器自动化测试库【2018/7/22-更新】

64位py2.7版本 更新 document_GetResources 枚举页面资源 document_GetresourceText 获取指定url的内容 包括页面图片 下载地址下载地址 密码:upr47x...

开飞色
今天
41
0
关于DCL双重锁失效及解决方案

关于DCL双重锁失效及解决方案 Double Check Lock (DCL)实现单例 DCL 方式实现单例的优点是既能够在需要时才初始化单例,又能够保证线程安全,且单例对象初始化后调用getInstance方法不进行...

DannyCoder
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部