了解一下android的蓝牙

setting app(按钮操作) ->framkwork (binder)->bluetooth app service (JNI_OnLoad)-> native (dlopen)-> default.so(dlopen) -> vendor.so -> dev

 

整个过程的核心在default.so,蓝牙协议会放这里,比如修改inquiry scan page scan  interval window等等参数

目录在 system/bt

经常要修改配置在

system/bt/include/bt_target.h
system/bt/conf/bt_stack.conf

每个厂家的BT

android8之前,会有些厂商修改system/bt,后面大多只是改vendor了,主要就是启动蓝牙方式不同,8.0之后启动部分vendor.so也放到了vendor分区,启动有一个class为hal的init启动

整个部分肯定很庞大在android

 

先看一下bluetooth.app部分,主要跑了蓝牙需要的service,如图是蓝牙连接起来最重要service

Android蓝牙是否被正常打开 安卓打开蓝牙_java

还有其它可以选择的service,a2dp播放需要之类

Android蓝牙是否被正常打开 安卓打开蓝牙_Android蓝牙是否被正常打开_02

选择的地方在config.xml

Android蓝牙是否被正常打开 安卓打开蓝牙_android_03

这个可以选择需要的profile,刚开始跑起来的时候,就是这些service跑到最前面,有些必须要跑,有些可以选择跑或者不跑,

像AdapterService 就是跑在最前的,可以说的上是init函数,都不用选,必须得跑,像gatt service都是必须要跑的,低的安卓版本不跑gatt蓝牙直接起不来。

 

接下来要分析一个android 7.1版本   "按setting打开蓝牙按钮,然后打开蓝牙的一部分过程",这样对整个架构会有点感觉

如果从setting app开始,肯定会乱,从中间到两边分步骤,舒服一点,也可以由此进去打开门

 

android 7.1版本(其它版本多少有点改动,但也差不多)

第一部分:从bluetooth app -> native

这一部分的目的就是要找到,哪个地方调用了JNI 打开蓝牙的接口,先定位一下打开蓝牙的接口。

这个地方其实不难找到

Android蓝牙是否被正常打开 安卓打开蓝牙_ci_04

就在AdapterService上面,enableNative 这个函数就是JNI打开蓝牙的接口,已经找到了终点的接口,

 

那这一部分的起点在哪里???这个很难找,而且不止是能不能找到的问题,还有逻辑上的关系。

一共涉及到有如下几个文件

src/com/android/bluetooth/btservice/ProfileService.java
 src/com/android/bluetooth/btservice/AdapterService.java
 src/com/android/bluetooth/btservice/AdapterState.java
 src/com/android/bluetooth/gatt/GattService.java

总体思路:先打开GATT profile,打开GATT的时候enable 蓝牙,这个enable过程包括蓝牙module 协议栈初始化,比如hci_module init的时候,就会打开串口,使能或者不使能流控,加载蓝牙模块的固件(包括config和fw)

然后再打开其它其它的profile,这些profile以service的方式在后台运行,state的状态在framkwork以接口定义,在bluetooth app使用,profile如下显示,过程就到此先。

Android蓝牙是否被正常打开 安卓打开蓝牙_android_05

 

 

1、这个就是起点,从bluetooth app的起点,先不用管framkwork是怎么跑到这里来的

Android蓝牙是否被正常打开 安卓打开蓝牙_java_06

 

这个地方通过管道的方式sendMessage BLE_TURN_ON给 AdapterState

 

2、跑到 AdapterState的 BLE_TURN_ON

Android蓝牙是否被正常打开 安卓打开蓝牙_java_07

这个上面调用了BleOnProcessStart

 

3、运行到BleOnProcessStart 

Android蓝牙是否被正常打开 安卓打开蓝牙_android_08

Android蓝牙是否被正常打开 安卓打开蓝牙_ci_09

 

这个部分就跑到了setGattProfileServiceState,

这个是一个重点!一个重点,BluetoorfAdapter.STATE_ON,这个参数是为什么运行别的profile不会enable蓝牙

因为就是从STATE_OFF -> STATE_ON,这个变化会触发enable 蓝牙

 

开启gatt  profile

 

4、运行setGattProfileServiceState

Android蓝牙是否被正常打开 安卓打开蓝牙_ci_10

Android蓝牙是否被正常打开 安卓打开蓝牙_Android蓝牙是否被正常打开_11

 

5、从startService跑到GattService.java的打开onStartConmmand

Android蓝牙是否被正常打开 安卓打开蓝牙_ci_12

????

没有看到打开蓝牙啊?麻痹,在哪里,跑到这里去哪找,我了个去,看到哪个Override没有,叫做重写,

就是隐藏在这里

 

6、重写的父类中,有enable 蓝牙的逻辑,开始运行到

Android蓝牙是否被正常打开 安卓打开蓝牙_ci_13

 

Android蓝牙是否被正常打开 安卓打开蓝牙_java_14

从STATE_OFF -> STATE_ON,这个变化会触发enable 蓝牙

如果从STATE_ON ->STATE_OFF 这个变化就会关闭蓝牙。

为什么打开其它profile不会再enable蓝牙,因为已经变成STATE_ON了

在ProfileService.java管理着这些profile

看到没有,还没完,还有很多事情,这个父类当中,有跑doStop和doStart,我们只看doStart

 

7、我们去doStart看看 

Android蓝牙是否被正常打开 安卓打开蓝牙_android_15

找到notifyProfileServiceStateChanged,看看这个东东,记着这个BluetoothAdapter.STATE_ON

 

8、notifyProfileServiceStateChanged

Android蓝牙是否被正常打开 安卓打开蓝牙_android_16

 

打开GATT的时候,是notifyProfileServiceStateChanged,其它profile是onProfileConnectionStateChanged经常会用到在ACL链路上连接的时候cid建立时。

 

说全一点可以看看framkwork的定义,看看,看一下

Android蓝牙是否被正常打开 安卓打开蓝牙_android_17

Android蓝牙是否被正常打开 安卓打开蓝牙_Android蓝牙是否被正常打开_18

 

 

9、看看onProfileServiceStatechanged

Android蓝牙是否被正常打开 安卓打开蓝牙_android_19

 

10、看看MESSAGE_PROFILE_SERVICE_STATE_CHANGED

Android蓝牙是否被正常打开 安卓打开蓝牙_android_20

 

11、看看processProfileServiceStateChanged

Android蓝牙是否被正常打开 安卓打开蓝牙_Android蓝牙是否被正常打开_21

Android蓝牙是否被正常打开 安卓打开蓝牙_java_22

 

isBleTurningOn在offstate的时候,这个值是设置为true的

Android蓝牙是否被正常打开 安卓打开蓝牙_Android蓝牙是否被正常打开_23

当开启其它profile才会从isBleTurningOn变成isTurningOn

Android蓝牙是否被正常打开 安卓打开蓝牙_java_24

然后就是干了这件事情

mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));

发消息BLE_STARTED

 

12、终于找到native的接口

Android蓝牙是否被正常打开 安卓打开蓝牙_java_25

 

这里终于调用native打开蓝牙,这部分可以了,没了