时间:2025-05-22 来源:网络 人气:
你有没有想过,那个小小的蓝牙功能,竟然在安卓系统中扮演着如此重要的角色?它就像一个神奇的魔法师,让手机、耳机、手表、键盘等设备之间能够轻松连接,成为现代生活中不可或缺的桥梁。今天,就让我带你一起揭开安卓系统蓝牙服务的神秘面纱,看看它是如何运作的!
想象蓝牙服务层的诞生就像一个新生儿一样,需要经历一系列的洗礼。在安卓系统中,这个过程被称为初始化。那么,它是怎么开始的呢?
1. 蓝牙管理者的诞生:当安卓系统启动时,蓝牙管理者(BluetoothManagerService)就像一位管家一样,在系统进程中诞生,开始执行各种任务。
2. 开启蓝牙的钥匙:在系统启动的不同阶段,蓝牙服务管理会根据设置中的蓝牙状态,自动打开蓝牙,就像一把钥匙,打开了蓝牙的大门。
3. 第三方应用的呼唤:有时候,第三方应用也会呼唤蓝牙,通过蓝牙适配器(BluetoothAdapter)主动打开蓝牙,就像一个使者,传递着指令。
4. 服务层的成长:不管是通过系统启动还是第三方应用,蓝牙服务层的初始化流程都是一样的。它会绑定一个叫做AdapterService的服务,就像一个小伙伴,一起成长。
蓝牙的成长离不开协议栈的支持。在安卓系统中,协议栈就像一个大脑,负责处理蓝牙协议和底层驱动的交互。
1. JNI层的桥梁:JNI(Java Native Interface)就像一座桥梁,连接着Java层和原生层。蓝牙服务层JNI使能协议栈bluedroid,通过interface函数接口下发指令到达协议栈入口。
在安卓Android系统中,蓝牙通信是通过一系列的类和服务进行管理的。BluetoothSettings和BluetoothDevice是用户界面层与蓝牙硬件交互的入口,允许用户开启或关闭蓝牙,查找和连接其他蓝牙设备。BluetoothHeadset接口则用于管理与蓝牙耳机的连接,而BluetoothHandsfree接口则是为了车载蓝牙设备设计的。这些接口通常由系统服务如BluetoothService来实现,该服务负责处理蓝牙的低级别操作。
在系统层面,BlueZ是一个开源的蓝牙协议栈,它是Linux内核的一部分,负责处理蓝牙协议和底层驱动的交互。在Android中,BlueZ被用作蓝牙硬件的抽象层,提供了一套API供上层应用调用。
AIDL(Android Interface Definition Language)是Android系统中定义进程间通信(IPC)接口的一种方式。在蓝牙通信中,AIDL被用来定义BluetoothAdapter和BluetoothProfile接口,使得应用程序可以安全地跨进程调用蓝牙服务。
安卓原生的蓝牙协议栈bluedroid在分层上被分为btif、bta、stack、hci这四层,每层的作用各不相同,但实际程序运行是在不同的线程运行的。
蓝牙服务层JNI使能协议栈bluedroid,通过interface函数接口下发指令到达协议栈入口。stackmanagergetinterface()->startupstackasync();将使能指令下发到协议栈管理模块,模块内部通过线程stackmanage继续处理。
依次使能btifconfig、btsnoop、hci等模块。
1. btsnoop模块:判断snoop开关是否打开,从而决定是否创建snoop文件来记录hci的交互信息。
2. snoop开关位置:在开发者选项中,打开该开关,则persist.bluetooth.btsnoopenable全局变量会被置为true;反之开关关闭,该变量会被置为false。
3. snoop文件默认存储位置:/data/misc/bluetooth/logs/
由于打开snoop开关的步骤比较复杂,一般用户根本不会进到开发者选项中,连从哪儿打开开发者选项都是一个难题。
蓝牙协议栈整体上分为:HOST Controller,它们之间以HCI为界线形象地分为上下两部分。Controller对应蓝牙固件也就是蓝牙芯片,这块协议的实现和各家厂商的策略差异很大,但依赖的协议都是相同的。而Host部分最为核心的就是协议栈,本篇分析我们就来扒一扒安卓系统中蓝牙协议栈初始化的实现流程。
协议栈源码路径:systembt
从该仓库下的相关编译配置文件可以知道,协议栈模块最终会被编译成动态so库的形式供其他模块调用。相关配置路径为:systembtmain Android.bp(安卓8之前为Android.mk)
上面的架构图可以明显看出协议栈的动态so库是被JNI层加载的,JNI使用系统提供的动态so库加载方法实现获取协议栈so库对应的句柄即内存地址,再从打开的so库中查找对应的函数地址,这样JNI就达到调用协议栈中函数的目的。
蓝牙JNI层通过dlopen()的系统